Print this page
3914 ill_frag_hash_tbl not allocated for loopback interfaces
Reviewed by: Sebastien Roy <sebastien.roy@delphix.com>

*** 20,29 **** --- 20,32 ---- */ /* * 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. */
*** 220,229 **** --- 223,234 ---- static void ipif_trace_cleanup(const ipif_t *); #endif 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. */ int ip_min_frag_prune_time = 0;
*** 278,288 **** { DL_OTHER, IFT_OTHER, ETHERTYPE_IP, ETHERTYPE_IPV6, ip_ether_v4_mapping, ip_ether_v6_mapping, ip_nodef_v6intfid, 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. */ sin6_t sin6_null; /* Zero address for quick clears */ sin_t sin_null; /* Zero address for quick clears */ --- 283,292 ----
*** 3327,3380 **** } return (B_TRUE); } /* ! * 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. */ ! int ! ill_init(queue_t *q, ill_t *ill) { int count; - dl_info_req_t *dlir; - mblk_t *info_mp; 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); ! info_mp = allocb(MAX(sizeof (dl_info_req_t), sizeof (dl_info_ack_t)), ! BPRI_HI); ! if (info_mp == NULL) ! return (ENOMEM); /* * 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); return (ENOMEM); - } ill->ill_frag_ptr = frag_ptr; ill->ill_frag_free_num_pkts = 0; ill->ill_last_frag_clean_time = 0; ill->ill_frag_hash_tbl = (ipfb_t *)frag_ptr; ill->ill_name = (char *)(frag_ptr + ILL_FRAG_HASH_TBL_SIZE); --- 3331,3376 ---- } return (B_TRUE); } /* ! * 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. */ ! static int ! ill_init_common(ill_t *ill, queue_t *q, boolean_t isv6, boolean_t is_loopback, ! boolean_t ipsq_enter) { int count; uchar_t *frag_ptr; 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; + 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; + } ! 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) return (ENOMEM); ill->ill_frag_ptr = frag_ptr; ill->ill_frag_free_num_pkts = 0; ill->ill_last_frag_clean_time = 0; ill->ill_frag_hash_tbl = (ipfb_t *)frag_ptr; ill->ill_name = (char *)(frag_ptr + ILL_FRAG_HASH_TBL_SIZE);
*** 3383,3421 **** NULL, MUTEX_DEFAULT, NULL); } 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; 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); 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; rw_init(&ill->ill_mcast_lock, NULL, RW_DEFAULT, NULL); --- 3379,3412 ---- NULL, MUTEX_DEFAULT, NULL); } ill->ill_phyint = (phyint_t *)mi_zalloc(sizeof (phyint_t)); if (ill->ill_phyint == NULL) { mi_free(frag_ptr); return (ENOMEM); } mutex_init(&ill->ill_phyint->phyint_lock, NULL, MUTEX_DEFAULT, 0); ! 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, ipsq_enter)) { mi_free(frag_ptr); mi_free(ill->ill_phyint); return (ENOMEM); } /* Frag queue limit stuff */ ill->ill_frag_count = 0; ill->ill_ipf_gen = 0; rw_init(&ill->ill_mcast_lock, NULL, RW_DEFAULT, NULL);
*** 3436,3445 **** --- 3427,3483 ---- ill->ill_reachable_time = ND_REACHABLE_TIME; ill->ill_xmit_count = ND_MAX_MULTICAST_SOLICIT; 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; info_mp->b_wptr = (uchar_t *)&dlir[1]; dlir->dl_primitive = DL_INFO_REQ;
*** 3683,3722 **** ill = (ill_t *)(mi_alloc(sizeof (ill_t) + sizeof (ipif_loopback_name), BPRI_MED)); if (ill == NULL) goto done; ! *ill = ill_null; ! mutex_init(&ill->ill_lock, NULL, MUTEX_DEFAULT, NULL); 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 * to make IP operate as if in the global zone. */ ill->ill_zoneid = GLOBAL_ZONEID; ! ill->ill_phyint = (phyint_t *)mi_zalloc(sizeof (phyint_t)); ! if (ill->ill_phyint == NULL) 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; /* * ipif_loopback_name can't be pointed at directly because its used --- 3721,3745 ---- ill = (ill_t *)(mi_alloc(sizeof (ill_t) + sizeof (ipif_loopback_name), BPRI_MED)); if (ill == NULL) goto done; ! bzero(ill, sizeof (*ill)); ill->ill_ipst = ipst; netstack_hold(ipst->ips_netstack); /* * For exclusive stacks we set the zoneid to zero * to make IP operate as if in the global zone. */ ill->ill_zoneid = GLOBAL_ZONEID; ! if (ill_init_common(ill, NULL, isv6, B_TRUE, B_FALSE) != 0) goto done; 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; /* * ipif_loopback_name can't be pointed at directly because its used
*** 3728,3752 **** (void) strcpy(ill->ill_name, ipif_loopback_name); ill->ill_name_length = sizeof (ipif_loopback_name); /* 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; ill->ill_flags = ILLF_MULTICAST; --- 3751,3760 ----
*** 3771,3791 **** /* * 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"); /* Let SCTP know so that it can add this to its list */ sctp_update_ill(ill, SCTP_ILL_INSERT); --- 3779,3792 ----