Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153166134
D25070.id72468.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D25070.id72468.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D25070: Add rib subscription API.
Attached
Detach File
Event Timeline
Log In to Comment