mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 06:50:17 +00:00
isisd: unify isis_nexthop and isis_nexthop6 into a single struct
This unification allows us to write code that works for both IPv4 and IPv6, reducing duplication. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
9e1194c20c
commit
363be4dd90
@ -39,7 +39,6 @@ DEFINE_MTYPE(ISISD, ISIS_SPFTREE, "ISIS SPFtree")
|
||||
DEFINE_MTYPE(ISISD, ISIS_VERTEX, "ISIS vertex")
|
||||
DEFINE_MTYPE(ISISD, ISIS_ROUTE_INFO, "ISIS route info")
|
||||
DEFINE_MTYPE(ISISD, ISIS_NEXTHOP, "ISIS nexthop")
|
||||
DEFINE_MTYPE(ISISD, ISIS_NEXTHOP6, "ISIS nexthop6")
|
||||
DEFINE_MTYPE(ISISD, ISIS_DICT, "ISIS dictionary")
|
||||
DEFINE_MTYPE(ISISD, ISIS_DICT_NODE, "ISIS dictionary node")
|
||||
DEFINE_MTYPE(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route")
|
||||
|
@ -38,7 +38,6 @@ DECLARE_MTYPE(ISIS_SPFTREE)
|
||||
DECLARE_MTYPE(ISIS_VERTEX)
|
||||
DECLARE_MTYPE(ISIS_ROUTE_INFO)
|
||||
DECLARE_MTYPE(ISIS_NEXTHOP)
|
||||
DECLARE_MTYPE(ISIS_NEXTHOP6)
|
||||
DECLARE_MTYPE(ISIS_DICT)
|
||||
DECLARE_MTYPE(ISIS_DICT_NODE)
|
||||
DECLARE_MTYPE(ISIS_EXT_ROUTE)
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "linklist.h"
|
||||
#include "vty.h"
|
||||
#include "log.h"
|
||||
#include "lib_errors.h"
|
||||
#include "memory.h"
|
||||
#include "prefix.h"
|
||||
#include "hash.h"
|
||||
@ -48,17 +49,15 @@
|
||||
#include "isis_route.h"
|
||||
#include "isis_zebra.h"
|
||||
|
||||
static struct isis_nexthop *
|
||||
nexthoplookup(struct list *nexthops, struct in_addr *ip, ifindex_t ifindex);
|
||||
static struct isis_nexthop6 *
|
||||
nexthop6lookup(struct list *nexthops6, struct in6_addr *ip6, ifindex_t ifindex);
|
||||
static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
|
||||
union g_addr *ip, ifindex_t ifindex);
|
||||
|
||||
static struct isis_nexthop *isis_nexthop_create(struct in_addr *ip,
|
||||
static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
struct isis_nexthop *nexthop;
|
||||
|
||||
nexthop = nexthoplookup(isis->nexthops, ip, ifindex);
|
||||
nexthop = nexthoplookup(isis->nexthops, family, ip, ifindex);
|
||||
if (nexthop) {
|
||||
nexthop->lock++;
|
||||
return nexthop;
|
||||
@ -66,8 +65,9 @@ static struct isis_nexthop *isis_nexthop_create(struct in_addr *ip,
|
||||
|
||||
nexthop = XCALLOC(MTYPE_ISIS_NEXTHOP, sizeof(struct isis_nexthop));
|
||||
|
||||
nexthop->family = family;
|
||||
nexthop->ifindex = ifindex;
|
||||
memcpy(&nexthop->ip, ip, sizeof(struct in_addr));
|
||||
nexthop->ip = *ip;
|
||||
listnode_add(isis->nexthops, nexthop);
|
||||
nexthop->lock++;
|
||||
|
||||
@ -85,107 +85,79 @@ static void isis_nexthop_delete(struct isis_nexthop *nexthop)
|
||||
return;
|
||||
}
|
||||
|
||||
static struct isis_nexthop *nexthoplookup(struct list *nexthops,
|
||||
struct in_addr *ip, ifindex_t ifindex)
|
||||
static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
|
||||
union g_addr *ip, ifindex_t ifindex)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct isis_nexthop *nh;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(nexthops, node, nh)) {
|
||||
if (!(memcmp(ip, &nh->ip, sizeof(struct in_addr)))
|
||||
&& ifindex == nh->ifindex)
|
||||
return nh;
|
||||
if (nh->family != family)
|
||||
continue;
|
||||
if (nh->ifindex != ifindex)
|
||||
continue;
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
if (IPV4_ADDR_CMP(&nh->ip.ipv4, &ip->ipv4))
|
||||
continue;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (IPV6_ADDR_CMP(&nh->ip.ipv6, &ip->ipv6))
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
flog_err(EC_LIB_DEVELOPMENT,
|
||||
"%s: unknown address family [%d]", __func__,
|
||||
family);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return nh;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct isis_nexthop6 *isis_nexthop6_new(struct in6_addr *ip6,
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
struct isis_nexthop6 *nexthop6;
|
||||
|
||||
nexthop6 = XCALLOC(MTYPE_ISIS_NEXTHOP6, sizeof(struct isis_nexthop6));
|
||||
|
||||
nexthop6->ifindex = ifindex;
|
||||
memcpy(&nexthop6->ip6, ip6, sizeof(struct in6_addr));
|
||||
nexthop6->lock++;
|
||||
|
||||
return nexthop6;
|
||||
}
|
||||
|
||||
static struct isis_nexthop6 *isis_nexthop6_create(struct in6_addr *ip6,
|
||||
ifindex_t ifindex)
|
||||
{
|
||||
struct isis_nexthop6 *nexthop6;
|
||||
|
||||
nexthop6 = nexthop6lookup(isis->nexthops6, ip6, ifindex);
|
||||
if (nexthop6) {
|
||||
nexthop6->lock++;
|
||||
return nexthop6;
|
||||
}
|
||||
|
||||
nexthop6 = isis_nexthop6_new(ip6, ifindex);
|
||||
|
||||
return nexthop6;
|
||||
}
|
||||
|
||||
static void isis_nexthop6_delete(struct isis_nexthop6 *nexthop6)
|
||||
{
|
||||
|
||||
nexthop6->lock--;
|
||||
if (nexthop6->lock == 0) {
|
||||
listnode_delete(isis->nexthops6, nexthop6);
|
||||
XFREE(MTYPE_ISIS_NEXTHOP6, nexthop6);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct isis_nexthop6 *
|
||||
nexthop6lookup(struct list *nexthops6, struct in6_addr *ip6, ifindex_t ifindex)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct isis_nexthop6 *nh6;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(nexthops6, node, nh6)) {
|
||||
if (!(memcmp(ip6, &nh6->ip6, sizeof(struct in6_addr)))
|
||||
&& ifindex == nh6->ifindex)
|
||||
return nh6;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj)
|
||||
static void adjinfo2nexthop(int family, struct list *nexthops,
|
||||
struct isis_adjacency *adj)
|
||||
{
|
||||
struct isis_nexthop *nh;
|
||||
union g_addr ip = {};
|
||||
|
||||
for (unsigned int i = 0; i < adj->ipv4_address_count; i++) {
|
||||
struct in_addr *ipv4_addr = &adj->ipv4_addresses[i];
|
||||
if (!nexthoplookup(nexthops, ipv4_addr,
|
||||
adj->circuit->interface->ifindex)) {
|
||||
nh = isis_nexthop_create(
|
||||
ipv4_addr, adj->circuit->interface->ifindex);
|
||||
listnode_add(nexthops, nh);
|
||||
return;
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
for (unsigned int i = 0; i < adj->ipv4_address_count; i++) {
|
||||
ip.ipv4 = adj->ipv4_addresses[i];
|
||||
|
||||
if (!nexthoplookup(nexthops, AF_INET, &ip,
|
||||
adj->circuit->interface->ifindex)) {
|
||||
nh = isis_nexthop_create(
|
||||
AF_INET, &ip,
|
||||
adj->circuit->interface->ifindex);
|
||||
listnode_add(nexthops, nh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
|
||||
ip.ipv6 = adj->ipv6_addresses[i];
|
||||
|
||||
static void adjinfo2nexthop6(struct list *nexthops6, struct isis_adjacency *adj)
|
||||
{
|
||||
struct isis_nexthop6 *nh6;
|
||||
|
||||
for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
|
||||
struct in6_addr *ipv6_addr = &adj->ipv6_addresses[i];
|
||||
if (!nexthop6lookup(nexthops6, ipv6_addr,
|
||||
adj->circuit->interface->ifindex)) {
|
||||
nh6 = isis_nexthop6_create(
|
||||
ipv6_addr, adj->circuit->interface->ifindex);
|
||||
listnode_add(nexthops6, nh6);
|
||||
return;
|
||||
if (!nexthoplookup(nexthops, AF_INET6, &ip,
|
||||
adj->circuit->interface->ifindex)) {
|
||||
nh = isis_nexthop_create(
|
||||
AF_INET6, &ip,
|
||||
adj->circuit->interface->ifindex);
|
||||
listnode_add(nexthops, nh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
flog_err(EC_LIB_DEVELOPMENT, "%s: unknown address family [%d]",
|
||||
__func__, family);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,35 +173,32 @@ static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
|
||||
|
||||
rinfo = XCALLOC(MTYPE_ISIS_ROUTE_INFO, sizeof(struct isis_route_info));
|
||||
|
||||
if (prefix->family == AF_INET) {
|
||||
rinfo->nexthops = list_new();
|
||||
for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) {
|
||||
/* check for force resync this route */
|
||||
if (CHECK_FLAG(adj->circuit->flags,
|
||||
ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
|
||||
SET_FLAG(rinfo->flag,
|
||||
ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
/* update neighbor router address */
|
||||
rinfo->nexthops = list_new();
|
||||
for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) {
|
||||
/* check for force resync this route */
|
||||
if (CHECK_FLAG(adj->circuit->flags,
|
||||
ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
|
||||
SET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
|
||||
/* update neighbor router address */
|
||||
switch (prefix->family) {
|
||||
case AF_INET:
|
||||
if (depth == 2 && prefix->prefixlen == 32)
|
||||
adj->router_address = prefix->u.prefix4;
|
||||
adjinfo2nexthop(rinfo->nexthops, adj);
|
||||
}
|
||||
}
|
||||
if (prefix->family == AF_INET6) {
|
||||
rinfo->nexthops6 = list_new();
|
||||
for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) {
|
||||
/* check for force resync this route */
|
||||
if (CHECK_FLAG(adj->circuit->flags,
|
||||
ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
|
||||
SET_FLAG(rinfo->flag,
|
||||
ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
/* update neighbor router address */
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (depth == 2 && prefix->prefixlen == 128
|
||||
&& (!src_p || !src_p->prefixlen)) {
|
||||
adj->router_address6 = prefix->u.prefix6;
|
||||
}
|
||||
adjinfo2nexthop6(rinfo->nexthops6, adj);
|
||||
break;
|
||||
default:
|
||||
flog_err(EC_LIB_DEVELOPMENT,
|
||||
"%s: unknown address family [%d]", __func__,
|
||||
prefix->family);
|
||||
exit(1);
|
||||
}
|
||||
adjinfo2nexthop(prefix->family, rinfo->nexthops, adj);
|
||||
}
|
||||
|
||||
rinfo->cost = cost;
|
||||
@ -246,12 +215,6 @@ static void isis_route_info_delete(struct isis_route_info *route_info)
|
||||
list_delete(&route_info->nexthops);
|
||||
}
|
||||
|
||||
if (route_info->nexthops6) {
|
||||
route_info->nexthops6->del =
|
||||
(void (*)(void *))isis_nexthop6_delete;
|
||||
list_delete(&route_info->nexthops6);
|
||||
}
|
||||
|
||||
XFREE(MTYPE_ISIS_ROUTE_INFO, route_info);
|
||||
}
|
||||
|
||||
@ -271,7 +234,6 @@ static int isis_route_info_same(struct isis_route_info *new,
|
||||
{
|
||||
struct listnode *node;
|
||||
struct isis_nexthop *nexthop;
|
||||
struct isis_nexthop6 *nexthop6;
|
||||
|
||||
if (!CHECK_FLAG(old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
|
||||
return 0;
|
||||
@ -282,31 +244,15 @@ static int isis_route_info_same(struct isis_route_info *new,
|
||||
if (!isis_route_info_same_attrib(new, old))
|
||||
return 0;
|
||||
|
||||
if (family == AF_INET) {
|
||||
for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, nexthop))
|
||||
if (nexthoplookup(old->nexthops, &nexthop->ip,
|
||||
nexthop->ifindex)
|
||||
== NULL)
|
||||
return 0;
|
||||
for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, nexthop))
|
||||
if (!nexthoplookup(old->nexthops, nexthop->family, &nexthop->ip,
|
||||
nexthop->ifindex))
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(old->nexthops, node, nexthop))
|
||||
if (nexthoplookup(new->nexthops, &nexthop->ip,
|
||||
nexthop->ifindex)
|
||||
== NULL)
|
||||
return 0;
|
||||
} else if (family == AF_INET6) {
|
||||
for (ALL_LIST_ELEMENTS_RO(new->nexthops6, node, nexthop6))
|
||||
if (nexthop6lookup(old->nexthops6, &nexthop6->ip6,
|
||||
nexthop6->ifindex)
|
||||
== 0)
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(old->nexthops6, node, nexthop6))
|
||||
if (nexthop6lookup(new->nexthops6, &nexthop6->ip6,
|
||||
nexthop6->ifindex)
|
||||
== 0)
|
||||
return 0;
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS_RO(old->nexthops, node, nexthop))
|
||||
if (!nexthoplookup(new->nexthops, nexthop->family, &nexthop->ip,
|
||||
nexthop->ifindex))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -25,15 +25,12 @@
|
||||
#ifndef _ZEBRA_ISIS_ROUTE_H
|
||||
#define _ZEBRA_ISIS_ROUTE_H
|
||||
|
||||
struct isis_nexthop6 {
|
||||
ifindex_t ifindex;
|
||||
struct in6_addr ip6;
|
||||
unsigned int lock;
|
||||
};
|
||||
#include "lib/nexthop.h"
|
||||
|
||||
struct isis_nexthop {
|
||||
ifindex_t ifindex;
|
||||
struct in_addr ip;
|
||||
int family;
|
||||
union g_addr ip;
|
||||
unsigned int lock;
|
||||
};
|
||||
|
||||
@ -45,7 +42,6 @@ struct isis_route_info {
|
||||
uint32_t cost;
|
||||
uint32_t depth;
|
||||
struct list *nexthops;
|
||||
struct list *nexthops6;
|
||||
};
|
||||
|
||||
struct isis_route_info *isis_route_create(struct prefix *prefix,
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "log.h"
|
||||
#include "lib_errors.h"
|
||||
#include "if.h"
|
||||
#include "network.h"
|
||||
#include "prefix.h"
|
||||
@ -225,7 +226,6 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
||||
struct zapi_route api;
|
||||
struct zapi_nexthop *api_nh;
|
||||
struct isis_nexthop *nexthop;
|
||||
struct isis_nexthop6 *nexthop6;
|
||||
struct listnode *node;
|
||||
int count = 0;
|
||||
|
||||
@ -250,47 +250,41 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
||||
#endif
|
||||
|
||||
/* Nexthops */
|
||||
switch (prefix->family) {
|
||||
case AF_INET:
|
||||
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
|
||||
nexthop)) {
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
if (fabricd)
|
||||
api_nh->onlink = true;
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) {
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
api_nh = &api.nexthops[count];
|
||||
if (fabricd)
|
||||
api_nh->onlink = true;
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
|
||||
switch (nexthop->family) {
|
||||
case AF_INET:
|
||||
/* FIXME: can it be ? */
|
||||
if (nexthop->ip.s_addr != INADDR_ANY) {
|
||||
if (nexthop->ip.ipv4.s_addr != INADDR_ANY) {
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
api_nh->gate.ipv4 = nexthop->ip;
|
||||
api_nh->gate.ipv4 = nexthop->ip.ipv4;
|
||||
} else {
|
||||
api_nh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
}
|
||||
api_nh->ifindex = nexthop->ifindex;
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
|
||||
nexthop6)) {
|
||||
if (count >= MULTIPATH_NUM)
|
||||
break;
|
||||
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
|
||||
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop->ip.ipv6)
|
||||
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop->ip.ipv6)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
api_nh = &api.nexthops[count];
|
||||
if (fabricd)
|
||||
api_nh->onlink = true;
|
||||
api_nh->vrf_id = VRF_DEFAULT;
|
||||
api_nh->gate.ipv6 = nexthop6->ip6;
|
||||
api_nh->ifindex = nexthop6->ifindex;
|
||||
api_nh->gate.ipv6 = nexthop->ip.ipv6;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
count++;
|
||||
break;
|
||||
default:
|
||||
flog_err(EC_LIB_DEVELOPMENT,
|
||||
"%s: unknown address family [%d]", __func__,
|
||||
nexthop->family);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
api_nh->ifindex = nexthop->ifindex;
|
||||
count++;
|
||||
}
|
||||
if (!count)
|
||||
return;
|
||||
|
@ -88,7 +88,6 @@ void isis_new(unsigned long process_id)
|
||||
isis->init_circ_list = list_new();
|
||||
isis->uptime = time(NULL);
|
||||
isis->nexthops = list_new();
|
||||
isis->nexthops6 = list_new();
|
||||
dyn_cache_init();
|
||||
/*
|
||||
* uncomment the next line for full debugs
|
||||
|
@ -69,8 +69,7 @@ struct isis {
|
||||
uint32_t router_id; /* Router ID from zebra */
|
||||
struct list *area_list; /* list of IS-IS areas */
|
||||
struct list *init_circ_list;
|
||||
struct list *nexthops; /* IPv4 next hops from this IS */
|
||||
struct list *nexthops6; /* IPv6 next hops from this IS */
|
||||
struct list *nexthops; /* IP next hops from this IS */
|
||||
uint8_t max_area_addrs; /* maximumAreaAdresses */
|
||||
struct area_addr *man_area_addrs; /* manualAreaAddresses */
|
||||
uint32_t debugs; /* bitmap for debug */
|
||||
|
Loading…
Reference in New Issue
Block a user