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