diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-03-08 13:49:08 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-03-08 13:49:08 +0000 |
commit | f7727d2fcdbe449f7d6b4be393220a427c3bbcab (patch) | |
tree | 7b017aa12f9ec85625241325a41f8ba2f5c5c5e4 | |
parent | cbda4665a87328ce8644ec7f8dd638a2788e91af (diff) |
Fix logic of the kroute code. First of all there was a porblem if a prefix
is known via kernel and ospf. If the kernel route is removed the ospf one
was not added to the FIB. This is an uncommon event so it is OK to request
an update from the RIB in this case.
Additionally ospfd treated bgpd inserted routes like static routes. This
is wrong because IGP routes habe a higher preference over EGP routes. In
this case a bgpd route needs to be overridden by a ospfd one.
With these to fixes bgpd and ospfd start to play nicely together.
OK norby@
-rw-r--r-- | usr.sbin/ospfd/kroute.c | 80 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfd.h | 7 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde.c | 23 |
3 files changed, 75 insertions, 35 deletions
diff --git a/usr.sbin/ospfd/kroute.c b/usr.sbin/ospfd/kroute.c index 486302902b5..d707a3d3e3a 100644 --- a/usr.sbin/ospfd/kroute.c +++ b/usr.sbin/ospfd/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.25 2006/01/23 22:29:15 claudio Exp $ */ +/* $OpenBSD: kroute.c,v 1.26 2006/03/08 13:49:07 claudio Exp $ */ /* * Copyright (c) 2004 Esben Norby <norby@openbsd.org> @@ -166,10 +166,23 @@ kr_change(struct kroute *kroute) if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen)) != NULL) { - if (kr->r.flags & F_OSPFD_INSERTED) + if (!(kr->r.flags & F_KERNEL)) action = RTM_CHANGE; - else /* a non-ospf route already exists. not a problem */ - return (0); + else { /* a non-ospf route already exists. not a problem */ + if (!(kr->r.flags & F_BGPD_INSERTED)) { + kr->r.flags |= F_OSPFD_INSERTED; + return (0); + } + /* + * 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; + kr->r.flags = kroute->flags | F_OSPFD_INSERTED; + kr->r.ifindex = 0; + } } /* nexthop within 127/8 -> ignore silently */ @@ -210,10 +223,12 @@ kr_delete(struct kroute *kroute) if (!(kr->r.flags & F_OSPFD_INSERTED)) return (0); - /* nexthop within 127/8 -> ignore silently */ - if ((kroute->nexthop.s_addr & htonl(IN_CLASSA_NET)) == - htonl(INADDR_LOOPBACK & IN_CLASSA_NET)) + if (kr->r.flags & F_KERNEL) { + /* remove F_OSPFD_INSERTED flag, route still exists in kernel */ + kr->r.flags &= ~F_OSPFD_INSERTED; + kr->r.ifindex = 0; /* ifindex is no longer relevant */ return (0); + } if (send_rtmsg(kr_state.fd, RTM_DELETE, kroute) == -1) return (-1); @@ -243,7 +258,7 @@ kr_fib_couple(void) kr_state.fib_sync = 1; RB_FOREACH(kr, kroute_tree, &krt) - if ((kr->r.flags & F_OSPFD_INSERTED)) + if (!(kr->r.flags & F_KERNEL)) send_rtmsg(kr_state.fd, RTM_ADD, &kr->r); log_info("kernel routing table coupled"); @@ -258,7 +273,7 @@ kr_fib_decouple(void) return; RB_FOREACH(kr, kroute_tree, &krt) - if ((kr->r.flags & F_OSPFD_INSERTED)) + if (!(kr->r.flags & F_KERNEL)) send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r); kr_state.fib_sync = 0; @@ -345,7 +360,7 @@ kr_redistribute(int type, struct kroute *kr) } /* Only non-ospfd routes are considered for redistribution. */ - if (kr->flags & F_OSPFD_INSERTED) + if (!(kr->flags & F_KERNEL)) return; /* Dynamic routes are not redistributable. */ @@ -422,7 +437,7 @@ kroute_insert(struct kroute_node *kr) return (-1); } - if (kr->r.flags & F_OSPFD_INSERTED) { + if (!(kr->r.flags & F_KERNEL)) { /* don't validate or redistribute ospf route */ kr->r.flags &= ~F_DOWN; return (0); @@ -712,6 +727,9 @@ send_rtmsg(int fd, int action, struct kroute *kroute) r.hdr.rtm_version = RTM_VERSION; r.hdr.rtm_type = action; r.hdr.rtm_flags = RTF_PROTO2; + if (action == RTM_CHANGE) /* force PROTO2 reset the other flags */ + r.hdr.rtm_fmask = + RTF_PROTO2|RTF_PROTO1|RTF_REJECT|RTF_BLACKHOLE; r.hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ r.hdr.rtm_addrs = RTA_DST|RTA_GATEWAY|RTA_NETMASK; r.prefix.sin_len = sizeof(r.prefix); @@ -825,6 +843,8 @@ 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; @@ -1005,6 +1025,8 @@ 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; @@ -1034,24 +1056,21 @@ dispatch_rtmsg(void) if ((kr = kroute_find(prefix.s_addr, prefixlen)) != NULL) { - if (kr->r.flags & F_KERNEL) { - kr->r.nexthop.s_addr = nexthop.s_addr; - kr->r.flags = flags; - - if (kif_validate(kr->r.ifindex)) - kr->r.flags &= ~F_DOWN; - else - kr->r.flags |= F_DOWN; - - /* just readd, the RDE will care */ - kr_redistribute(IMSG_NETWORK_ADD, - &kr->r); - } - } else if (rtm->rtm_type == RTM_CHANGE) { - log_warnx("change req for %s/%u: not " - "in table", inet_ntoa(prefix), - prefixlen); - continue; + /* ospf route overridden by kernel */ + /* pref is not checked because this is forced */ + if (kr->r.flags & F_OSPFD_INSERTED) + flags |= F_OSPFD_INSERTED; + kr->r.nexthop.s_addr = nexthop.s_addr; + kr->r.flags = flags; + kr->r.ifindex = ifindex; + + if (kif_validate(kr->r.ifindex)) + kr->r.flags &= ~F_DOWN; + else + kr->r.flags |= F_DOWN; + + /* just readd, the RDE will care */ + kr_redistribute(IMSG_NETWORK_ADD, &kr->r); } else { if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) { @@ -1073,6 +1092,9 @@ dispatch_rtmsg(void) continue; if (!(kr->r.flags & F_KERNEL)) continue; + if (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 59d729fd377..e14cf91eb2a 100644 --- a/usr.sbin/ospfd/ospfd.h +++ b/usr.sbin/ospfd/ospfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfd.h,v 1.46 2006/02/24 21:06:47 norby Exp $ */ +/* $OpenBSD: ospfd.h,v 1.47 2006/03/08 13:49:07 claudio Exp $ */ /* * Copyright (c) 2004 Esben Norby <norby@openbsd.org> @@ -48,11 +48,11 @@ #define F_OSPFD_INSERTED 0x0001 #define F_KERNEL 0x0002 -#define F_CONNECTED 0x0004 +#define F_BGPD_INSERTED 0x0004 +#define F_CONNECTED 0x0008 #define F_DOWN 0x0010 #define F_STATIC 0x0020 #define F_DYNAMIC 0x0040 -#define F_LONGER 0x0080 #define F_REDISTRIBUTED 0x0100 #define REDISTRIBUTE_STATIC 0x01 @@ -119,6 +119,7 @@ enum imsg_type { IMSG_CTL_END, IMSG_KROUTE_CHANGE, IMSG_KROUTE_DELETE, + IMSG_KROUTE_GET, IMSG_IFINFO, IMSG_NEIGHBOR_UP, IMSG_NEIGHBOR_DOWN, diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c index 8b78008544e..4970f1207dc 100644 --- a/usr.sbin/ospfd/rde.c +++ b/usr.sbin/ospfd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.40 2006/02/21 13:02:59 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.41 2006/03/08 13:49:07 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -560,11 +560,12 @@ rde_dispatch_imsg(int fd, short event, void *bula) void rde_dispatch_parent(int fd, short event, void *bula) { - struct imsgbuf *ibuf = bula; struct imsg imsg; + struct kroute kr; + struct imsgbuf *ibuf = bula; struct lsa *lsa; struct vertex *v; - struct kroute kr; + struct rt_node *rn; int n; switch (event) { @@ -618,6 +619,22 @@ 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: 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; default: log_debug("rde_dispatch_parent: unexpected imsg %d", imsg.hdr.type); |