--- old/usr/src/uts/common/inet/ip/ip_if.c	Sat Jul 27 17:23:33 2013
+++ new/usr/src/uts/common/inet/ip/ip_if.c	Sat Jul 27 17:23:33 2013
@@ -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	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 @@
 	    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,40 +3333,34 @@
 }
 
 /*
- * 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
@@ -3369,10 +3367,8 @@
 	 * 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->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->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 @@
 	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->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 @@
 	/* 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 @@
 	 * 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");
 
--- old/usr/src/uts/intel/ip/ip.global-objs.debug64	Sat Jul 27 17:23:35 2013
+++ new/usr/src/uts/intel/ip/ip.global-objs.debug64	Sat Jul 27 17:23:36 2013
@@ -100,7 +100,6 @@
 ilb_sticky_timer_size
 ilb_sticky_timeout
 ill_no_arena
-ill_null
 inet_dev_info
 inet_devops
 ip6_ftable_hash_size
--- old/usr/src/uts/intel/ip/ip.global-objs.obj64	Sat Jul 27 17:23:38 2013
+++ new/usr/src/uts/intel/ip/ip.global-objs.obj64	Sat Jul 27 17:23:38 2013
@@ -100,7 +100,6 @@
 ilb_sticky_timer_size
 ilb_sticky_timeout
 ill_no_arena
-ill_null
 inet_dev_info
 inet_devops
 ip6_ftable_hash_size
--- old/usr/src/uts/sparc/ip/ip.global-objs.debug64	Sat Jul 27 17:23:38 2013
+++ new/usr/src/uts/sparc/ip/ip.global-objs.debug64	Sat Jul 27 17:23:38 2013
@@ -100,7 +100,6 @@
 ilb_sticky_timer_size
 ilb_sticky_timeout
 ill_no_arena
-ill_null
 inet_dev_info
 inet_devops
 ip6_ftable_hash_size
--- old/usr/src/uts/sparc/ip/ip.global-objs.obj64	Sat Jul 27 17:23:40 2013
+++ new/usr/src/uts/sparc/ip/ip.global-objs.obj64	Sat Jul 27 17:23:40 2013
@@ -100,7 +100,6 @@
 ilb_sticky_timer_size
 ilb_sticky_timeout
 ill_no_arena
-ill_null
 inet_dev_info
 inet_devops
 ip6_ftable_hash_size
