- 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));