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. MFC after: 3 days
This commit is contained in:
parent
ab6d9aaed7
commit
dd9163003c
@ -1407,13 +1407,31 @@ rib_subscribe_internal(struct rib_head *rnh, rib_subscription_cb_t *f, void *arg
|
|||||||
|
|
||||||
NET_EPOCH_ENTER(et);
|
NET_EPOCH_ENTER(et);
|
||||||
RIB_WLOCK(rnh);
|
RIB_WLOCK(rnh);
|
||||||
CK_STAILQ_INSERT_TAIL(&rnh->rnh_subscribers, rs, next);
|
CK_STAILQ_INSERT_HEAD(&rnh->rnh_subscribers, rs, next);
|
||||||
RIB_WUNLOCK(rnh);
|
RIB_WUNLOCK(rnh);
|
||||||
NET_EPOCH_EXIT(et);
|
NET_EPOCH_EXIT(et);
|
||||||
|
|
||||||
return (rs);
|
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.
|
* Remove rtable subscription @rs from the routing table.
|
||||||
* Needs to be run in network epoch.
|
* Needs to be run in network epoch.
|
||||||
@ -1433,6 +1451,20 @@ rib_unsibscribe(struct rib_subscription *rs)
|
|||||||
&rs->epoch_ctx);
|
&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
|
* Epoch callback indicating subscription is safe to destroy
|
||||||
*/
|
*/
|
||||||
|
@ -144,6 +144,9 @@ struct rib_subscription *rib_subscribe(uint32_t fibnum, int family,
|
|||||||
struct rib_subscription *rib_subscribe_internal(struct rib_head *rnh,
|
struct rib_subscription *rib_subscribe_internal(struct rib_head *rnh,
|
||||||
rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type,
|
rib_subscription_cb_t *f, void *arg, enum rib_subscription_type type,
|
||||||
bool waitok);
|
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(struct rib_subscription *rs);
|
||||||
|
void rib_unsibscribe_locked(struct rib_subscription *rs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user