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:
Renato Westphal 2019-08-06 17:43:46 -03:00
parent 9e1194c20c
commit 363be4dd90
7 changed files with 122 additions and 190 deletions

View File

@ -39,7 +39,6 @@ DEFINE_MTYPE(ISISD, ISIS_SPFTREE, "ISIS SPFtree")
DEFINE_MTYPE(ISISD, ISIS_VERTEX, "ISIS vertex") DEFINE_MTYPE(ISISD, ISIS_VERTEX, "ISIS vertex")
DEFINE_MTYPE(ISISD, ISIS_ROUTE_INFO, "ISIS route info") DEFINE_MTYPE(ISISD, ISIS_ROUTE_INFO, "ISIS route info")
DEFINE_MTYPE(ISISD, ISIS_NEXTHOP, "ISIS nexthop") 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, "ISIS dictionary")
DEFINE_MTYPE(ISISD, ISIS_DICT_NODE, "ISIS dictionary node") DEFINE_MTYPE(ISISD, ISIS_DICT_NODE, "ISIS dictionary node")
DEFINE_MTYPE(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route") DEFINE_MTYPE(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route")

View File

@ -38,7 +38,6 @@ DECLARE_MTYPE(ISIS_SPFTREE)
DECLARE_MTYPE(ISIS_VERTEX) DECLARE_MTYPE(ISIS_VERTEX)
DECLARE_MTYPE(ISIS_ROUTE_INFO) DECLARE_MTYPE(ISIS_ROUTE_INFO)
DECLARE_MTYPE(ISIS_NEXTHOP) DECLARE_MTYPE(ISIS_NEXTHOP)
DECLARE_MTYPE(ISIS_NEXTHOP6)
DECLARE_MTYPE(ISIS_DICT) DECLARE_MTYPE(ISIS_DICT)
DECLARE_MTYPE(ISIS_DICT_NODE) DECLARE_MTYPE(ISIS_DICT_NODE)
DECLARE_MTYPE(ISIS_EXT_ROUTE) DECLARE_MTYPE(ISIS_EXT_ROUTE)

View File

@ -28,6 +28,7 @@
#include "linklist.h" #include "linklist.h"
#include "vty.h" #include "vty.h"
#include "log.h" #include "log.h"
#include "lib_errors.h"
#include "memory.h" #include "memory.h"
#include "prefix.h" #include "prefix.h"
#include "hash.h" #include "hash.h"
@ -48,17 +49,15 @@
#include "isis_route.h" #include "isis_route.h"
#include "isis_zebra.h" #include "isis_zebra.h"
static struct isis_nexthop * static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
nexthoplookup(struct list *nexthops, struct in_addr *ip, ifindex_t ifindex); union g_addr *ip, ifindex_t ifindex);
static struct isis_nexthop6 *
nexthop6lookup(struct list *nexthops6, struct in6_addr *ip6, 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) ifindex_t ifindex)
{ {
struct isis_nexthop *nexthop; struct isis_nexthop *nexthop;
nexthop = nexthoplookup(isis->nexthops, ip, ifindex); nexthop = nexthoplookup(isis->nexthops, family, ip, ifindex);
if (nexthop) { if (nexthop) {
nexthop->lock++; nexthop->lock++;
return nexthop; 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 = XCALLOC(MTYPE_ISIS_NEXTHOP, sizeof(struct isis_nexthop));
nexthop->family = family;
nexthop->ifindex = ifindex; nexthop->ifindex = ifindex;
memcpy(&nexthop->ip, ip, sizeof(struct in_addr)); nexthop->ip = *ip;
listnode_add(isis->nexthops, nexthop); listnode_add(isis->nexthops, nexthop);
nexthop->lock++; nexthop->lock++;
@ -85,108 +85,80 @@ static void isis_nexthop_delete(struct isis_nexthop *nexthop)
return; return;
} }
static struct isis_nexthop *nexthoplookup(struct list *nexthops, static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
struct in_addr *ip, ifindex_t ifindex) union g_addr *ip, ifindex_t ifindex)
{ {
struct listnode *node; struct listnode *node;
struct isis_nexthop *nh; struct isis_nexthop *nh;
for (ALL_LIST_ELEMENTS_RO(nexthops, node, nh)) { for (ALL_LIST_ELEMENTS_RO(nexthops, node, nh)) {
if (!(memcmp(ip, &nh->ip, sizeof(struct in_addr))) if (nh->family != family)
&& ifindex == nh->ifindex) 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 nh;
} }
return NULL; return NULL;
} }
static struct isis_nexthop6 *isis_nexthop6_new(struct in6_addr *ip6, static void adjinfo2nexthop(int family, struct list *nexthops,
ifindex_t ifindex) struct isis_adjacency *adj)
{
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)
{ {
struct isis_nexthop *nh; struct isis_nexthop *nh;
union g_addr ip = {};
switch (family) {
case AF_INET:
for (unsigned int i = 0; i < adj->ipv4_address_count; i++) { for (unsigned int i = 0; i < adj->ipv4_address_count; i++) {
struct in_addr *ipv4_addr = &adj->ipv4_addresses[i]; ip.ipv4 = adj->ipv4_addresses[i];
if (!nexthoplookup(nexthops, ipv4_addr,
if (!nexthoplookup(nexthops, AF_INET, &ip,
adj->circuit->interface->ifindex)) { adj->circuit->interface->ifindex)) {
nh = isis_nexthop_create( nh = isis_nexthop_create(
ipv4_addr, adj->circuit->interface->ifindex); AF_INET, &ip,
adj->circuit->interface->ifindex);
listnode_add(nexthops, nh); listnode_add(nexthops, nh);
return; break;
} }
} }
} break;
case AF_INET6:
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++) { for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
struct in6_addr *ipv6_addr = &adj->ipv6_addresses[i]; ip.ipv6 = adj->ipv6_addresses[i];
if (!nexthop6lookup(nexthops6, ipv6_addr,
if (!nexthoplookup(nexthops, AF_INET6, &ip,
adj->circuit->interface->ifindex)) { adj->circuit->interface->ifindex)) {
nh6 = isis_nexthop6_create( nh = isis_nexthop_create(
ipv6_addr, adj->circuit->interface->ifindex); AF_INET6, &ip,
listnode_add(nexthops6, nh6); adj->circuit->interface->ifindex);
return; listnode_add(nexthops, nh);
break;
} }
} }
break;
default:
flog_err(EC_LIB_DEVELOPMENT, "%s: unknown address family [%d]",
__func__, family);
exit(1);
}
} }
static struct isis_route_info *isis_route_info_new(struct prefix *prefix, static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
@ -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)); rinfo = XCALLOC(MTYPE_ISIS_ROUTE_INFO, sizeof(struct isis_route_info));
if (prefix->family == AF_INET) {
rinfo->nexthops = list_new(); rinfo->nexthops = list_new();
for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) { for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) {
/* check for force resync this route */ /* check for force resync this route */
if (CHECK_FLAG(adj->circuit->flags, if (CHECK_FLAG(adj->circuit->flags,
ISIS_CIRCUIT_FLAPPED_AFTER_SPF)) ISIS_CIRCUIT_FLAPPED_AFTER_SPF))
SET_FLAG(rinfo->flag, SET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
/* update neighbor router address */ /* update neighbor router address */
switch (prefix->family) {
case AF_INET:
if (depth == 2 && prefix->prefixlen == 32) if (depth == 2 && prefix->prefixlen == 32)
adj->router_address = prefix->u.prefix4; adj->router_address = prefix->u.prefix4;
adjinfo2nexthop(rinfo->nexthops, adj); break;
} case AF_INET6:
}
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 */
if (depth == 2 && prefix->prefixlen == 128 if (depth == 2 && prefix->prefixlen == 128
&& (!src_p || !src_p->prefixlen)) { && (!src_p || !src_p->prefixlen)) {
adj->router_address6 = prefix->u.prefix6; 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; rinfo->cost = cost;
@ -246,12 +215,6 @@ static void isis_route_info_delete(struct isis_route_info *route_info)
list_delete(&route_info->nexthops); 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); 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 listnode *node;
struct isis_nexthop *nexthop; struct isis_nexthop *nexthop;
struct isis_nexthop6 *nexthop6;
if (!CHECK_FLAG(old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) if (!CHECK_FLAG(old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return 0; 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)) if (!isis_route_info_same_attrib(new, old))
return 0; return 0;
if (family == AF_INET) {
for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, nexthop)) for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, nexthop))
if (nexthoplookup(old->nexthops, &nexthop->ip, if (!nexthoplookup(old->nexthops, nexthop->family, &nexthop->ip,
nexthop->ifindex) nexthop->ifindex))
== NULL)
return 0; return 0;
for (ALL_LIST_ELEMENTS_RO(old->nexthops, node, nexthop)) for (ALL_LIST_ELEMENTS_RO(old->nexthops, node, nexthop))
if (nexthoplookup(new->nexthops, &nexthop->ip, if (!nexthoplookup(new->nexthops, nexthop->family, &nexthop->ip,
nexthop->ifindex) nexthop->ifindex))
== NULL)
return 0; 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;
}
return 1; return 1;
} }

View File

@ -25,15 +25,12 @@
#ifndef _ZEBRA_ISIS_ROUTE_H #ifndef _ZEBRA_ISIS_ROUTE_H
#define _ZEBRA_ISIS_ROUTE_H #define _ZEBRA_ISIS_ROUTE_H
struct isis_nexthop6 { #include "lib/nexthop.h"
ifindex_t ifindex;
struct in6_addr ip6;
unsigned int lock;
};
struct isis_nexthop { struct isis_nexthop {
ifindex_t ifindex; ifindex_t ifindex;
struct in_addr ip; int family;
union g_addr ip;
unsigned int lock; unsigned int lock;
}; };
@ -45,7 +42,6 @@ struct isis_route_info {
uint32_t cost; uint32_t cost;
uint32_t depth; uint32_t depth;
struct list *nexthops; struct list *nexthops;
struct list *nexthops6;
}; };
struct isis_route_info *isis_route_create(struct prefix *prefix, struct isis_route_info *isis_route_create(struct prefix *prefix,

View File

@ -27,6 +27,7 @@
#include "command.h" #include "command.h"
#include "memory.h" #include "memory.h"
#include "log.h" #include "log.h"
#include "lib_errors.h"
#include "if.h" #include "if.h"
#include "network.h" #include "network.h"
#include "prefix.h" #include "prefix.h"
@ -225,7 +226,6 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
struct zapi_route api; struct zapi_route api;
struct zapi_nexthop *api_nh; struct zapi_nexthop *api_nh;
struct isis_nexthop *nexthop; struct isis_nexthop *nexthop;
struct isis_nexthop6 *nexthop6;
struct listnode *node; struct listnode *node;
int count = 0; int count = 0;
@ -250,47 +250,41 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
#endif #endif
/* Nexthops */ /* Nexthops */
switch (prefix->family) { for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) {
case AF_INET:
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
nexthop)) {
if (count >= MULTIPATH_NUM) if (count >= MULTIPATH_NUM)
break; break;
api_nh = &api.nexthops[count]; api_nh = &api.nexthops[count];
if (fabricd) if (fabricd)
api_nh->onlink = true; api_nh->onlink = true;
api_nh->vrf_id = VRF_DEFAULT; api_nh->vrf_id = VRF_DEFAULT;
switch (nexthop->family) {
case AF_INET:
/* FIXME: can it be ? */ /* 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->type = NEXTHOP_TYPE_IPV4_IFINDEX;
api_nh->gate.ipv4 = nexthop->ip; api_nh->gate.ipv4 = nexthop->ip.ipv4;
} else { } else {
api_nh->type = NEXTHOP_TYPE_IFINDEX; api_nh->type = NEXTHOP_TYPE_IFINDEX;
} }
api_nh->ifindex = nexthop->ifindex;
count++;
}
break; break;
case AF_INET6: case AF_INET6:
for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, if (!IN6_IS_ADDR_LINKLOCAL(&nexthop->ip.ipv6)
nexthop6)) { && !IN6_IS_ADDR_UNSPECIFIED(&nexthop->ip.ipv6)) {
if (count >= MULTIPATH_NUM)
break;
if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
&& !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
continue; continue;
} }
api_nh->gate.ipv6 = nexthop->ip.ipv6;
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->type = NEXTHOP_TYPE_IPV6_IFINDEX; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
count++;
}
break; break;
default:
flog_err(EC_LIB_DEVELOPMENT,
"%s: unknown address family [%d]", __func__,
nexthop->family);
exit(1);
}
api_nh->ifindex = nexthop->ifindex;
count++;
} }
if (!count) if (!count)
return; return;

View File

@ -88,7 +88,6 @@ void isis_new(unsigned long process_id)
isis->init_circ_list = list_new(); isis->init_circ_list = list_new();
isis->uptime = time(NULL); isis->uptime = time(NULL);
isis->nexthops = list_new(); isis->nexthops = list_new();
isis->nexthops6 = list_new();
dyn_cache_init(); dyn_cache_init();
/* /*
* uncomment the next line for full debugs * uncomment the next line for full debugs

View File

@ -69,8 +69,7 @@ struct isis {
uint32_t router_id; /* Router ID from zebra */ uint32_t router_id; /* Router ID from zebra */
struct list *area_list; /* list of IS-IS areas */ struct list *area_list; /* list of IS-IS areas */
struct list *init_circ_list; struct list *init_circ_list;
struct list *nexthops; /* IPv4 next hops from this IS */ struct list *nexthops; /* IP next hops from this IS */
struct list *nexthops6; /* IPv6 next hops from this IS */
uint8_t max_area_addrs; /* maximumAreaAdresses */ uint8_t max_area_addrs; /* maximumAreaAdresses */
struct area_addr *man_area_addrs; /* manualAreaAddresses */ struct area_addr *man_area_addrs; /* manualAreaAddresses */
uint32_t debugs; /* bitmap for debug */ uint32_t debugs; /* bitmap for debug */