Page MenuHomeFreeBSD

D57375.id181619.diff
No OneTemporary

D57375.id181619.diff

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

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)

Event Timeline