diff options
author | friehm <friehm@cvs.openbsd.org> | 2017-06-19 19:55:58 +0000 |
---|---|---|
committer | friehm <friehm@cvs.openbsd.org> | 2017-06-19 19:55:58 +0000 |
commit | d7ca4b97d32e20952a3de11627fe04135c68632f (patch) | |
tree | 6c0d89309f6972718114c48518ca55e8fa0fb6d5 /usr.sbin/ospf6d/kroute.c | |
parent | 6d76c4c10c7d583e5361ebad216894dc4cbde3de (diff) |
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@
Diffstat (limited to 'usr.sbin/ospf6d/kroute.c')
-rw-r--r-- | usr.sbin/ospf6d/kroute.c | 143 |
1 files changed, 63 insertions, 80 deletions
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 <norby@openbsd.org> @@ -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; |