Nice feature lots of real world use cases.
On 10 Feb 2018 9:19 AM, "Sebastian Benoit" <be...@openbsd.org> wrote: > > > - 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)); > >