diff options
author | Joshua M. Clulow <jmc@joyent.com> | 2013-06-11 13:44:16 -0700 |
---|---|---|
committer | Joshua M. Clulow <jmc@joyent.com> | 2013-06-11 20:44:16 +0000 |
commit | 7ca91a34cb7e9c014f15891eb588c5040094d98c (patch) | |
tree | 9ea527e95abbf36c09e67ecf0fc1b0a81c66ae93 | |
parent | 9162aa20aa4aa82ef715609015d0e5db1501a076 (diff) | |
download | illumos-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.c | 169 | ||||
-rw-r--r-- | usr/src/uts/intel/ip/ip.global-objs.debug64 | 1 | ||||
-rw-r--r-- | usr/src/uts/intel/ip/ip.global-objs.obj64 | 1 | ||||
-rw-r--r-- | usr/src/uts/sparc/ip/ip.global-objs.debug64 | 1 | ||||
-rw-r--r-- | usr/src/uts/sparc/ip/ip.global-objs.obj64 | 1 |
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 |