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_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")

View File

@ -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)

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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 */