Index: head/sys/net/route/nhgrp_ctl.c =================================================================== --- head/sys/net/route/nhgrp_ctl.c +++ head/sys/net/route/nhgrp_ctl.c @@ -762,6 +762,21 @@ return (nhg_priv->nhg_idx); } +uint32_t +nhgrp_get_count(struct rib_head *rh) +{ + struct nh_control *ctl; + uint32_t count; + + ctl = rh->nh_control; + + NHOPS_RLOCK(ctl); + count = ctl->gr_head.items_count; + NHOPS_RUNLOCK(ctl); + + return (count); +} + int nhgrp_dump_sysctl(struct rib_head *rh, struct sysctl_req *w) { Index: head/sys/net/route/nhop_ctl.c =================================================================== --- head/sys/net/route/nhop_ctl.c +++ head/sys/net/route/nhop_ctl.c @@ -852,6 +852,21 @@ return (error); } +uint32_t +nhops_get_count(struct rib_head *rh) +{ + struct nh_control *ctl; + uint32_t count; + + ctl = rh->nh_control; + + NHOPS_RLOCK(ctl); + count = ctl->nh_head.items_count; + NHOPS_RUNLOCK(ctl); + + return (count); +} + int nhops_dump_sysctl(struct rib_head *rh, struct sysctl_req *w) { Index: head/sys/net/route/route_ctl.h =================================================================== --- head/sys/net/route/route_ctl.h +++ head/sys/net/route/route_ctl.h @@ -87,13 +87,18 @@ const struct rtentry *rib_lookup_lpm(uint32_t fibnum, int family, const struct sockaddr *dst, struct route_nhop_data *rnd); +/* Nexthops */ +uint32_t nhops_get_count(struct rib_head *rh); + /* Multipath */ struct nhgrp_object; struct weightened_nhop; struct weightened_nhop *nhgrp_get_nhops(struct nhgrp_object *nhg, uint32_t *pnum_nhops); +uint32_t nhgrp_get_count(struct rib_head *rh); +/* Route subscriptions */ enum rib_subscription_type { RIB_NOTIFY_IMMEDIATE, RIB_NOTIFY_DELAYED @@ -109,6 +114,6 @@ struct rib_subscription *rib_subscribe_internal(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type, bool waitok); -int rib_unsibscribe(uint32_t fibnum, int family, struct rib_subscription *rs); +void rib_unsibscribe(struct rib_subscription *rs); #endif Index: head/sys/net/route/route_ctl.c =================================================================== --- head/sys/net/route/route_ctl.c +++ head/sys/net/route/route_ctl.c @@ -70,6 +70,7 @@ CK_STAILQ_ENTRY(rib_subscription) next; rib_subscription_cb_t *func; void *arg; + struct rib_head *rnh; enum rib_subscription_type type; struct epoch_context epoch_ctx; }; @@ -669,6 +670,8 @@ /* Finalize notification */ rnh->rnh_gen++; + rnh->rnh_prefixes--; + rc->rc_cmd = RTM_DELETE; rc->rc_rt = rt; rc->rc_nh_old = rt->rt_nhop; @@ -929,6 +932,7 @@ /* Finalize notification */ rnh->rnh_gen++; + rnh->rnh_prefixes++; rc->rc_cmd = RTM_ADD; rc->rc_rt = rt; @@ -984,6 +988,8 @@ /* Finalize notification */ rnh->rnh_gen++; + if (rnd->rnd_nhop == NULL) + rnh->rnh_prefixes--; rc->rc_cmd = (rnd->rnd_nhop != NULL) ? RTM_CHANGE : RTM_DELETE; rc->rc_rt = rt; @@ -1222,7 +1228,7 @@ enum rib_subscription_type type, bool waitok) { struct rib_subscription *rs; - int flags = M_ZERO | (waitok ? M_WAITOK : 0); + int flags = M_ZERO | (waitok ? M_WAITOK : M_NOWAIT); rs = malloc(sizeof(struct rib_subscription), M_RTABLE, flags); if (rs == NULL) @@ -1246,22 +1252,14 @@ enum rib_subscription_type type, bool waitok) { struct rib_head *rnh; - struct rib_subscription *rs; struct epoch_tracker et; - if ((rs = allocate_subscription(f, arg, type, waitok)) == NULL) - return (NULL); - NET_EPOCH_ENTER(et); KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__)); rnh = rt_tables_get_rnh(fibnum, family); - - RIB_WLOCK(rnh); - CK_STAILQ_INSERT_TAIL(&rnh->rnh_subscribers, rs, next); - RIB_WUNLOCK(rnh); NET_EPOCH_EXIT(et); - return (rs); + return (rib_subscribe_internal(rnh, f, arg, type, waitok)); } struct rib_subscription * @@ -1273,6 +1271,7 @@ if ((rs = allocate_subscription(f, arg, type, waitok)) == NULL) return (NULL); + rs->rnh = rnh; NET_EPOCH_ENTER(et); RIB_WLOCK(rnh); @@ -1284,32 +1283,22 @@ } /* - * Remove rtable subscription @rs from the table specified by @fibnum - * and @family. + * Remove rtable subscription @rs from the routing table. * Needs to be run in network epoch. - * - * Returns 0 on success. */ -int -rib_unsibscribe(uint32_t fibnum, int family, struct rib_subscription *rs) +void +rib_unsibscribe(struct rib_subscription *rs) { - struct rib_head *rnh; + struct rib_head *rnh = rs->rnh; NET_EPOCH_ASSERT(); - KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__)); - rnh = rt_tables_get_rnh(fibnum, family); - if (rnh == NULL) - return (ENOENT); - RIB_WLOCK(rnh); CK_STAILQ_REMOVE(&rnh->rnh_subscribers, rs, rib_subscription, next); RIB_WUNLOCK(rnh); epoch_call(net_epoch_preempt, destroy_subscription_epoch, &rs->epoch_ctx); - - return (0); } /* Index: head/sys/net/route/route_var.h =================================================================== --- head/sys/net/route/route_var.h +++ head/sys/net/route/route_var.h @@ -70,6 +70,7 @@ u_int rib_fibnum; /* fib number */ struct callout expire_callout; /* Callout for expiring dynamic routes */ time_t next_expire; /* Next expire run ts */ + uint32_t rnh_prefixes; /* Number of prefixes */ struct nh_control *nh_control; /* nexthop subsystem data */ CK_STAILQ_HEAD(, rib_subscription) rnh_subscribers;/* notification subscribers */ };