From d2e5d5d4445fa2b3a1150beef609e2826010e9c1 Mon Sep 17 00:00:00 2001 From: Mobashshera Rasool Date: Wed, 14 Jul 2021 05:14:17 +0000 Subject: [PATCH] ospf6d: support blackhole next hops This feature is required for creating summary routes that drop traffic without more specific routes. Authored-by: Rafael Zalamena Signed-off-by: Rafael Zalamena Signed-off-by: Mobashshera Rasool --- ospf6d/ospf6_route.c | 79 +++++++++++++++++++++++++++++++++++--------- ospf6d/ospf6_route.h | 69 +++++++++++++++++++++++++++++--------- 2 files changed, 118 insertions(+), 30 deletions(-) diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 0a026785f4..d785e623b4 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -284,12 +284,21 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr) struct ospf6_nexthop nh_match; if (nh_list) { - nh_match.ifindex = ifindex; - if (addr != NULL) + if (addr) { + if (ifindex) + nh_match.type = NEXTHOP_TYPE_IPV6_IFINDEX; + else + nh_match.type = NEXTHOP_TYPE_IPV6; + memcpy(&nh_match.address, addr, sizeof(struct in6_addr)); - else + } else { + nh_match.type = NEXTHOP_TYPE_IFINDEX; + memset(&nh_match.address, 0, sizeof(struct in6_addr)); + } + + nh_match.ifindex = ifindex; if (!ospf6_route_find_nexthop(nh_list, &nh_match)) { nh = ospf6_nexthop_create(); @@ -299,36 +308,76 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr) } } +void ospf6_add_route_nexthop_blackhole(struct ospf6_route *route) +{ + struct ospf6_nexthop *nh; + struct ospf6_nexthop nh_match = {}; + + /* List not allocated. */ + if (route->nh_list == NULL) + return; + + /* Entry already exists. */ + nh_match.type = NEXTHOP_TYPE_BLACKHOLE; + if (ospf6_route_find_nexthop(route->nh_list, &nh_match)) + return; + + nh = ospf6_nexthop_create(); + ospf6_nexthop_copy(nh, &nh_match); + listnode_add(route->nh_list, nh); +} + void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, struct zapi_nexthop nexthops[], int entries, vrf_id_t vrf_id) { struct ospf6_nexthop *nh; struct listnode *node; - char buf[64]; int i; if (route) { i = 0; for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) { if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { - const char *ifname; - inet_ntop(AF_INET6, &nh->address, buf, - sizeof(buf)); - ifname = ifindex2ifname(nh->ifindex, vrf_id); - zlog_debug(" nexthop: %s%%%.*s(%d)", buf, - IFNAMSIZ, ifname, nh->ifindex); + zlog_debug(" nexthop: %s %pI6%%%.*s(%d)", + nexthop_type_to_str(nh->type), + &nh->address, IFNAMSIZ, + ifindex2ifname(nh->ifindex, vrf_id), + nh->ifindex); } + if (i >= entries) return; nexthops[i].vrf_id = vrf_id; - nexthops[i].ifindex = nh->ifindex; - if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) { + nexthops[i].type = nh->type; + + switch (nh->type) { + case NEXTHOP_TYPE_BLACKHOLE: + /* NOTHING */ + break; + + case NEXTHOP_TYPE_IFINDEX: + nexthops[i].ifindex = nh->ifindex; + break; + + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + /* + * OSPFv3 with IPv4 routes is not supported + * yet. Skip this next hop. + */ + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug(" Skipping IPv4 next hop"); + continue; + + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthops[i].ifindex = nh->ifindex; + /* FALLTHROUGH */ + case NEXTHOP_TYPE_IPV6: nexthops[i].gate.ipv6 = nh->address; - nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX; - } else - nexthops[i].type = NEXTHOP_TYPE_IFINDEX; + break; + } i++; } } diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 01b735b1e8..c354d4adb1 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -24,6 +24,7 @@ #include "command.h" #include "zclient.h" #include "lib/json.h" +#include "lib/nexthop.h" #define OSPF6_MULTI_PATH_LIMIT 4 @@ -44,23 +45,60 @@ struct ospf6_nexthop { /* IP address, if any */ struct in6_addr address; + + /** Next-hop type information. */ + enum nexthop_types_t type; }; -#define ospf6_nexthop_is_set(x) \ - ((x)->ifindex || !IN6_IS_ADDR_UNSPECIFIED(&(x)->address)) -#define ospf6_nexthop_is_same(a, b) \ - ((a)->ifindex == (b)->ifindex \ - && IN6_ARE_ADDR_EQUAL(&(a)->address, &(b)->address)) -#define ospf6_nexthop_clear(x) \ - do { \ - (x)->ifindex = 0; \ - memset(&(x)->address, 0, sizeof(struct in6_addr)); \ - } while (0) -#define ospf6_nexthop_copy(a, b) \ - do { \ - (a)->ifindex = (b)->ifindex; \ - memcpy(&(a)->address, &(b)->address, sizeof(struct in6_addr)); \ - } while (0) +static inline bool ospf6_nexthop_is_set(const struct ospf6_nexthop *nh) +{ + return nh->type != 0; +} + +static inline bool ospf6_nexthop_is_same(const struct ospf6_nexthop *nha, + const struct ospf6_nexthop *nhb) +{ + if (nha->type != nhb->type) + return false; + + switch (nha->type) { + case NEXTHOP_TYPE_BLACKHOLE: + /* NOTHING */ + break; + + case NEXTHOP_TYPE_IFINDEX: + if (nha->ifindex != nhb->ifindex) + return false; + break; + + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + /* OSPFv3 does not support IPv4 next hops. */ + return false; + + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (nha->ifindex != nhb->ifindex) + return false; + /* FALLTHROUGH */ + case NEXTHOP_TYPE_IPV6: + if (!IN6_ARE_ADDR_EQUAL(&nha->address, &nhb->address)) + return false; + break; + } + + return true; +} + +static inline void ospf6_nexthop_clear(struct ospf6_nexthop *nh) +{ + memset(nh, 0, sizeof(*nh)); +} + +static inline void ospf6_nexthop_copy(struct ospf6_nexthop *nha, + const struct ospf6_nexthop *nhb) +{ + memcpy(nha, nhb, sizeof(*nha)); +} /* Path */ struct ospf6_ls_origin { @@ -285,6 +323,7 @@ extern void ospf6_copy_nexthops(struct list *dst, struct list *src); extern void ospf6_merge_nexthops(struct list *dst, struct list *src); extern void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr); +extern void ospf6_add_route_nexthop_blackhole(struct ospf6_route *route); extern int ospf6_num_nexthops(struct list *nh_list); extern int ospf6_route_cmp_nexthops(struct ospf6_route *a, struct ospf6_route *b); -- 2.39.5