- add ROUTE_PRIOFILTER
- it has one argument that is interpreted as a route priority
- all route updates with prio lower or equal will pass the filter,
  all with higher priority value will be filtered.
- example use in ospfd

comments/oks?

(benno_ospfd_route_priofilter_1.diff)

diff --git sys/net/route.h sys/net/route.h
index 1ca0a22c45f..7a4008b7ac1 100644
--- sys/net/route.h
+++ sys/net/route.h
@@ -298,6 +298,9 @@ struct rt_msghdr {
 #define ROUTE_TABLEFILTER 2    /* change routing table the socket is listening
                                   on, RTABLE_ANY listens on all tables. */
 
+#define ROUTE_PRIOFILTER 3     /* change routing table the socket is listening
+                                  on, RTABLE_ANY listens on all tables. */
+
 #define ROUTE_FILTER(m)        (1 << (m))
 #define RTABLE_ANY     0xffffffff
 
diff --git sys/net/rtsock.c sys/net/rtsock.c
index 35bdd09d143..5f4244e6057 100644
--- sys/net/rtsock.c
+++ sys/net/rtsock.c
@@ -141,6 +141,7 @@ struct routecb {
        unsigned int            msgfilter;
        unsigned int            flags;
        u_int                   rtableid;
+       u_char                  priority;
 };
 #define        sotoroutecb(so) ((struct routecb *)(so)->so_pcb)
 
@@ -309,6 +310,7 @@ route_ctloutput(int op, struct socket *so, int level, int 
optname,
        struct routecb *rop = sotoroutecb(so);
        int error = 0;
        unsigned int tid;
+       u_char prio;
 
        if (level != AF_ROUTE)
                return (EINVAL);
@@ -333,6 +335,17 @@ route_ctloutput(int op, struct socket *so, int level, int 
optname,
                        else
                                rop->rtableid = tid;
                        break;
+               case ROUTE_PRIOFILTER:
+                       if (m == NULL || m->m_len != sizeof(u_char)) {
+                               error = EINVAL;
+                               break;
+                       }
+                       prio = *mtod(m, u_char *);
+                       if (prio > RTP_MAX)
+                               error = EINVAL;
+                       else
+                               rop->priority = prio;
+                       break;
                default:
                        error = ENOPROTOOPT;
                        break;
@@ -348,6 +361,10 @@ route_ctloutput(int op, struct socket *so, int level, int 
optname,
                        m->m_len = sizeof(unsigned int);
                        *mtod(m, unsigned int *) = rop->rtableid;
                        break;
+               case ROUTE_PRIOFILTER:
+                       m->m_len = sizeof(u_char);
+                       *mtod(m, u_char *) = rop->priority;
+                       break;
                default:
                        error = ENOPROTOOPT;
                        break;
@@ -431,6 +448,8 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t 
sa_family)
                if (rtm->rtm_type != RTM_DESYNC && rop->msgfilter != 0 &&
                    !(rop->msgfilter & (1 << rtm->rtm_type)))
                        continue;
+               if (rop->priority != 0 && rop->priority < rtm->rtm_priority)
+                       continue;
                switch (rtm->rtm_type) {
                case RTM_IFANNOUNCE:
                case RTM_DESYNC:
diff --git usr.sbin/ospfd/kroute.c usr.sbin/ospfd/kroute.c
index 17febefbdcb..a5c069aa540 100644
--- usr.sbin/ospfd/kroute.c
+++ usr.sbin/ospfd/kroute.c
@@ -127,10 +127,11 @@ kif_init(void)
 }
 
 int
-kr_init(int fs, u_int rdomain)
+kr_init(int fs, u_int rdomain, u_int8_t redis_label_or_prefix)
 {
        int             opt = 0, rcvbuf, default_rcvbuf;
        socklen_t       optlen;
+       u_char          filter_prio = RTP_OSPF;
 
        kr_state.fib_sync = fs;
        kr_state.rdomain = rdomain;
@@ -146,6 +147,14 @@ kr_init(int fs, u_int rdomain)
            &opt, sizeof(opt)) == -1)
                log_warn("kr_init: setsockopt");        /* not fatal */
 
+       if (redis_label_or_prefix)
+               filter_prio = 0;
+       if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_PRIOFILTER, &filter_prio,
+           sizeof(filter_prio)) == -1) {
+               log_warn("%s: setsockopt AF_ROUTE ROUTE_PRIOFILTER", __func__);
+               return (-1);
+       }
+
        /* grow receive buffer, don't wanna miss messages */
        optlen = sizeof(default_rcvbuf);
        if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
diff --git usr.sbin/ospfd/ospfd.c usr.sbin/ospfd/ospfd.c
index 3c5057ae04e..0e91819f673 100644
--- usr.sbin/ospfd/ospfd.c
+++ usr.sbin/ospfd/ospfd.c
@@ -265,7 +265,7 @@ main(int argc, char *argv[])
        event_add(&iev_rde->ev, NULL);
 
        if (kr_init(!(ospfd_conf->flags & OSPFD_FLAG_NO_FIB_UPDATE),
-           ospfd_conf->rdomain) == -1)
+           ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix) == -1)
                fatalx("kr_init failed");
 
        /* remove unneeded stuff from config */
diff --git usr.sbin/ospfd/ospfd.h usr.sbin/ospfd/ospfd.h
index af082b1079c..ca66511228a 100644
--- usr.sbin/ospfd/ospfd.h
+++ usr.sbin/ospfd/ospfd.h
@@ -397,6 +397,7 @@ struct ospfd_conf {
        u_int8_t                rfc1583compat;
        u_int8_t                border;
        u_int8_t                redistribute;
+       u_int8_t                redist_label_or_prefix;
        u_int                   rdomain;
        char                    *csock;
 };
@@ -567,7 +568,7 @@ u_int16_t    iso_cksum(void *, u_int16_t, u_int16_t);
 /* kroute.c */
 int             kif_init(void);
 void            kif_clear(void);
-int             kr_init(int, u_int);
+int             kr_init(int, u_int, u_int8_t);
 int             kr_change(struct kroute *, int);
 int             kr_delete(struct kroute *);
 void            kr_shutdown(void);
diff --git usr.sbin/ospfd/parse.y usr.sbin/ospfd/parse.y
index 4bf64d5d7e3..deb93cc6524 100644
--- usr.sbin/ospfd/parse.y
+++ usr.sbin/ospfd/parse.y
@@ -302,6 +302,7 @@ redistribute        : no REDISTRIBUTE NUMBER '/' NUMBER 
optlist dependon {
                                r->dependon[0] = '\0';
                        free($7);
                        $$ = r;
+                       conf->redist_label_or_prefix = 1;
                }
                | no REDISTRIBUTE STRING optlist dependon {
                        struct redistribute     *r;
@@ -314,9 +315,10 @@ redistribute       : no REDISTRIBUTE NUMBER '/' NUMBER 
optlist dependon {
                                r->type = REDIST_STATIC;
                        else if (!strcmp($3, "connected"))
                                r->type = REDIST_CONNECTED;
-                       else if (host($3, &r->addr, &r->mask))
+                       else if (host($3, &r->addr, &r->mask)) {
                                r->type = REDIST_ADDR;
-                       else {
+                               conf->redist_label_or_prefix = (!$1);
+                       } else {
                                yyerror("unknown redistribute type");
                                free($3);
                                free(r);
@@ -343,6 +345,8 @@ redistribute        : no REDISTRIBUTE NUMBER '/' NUMBER 
optlist dependon {
                        r->label = rtlabel_name2id($4);
                        if ($1)
                                r->type |= REDIST_NO;
+                       else
+                               conf->redist_label_or_prefix = 1;
                        r->metric = $5;
                        if ($6)
                                strlcpy(r->dependon, $6, sizeof(r->dependon));

Reply via email to