Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163449606
D57375.id181619.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
D57375.id181619.diff
View Options
diff --git a/sys/net/route.h b/sys/net/route.h
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -205,6 +205,7 @@
#define NHF_BROADCAST 0x0100 /* RTF_BROADCAST */
#define NHF_GATEWAY 0x0200 /* RTF_GATEWAY */
#define NHF_HOST 0x0400 /* RTF_HOST */
+#define NHF_INVALID 0x0800 /* Nexthop is unreachable */
/* Nexthop request flags */
#define NHR_NONE 0x00 /* empty flags field */
@@ -368,9 +369,6 @@
#ifdef _KERNEL
-#define RT_LINK_IS_UP(ifp) (!((ifp)->if_capabilities & IFCAP_LINKSTATE) \
- || (ifp)->if_link_state == LINK_STATE_UP)
-
#define RO_NHFREE(_ro) do { \
if ((_ro)->ro_nh) { \
NH_FREE((_ro)->ro_nh); \
diff --git a/sys/net/route/nhop.h b/sys/net/route/nhop.h
--- a/sys/net/route/nhop.h
+++ b/sys/net/route/nhop.h
@@ -145,14 +145,8 @@
/*
* Nhop validness.
- *
- * Currently we verify whether link is up or not on every packet, which can be
- * quite costy.
- * TODO: subscribe for the interface notifications and update the nexthops
- * with NHF_INVALID flag.
*/
-
-#define NH_IS_VALID(_nh) RT_LINK_IS_UP((_nh)->nh_ifp)
+#define NH_IS_VALID(_nh) (!((_nh)->nh_flags & NHF_INVALID))
#define NH_IS_NHGRP(_nh) ((_nh)->nh_flags & NHF_MULTIPATH)
#define NH_FREE(_nh) do { \
diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c
--- a/sys/net/route/nhop_ctl.c
+++ b/sys/net/route/nhop_ctl.c
@@ -90,6 +90,8 @@
static void destroy_nhop_epoch(epoch_context_t ctx);
static void destroy_nhop(struct nhop_object *nh);
+static void nhops_ifnet_event(void *arg, struct ifnet *ifp, int state);
+static void nhops_ifnet_link_event(void *arg, struct ifnet *ifp, int state);
_Static_assert(__offsetof(struct nhop_object, nh_ifp) == 32,
"nhop_object: wrong nh_ifp offset");
@@ -109,6 +111,10 @@
nhops_zone = uma_zcreate("routing nhops",
NHOP_OBJECT_ALIGNED_SIZE + NHOP_PRIV_ALIGNED_SIZE,
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+ EVENTHANDLER_REGISTER(ifnet_event, nhops_ifnet_event, NULL,
+ EVENTHANDLER_PRI_ANY);
+ EVENTHANDLER_REGISTER(ifnet_link_event, nhops_ifnet_link_event, NULL,
+ EVENTHANDLER_PRI_ANY);
}
/*
@@ -1101,15 +1107,18 @@
}
-struct nhop_object *
-nhops_iter_start(struct nhop_iter *iter)
+static struct nhop_object *
+nhops_iter_start_internal(struct nhop_iter *iter, bool wlock)
{
if (iter->rh == NULL)
iter->rh = rt_tables_get_rnh_safe(iter->fibnum, iter->family);
if (iter->rh != NULL) {
struct nh_control *ctl = iter->rh->nh_control;
- NHOPS_RLOCK(ctl);
+ if (wlock)
+ NHOPS_WLOCK(ctl);
+ else
+ NHOPS_RLOCK(ctl);
iter->_i = 0;
iter->_next = CHT_FIRST(&ctl->nh_head, iter->_i);
@@ -1119,6 +1128,13 @@
return (NULL);
}
+struct nhop_object *
+nhops_iter_start(struct nhop_iter *iter)
+{
+
+ return (nhops_iter_start_internal(iter, false));
+}
+
struct nhop_object *
nhops_iter_next(struct nhop_iter *iter)
{
@@ -1141,16 +1157,26 @@
return (NULL);
}
-void
-nhops_iter_stop(struct nhop_iter *iter)
+static void
+nhops_iter_stop_internal(struct nhop_iter *iter, bool wlock)
{
if (iter->rh != NULL) {
struct nh_control *ctl = iter->rh->nh_control;
- NHOPS_RUNLOCK(ctl);
+ if (wlock)
+ NHOPS_WUNLOCK(ctl);
+ else
+ NHOPS_RUNLOCK(ctl);
}
}
+void
+nhops_iter_stop(struct nhop_iter *iter)
+{
+
+ nhops_iter_stop_internal(iter, false);
+}
+
/*
* Prints nexthop @nh data in the provided @buf.
* Example: nh#33/inet/em0/192.168.0.1
@@ -1317,3 +1343,55 @@
return (0);
}
+
+static void
+nhops_ifnet_state_changed(struct ifnet *ifp, bool status)
+{
+ struct nhop_object *nh;
+ struct nhop_iter iter = { .fibnum = ifp->if_fib };
+
+ for (iter.family = 1; iter.family <= AF_MAX; iter.family++) {
+ iter.rh = rt_tables_get_rnh_safe(iter.fibnum, iter.family);
+ for (nh = nhops_iter_start_internal(&iter, true); nh != NULL;
+ nh = nhops_iter_next(&iter)) {
+ if (nh->nh_ifp != ifp)
+ continue;
+
+ if (status)
+ nh->nh_flags &= ~NHF_INVALID;
+ else
+ nh->nh_flags |= NHF_INVALID;
+ }
+ nhops_iter_stop_internal(&iter, true);
+ }
+}
+
+static void
+nhops_ifnet_event(void *arg __unused, struct ifnet *ifp, int state)
+{
+
+ if ((ifp->if_flags & IFF_DYING) != 0 ||
+ (state != IFNET_EVENT_UP && state != IFNET_EVENT_DOWN))
+ return;
+
+ nhops_ifnet_state_changed(ifp, state == IFNET_EVENT_UP);
+}
+
+static void
+nhops_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int state)
+{
+#ifdef VIMAGE
+ /*
+ * rib_head will be calculated from V_tables in rt_tables_get_rnh
+ * and the VNET is destroyed.
+ */
+ if (VNET_IS_SHUTTING_DOWN(ifp->if_vnet))
+ return;
+#endif
+
+ if ((ifp->if_flags & IFF_DYING) != 0 ||
+ (state != LINK_STATE_UP && state != LINK_STATE_DOWN))
+ return;
+
+ nhops_ifnet_state_changed(ifp, state == LINK_STATE_UP);
+}
diff --git a/sys/netinet/in_fib.c b/sys/netinet/in_fib.c
--- a/sys/netinet/in_fib.c
+++ b/sys/netinet/in_fib.c
@@ -117,7 +117,7 @@
if (nh != NULL) {
nh = nhop_select(nh, flowid);
/* Ensure route & ifp is UP */
- if (RT_LINK_IS_UP(nh->nh_ifp)) {
+ if (NH_IS_VALID(nh)) {
if (flags & NHR_REF)
nhop_ref_object(nh);
return (nh);
@@ -154,7 +154,7 @@
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
nh = nhop_select((RNTORT(rn))->rt_nhop, flowid);
/* Ensure route & ifp is UP */
- if (RT_LINK_IS_UP(nh->nh_ifp)) {
+ if (NH_IS_VALID(nh)) {
if (flags & NHR_REF)
nhop_ref_object(nh);
RIB_RUNLOCK(rh);
@@ -320,7 +320,7 @@
if (rt != NULL) {
struct nhop_object *nh = nhop_select(rnd.rnd_nhop, 0);
/* Ensure route & ifp is UP */
- if (RT_LINK_IS_UP(nh->nh_ifp))
+ if (NH_IS_VALID(nh))
return (nh);
}
diff --git a/sys/netinet6/in6_fib.c b/sys/netinet6/in6_fib.c
--- a/sys/netinet6/in6_fib.c
+++ b/sys/netinet6/in6_fib.c
@@ -125,7 +125,7 @@
if (nh != NULL) {
nh = nhop_select(nh, flowid);
/* Ensure route & ifp is UP */
- if (RT_LINK_IS_UP(nh->nh_ifp)) {
+ if (NH_IS_VALID(nh)) {
if (flags & NHR_REF)
nhop_ref_object(nh);
return (nh);
@@ -163,7 +163,7 @@
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
nh = nhop_select((RNTORT(rn))->rt_nhop, flowid);
/* Ensure route & ifp is UP */
- if (RT_LINK_IS_UP(nh->nh_ifp)) {
+ if (NH_IS_VALID(nh)) {
if (flags & NHR_REF)
nhop_ref_object(nh);
RIB_RUNLOCK(rh);
@@ -335,7 +335,7 @@
if (rt != NULL) {
struct nhop_object *nh = nhop_select(rnd.rnd_nhop, 0);
/* Ensure route & ifp is UP */
- if (RT_LINK_IS_UP(nh->nh_ifp))
+ if (NH_IS_VALID(nh))
return (nh);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 24, 7:27 AM (36 m, 40 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35436329
Default Alt Text
D57375.id181619.diff (6 KB)
Attached To
Mode
D57375: routing: Subscribe nhops to ifnet link events
Attached
Detach File
Event Timeline
Log In to Comment