mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 01:57:26 +00:00
ospf6d: support blackhole next hops
This feature is required for creating summary routes that drop traffic without more specific routes. Authored-by: Rafael Zalamena <rzalamena@opensourcerouting.org> Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org> Signed-off-by: Mobashshera Rasool <mrasool@vmware.com>
This commit is contained in:
parent
c3a70f6517
commit
d2e5d5d444
@ -284,12 +284,21 @@ void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr)
|
|||||||
struct ospf6_nexthop nh_match;
|
struct ospf6_nexthop nh_match;
|
||||||
|
|
||||||
if (nh_list) {
|
if (nh_list) {
|
||||||
nh_match.ifindex = ifindex;
|
if (addr) {
|
||||||
if (addr != NULL)
|
if (ifindex)
|
||||||
|
nh_match.type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||||
|
else
|
||||||
|
nh_match.type = NEXTHOP_TYPE_IPV6;
|
||||||
|
|
||||||
memcpy(&nh_match.address, addr,
|
memcpy(&nh_match.address, addr,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
else
|
} else {
|
||||||
|
nh_match.type = NEXTHOP_TYPE_IFINDEX;
|
||||||
|
|
||||||
memset(&nh_match.address, 0, sizeof(struct in6_addr));
|
memset(&nh_match.address, 0, sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
nh_match.ifindex = ifindex;
|
||||||
|
|
||||||
if (!ospf6_route_find_nexthop(nh_list, &nh_match)) {
|
if (!ospf6_route_find_nexthop(nh_list, &nh_match)) {
|
||||||
nh = ospf6_nexthop_create();
|
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,
|
void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route,
|
||||||
struct zapi_nexthop nexthops[],
|
struct zapi_nexthop nexthops[],
|
||||||
int entries, vrf_id_t vrf_id)
|
int entries, vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
struct ospf6_nexthop *nh;
|
struct ospf6_nexthop *nh;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
char buf[64];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (route) {
|
if (route) {
|
||||||
i = 0;
|
i = 0;
|
||||||
for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) {
|
for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) {
|
||||||
if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
|
if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
|
||||||
const char *ifname;
|
zlog_debug(" nexthop: %s %pI6%%%.*s(%d)",
|
||||||
inet_ntop(AF_INET6, &nh->address, buf,
|
nexthop_type_to_str(nh->type),
|
||||||
sizeof(buf));
|
&nh->address, IFNAMSIZ,
|
||||||
ifname = ifindex2ifname(nh->ifindex, vrf_id);
|
ifindex2ifname(nh->ifindex, vrf_id),
|
||||||
zlog_debug(" nexthop: %s%%%.*s(%d)", buf,
|
nh->ifindex);
|
||||||
IFNAMSIZ, ifname, nh->ifindex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= entries)
|
if (i >= entries)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nexthops[i].vrf_id = vrf_id;
|
nexthops[i].vrf_id = vrf_id;
|
||||||
nexthops[i].ifindex = nh->ifindex;
|
nexthops[i].type = nh->type;
|
||||||
if (!IN6_IS_ADDR_UNSPECIFIED(&nh->address)) {
|
|
||||||
|
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].gate.ipv6 = nh->address;
|
||||||
nexthops[i].type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
break;
|
||||||
} else
|
}
|
||||||
nexthops[i].type = NEXTHOP_TYPE_IFINDEX;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
#include "lib/json.h"
|
#include "lib/json.h"
|
||||||
|
#include "lib/nexthop.h"
|
||||||
|
|
||||||
#define OSPF6_MULTI_PATH_LIMIT 4
|
#define OSPF6_MULTI_PATH_LIMIT 4
|
||||||
|
|
||||||
@ -44,23 +45,60 @@ struct ospf6_nexthop {
|
|||||||
|
|
||||||
/* IP address, if any */
|
/* IP address, if any */
|
||||||
struct in6_addr address;
|
struct in6_addr address;
|
||||||
|
|
||||||
|
/** Next-hop type information. */
|
||||||
|
enum nexthop_types_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ospf6_nexthop_is_set(x) \
|
static inline bool ospf6_nexthop_is_set(const struct ospf6_nexthop *nh)
|
||||||
((x)->ifindex || !IN6_IS_ADDR_UNSPECIFIED(&(x)->address))
|
{
|
||||||
#define ospf6_nexthop_is_same(a, b) \
|
return nh->type != 0;
|
||||||
((a)->ifindex == (b)->ifindex \
|
}
|
||||||
&& IN6_ARE_ADDR_EQUAL(&(a)->address, &(b)->address))
|
|
||||||
#define ospf6_nexthop_clear(x) \
|
static inline bool ospf6_nexthop_is_same(const struct ospf6_nexthop *nha,
|
||||||
do { \
|
const struct ospf6_nexthop *nhb)
|
||||||
(x)->ifindex = 0; \
|
{
|
||||||
memset(&(x)->address, 0, sizeof(struct in6_addr)); \
|
if (nha->type != nhb->type)
|
||||||
} while (0)
|
return false;
|
||||||
#define ospf6_nexthop_copy(a, b) \
|
|
||||||
do { \
|
switch (nha->type) {
|
||||||
(a)->ifindex = (b)->ifindex; \
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
memcpy(&(a)->address, &(b)->address, sizeof(struct in6_addr)); \
|
/* NOTHING */
|
||||||
} while (0)
|
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 */
|
/* Path */
|
||||||
struct ospf6_ls_origin {
|
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_merge_nexthops(struct list *dst, struct list *src);
|
||||||
extern void ospf6_add_nexthop(struct list *nh_list, int ifindex,
|
extern void ospf6_add_nexthop(struct list *nh_list, int ifindex,
|
||||||
struct in6_addr *addr);
|
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_num_nexthops(struct list *nh_list);
|
||||||
extern int ospf6_route_cmp_nexthops(struct ospf6_route *a,
|
extern int ospf6_route_cmp_nexthops(struct ospf6_route *a,
|
||||||
struct ospf6_route *b);
|
struct ospf6_route *b);
|
||||||
|
Loading…
Reference in New Issue
Block a user