diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2008-12-12 22:43:18 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2008-12-12 22:43:18 +0000 |
commit | fe2d6de7fe376f66266225d7022850969de7496b (patch) | |
tree | 779473022f8cacc83fab48900b2b209cf03694a6 /usr.sbin | |
parent | 960ceb1a6888c8b2ae8f47f12d164138bb12bd8b (diff) |
Make the kroute code routing priority aware. This solves a few issues and
makes to code simpler. While the routing table is somewhat simpler the
redistribution code does not allow a much more radical approach. With some
additional help of Mr. Kernel and his rtsock it should be possible to rip
even more code out of kroute.c.
Tested and OK sthen@, gollo@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ospfd/kroute.c | 144 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfd.h | 7 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde.c | 20 |
3 files changed, 68 insertions, 103 deletions
diff --git a/usr.sbin/ospfd/kroute.c b/usr.sbin/ospfd/kroute.c index 90d8357aef3..ac71ef3d207 100644 --- a/usr.sbin/ospfd/kroute.c +++ b/usr.sbin/ospfd/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.61 2008/11/21 17:10:45 claudio Exp $ */ +/* $OpenBSD: kroute.c,v 1.62 2008/12/12 22:43:17 claudio Exp $ */ /* * Copyright (c) 2004 Esben Norby <norby@openbsd.org> @@ -68,7 +68,7 @@ int kif_compare(struct kif_node *, struct kif_node *); int kr_change_fib(struct kroute_node *, struct kroute *, int, int); int kr_delete_fib(struct kroute_node *); -struct kroute_node *kroute_find(in_addr_t, u_int8_t); +struct kroute_node *kroute_find(in_addr_t, u_int8_t, u_int8_t); struct kroute_node *kroute_matchgw(struct kroute_node *, struct in_addr); int kroute_insert(struct kroute_node *); int kroute_remove(struct kroute_node *); @@ -229,6 +229,7 @@ kr_change_fib(struct kroute_node *kr, struct kroute *kroute, int krcount, kn->r.prefixlen = kroute[i].prefixlen; kn->r.nexthop.s_addr = kroute[i].nexthop.s_addr; 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; @@ -252,32 +253,10 @@ kr_change(struct kroute *kroute, int krcount) kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag); - kr = kroute_find(kroute->prefix.s_addr, 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.s_addr, 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)); } @@ -285,14 +264,9 @@ 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", + inet_ntoa(kr->r.prefix), kr->r.prefixlen, kr->r.priority); if (send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r) == -1) return (-1); @@ -308,8 +282,8 @@ kr_delete(struct kroute *kroute) { struct kroute_node *kr, *nkr; - if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen)) == - NULL) + if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen, + RTP_OSPF)) == NULL) return (0); while (kr != NULL) { @@ -341,10 +315,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"); } @@ -358,12 +331,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; @@ -374,6 +345,7 @@ kr_fib_decouple(void) void kr_dispatch_msg(int fd, short event, void *bula) { + /* XXX this is stupid */ dispatch_rtmsg(); } @@ -524,6 +496,10 @@ kr_redistribute(struct kroute_node *kh) struct rroute rr; int redistribute = 0; + /* only the highest prio route can be redistributed */ + if (kroute_find(kh->r.prefix.s_addr, kh->r.prefixlen, RTP_ANY) != kh) + return; + bzero(&rr, sizeof(rr)); rr.metric = UINT_MAX; for (kn = kh; kn; kn = kn->next) @@ -583,6 +559,14 @@ 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); } @@ -594,14 +578,27 @@ kif_compare(struct kif_node *a, struct kif_node *b) /* tree management */ struct kroute_node * -kroute_find(in_addr_t prefix, u_int8_t prefixlen) +kroute_find(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio) { struct kroute_node s; + struct kroute_node *kn, *tmp; s.r.prefix.s_addr = 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 * @@ -631,7 +628,6 @@ kroute_insert(struct kroute_node *kr) * Multipath route, add at end of list and clone the * ospfd inserted flag. */ - kr->r.flags |= krm->r.flags & F_OSPFD_INSERTED; while (krm->next != NULL) krm = krm->next; krm->next = kr; @@ -841,11 +837,12 @@ kroute_match(in_addr_t key) /* we will never match the default route */ for (i = 32; i > 0; i--) - if ((kr = kroute_find(key & prefixlen2mask(i), i)) != NULL) + if ((kr = kroute_find(key & prefixlen2mask(i), i, + RTP_ANY)) != NULL) return (kr); /* if we don't have a match yet, try to find a default route */ - if ((kr = kroute_find(0, 0)) != NULL) + if ((kr = kroute_find(0, 0, RTP_ANY)) != NULL) return (kr); return (NULL); @@ -1034,10 +1031,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_PROTO2|RTF_MPATH; hdr.rtm_priority = RTP_OSPF; - if (action == RTM_CHANGE) /* force PROTO2 reset the other flags */ - hdr.rtm_fmask = RTF_PROTO2|RTF_PROTO1|RTF_REJECT|RTF_BLACKHOLE; + 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_msglen = sizeof(hdr); /* adjust iovec */ @@ -1184,6 +1182,7 @@ fetchtable(void) } kr->r.flags = F_KERNEL; + kr->r.priority = rtm->rtm_priority; switch (sa->sa_family) { case AF_INET: @@ -1194,8 +1193,6 @@ fetchtable(void) kr->r.flags |= F_STATIC; 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_in != NULL) { if (sa_in->sin_len == 0) break; @@ -1224,7 +1221,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 { @@ -1321,7 +1318,7 @@ dispatch_rtmsg(void) struct sockaddr_rtlabel *label; struct kroute_node *kr, *okr; struct in_addr prefix, nexthop; - u_int8_t prefixlen; + u_int8_t prefixlen, prio; int flags, mpath; u_short ifindex = 0; @@ -1346,6 +1343,7 @@ dispatch_rtmsg(void) flags = F_KERNEL; nexthop.s_addr = 0; mpath = 0; + prio = 0; if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE || rtm->rtm_type == RTM_DELETE) { @@ -1368,6 +1366,8 @@ dispatch_rtmsg(void) if (rtm->rtm_flags & RTF_MPATH) mpath = 1; #endif + prio = rtm->rtm_priority; + switch (sa->sa_family) { case AF_INET: prefix.s_addr = @@ -1387,8 +1387,6 @@ dispatch_rtmsg(void) flags |= F_STATIC; if (rtm->rtm_flags & RTF_DYNAMIC) flags |= F_DYNAMIC; - if (rtm->rtm_flags & RTF_PROTO1) - flags |= F_BGPD_INSERTED; break; default: continue; @@ -1417,8 +1415,8 @@ dispatch_rtmsg(void) continue; } - if ((okr = kroute_find(prefix.s_addr, prefixlen)) != - NULL) { + if ((okr = kroute_find(prefix.s_addr, prefixlen, prio)) + != NULL) { /* just add new multipath routes */ if (mpath && rtm->rtm_type == RTM_ADD) goto add; @@ -1432,13 +1430,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.s_addr = nexthop.s_addr; @@ -1475,6 +1466,7 @@ add: kr->r.nexthop.s_addr = nexthop.s_addr; kr->r.flags = flags; kr->r.ifindex = ifindex; + kr->r.priority = prio; if ((label = (struct sockaddr_rtlabel *) rti_info[RTAX_LABEL]) != NULL) { @@ -1488,8 +1480,8 @@ add: } break; case RTM_DELETE: - if ((kr = kroute_find(prefix.s_addr, prefixlen)) == - NULL) + if ((kr = kroute_find(prefix.s_addr, prefixlen, prio)) + == NULL) continue; if (!(kr->r.flags & F_KERNEL)) continue; @@ -1501,14 +1493,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/ospfd/ospfd.h b/usr.sbin/ospfd/ospfd.h index 9b1213ff955..8e20005846a 100644 --- a/usr.sbin/ospfd/ospfd.h +++ b/usr.sbin/ospfd/ospfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfd.h,v 1.72 2008/11/24 18:28:02 claudio Exp $ */ +/* $OpenBSD: ospfd.h,v 1.73 2008/12/12 22:43:17 claudio Exp $ */ /* * Copyright (c) 2004 Esben Norby <norby@openbsd.org> @@ -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 @@ -121,7 +120,6 @@ enum imsg_type { IMSG_CTL_END, IMSG_KROUTE_CHANGE, IMSG_KROUTE_DELETE, - IMSG_KROUTE_GET, IMSG_IFINFO, IMSG_NEIGHBOR_UP, IMSG_NEIGHBOR_DOWN, @@ -417,11 +415,12 @@ struct ospfd_conf { struct kroute { struct in_addr prefix; struct in_addr nexthop; + u_int32_t ext_tag; u_int16_t flags; u_int16_t rtlabel; - u_int32_t ext_tag; u_short ifindex; u_int8_t prefixlen; + u_int8_t priority; }; struct rroute { diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c index 587c637c8e8..5e63c5d3225 100644 --- a/usr.sbin/ospfd/rde.c +++ b/usr.sbin/ospfd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.74 2008/11/24 18:28:02 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.75 2008/12/12 22:43:17 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -585,12 +585,10 @@ rde_dispatch_parent(int fd, short event, void *bula) static struct area *narea; struct iface *niface; struct imsg imsg; - struct kroute kr; struct rroute rr; struct imsgbuf *ibuf = bula; struct lsa *lsa; struct vertex *v; - struct rt_node *rn; ssize_t n; int shut = 0; @@ -652,22 +650,6 @@ rde_dispatch_parent(int fd, short event, void *bula) lsa_merge(nbrself, lsa, v); } 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.s_addr, kr.prefixlen, - DT_NET)) != NULL) - rde_send_change_kroute(rn); - else - /* should not happen */ - imsg_compose(ibuf_main, IMSG_KROUTE_DELETE, 0, - 0, &kr, sizeof(kr)); - break; case IMSG_RECONF_CONF: if ((nconf = malloc(sizeof(struct ospfd_conf))) == NULL) |