+static void
+rte_if_ref(struct ifnet *ifp, int cnt)
+{
+ struct kev_msg ev_msg;
+ struct net_event_data ev_data;
+ uint32_t old;
+
+ /* Force cnt to 1 increment/decrement */
+ if (cnt < -1 || cnt > 1)
+ panic("%s: invalid count argument (%d)", __func__, cnt);
+
+ old = atomic_add_32_ov(&ifp->if_route_refcnt, cnt);
+ if (cnt < 0 && old == 0)
+ panic("%s: ifp=%p negative route refcnt!", __func__, ifp);
+
+ /*
+ * The following is done without first holding the ifnet lock,
+ * for performance reasons. The relevant ifnet fields, with
+ * the exception of the if_idle_flags, are never changed
+ * during the lifetime of the ifnet. The if_idle_flags
+ * may possibly be modified, so in the event that the value
+ * is stale because IFRF_IDLE_NOTIFY was cleared, we'd end up
+ * sending the event anyway. This is harmless as it is just
+ * a notification to the monitoring agent in user space, and
+ * it is expected to check via SIOCGIFGETRTREFCNT again anyway.
+ */
+ if ((ifp->if_idle_flags & IFRF_IDLE_NOTIFY) && cnt < 0 && old == 1) {
+ bzero(&ev_msg, sizeof (ev_msg));
+ bzero(&ev_data, sizeof (ev_data));
+
+ ev_msg.vendor_code = KEV_VENDOR_APPLE;
+ ev_msg.kev_class = KEV_NETWORK_CLASS;
+ ev_msg.kev_subclass = KEV_DL_SUBCLASS;
+ ev_msg.event_code = KEV_DL_IF_IDLE_ROUTE_REFCNT;
+
+ strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
+
+ ev_data.if_family = ifp->if_family;
+ ev_data.if_unit = ifp->if_unit;
+ ev_msg.dv[0].data_length = sizeof (struct net_event_data);
+ ev_msg.dv[0].data_ptr = &ev_data;
+
+ kev_post_msg(&ev_msg);
+ }
+}
+