diff options
Diffstat (limited to 'isisd/isis_route.c')
| -rw-r--r-- | isisd/isis_route.c | 249 |
1 files changed, 93 insertions, 156 deletions
diff --git a/isisd/isis_route.c b/isisd/isis_route.c index 281eaf11bc..636a63e290 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -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,26 +49,25 @@ #include "isis_route.h" #include "isis_zebra.h" -static struct isis_nexthop *isis_nexthop_create(struct in_addr *ip, +static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family, + union g_addr *ip, ifindex_t ifindex); + +static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip, ifindex_t ifindex) { - struct listnode *node; struct isis_nexthop *nexthop; - for (ALL_LIST_ELEMENTS_RO(isis->nexthops, node, nexthop)) { - if (nexthop->ifindex != ifindex) - continue; - if (ip && memcmp(&nexthop->ip, ip, sizeof(struct in_addr)) != 0) - continue; - + nexthop = nexthoplookup(isis->nexthops, family, ip, ifindex); + if (nexthop) { nexthop->lock++; return nexthop; } 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,116 +85,79 @@ static void isis_nexthop_delete(struct isis_nexthop *nexthop) return; } -static int 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 1; - } - - return 0; -} - -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 listnode *node; - struct isis_nexthop6 *nexthop6; - - for (ALL_LIST_ELEMENTS_RO(isis->nexthops6, node, nexthop6)) { - if (nexthop6->ifindex != ifindex) + if (nh->family != family) continue; - if (ip6 - && memcmp(&nexthop6->ip6, ip6, sizeof(struct in6_addr)) - != 0) + if (nh->ifindex != ifindex) continue; - 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 int nexthop6lookup(struct list *nexthops6, struct in6_addr *ip6, - ifindex_t ifindex) -{ - struct listnode *node; - struct isis_nexthop6 *nh6; + 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); + } - for (ALL_LIST_ELEMENTS_RO(nexthops6, node, nh6)) { - if (!(memcmp(ip6, &nh6->ip6, sizeof(struct in6_addr))) - && ifindex == nh6->ifindex) - return 1; + return nh; } - return 0; + 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; - - 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); - nh->router_address = adj->router_address; - listnode_add(nexthops, nh); - return; + union g_addr ip = {}; + + 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; + } } - } -} - -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); - nh6->router_address6 = adj->router_address6; - listnode_add(nexthops6, nh6); - return; + break; + case AF_INET6: + for (unsigned int i = 0; i < adj->ipv6_address_count; i++) { + ip.ipv6 = adj->ipv6_addresses[i]; + + 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); } } @@ -210,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; @@ -255,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); } @@ -280,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; @@ -291,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) - == 0) - return 0; - - for (ALL_LIST_ELEMENTS_RO(old->nexthops, node, nexthop)) - if (nexthoplookup(new->nexthops, &nexthop->ip, - nexthop->ifindex) - == 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; - } + 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->family, &nexthop->ip, + nexthop->ifindex)) + return 0; return 1; } |
