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: