summaryrefslogtreecommitdiff
path: root/ospf6d/ospf6_asbr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospf6d/ospf6_asbr.c')
-rw-r--r--ospf6d/ospf6_asbr.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 713dd82075..d1c2b8bfc9 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -481,7 +481,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
static int ospf6_ase_forward_address_check(struct ospf6 *ospf6,
struct in6_addr *fwd_addr)
{
- struct listnode *anode, *node, *cnode;
+ struct listnode *anode, *node;
struct ospf6_interface *oi;
struct ospf6_area *oa;
struct interface *ifp;
@@ -494,7 +494,7 @@ static int ospf6_ase_forward_address_check(struct ospf6 *ospf6,
continue;
ifp = oi->interface;
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
+ frr_each (if_connected, ifp->connected, c) {
if (IPV6_ADDR_SAME(&c->address->u.prefix6,
fwd_addr))
return 0;
@@ -1376,6 +1376,55 @@ ospf6_external_aggr_match(struct ospf6 *ospf6, struct prefix *p)
return node->info;
}
+static void ospf6_external_lsa_fwd_addr_set(struct ospf6 *ospf6,
+ const struct in6_addr *nexthop,
+ struct in6_addr *fwd_addr)
+{
+ struct vrf *vrf;
+ struct interface *ifp;
+ struct prefix nh;
+
+ /* Initialize forwarding address to zero. */
+ memset(fwd_addr, 0, sizeof(*fwd_addr));
+
+ vrf = vrf_lookup_by_id(ospf6->vrf_id);
+ if (!vrf)
+ return;
+
+ nh.family = AF_INET6;
+ nh.u.prefix6 = *nexthop;
+ nh.prefixlen = IPV6_MAX_BITLEN;
+
+ /*
+ * Use the route's nexthop as the forwarding address if it meets the
+ * following conditions:
+ * - It's a global address.
+ * - The associated nexthop interface is OSPF-enabled.
+ */
+ if (IN6_IS_ADDR_UNSPECIFIED(nexthop) || IN6_IS_ADDR_LINKLOCAL(nexthop))
+ return;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ struct ospf6_interface *oi = ifp->info;
+ struct connected *connected;
+
+ if (!oi || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
+ continue;
+
+ frr_each (if_connected, ifp->connected, connected) {
+ if (connected->address->family != AF_INET6)
+ continue;
+ if (IN6_IS_ADDR_LINKLOCAL(&connected->address->u.prefix6))
+ continue;
+ if (!prefix_match(connected->address, &nh))
+ continue;
+
+ *fwd_addr = *nexthop;
+ return;
+ }
+ }
+}
+
void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
@@ -1470,10 +1519,8 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
if (nexthop_num && nexthop) {
ospf6_route_add_nexthop(match, ifindex, nexthop);
- if (!IN6_IS_ADDR_UNSPECIFIED(nexthop)
- && !IN6_IS_ADDR_LINKLOCAL(nexthop))
- memcpy(&info->forwarding, nexthop,
- sizeof(struct in6_addr));
+ ospf6_external_lsa_fwd_addr_set(ospf6, nexthop,
+ &info->forwarding);
} else
ospf6_route_add_nexthop(match, ifindex, NULL);
@@ -1520,10 +1567,8 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
info->type = type;
if (nexthop_num && nexthop) {
ospf6_route_add_nexthop(route, ifindex, nexthop);
- if (!IN6_IS_ADDR_UNSPECIFIED(nexthop)
- && !IN6_IS_ADDR_LINKLOCAL(nexthop))
- memcpy(&info->forwarding, nexthop,
- sizeof(struct in6_addr));
+ ospf6_external_lsa_fwd_addr_set(ospf6, nexthop,
+ &info->forwarding);
} else
ospf6_route_add_nexthop(route, ifindex, NULL);