Page MenuHomeFreeBSD

D25070.diff
No OneTemporary

D25070.diff

Index: head/sys/net/route/route_ctl.h
===================================================================
--- head/sys/net/route/route_ctl.h
+++ head/sys/net/route/route_ctl.h
@@ -64,5 +64,20 @@
typedef void rt_setwarg_t(struct rib_head *, uint32_t, int, void *);
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: head/sys/net/route/route_ctl.c
===================================================================
--- head/sys/net/route/route_ctl.c
+++ head/sys/net/route/route_ctl.c
@@ -68,10 +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);
static struct rib_head *
get_rnh(uint32_t fibnum, const struct rt_addrinfo *info)
@@ -263,6 +272,9 @@
}
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);
@@ -419,6 +431,7 @@
if (error != 0)
return (error);
+ rib_notify(rnh, RIB_NOTIFY_DELAYED, rc);
rt_notifydelete(rt, info);
/*
@@ -559,11 +572,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);
@@ -614,6 +628,7 @@
struct rt_addrinfo info;
struct rib_head *rnh;
struct rtentry *head;
+ struct rib_cmd_info rc;
};
/*
@@ -643,7 +658,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;
@@ -665,6 +686,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)
@@ -674,20 +696,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);
@@ -699,6 +725,8 @@
fibnum);
rtfree(rt);
}
+
+ NET_EPOCH_EXIT(et);
}
static void
@@ -713,6 +741,13 @@
}
}
+/*
+ * 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)
@@ -740,6 +775,13 @@
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)
{
@@ -756,7 +798,21 @@
CK_STAILQ_REMOVE(&rnh->rnh_subscribers, rs, rib_subscription, next);
RIB_WUNLOCK(rnh);
- free(rs, M_RTABLE);
+ 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);
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 25, 6:05 AM (16 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32112728
Default Alt Text
D25070.diff (4 KB)

Event Timeline