From afd0ab5d3d5f040bbc02cf4c27e3190ff1871a82 Mon Sep 17 00:00:00 2001 From: friehm Date: Mon, 19 Jun 2017 19:55:57 +0000 Subject: [PATCH] Import route priority support from ospfd to ospf6d. Also remove the RTF_UP flag from hdr.rtm_flags in send_rtmsg() since ospfd and bgpd don't set the flag. OK bluhm@ claudio@ --- usr.sbin/ospf6ctl/ospf6ctl.c | 6 +- usr.sbin/ospf6d/kroute.c | 143 +++++++++++++++-------------------- usr.sbin/ospf6d/ospf6d.h | 5 +- usr.sbin/ospf6d/rde.c | 19 +---- 4 files changed, 70 insertions(+), 103 deletions(-) diff --git a/usr.sbin/ospf6ctl/ospf6ctl.c b/usr.sbin/ospf6ctl/ospf6ctl.c index 3b384e10fe4..fc0c433b976 100644 --- a/usr.sbin/ospf6ctl/ospf6ctl.c +++ b/usr.sbin/ospf6ctl/ospf6ctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospf6ctl.c,v 1.44 2016/12/22 23:03:55 jca Exp $ */ +/* $OpenBSD: ospf6ctl.c,v 1.45 2017/06/19 19:55:57 friehm Exp $ */ /* * Copyright (c) 2005 Claudio Jeker @@ -1256,7 +1256,8 @@ void show_fib_head(void) { printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n"); - printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop"); + printf("%-6s %-4s %-20s %-17s\n", + "Flags", "Prio", "Destination", "Nexthop"); } int @@ -1286,6 +1287,7 @@ show_fib_msg(struct imsg *imsg) printf(" "); printf(" "); + printf("%4d ", k->priority); if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix), k->prefixlen) == -1) err(1, NULL); diff --git a/usr.sbin/ospf6d/kroute.c b/usr.sbin/ospf6d/kroute.c index 00319849915..11fb77f8ebb 100644 --- a/usr.sbin/ospf6d/kroute.c +++ b/usr.sbin/ospf6d/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.51 2017/05/30 12:42:31 friehm Exp $ */ +/* $OpenBSD: kroute.c,v 1.52 2017/06/19 19:55:57 friehm Exp $ */ /* * Copyright (c) 2004 Esben Norby @@ -62,7 +62,8 @@ int kroute_compare(struct kroute_node *, struct kroute_node *); int kr_change_fib(struct kroute_node *, struct kroute *, int, int); int kr_delete_fib(struct kroute_node *); -struct kroute_node *kroute_find(const struct in6_addr *, u_int8_t); +struct kroute_node *kroute_find(const struct in6_addr *, u_int8_t, + u_int8_t); struct kroute_node *kroute_matchgw(struct kroute_node *, struct in6_addr *, unsigned int); int kroute_insert(struct kroute_node *); @@ -215,6 +216,7 @@ kr_change_fib(struct kroute_node *kr, struct kroute *kroute, int krcount, kn->r.nexthop = kroute[i].nexthop; kn->r.scope = kroute[i].scope; kn->r.flags = kroute[i].flags | F_OSPFD_INSERTED; + kn->r.priority = RTP_OSPF; kn->r.ext_tag = kroute[i].ext_tag; rtlabel_unref(kn->r.rtlabel); /* for RTM_CHANGE */ kn->r.rtlabel = kroute[i].rtlabel; @@ -238,31 +240,10 @@ kr_change(struct kroute *kroute, int krcount) kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag); - kr = kroute_find(&kroute->prefix, kroute->prefixlen); - if (kr != NULL) { - if (kr->r.flags & F_KERNEL) { - /* a non-ospf route already exists. not a problem */ - if (!(kr->r.flags & F_BGPD_INSERTED)) { - do { - kr->r.flags |= F_OSPFD_INSERTED; - kr = kr->next; - } while (kr); - return (0); - } - /* - * XXX as long as there is no multipath support in - * bgpd this is safe else we end up in a bad situation. - */ - /* - * ospf route has higher pref - * - reset flags to the ospf ones - * - use RTM_CHANGE - * - zero out ifindex (this is no longer relevant) - */ - action = RTM_CHANGE; - } else if (kr->next == NULL) /* single path OSPF route */ - action = RTM_CHANGE; - } + kr = kroute_find(&kroute->prefix, kroute->prefixlen, RTP_OSPF); + if (kr != NULL && kr->next == NULL && krcount == 1) + /* single path OSPF route */ + action = RTM_CHANGE; return (kr_change_fib(kr, kroute, krcount, action)); } @@ -270,14 +251,10 @@ kr_change(struct kroute *kroute, int krcount) int kr_delete_fib(struct kroute_node *kr) { - if (!(kr->r.flags & F_OSPFD_INSERTED)) - return 0; - - if (kr->r.flags & F_KERNEL) { - /* remove F_OSPFD_INSERTED flag, route still exists in kernel */ - kr->r.flags &= ~F_OSPFD_INSERTED; - return (0); - } + if (kr->r.priority != RTP_OSPF) + log_warn("kr_delete_fib: %s/%d has wrong priority %d", + log_in6addr(&kr->r.prefix), kr->r.prefixlen, + kr->r.priority); if (send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r) == -1) return (-1); @@ -293,8 +270,8 @@ kr_delete(struct kroute *kroute) { struct kroute_node *kr, *nkr; - if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen)) == - NULL) + if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen, + RTP_OSPF)) == NULL) return (0); while (kr != NULL) { @@ -326,10 +303,9 @@ kr_fib_couple(void) kr_state.fib_sync = 1; RB_FOREACH(kr, kroute_tree, &krt) - if (!(kr->r.flags & F_KERNEL)) - for (kn = kr; kn != NULL; kn = kn->next) { + if (kr->r.priority == RTP_OSPF) + for (kn = kr; kn != NULL; kn = kn->next) send_rtmsg(kr_state.fd, RTM_ADD, &kn->r); - } log_info("kernel routing table coupled"); } @@ -343,12 +319,10 @@ kr_fib_decouple(void) if (kr_state.fib_sync == 0) /* already decoupled */ return; - RB_FOREACH(kr, kroute_tree, &krt) { - if (!(kr->r.flags & F_KERNEL)) - for (kn = kr; kn != NULL; kn = kn->next) { + RB_FOREACH(kr, kroute_tree, &krt) + if (kr->r.priority == RTP_OSPF) + for (kn = kr; kn != NULL; kn = kn->next) send_rtmsg(kr_state.fd, RTM_DELETE, &kn->r); - } - } kr_state.fib_sync = 0; @@ -359,6 +333,7 @@ kr_fib_decouple(void) void kr_dispatch_msg(int fd, short event, void *bula) { + /* XXX this is stupid */ dispatch_rtmsg(); } @@ -500,6 +475,10 @@ kr_redistribute(struct kroute_node *kh) struct kroute kr; int redistribute = 0; + /* only the highest prio route can be redistributed */ + if (kroute_find(&kh->r.prefix, kh->r.prefixlen, RTP_ANY) != kh) + return; + bzero(&kr, sizeof(kr)); kr.metric = UINT_MAX; for (kn = kh; kn; kn = kn->next) @@ -560,19 +539,40 @@ kroute_compare(struct kroute_node *a, struct kroute_node *b) return (-1); if (a->r.prefixlen > b->r.prefixlen) return (1); + + /* if the priority is RTP_ANY finish on the first address hit */ + if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY) + return (0); + if (a->r.priority < b->r.priority) + return (-1); + if (a->r.priority > b->r.priority) + return (1); return (0); } /* tree management */ struct kroute_node * -kroute_find(const struct in6_addr *prefix, u_int8_t prefixlen) +kroute_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t prio) { struct kroute_node s; + struct kroute_node *kn, *tmp; s.r.prefix = *prefix; s.r.prefixlen = prefixlen; - - return (RB_FIND(kroute_tree, &krt, &s)); + s.r.priority = prio; + + kn = RB_FIND(kroute_tree, &krt, &s); + if (kn && prio == RTP_ANY) { + tmp = RB_PREV(kroute_tree, &krt, kn); + while (tmp) { + if (kroute_compare(&s, tmp) == 0) + kn = tmp; + else + break; + tmp = RB_PREV(kroute_tree, &krt, kn); + } + } + return (kn); } struct kroute_node * @@ -595,11 +595,9 @@ kroute_insert(struct kroute_node *kr) if ((krh = RB_INSERT(kroute_tree, &krt, kr)) != NULL) { /* - * Multipath route, add at end of list and clone the - * ospfd inserted flag. + * Multipath route, add at end of list. */ krm = krh; - kr->r.flags |= krm->r.flags & F_OSPFD_INSERTED; while (krm->next != NULL) krm = krm->next; krm->next = kr; @@ -730,12 +728,12 @@ kroute_match(struct in6_addr *key) /* we will never match the default route */ for (i = 128; i > 0; i--) { inet6applymask(&ina, key, i); - if ((kr = kroute_find(&ina, i)) != NULL) + if ((kr = kroute_find(&ina, i, RTP_ANY)) != NULL) return (kr); } /* if we don't have a match yet, try to find a default route */ - if ((kr = kroute_find(&in6addr_any, 0)) != NULL) + if ((kr = kroute_find(&in6addr_any, 0, RTP_ANY)) != NULL) return (kr); return (NULL); @@ -999,10 +997,11 @@ send_rtmsg(int fd, int action, struct kroute *kroute) bzero(&hdr, sizeof(hdr)); hdr.rtm_version = RTM_VERSION; hdr.rtm_type = action; - hdr.rtm_flags = RTF_UP|RTF_MPATH; hdr.rtm_priority = RTP_OSPF; if (action == RTM_CHANGE) hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE; + else + hdr.rtm_flags = RTF_MPATH; hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ hdr.rtm_hdrlen = sizeof(hdr); hdr.rtm_msglen = sizeof(hdr); @@ -1168,6 +1167,7 @@ fetchtable(void) } kr->r.flags = F_KERNEL; + kr->r.priority = rtm->rtm_priority; switch (sa->sa_family) { case AF_INET6: @@ -1182,8 +1182,6 @@ fetchtable(void) kr->r.flags |= F_REJECT; if (rtm->rtm_flags & RTF_DYNAMIC) kr->r.flags |= F_DYNAMIC; - if (rtm->rtm_flags & RTF_PROTO1) - kr->r.flags |= F_BGPD_INSERTED; if (sa_in6 != NULL) { if (sa_in6->sin6_len == 0) break; @@ -1226,7 +1224,7 @@ fetchtable(void) break; } - if (rtm->rtm_flags & RTF_PROTO2) { + if (rtm->rtm_priority == RTP_OSPF) { send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); free(kr); } else { @@ -1326,7 +1324,7 @@ dispatch_rtmsg(void) struct sockaddr_rtlabel *label; struct kroute_node *kr, *okr; struct in6_addr prefix, nexthop; - u_int8_t prefixlen; + u_int8_t prefixlen, prio; int flags, mpath; unsigned int scope; u_short ifindex = 0; @@ -1358,6 +1356,7 @@ dispatch_rtmsg(void) prefixlen = 0; flags = F_KERNEL; mpath = 0; + prio = 0; if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE || rtm->rtm_type == RTM_DELETE) { @@ -1377,10 +1376,10 @@ dispatch_rtmsg(void) if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST)) continue; -#ifdef RTF_MPATH if (rtm->rtm_flags & RTF_MPATH) mpath = 1; -#endif + prio = rtm->rtm_priority; + switch (sa->sa_family) { case AF_INET6: prefix = @@ -1403,8 +1402,6 @@ dispatch_rtmsg(void) flags |= F_REJECT; if (rtm->rtm_flags & RTF_DYNAMIC) flags |= F_DYNAMIC; - if (rtm->rtm_flags & RTF_PROTO1) - flags |= F_BGPD_INSERTED; break; default: continue; @@ -1441,8 +1438,8 @@ dispatch_rtmsg(void) continue; } - if ((okr = kroute_find(&prefix, prefixlen)) != - NULL) { + if ((okr = kroute_find(&prefix, prefixlen, prio)) + != NULL) { /* just add new multipath routes */ if (mpath && rtm->rtm_type == RTM_ADD) goto add; @@ -1456,13 +1453,6 @@ dispatch_rtmsg(void) goto add; } - /* - * ospf route overridden by kernel. Preference - * of the route is not checked because this is - * forced -- most probably by a user. - */ - if (kr->r.flags & F_OSPFD_INSERTED) - flags |= F_OSPFD_INSERTED; if (kr->r.flags & F_REDISTRIBUTED) flags |= F_REDISTRIBUTED; kr->r.nexthop = nexthop; @@ -1501,6 +1491,7 @@ add: kr->r.scope = scope; kr->r.flags = flags; kr->r.ifindex = ifindex; + kr->r.priority = prio; if ((label = (struct sockaddr_rtlabel *) rti_info[RTAX_LABEL]) != NULL) { @@ -1514,7 +1505,7 @@ add: } break; case RTM_DELETE: - if ((kr = kroute_find(&prefix, prefixlen)) == + if ((kr = kroute_find(&prefix, prefixlen, prio)) == NULL) continue; if (!(kr->r.flags & F_KERNEL)) @@ -1527,14 +1518,6 @@ add: " not found"); return (-1); } - /* - * last route is getting removed request the - * ospf route from the RDE to insert instead - */ - if (okr == kr && kr->next == NULL && - kr->r.flags & F_OSPFD_INSERTED) - main_imsg_compose_rde(IMSG_KROUTE_GET, 0, - &kr->r, sizeof(struct kroute)); if (kroute_remove(kr) == -1) return (-1); break; diff --git a/usr.sbin/ospf6d/ospf6d.h b/usr.sbin/ospf6d/ospf6d.h index bd07669f008..abed9c97e2a 100644 --- a/usr.sbin/ospf6d/ospf6d.h +++ b/usr.sbin/ospf6d/ospf6d.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospf6d.h,v 1.32 2017/05/30 12:42:31 friehm Exp $ */ +/* $OpenBSD: ospf6d.h,v 1.33 2017/06/19 19:55:57 friehm Exp $ */ /* * Copyright (c) 2004, 2007 Esben Norby @@ -51,7 +51,6 @@ #define F_OSPFD_INSERTED 0x0001 #define F_KERNEL 0x0002 -#define F_BGPD_INSERTED 0x0004 #define F_CONNECTED 0x0008 #define F_DOWN 0x0010 #define F_STATIC 0x0020 @@ -101,7 +100,6 @@ enum imsg_type { IMSG_CTL_LOG_VERBOSE, IMSG_KROUTE_CHANGE, IMSG_KROUTE_DELETE, - IMSG_KROUTE_GET, IMSG_IFINFO, IMSG_IFADD, IMSG_IFDELETE, @@ -396,6 +394,7 @@ struct kroute { u_int16_t rtlabel; u_short ifindex; u_int8_t prefixlen; + u_int8_t priority; }; /* name2id */ diff --git a/usr.sbin/ospf6d/rde.c b/usr.sbin/ospf6d/rde.c index 45c35987f9f..62de3c33521 100644 --- a/usr.sbin/ospf6d/rde.c +++ b/usr.sbin/ospf6d/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.70 2017/05/30 12:42:31 friehm Exp $ */ +/* $OpenBSD: rde.c,v 1.71 2017/06/19 19:55:57 friehm Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker @@ -633,7 +633,6 @@ rde_dispatch_parent(int fd, short event, void *bula) struct imsgbuf *ibuf = &iev->ibuf; struct lsa *lsa; struct vertex *v; - struct rt_node *rn; ssize_t n; int shut = 0, wasvalid; unsigned int ifindex; @@ -695,22 +694,6 @@ rde_dispatch_parent(int fd, short event, void *bula) free(lsa); } break; - case IMSG_KROUTE_GET: - if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { - log_warnx("rde_dispatch_parent: " - "wrong imsg len"); - break; - } - memcpy(&kr, imsg.data, sizeof(kr)); - - if ((rn = rt_find(&kr.prefix, kr.prefixlen, - DT_NET)) != NULL) - rde_send_change_kroute(rn); - else - /* should not happen */ - imsg_compose_event(iev_main, IMSG_KROUTE_DELETE, - 0, 0, -1, &kr, sizeof(kr)); - break; case IMSG_IFINFO: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct iface)) -- 2.20.1