Most (all?) of our routing daemons don't care about layer 2 or broadcast
routing entries, so they do something like this after reading a message
off the socket:
/* Skip ARP/ND cache and broadcast routes. */
if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
continue;
ARP can generate a lot of routing messages during an address space scan,
and then again when the entries expire, and this can cause routing daemons
to desync. To reduce the impact of this, we'd like to filter these out on
the kernel side. There's another issue we need to fix to make this work
properly, but that can be done separately.
This adds a new type of filter on the routing socket, specifying a flag
bitmask, which filters out messages for routes with flags matching the mask.
ok?
Index: route.h
===================================================================
RCS file: /cvs/src/sys/net/route.h,v
retrieving revision 1.181
diff -u -p -u -p -r1.181 route.h
--- route.h 10 Mar 2020 21:35:41 -0000 1.181
+++ route.h 6 Aug 2020 01:47:11 -0000
@@ -297,6 +297,8 @@ struct rt_msghdr {
#define ROUTE_PRIOFILTER 3 /* only pass updates with a priority higher or
equal (actual value lower) to the specified
priority. */
+#define ROUTE_FLAGFILTER 4 /* do not pass updates for routes with flags
+ in this bitmask. */
#define ROUTE_FILTER(m) (1 << (m))
#define RTABLE_ANY 0xffffffff
Index: rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.299
diff -u -p -u -p -r1.299 rtsock.c
--- rtsock.c 24 Jun 2020 22:03:42 -0000 1.299
+++ rtsock.c 6 Aug 2020 01:47:11 -0000
@@ -145,6 +145,7 @@ struct rtpcb {
struct refcnt rop_refcnt;
struct timeout rop_timeout;
unsigned int rop_msgfilter;
+ unsigned int rop_flagfilter;
unsigned int rop_flags;
u_int rop_rtableid;
unsigned short rop_proto;
@@ -402,6 +403,12 @@ route_ctloutput(int op, struct socket *s
else
rop->rop_priority = prio;
break;
+ case ROUTE_FLAGFILTER:
+ if (m == NULL || m->m_len != sizeof(unsigned int))
+ error = EINVAL;
+ else
+ rop->rop_flagfilter = *mtod(m, unsigned int *);
+ break;
default:
error = ENOPROTOOPT;
break;
@@ -421,6 +428,10 @@ route_ctloutput(int op, struct socket *s
m->m_len = sizeof(unsigned int);
*mtod(m, unsigned int *) = rop->rop_priority;
break;
+ case ROUTE_FLAGFILTER:
+ m->m_len = sizeof(unsigned int);
+ *mtod(m, unsigned int *) = rop->rop_flagfilter;
+ break;
default:
error = ENOPROTOOPT;
break;
@@ -516,9 +527,13 @@ next:
/* filter messages that the process does not want */
rtm = mtod(m, struct rt_msghdr *);
/* but RTM_DESYNC can't be filtered */
- if (rtm->rtm_type != RTM_DESYNC && rop->rop_msgfilter != 0 &&
- !(rop->rop_msgfilter & (1 << rtm->rtm_type)))
- goto next;
+ if (rtm->rtm_type != RTM_DESYNC) {
+ if (rop->rop_msgfilter != 0 &&
+ !(rop->rop_msgfilter & (1 << rtm->rtm_type)))
+ goto next;
+ if (ISSET(rop->rop_flagfilter, rtm->rtm_flags))
+ goto next;
+ }
switch (rtm->rtm_type) {
case RTM_IFANNOUNCE:
case RTM_DESYNC: