Add tracking for rib/nhops/nhgrp objects and provide cumulative number accessors.

The resulting KPI can be used by routing table consumers to estimate the required
 scale for route table export.

* Add tracking for rib routes
* Add accessors for number of nexthops/nexthop objects
* Simplify rib_unsubscribe: store rnh we're attached to instead of requiring it up
 again on destruction. This helps in the cases when rnh is not linked yet/already unlinked.

Differential Revision:	https://reviews.freebsd.org/D27404
This commit is contained in:
Alexander V. Chernikov 2020-11-29 13:27:24 +00:00
parent 3c48106aaa
commit 98d5c4e5c8
5 changed files with 50 additions and 25 deletions

View File

@ -762,6 +762,21 @@ nhgrp_get_idx(const struct nhgrp_object *nhg)
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)
{

View File

@ -852,6 +852,21 @@ dump_nhop_entry(struct rib_head *rh, struct nhop_object *nh, struct sysctl_req *
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)
{

View File

@ -70,6 +70,7 @@ struct rib_subscription {
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 @@ rt_unlinkrte(struct rib_head *rnh, struct rt_addrinfo *info, struct rib_cmd_info
/* 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 @@ add_route_nhop(struct rib_head *rnh, struct rtentry *rt,
/* Finalize notification */
rnh->rnh_gen++;
rnh->rnh_prefixes++;
rc->rc_cmd = RTM_ADD;
rc->rc_rt = rt;
@ -984,6 +988,8 @@ change_route_nhop(struct rib_head *rnh, struct rtentry *rt,
/* 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 @@ allocate_subscription(rib_subscription_cb_t *f, void *arg,
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 @@ rib_subscribe(uint32_t fibnum, int family, rib_subscription_cb_t *f, void *arg,
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 @@ rib_subscribe_internal(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg
if ((rs = allocate_subscription(f, arg, type, waitok)) == NULL)
return (NULL);
rs->rnh = rnh;
NET_EPOCH_ENTER(et);
RIB_WLOCK(rnh);
@ -1284,23 +1283,15 @@ rib_subscribe_internal(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg
}
/*
* 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);
@ -1308,8 +1299,6 @@ rib_unsibscribe(uint32_t fibnum, int family, struct rib_subscription *rs)
epoch_call(net_epoch_preempt, destroy_subscription_epoch,
&rs->epoch_ctx);
return (0);
}
/*

View File

@ -87,13 +87,18 @@ const struct rtentry *rib_lookup_prefix(uint32_t fibnum, int family,
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(uint32_t fibnum, int family,
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

View File

@ -70,6 +70,7 @@ struct rib_head {
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 */
};