aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-01-30 21:52:44 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2021-02-04 22:34:15 +0000
commit2a3cbb6c8954b71ee5bcd49cd2d05e41b960975d (patch)
treeee72090329074447f328a7151946e3d45827a5aa
parentf5f50ec15688d6aab67d3fb8fb0c98b89e4dbce0 (diff)
downloadsrc-2a3cbb6c8954b71ee5bcd49cd2d05e41b960975d.tar.gz
src-2a3cbb6c8954b71ee5bcd49cd2d05e41b960975d.zip
MFC dd9163003cb1: Add rib_subscribe_locked() and rib_unsubsribe_locked()
to support subscriptions during RIB modifications. Add new subscriptions to the beginning of the lists instead of the end. This fixes the situation when new subscription is created int the callback for the existing subscription, leading to the subscription notification handler pick it.
-rw-r--r--sys/net/route/route_ctl.c34
-rw-r--r--sys/net/route/route_ctl.h3
2 files changed, 36 insertions, 1 deletions
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
index 955b1df9029f..6b0869196d12 100644
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -1407,13 +1407,31 @@ rib_subscribe_internal(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg
NET_EPOCH_ENTER(et);
RIB_WLOCK(rnh);
- CK_STAILQ_INSERT_TAIL(&rnh->rnh_subscribers, rs, next);
+ CK_STAILQ_INSERT_HEAD(&rnh->rnh_subscribers, rs, next);
RIB_WUNLOCK(rnh);
NET_EPOCH_EXIT(et);
return (rs);
}
+struct rib_subscription *
+rib_subscribe_locked(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg,
+ enum rib_subscription_type type)
+{
+ struct rib_subscription *rs;
+
+ NET_EPOCH_ASSERT();
+ RIB_WLOCK_ASSERT(rnh);
+
+ if ((rs = allocate_subscription(f, arg, type, false)) == NULL)
+ return (NULL);
+ rs->rnh = rnh;
+
+ CK_STAILQ_INSERT_HEAD(&rnh->rnh_subscribers, rs, next);
+
+ return (rs);
+}
+
/*
* Remove rtable subscription @rs from the routing table.
* Needs to be run in network epoch.
@@ -1433,6 +1451,20 @@ rib_unsibscribe(struct rib_subscription *rs)
&rs->epoch_ctx);
}
+void
+rib_unsibscribe_locked(struct rib_subscription *rs)
+{
+ struct rib_head *rnh = rs->rnh;
+
+ NET_EPOCH_ASSERT();
+ RIB_WLOCK_ASSERT(rnh);
+
+ CK_STAILQ_REMOVE(&rnh->rnh_subscribers, rs, rib_subscription, next);
+
+ epoch_call(net_epoch_preempt, destroy_subscription_epoch,
+ &rs->epoch_ctx);
+}
+
/*
* Epoch callback indicating subscription is safe to destroy
*/
diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h
index ecbc9ee91dc0..bd256e9f0834 100644
--- a/sys/net/route/route_ctl.h
+++ b/sys/net/route/route_ctl.h
@@ -144,6 +144,9 @@ 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);
+struct rib_subscription *rib_subscribe_locked(struct rib_head *rnh,
+ rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type);
void rib_unsibscribe(struct rib_subscription *rs);
+void rib_unsibscribe_locked(struct rib_subscription *rs);
#endif