]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospf6d: correct nexthop through directly connected networks
authorDinesh Dutt <ddutt@cumulusnetworks.com>
Sat, 24 Aug 2013 07:55:50 +0000 (07:55 +0000)
committerDavid Lamparter <equinox@opensourcerouting.org>
Fri, 8 Nov 2013 02:15:43 +0000 (18:15 -0800)
This is implementing this part of RFC 2328:

This is the "first case", see below,

16.1.1. The next hop calculation

...
If there is at least one intervening router in the current
shortest path between the destination and the root, the
destination simply inherits the set of next hops from the
parent. Otherwise, there are two cases. In the first case,
the parent vertex is the root (the calculating router
itself). This means that the destination is either a
directly connected network or directly connected router.
The outgoing interface in this case is simply the OSPF
interface connecting to the destination network/router.
...

The current Quagga code always tries to inherit the nexthop from
a parent vertex, but does not cover the case that the destination
is directly connected to the root vertex. This patch adds support
for that case.

Signed-off-by: James Li <jli at cumulusnetworks.com>
Reviewed-by: Dinesh G Dutt <ddutt at cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
lib/if.c
lib/if.h
ospf6d/ospf6_intra.c

index e26aa046f8fff39ba0fcd4b921255d4a5b1cf713..6348403b670ceec1b53b5d25fdc2f11036671025 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -304,6 +304,30 @@ if_lookup_address (struct in_addr src)
   return match;
 }
 
+/* Lookup interface by prefix */
+struct interface *
+if_lookup_prefix (struct prefix *prefix)
+{
+  struct listnode *node;
+  struct prefix addr;
+  int bestlen = 0;
+  struct listnode *cnode;
+  struct interface *ifp;
+  struct connected *c;
+
+  for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
+    {
+      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
+        {
+          if (prefix_cmp(c->address, prefix) == 0)
+            {
+              return ifp;
+            }
+        }
+    }
+  return NULL;
+}
+
 /* Get interface by name if given name interface doesn't exist create
    one. */
 struct interface *
index 13cc254e262863f63837a2a629cc3dae7b241e25..8081be87df0df5d5725cf8c441c46ca4b8b01f55 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -245,6 +245,7 @@ extern struct interface *if_create (const char *name, int namelen);
 extern struct interface *if_lookup_by_index (unsigned int);
 extern struct interface *if_lookup_exact_address (struct in_addr);
 extern struct interface *if_lookup_address (struct in_addr);
+extern struct interface *if_lookup_prefix (struct prefix *prefix);
 
 /* These 2 functions are to be used when the ifname argument is terminated
    by a '\0' character: */
index 4cb751f01d10e0e3b1762c9c50f47ec64ed55287..c08a6ae640d9e96e869d93e8f60391aee27d5061 100644 (file)
@@ -1024,6 +1024,8 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
   struct ospf6_prefix *op;
   char *start, *current, *end;
   char buf[64];
+  struct interface *ifp;
+  int direct_connect = 0;
 
   if (OSPF6_LSA_IS_MAXAGE (lsa))
     return;
@@ -1060,6 +1062,12 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
       return;
     }
 
+  if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
+    {
+      /* the intra-prefix are directly connected */
+      direct_connect = 1;
+    }
+
   prefix_num = ntohs (intra_prefix_lsa->prefix_num);
   start = (caddr_t) intra_prefix_lsa +
           sizeof (struct ospf6_intra_prefix_lsa);
@@ -1090,9 +1098,18 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
       route->path.cost = ls_entry->path.cost +
                          ntohs (op->prefix_metric);
 
-      for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
-           i < OSPF6_MULTI_PATH_LIMIT; i++)
-        ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
+      if (direct_connect)
+        {
+          ifp = if_lookup_prefix(&route->prefix);
+          if (ifp)
+            route->nexthop[0].ifindex = ifp->ifindex;
+        }
+      else
+        {
+          for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
+               i < OSPF6_MULTI_PATH_LIMIT; i++)
+            ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
+        }
 
       if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
         {