106 static void     netstack_zone_shutdown(zoneid_t zoneid, void *arg);
 107 static void     netstack_zone_destroy(zoneid_t zoneid, void *arg);
 108 
 109 static void     netstack_shared_zone_add(zoneid_t zoneid);
 110 static void     netstack_shared_zone_remove(zoneid_t zoneid);
 111 static void     netstack_shared_kstat_add(kstat_t *ks);
 112 static void     netstack_shared_kstat_remove(kstat_t *ks);
 113 
 114 typedef boolean_t applyfn_t(kmutex_t *, netstack_t *, int);
 115 
 116 static void     apply_all_netstacks(int, applyfn_t *);
 117 static void     apply_all_modules(netstack_t *, applyfn_t *);
 118 static void     apply_all_modules_reverse(netstack_t *, applyfn_t *);
 119 static boolean_t netstack_apply_create(kmutex_t *, netstack_t *, int);
 120 static boolean_t netstack_apply_shutdown(kmutex_t *, netstack_t *, int);
 121 static boolean_t netstack_apply_destroy(kmutex_t *, netstack_t *, int);
 122 static boolean_t wait_for_zone_creator(netstack_t *, kmutex_t *);
 123 static boolean_t wait_for_nms_inprogress(netstack_t *, nm_state_t *,
 124     kmutex_t *);
 125 
 126 static void netstack_reap_work(netstack_t *, boolean_t);
 127 ksema_t netstack_reap_limiter;
 128 
 129 void
 130 netstack_init(void)
 131 {
 132         mutex_init(&netstack_g_lock, NULL, MUTEX_DEFAULT, NULL);
 133         mutex_init(&netstack_shared_lock, NULL, MUTEX_DEFAULT, NULL);
 134 
 135         /* XXX KEBE SAYS hard-coded constant needs to be fixed. */
 136         sema_init(&netstack_reap_limiter, 1024, NULL, SEMA_DRIVER, NULL);
 137 
 138         netstack_initialized = 1;
 139 
 140         /*
 141          * We want to be informed each time a zone is created or
 142          * destroyed in the kernel, so we can maintain the
 143          * stack instance information.
 144          */
 145         zone_key_create(&netstack_zone_key, netstack_zone_create,
 
1020         return (ns);
1021 }
1022 
1023 /*
1024  * Find a stack instance given the stackid with exact match?
1025  * Increases the reference count if found; caller must do a
1026  * netstack_rele().
1027  *
1028  * Skip the unitialized ones.
1029  */
1030 netstack_t *
1031 netstack_find_by_stackid(netstackid_t stackid)
1032 {
1033         netstack_t *ns;
1034 
1035         mutex_enter(&netstack_g_lock);
1036         for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1037                 mutex_enter(&ns->netstack_lock);
1038                 if (ns->netstack_stackid == stackid &&
1039                     !(ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))) {
1040                         mutex_exit(&ns->netstack_lock);
1041                         netstack_hold(ns);
1042                         mutex_exit(&netstack_g_lock);
1043                         return (ns);
1044                 }
1045                 mutex_exit(&ns->netstack_lock);
1046         }
1047         mutex_exit(&netstack_g_lock);
1048         return (NULL);
1049 }
1050 
1051 boolean_t
1052 netstack_inuse_by_stackid(netstackid_t stackid)
1053 {
1054         netstack_t *ns;
1055         boolean_t rval = B_FALSE;
1056 
1057         mutex_enter(&netstack_g_lock);
1058 
1059         for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1060                 if (ns->netstack_stackid == stackid) {
1061                         rval = B_TRUE;
 
1178                         sema_p(&netstack_reap_limiter);
1179                         /* Caputre delay in ns. */
1180                         DTRACE_PROBE1(netstack__reap__rate__limited,
1181                             hrtime_t *, gethrtime() - measurement);
1182                 }
1183 
1184                 if (taskq_dispatch(system_taskq,
1185                     is_not_intr ? netstack_reap : netstack_reap_intr, ns,
1186                     TQ_NOSLEEP) == NULL) {
1187                         /*
1188                          * Well shoot, why can't we taskq_dispatch?
1189                          * Take our chances with a direct call.
1190                          */
1191                         DTRACE_PROBE1(netstack__reap__taskq__fail,
1192                             netstack_t *, ns);
1193                         netstack_reap_work(ns, is_not_intr);
1194                 }
1195         }
1196 }
1197 
1198 void
1199 netstack_hold(netstack_t *ns)
1200 {
1201         mutex_enter(&ns->netstack_lock);
1202         ns->netstack_refcnt++;
1203         ASSERT(ns->netstack_refcnt > 0);
1204         mutex_exit(&ns->netstack_lock);
1205         DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns);
1206 }
1207 
1208 /*
1209  * To support kstat_create_netstack() using kstat_zone_add we need
1210  * to track both
1211  *  - all zoneids that use the global/shared stack
1212  *  - all kstats that have been added for the shared stack
1213  */
1214 kstat_t *
1215 kstat_create_netstack(char *ks_module, int ks_instance, char *ks_name,
1216     char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
1217     netstackid_t ks_netstackid)
1218 {
1219         kstat_t *ks;
1220 
1221         if (ks_netstackid == GLOBAL_NETSTACKID) {
1222                 ks = kstat_create_zone(ks_module, ks_instance, ks_name,
1223                     ks_class, ks_type, ks_ndata, ks_flags, GLOBAL_ZONEID);
1224                 if (ks != NULL)
1225                         netstack_shared_kstat_add(ks);
 
 | 
 
 
 106 static void     netstack_zone_shutdown(zoneid_t zoneid, void *arg);
 107 static void     netstack_zone_destroy(zoneid_t zoneid, void *arg);
 108 
 109 static void     netstack_shared_zone_add(zoneid_t zoneid);
 110 static void     netstack_shared_zone_remove(zoneid_t zoneid);
 111 static void     netstack_shared_kstat_add(kstat_t *ks);
 112 static void     netstack_shared_kstat_remove(kstat_t *ks);
 113 
 114 typedef boolean_t applyfn_t(kmutex_t *, netstack_t *, int);
 115 
 116 static void     apply_all_netstacks(int, applyfn_t *);
 117 static void     apply_all_modules(netstack_t *, applyfn_t *);
 118 static void     apply_all_modules_reverse(netstack_t *, applyfn_t *);
 119 static boolean_t netstack_apply_create(kmutex_t *, netstack_t *, int);
 120 static boolean_t netstack_apply_shutdown(kmutex_t *, netstack_t *, int);
 121 static boolean_t netstack_apply_destroy(kmutex_t *, netstack_t *, int);
 122 static boolean_t wait_for_zone_creator(netstack_t *, kmutex_t *);
 123 static boolean_t wait_for_nms_inprogress(netstack_t *, nm_state_t *,
 124     kmutex_t *);
 125 
 126 static void netstack_hold_locked(netstack_t *);
 127 static void netstack_reap_work(netstack_t *, boolean_t);
 128 ksema_t netstack_reap_limiter;
 129 
 130 void
 131 netstack_init(void)
 132 {
 133         mutex_init(&netstack_g_lock, NULL, MUTEX_DEFAULT, NULL);
 134         mutex_init(&netstack_shared_lock, NULL, MUTEX_DEFAULT, NULL);
 135 
 136         /* XXX KEBE SAYS hard-coded constant needs to be fixed. */
 137         sema_init(&netstack_reap_limiter, 1024, NULL, SEMA_DRIVER, NULL);
 138 
 139         netstack_initialized = 1;
 140 
 141         /*
 142          * We want to be informed each time a zone is created or
 143          * destroyed in the kernel, so we can maintain the
 144          * stack instance information.
 145          */
 146         zone_key_create(&netstack_zone_key, netstack_zone_create,
 
1021         return (ns);
1022 }
1023 
1024 /*
1025  * Find a stack instance given the stackid with exact match?
1026  * Increases the reference count if found; caller must do a
1027  * netstack_rele().
1028  *
1029  * Skip the unitialized ones.
1030  */
1031 netstack_t *
1032 netstack_find_by_stackid(netstackid_t stackid)
1033 {
1034         netstack_t *ns;
1035 
1036         mutex_enter(&netstack_g_lock);
1037         for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1038                 mutex_enter(&ns->netstack_lock);
1039                 if (ns->netstack_stackid == stackid &&
1040                     !(ns->netstack_flags & (NSF_UNINIT|NSF_CLOSING))) {
1041                         netstack_hold_locked(ns);
1042                         mutex_exit(&ns->netstack_lock);
1043                         mutex_exit(&netstack_g_lock);
1044                         return (ns);
1045                 }
1046                 mutex_exit(&ns->netstack_lock);
1047         }
1048         mutex_exit(&netstack_g_lock);
1049         return (NULL);
1050 }
1051 
1052 boolean_t
1053 netstack_inuse_by_stackid(netstackid_t stackid)
1054 {
1055         netstack_t *ns;
1056         boolean_t rval = B_FALSE;
1057 
1058         mutex_enter(&netstack_g_lock);
1059 
1060         for (ns = netstack_head; ns != NULL; ns = ns->netstack_next) {
1061                 if (ns->netstack_stackid == stackid) {
1062                         rval = B_TRUE;
 
1179                         sema_p(&netstack_reap_limiter);
1180                         /* Caputre delay in ns. */
1181                         DTRACE_PROBE1(netstack__reap__rate__limited,
1182                             hrtime_t *, gethrtime() - measurement);
1183                 }
1184 
1185                 if (taskq_dispatch(system_taskq,
1186                     is_not_intr ? netstack_reap : netstack_reap_intr, ns,
1187                     TQ_NOSLEEP) == NULL) {
1188                         /*
1189                          * Well shoot, why can't we taskq_dispatch?
1190                          * Take our chances with a direct call.
1191                          */
1192                         DTRACE_PROBE1(netstack__reap__taskq__fail,
1193                             netstack_t *, ns);
1194                         netstack_reap_work(ns, is_not_intr);
1195                 }
1196         }
1197 }
1198 
1199 static void
1200 netstack_hold_locked(netstack_t *ns)
1201 {
1202         ASSERT(MUTEX_HELD(&ns->netstack_lock));
1203         ns->netstack_refcnt++;
1204         ASSERT(ns->netstack_refcnt > 0);
1205         DTRACE_PROBE1(netstack__inc__ref, netstack_t *, ns);
1206 }
1207 
1208 void
1209 netstack_hold(netstack_t *ns)
1210 {
1211         mutex_enter(&ns->netstack_lock);
1212         netstack_hold_locked(ns);
1213         mutex_exit(&ns->netstack_lock);
1214 }
1215 
1216 /*
1217  * To support kstat_create_netstack() using kstat_zone_add we need
1218  * to track both
1219  *  - all zoneids that use the global/shared stack
1220  *  - all kstats that have been added for the shared stack
1221  */
1222 kstat_t *
1223 kstat_create_netstack(char *ks_module, int ks_instance, char *ks_name,
1224     char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
1225     netstackid_t ks_netstackid)
1226 {
1227         kstat_t *ks;
1228 
1229         if (ks_netstackid == GLOBAL_NETSTACKID) {
1230                 ks = kstat_create_zone(ks_module, ks_instance, ks_name,
1231                     ks_class, ks_type, ks_ndata, ks_flags, GLOBAL_ZONEID);
1232                 if (ks != NULL)
1233                         netstack_shared_kstat_add(ks);
 
 |