On Mon, Jan 3, 2011 at 5:27 PM, Jan Johansson <janj+open...@wenf.org> wrote: > If an CARP interface is in BACKUP state the route is still > advertised which leads to assymetric routing.
Ok, the following should fix this. It's a little more involved; here's what's new: - Avoid sending LSAs if the link state is down (to avoid double-advertising CARP interfaces). OSPFd does this a little more elegantly using metrics[1], but I wasn't able to get that to work, perhaps I'm not understanding the protocol. Suggestions appreciated. - Don't send LSAs if the interface is down (ifconfig carp1 down), because that's silly - Make the OSPF engine update the RDE about interface changes even when the interface state does not change, so the RDE is informed when a passive interface's link state changes (so we can then make a decision using that data) - Resend intra-area LSAs in the RDE when interface flags change, not just interface state (avoids a race condition where LSAs get sent before the OSPF engine updates the RDE with new linkstate data) Cheers, Patrick [1] See ospfe.c:851 through ospfe.c:883 in ospfd. -- http://www.labyrinthdata.net.au - WA Backup, Web and VPS Hosting http://patrick.ld.net.au/ospf6d-fix-passive-interfaces-mk2.patch Index: interface.c =================================================================== RCS file: /cvs/src/usr.sbin/ospf6d/interface.c,v retrieving revision 1.15 diff -u -p -r1.15 interface.c --- interface.c 20 Sep 2009 20:45:06 -0000 1.15 +++ interface.c 4 Jan 2011 08:44:10 -0000 @@ -145,11 +145,15 @@ if_fsm(struct iface *iface, enum iface_e if (iface->state != old_state) { orig_rtr_lsa(iface); orig_link_lsa(iface); - - /* state change inform RDE */ - ospfe_imsg_compose_rde(IMSG_IFINFO, - iface->self->peerid, 0, iface, sizeof(struct iface)); } + + /* + * Send interface update to RDE regardless of whether state changes - a + * passive interface will remain in the DOWN state but may need to have + * prefix LSAs sent regardless. + */ + ospfe_imsg_compose_rde(IMSG_IFINFO, + iface->self->peerid, 0, iface, sizeof(struct iface)); if (old_state & (IF_STA_MULTI | IF_STA_POINTTOPOINT) && (iface->state & (IF_STA_MULTI | IF_STA_POINTTOPOINT)) == 0) Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/ospf6d/rde.c,v retrieving revision 1.50 diff -u -p -r1.50 rde.c --- rde.c 22 Aug 2010 20:55:10 -0000 1.50 +++ rde.c 4 Jan 2011 08:44:11 -0000 @@ -22,6 +22,7 @@ #include <sys/socket.h> #include <sys/queue.h> #include <sys/param.h> +#include <net/if_types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <err.h> @@ -587,11 +588,17 @@ rde_dispatch_imsg(int fd, short event, v iface = if_find(ifp->ifindex); if (iface == NULL) fatalx("interface lost in rde"); - iface->flags = ifp->flags; - iface->linkstate = ifp->linkstate; iface->nh_reachable = ifp->nh_reachable; - if (iface->state != ifp->state) { + + /* Resend LSAs if interface flags change */ + if ((iface->state != ifp->state) || + (iface->linkstate != ifp->linkstate) || + (iface->flags != ifp->flags)) { + iface->state = ifp->state; + iface->flags = ifp->flags; + iface->linkstate = ifp->linkstate; + area = area_find(rdeconf, iface->area_id); if (!area) fatalx("interface lost area"); @@ -1459,8 +1466,27 @@ orig_intra_lsa_rtr(struct area *area, st numprefix = 0; LIST_FOREACH(iface, &area->iface_list, entry) { - if (iface->state & IF_STA_DOWN) + /* + * do not send a LSA for interfaces that: + * - have a link state that is not up, or + * - are down (kernel flags), or + * - are in the down state, and are not [carp or marked as passive], or + * - are unknown and are carp + * + * This will not advertise backup carp interfaces (which have a link + * state of down). + */ + if (!(LINK_STATE_IS_UP(iface->linkstate)) || + !(iface->flags & IFF_UP) || + ((iface->state & IF_STA_DOWN) && + !((iface->media_type == IFT_CARP) || + (iface->cflags & F_IFACE_PASSIVE))) || + ((iface->linkstate == LINK_STATE_UNKNOWN) && + (iface->media_type == IFT_CARP))) { + log_debug("orig_intra_lsa_rtr: area %s, interface %s: not including" + " in LSA", inet_ntoa(area->id), iface->name); continue; + } /* Broadcast links with adjacencies are handled * by orig_intra_lsa_net(), ignore. */