diff options
author | Dinesh Dutt <ddutt@cumulusnetworks.com> | 2013-08-24 07:55:50 +0000 |
---|---|---|
committer | David Lamparter <equinox@opensourcerouting.org> | 2013-11-07 18:15:43 -0800 |
commit | b81e97a8a7f85ecc7489dc8a7c7b9d403d9c4bc6 (patch) | |
tree | 48e2c8492f01cc177a6691878cf4e5a329fe4d2d | |
parent | 17d003da963d6294e5ab95c690de285eccf0bac0 (diff) | |
download | quagga-b81e97a8a7f85ecc7489dc8a7c7b9d403d9c4bc6.tar.bz2 quagga-b81e97a8a7f85ecc7489dc8a7c7b9d403d9c4bc6.tar.xz |
ospf6d: correct nexthop through directly connected networks
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>
-rw-r--r-- | lib/if.c | 24 | ||||
-rw-r--r-- | lib/if.h | 1 | ||||
-rw-r--r-- | ospf6d/ospf6_intra.c | 23 |
3 files changed, 45 insertions, 3 deletions
@@ -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 * @@ -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: */ diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 4cb751f0..c08a6ae6 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -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)) { |