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:

Reply via email to