Page MenuHomeFreeBSD

D25070.id72468.diff
No OneTemporary

D25070.id72468.diff

Index: sys/net/route.c
===================================================================
--- sys/net/route.c
+++ sys/net/route.c
@@ -347,6 +347,9 @@
nhops_init_rib(rh);
+ /* Init subscription system */
+ CK_STAILQ_INIT(&rh->rnh_subscribers);
+
/* Finally, set base callbacks */
rh->rnh_addaddr = rn_addroute;
rh->rnh_deladdr = rn_delete;
Index: sys/net/route/route_ctl.h
===================================================================
--- sys/net/route/route_ctl.h
+++ sys/net/route/route_ctl.h
@@ -65,5 +65,19 @@
void rt_foreach_fib_walk(int af, rt_setwarg_t *, rt_walktree_f_t *, void *);
void rt_foreach_fib_walk_del(int af, rt_filter_f_t *filter_f, void *arg);
+enum rib_subscription_type {
+ RIB_NOTIFY_IMMEDIATE,
+ RIB_NOTIFY_DELAYED
+};
+
+struct rib_subscription;
+typedef void rib_subscription_cb_t(struct rib_head *rnh, struct rib_cmd_info *rc,
+ void *arg);
+
+struct rib_subscription *rib_subscribe(uint32_t fibnum, int family,
+ rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type,
+ int waitok);
+int rib_unsibscribe(uint32_t fibnum, int family, struct rib_subscription *rs);
+
#endif
Index: sys/net/route/route_ctl.c
===================================================================
--- sys/net/route/route_ctl.c
+++ sys/net/route/route_ctl.c
@@ -68,7 +68,19 @@
* All functions assumes they are called in net epoch.
*/
+struct rib_subscription {
+ CK_STAILQ_ENTRY(rib_subscription) next;
+ rib_subscription_cb_t *func;
+ void *arg;
+ enum rib_subscription_type type;
+ struct epoch_context epoch_ctx;
+};
+
+static void rib_notify(struct rib_head *rnh, enum rib_subscription_type type,
+ struct rib_cmd_info *rc);
+
static void rt_notifydelete(struct rtentry *rt, struct rt_addrinfo *info);
+static void destroy_subscription_epoch(epoch_context_t ctx);
/*
* Returns rib_head poiner based on @fibnum and RTAX_DST family
@@ -227,6 +239,8 @@
rc->rc_rt = RNTORT(rn);
rc->rc_nh_new = nh;
+
+ rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc);
} else if ((info->rti_flags & RTF_PINNED) != 0) {
/*
@@ -256,10 +270,15 @@
}
rc->rc_nh_old = rt_old->rt_nhop;
rc->rc_nh_new = nh;
+
+ rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc);
}
}
RIB_WUNLOCK(rnh);
+ if ((rn != NULL) || (rt_old != NULL))
+ rib_notify(rnh, RIB_NOTIFY_DELAYED, rc);
+
if (rt_old != NULL) {
rt_notifydelete(rt_old, info);
rtfree(rt_old);
@@ -410,11 +429,13 @@
rnh->rnh_gen++;
rc->rc_rt = rt;
rc->rc_nh_old = rt->rt_nhop;
+ rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc);
}
RIB_WUNLOCK(rnh);
if (error != 0)
return (error);
+ rib_notify(rnh, RIB_NOTIFY_DELAYED, rc);
rt_notifydelete(rt, info);
/*
@@ -555,9 +576,12 @@
/* Update generation id to reflect rtable change */
rnh->rnh_gen++;
+ rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc);
RIB_WUNLOCK(rnh);
+ rib_notify(rnh, RIB_NOTIFY_DELAYED, rc);
+
nhop_free(nh_orig);
return (0);
@@ -608,6 +632,7 @@
struct rt_addrinfo info;
struct rib_head *rnh;
struct rtentry *head;
+ struct rib_cmd_info rc;
};
/*
@@ -637,7 +662,13 @@
return (0);
}
- /* Entry was unlinked. Add to the list and return */
+ /* Entry was unlinked. Notify subscribers */
+ di->rnh->rnh_gen++;
+ di->rc.rc_rt = rt;
+ di->rc.rc_nh_old = rt->rt_nhop;
+ rib_notify(di->rnh, RIB_NOTIFY_IMMEDIATE, &di->rc);
+
+ /* Add to the list and return */
rt->rt_chain = di->head;
di->head = rt;
@@ -659,6 +690,7 @@
struct rib_head *rnh;
struct rt_delinfo di;
struct rtentry *rt;
+ struct epoch_tracker et;
rnh = rt_tables_get_rnh(fibnum, family);
if (rnh == NULL)
@@ -668,20 +700,24 @@
di.info.rti_filter = filter_f;
di.info.rti_filterdata = arg;
di.rnh = rnh;
+ di.rc.rc_cmd = RTM_DELETE;
+
+ NET_EPOCH_ENTER(et);
RIB_WLOCK(rnh);
rnh->rnh_walktree(&rnh->head, rt_checkdelroute, &di);
RIB_WUNLOCK(rnh);
- if (di.head == NULL)
- return;
-
/* We might have something to reclaim. */
while (di.head != NULL) {
rt = di.head;
di.head = rt->rt_chain;
rt->rt_chain = NULL;
+ di.rc.rc_rt = rt;
+ di.rc.rc_nh_old = rt->rt_nhop;
+ rib_notify(rnh, RIB_NOTIFY_DELAYED, &di.rc);
+
/* TODO std rt -> rt_addrinfo export */
di.info.rti_info[RTAX_DST] = rt_key(rt);
di.info.rti_info[RTAX_NETMASK] = rt_mask(rt);
@@ -693,6 +729,95 @@
fibnum);
rtfree(rt);
}
+
+ NET_EPOCH_EXIT(et);
+}
+
+static void
+rib_notify(struct rib_head *rnh, enum rib_subscription_type type,
+ struct rib_cmd_info *rc)
+{
+ struct rib_subscription *rs;
+
+ CK_STAILQ_FOREACH(rs, &rnh->rnh_subscribers, next) {
+ if (rs->type == type)
+ rs->func(rnh, rc, rs->arg);
+ }
+}
+
+/*
+ * Subscribe for the changes in the routing table specified by @fibnum and
+ * @family.
+ * Needs to be run in network epoch.
+ *
+ * Returns pointer to the subscription structure on success.
+ */
+struct rib_subscription *
+rib_subscribe(uint32_t fibnum, int family, rib_subscription_cb_t *f, void *arg,
+ enum rib_subscription_type type, int waitok)
+{
+ struct rib_head *rnh;
+ struct rib_subscription *rs;
+ int flags = M_ZERO | (waitok ? M_WAITOK : 0);
+
+ NET_EPOCH_ASSERT();
+ KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__));
+ rnh = rt_tables_get_rnh(fibnum, family);
+
+ rs = malloc(sizeof(struct rib_subscription), M_RTABLE, flags);
+ if (rs == NULL)
+ return (NULL);
+
+ rs->func = f;
+ rs->arg = arg;
+ rs->type = type;
+
+ RIB_WLOCK(rnh);
+ CK_STAILQ_INSERT_TAIL(&rnh->rnh_subscribers, rs, next);
+ RIB_WUNLOCK(rnh);
+
+ return (rs);
+}
+
+/*
+ * Remove rtable subscription @rs from the table specified by @fibnum
+ * and @family.
+ * Needs to be run in network epoch.
+ *
+ * Returns 0 on success.
+ */
+int
+rib_unsibscribe(uint32_t fibnum, int family, struct rib_subscription *rs)
+{
+ struct rib_head *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);
}
+/*
+ * Epoch callback indicating subscription is safe to destroy
+ */
+static void
+destroy_subscription_epoch(epoch_context_t ctx)
+{
+ struct rib_subscription *rs;
+
+ rs = __containerof(ctx, struct rib_subscription, epoch_ctx);
+
+ free(rs, M_RTABLE);
+}
Index: sys/net/route/route_var.h
===================================================================
--- sys/net/route/route_var.h
+++ sys/net/route/route_var.h
@@ -64,6 +64,7 @@
struct callout expire_callout; /* Callout for expiring dynamic routes */
time_t next_expire; /* Next expire run ts */
struct nh_control *nh_control; /* nexthop subsystem data */
+ CK_STAILQ_HEAD(, rib_subscription) rnh_subscribers;/* notification subscribers */
};
#define RIB_RLOCK_TRACKER struct rm_priotracker _rib_tracker

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 20, 1:47 PM (19 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31750537
Default Alt Text
D25070.id72468.diff (6 KB)

Event Timeline