summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua M. Clulow <jmc@joyent.com>2013-06-11 13:44:16 -0700
committerJoshua M. Clulow <jmc@joyent.com>2013-06-11 20:44:16 +0000
commit7ca91a34cb7e9c014f15891eb588c5040094d98c (patch)
tree9ea527e95abbf36c09e67ecf0fc1b0a81c66ae93
parent9162aa20aa4aa82ef715609015d0e5db1501a076 (diff)
downloadillumos-joyent-7ca91a34cb7e9c014f15891eb588c5040094d98c.tar.gz
OS-2239 ill_frag_hash_tbl not allocated for loopback interfaces
Reviewed by: Sebastien Roy <sebastien.roy@delphix.com>
-rw-r--r--usr/src/uts/common/inet/ip/ip_if.c169
-rw-r--r--usr/src/uts/intel/ip/ip.global-objs.debug641
-rw-r--r--usr/src/uts/intel/ip/ip.global-objs.obj641
-rw-r--r--usr/src/uts/sparc/ip/ip.global-objs.debug641
-rw-r--r--usr/src/uts/sparc/ip/ip.global-objs.obj641
5 files changed, 85 insertions, 88 deletions
diff --git a/usr/src/uts/common/inet/ip/ip_if.c b/usr/src/uts/common/inet/ip/ip_if.c
index bb6b8aa631..73f44bddc1 100644
--- a/usr/src/uts/common/inet/ip/ip_if.c
+++ b/usr/src/uts/common/inet/ip/ip_if.c
@@ -22,6 +22,9 @@
* Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1990 Mentat Inc.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
/*
* This file contains the interface control functions for IP.
@@ -222,6 +225,8 @@ static void ipif_trace_cleanup(const ipif_t *);
static void ill_dlpi_clear_deferred(ill_t *ill);
+static void phyint_flags_init(phyint_t *, t_uscalar_t);
+
/*
* if we go over the memory footprint limit more than once in this msec
* interval, we'll start pruning aggressively.
@@ -280,7 +285,6 @@ static ip_m_t ip_m_tbl[] = {
ip_nodef_v6intfid }
};
-static ill_t ill_null; /* Empty ILL for init. */
char ipif_loopback_name[] = "lo0";
/* These are used by all IP network modules. */
@@ -3329,50 +3333,42 @@ ipsq_init(ill_t *ill, boolean_t enter)
}
/*
- * ill_init is called by ip_open when a device control stream is opened.
- * It does a few initializations, and shoots a DL_INFO_REQ message down
- * to the driver. The response is later picked up in ip_rput_dlpi and
- * used to set up default mechanisms for talking to the driver. (Always
- * called as writer.)
- *
- * If this function returns error, ip_open will call ip_close which in
- * turn will call ill_delete to clean up any memory allocated here that
- * is not yet freed.
+ * Here we perform initialisation of the ill_t common to both regular
+ * interface ILLs and the special loopback ILL created by ill_lookup_on_name.
*/
-int
-ill_init(queue_t *q, ill_t *ill)
+static int
+ill_init_common(ill_t *ill, queue_t *q, boolean_t isv6, boolean_t is_loopback,
+ boolean_t ipsq_enter)
{
- int count;
- dl_info_req_t *dlir;
- mblk_t *info_mp;
+ int count;
uchar_t *frag_ptr;
- /*
- * The ill is initialized to zero by mi_alloc*(). In addition
- * some fields already contain valid values, initialized in
- * ip_open(), before we reach here.
- */
mutex_init(&ill->ill_lock, NULL, MUTEX_DEFAULT, 0);
mutex_init(&ill->ill_saved_ire_lock, NULL, MUTEX_DEFAULT, NULL);
ill->ill_saved_ire_cnt = 0;
- ill->ill_rq = q;
- ill->ill_wq = WR(q);
+ if (is_loopback) {
+ ill->ill_max_frag = isv6 ? ip_loopback_mtu_v6plus :
+ ip_loopback_mtuplus;
+ /*
+ * No resolver here.
+ */
+ ill->ill_net_type = IRE_LOOPBACK;
+ } else {
+ ill->ill_rq = q;
+ ill->ill_wq = WR(q);
+ ill->ill_ppa = UINT_MAX;
+ }
- info_mp = allocb(MAX(sizeof (dl_info_req_t), sizeof (dl_info_ack_t)),
- BPRI_HI);
- if (info_mp == NULL)
- return (ENOMEM);
+ ill->ill_isv6 = isv6;
/*
* Allocate sufficient space to contain our fragment hash table and
* the device name.
*/
frag_ptr = (uchar_t *)mi_zalloc(ILL_FRAG_HASH_TBL_SIZE + 2 * LIFNAMSIZ);
- if (frag_ptr == NULL) {
- freemsg(info_mp);
+ if (frag_ptr == NULL)
return (ENOMEM);
- }
ill->ill_frag_ptr = frag_ptr;
ill->ill_frag_free_num_pkts = 0;
ill->ill_last_frag_clean_time = 0;
@@ -3385,35 +3381,30 @@ ill_init(queue_t *q, ill_t *ill)
ill->ill_phyint = (phyint_t *)mi_zalloc(sizeof (phyint_t));
if (ill->ill_phyint == NULL) {
- freemsg(info_mp);
mi_free(frag_ptr);
return (ENOMEM);
}
mutex_init(&ill->ill_phyint->phyint_lock, NULL, MUTEX_DEFAULT, 0);
- /*
- * For now pretend this is a v4 ill. We need to set phyint_ill*
- * at this point because of the following reason. If we can't
- * enter the ipsq at some point and cv_wait, the writer that
- * wakes us up tries to locate us using the list of all phyints
- * in an ipsq and the ills from the phyint thru the phyint_ill*.
- * If we don't set it now, we risk a missed wakeup.
- */
- ill->ill_phyint->phyint_illv4 = ill;
- ill->ill_ppa = UINT_MAX;
+ if (isv6) {
+ ill->ill_phyint->phyint_illv6 = ill;
+ } else {
+ ill->ill_phyint->phyint_illv4 = ill;
+ }
+ if (is_loopback) {
+ phyint_flags_init(ill->ill_phyint, DL_LOOP);
+ }
+
list_create(&ill->ill_nce, sizeof (nce_t), offsetof(nce_t, nce_node));
ill_set_inputfn(ill);
- if (!ipsq_init(ill, B_TRUE)) {
- freemsg(info_mp);
+ if (!ipsq_init(ill, ipsq_enter)) {
mi_free(frag_ptr);
mi_free(ill->ill_phyint);
return (ENOMEM);
}
- ill->ill_state_flags |= ILL_LL_SUBNET_PENDING;
-
/* Frag queue limit stuff */
ill->ill_frag_count = 0;
ill->ill_ipf_gen = 0;
@@ -3438,6 +3429,53 @@ ill_init(queue_t *q, ill_t *ill)
ill->ill_max_buf = ND_MAX_Q;
ill->ill_refcnt = 0;
+ return (0);
+}
+
+/*
+ * ill_init is called by ip_open when a device control stream is opened.
+ * It does a few initializations, and shoots a DL_INFO_REQ message down
+ * to the driver. The response is later picked up in ip_rput_dlpi and
+ * used to set up default mechanisms for talking to the driver. (Always
+ * called as writer.)
+ *
+ * If this function returns error, ip_open will call ip_close which in
+ * turn will call ill_delete to clean up any memory allocated here that
+ * is not yet freed.
+ *
+ * Note: ill_ipst and ill_zoneid must be set before calling ill_init.
+ */
+int
+ill_init(queue_t *q, ill_t *ill)
+{
+ int ret;
+ dl_info_req_t *dlir;
+ mblk_t *info_mp;
+
+ info_mp = allocb(MAX(sizeof (dl_info_req_t), sizeof (dl_info_ack_t)),
+ BPRI_HI);
+ if (info_mp == NULL)
+ return (ENOMEM);
+
+ /*
+ * The ill is initialized to zero by mi_alloc*(). In addition
+ * some fields already contain valid values, initialized in
+ * ip_open(), before we reach here.
+ *
+ * For now pretend this is a v4 ill. We need to set phyint_ill*
+ * at this point because of the following reason. If we can't
+ * enter the ipsq at some point and cv_wait, the writer that
+ * wakes us up tries to locate us using the list of all phyints
+ * in an ipsq and the ills from the phyint thru the phyint_ill*.
+ * If we don't set it now, we risk a missed wakeup.
+ */
+ if ((ret = ill_init_common(ill, q, B_FALSE, B_FALSE, B_TRUE)) != 0) {
+ freemsg(info_mp);
+ return (ret);
+ }
+
+ ill->ill_state_flags |= ILL_LL_SUBNET_PENDING;
+
/* Send down the Info Request to the driver. */
info_mp->b_datap->db_type = M_PCPROTO;
dlir = (dl_info_req_t *)info_mp->b_rptr;
@@ -3685,10 +3723,8 @@ ill_lookup_on_name(char *name, boolean_t do_alloc, boolean_t isv6,
if (ill == NULL)
goto done;
- *ill = ill_null;
- mutex_init(&ill->ill_lock, NULL, MUTEX_DEFAULT, NULL);
+ bzero(ill, sizeof (*ill));
ill->ill_ipst = ipst;
- list_create(&ill->ill_nce, sizeof (nce_t), offsetof(nce_t, nce_node));
netstack_hold(ipst->ips_netstack);
/*
* For exclusive stacks we set the zoneid to zero
@@ -3696,25 +3732,12 @@ ill_lookup_on_name(char *name, boolean_t do_alloc, boolean_t isv6,
*/
ill->ill_zoneid = GLOBAL_ZONEID;
- ill->ill_phyint = (phyint_t *)mi_zalloc(sizeof (phyint_t));
- if (ill->ill_phyint == NULL)
+ if (ill_init_common(ill, NULL, isv6, B_TRUE, B_FALSE) != 0)
goto done;
- if (isv6)
- ill->ill_phyint->phyint_illv6 = ill;
- else
- ill->ill_phyint->phyint_illv4 = ill;
- mutex_init(&ill->ill_phyint->phyint_lock, NULL, MUTEX_DEFAULT, 0);
- phyint_flags_init(ill->ill_phyint, DL_LOOP);
-
- if (isv6) {
- ill->ill_isv6 = B_TRUE;
- ill->ill_max_frag = ip_loopback_mtu_v6plus;
- } else {
- ill->ill_max_frag = ip_loopback_mtuplus;
- }
if (!ill_allocate_mibs(ill))
goto done;
+
ill->ill_current_frag = ill->ill_max_frag;
ill->ill_mtu = ill->ill_max_frag; /* Initial value */
ill->ill_mc_mtu = ill->ill_mtu;
@@ -3730,21 +3753,6 @@ ill_lookup_on_name(char *name, boolean_t do_alloc, boolean_t isv6,
/* Set ill_dlpi_pending for ipsq_current_finish() to work properly */
ill->ill_dlpi_pending = DL_PRIM_INVAL;
- rw_init(&ill->ill_mcast_lock, NULL, RW_DEFAULT, NULL);
- mutex_init(&ill->ill_mcast_serializer, NULL, MUTEX_DEFAULT, NULL);
- ill->ill_global_timer = INFINITY;
- ill->ill_mcast_v1_time = ill->ill_mcast_v2_time = 0;
- ill->ill_mcast_v1_tset = ill->ill_mcast_v2_tset = 0;
- ill->ill_mcast_rv = MCAST_DEF_ROBUSTNESS;
- ill->ill_mcast_qi = MCAST_DEF_QUERY_INTERVAL;
-
- /* No resolver here. */
- ill->ill_net_type = IRE_LOOPBACK;
-
- /* Initialize the ipsq */
- if (!ipsq_init(ill, B_FALSE))
- goto done;
-
ipif = ipif_allocate(ill, 0L, IRE_LOOPBACK, B_TRUE, B_TRUE, NULL);
if (ipif == NULL)
goto done;
@@ -3773,17 +3781,10 @@ ill_lookup_on_name(char *name, boolean_t do_alloc, boolean_t isv6,
* Chain us in at the end of the ill list. hold the ill
* before we make it globally visible. 1 for the lookup.
*/
- ill->ill_refcnt = 0;
ill_refhold(ill);
- ill->ill_frag_count = 0;
- ill->ill_frag_free_num_pkts = 0;
- ill->ill_last_frag_clean_time = 0;
-
ipsq = ill->ill_phyint->phyint_ipsq;
- ill_set_inputfn(ill);
-
if (ill_glist_insert(ill, "lo", isv6) != 0)
cmn_err(CE_PANIC, "cannot insert loopback interface");
diff --git a/usr/src/uts/intel/ip/ip.global-objs.debug64 b/usr/src/uts/intel/ip/ip.global-objs.debug64
index b05d399caf..3098f98265 100644
--- a/usr/src/uts/intel/ip/ip.global-objs.debug64
+++ b/usr/src/uts/intel/ip/ip.global-objs.debug64
@@ -105,7 +105,6 @@ ilb_sticky_expiry
ilb_sticky_timer_size
ilb_sticky_timeout
ill_no_arena
-ill_null
inet_dev_info
inet_devops
ip6_ftable_hash_size
diff --git a/usr/src/uts/intel/ip/ip.global-objs.obj64 b/usr/src/uts/intel/ip/ip.global-objs.obj64
index 7dd30502a0..f182d7198e 100644
--- a/usr/src/uts/intel/ip/ip.global-objs.obj64
+++ b/usr/src/uts/intel/ip/ip.global-objs.obj64
@@ -105,7 +105,6 @@ ilb_sticky_expiry
ilb_sticky_timer_size
ilb_sticky_timeout
ill_no_arena
-ill_null
inet_dev_info
inet_devops
ip6_ftable_hash_size
diff --git a/usr/src/uts/sparc/ip/ip.global-objs.debug64 b/usr/src/uts/sparc/ip/ip.global-objs.debug64
index 8766fae5e0..2dfae5d0d7 100644
--- a/usr/src/uts/sparc/ip/ip.global-objs.debug64
+++ b/usr/src/uts/sparc/ip/ip.global-objs.debug64
@@ -100,7 +100,6 @@ ilb_sticky_expiry
ilb_sticky_timer_size
ilb_sticky_timeout
ill_no_arena
-ill_null
inet_dev_info
inet_devops
ip6_ftable_hash_size
diff --git a/usr/src/uts/sparc/ip/ip.global-objs.obj64 b/usr/src/uts/sparc/ip/ip.global-objs.obj64
index b1199eaf38..e8210d402c 100644
--- a/usr/src/uts/sparc/ip/ip.global-objs.obj64
+++ b/usr/src/uts/sparc/ip/ip.global-objs.obj64
@@ -100,7 +100,6 @@ ilb_sticky_expiry
ilb_sticky_timer_size
ilb_sticky_timeout
ill_no_arena
-ill_null
inet_dev_info
inet_devops
ip6_ftable_hash_size