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. */

Reply via email to