diff --git a/isisd/isis_route.c b/isisd/isis_route.c index 9eb258a1eb..2257ccd57b 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -33,6 +33,7 @@ #include "hash.h" #include "if.h" #include "table.h" +#include "srcdest_table.h" #include "isis_constants.h" #include "isis_common.h" @@ -199,6 +200,7 @@ static void adjinfo2nexthop6(struct list *nexthops6, struct isis_adjacency *adj) } static struct isis_route_info *isis_route_info_new(struct prefix *prefix, + struct prefix_ipv6 *src_p, uint32_t cost, uint32_t depth, struct list *adjacencies) @@ -232,8 +234,10 @@ static struct isis_route_info *isis_route_info_new(struct prefix *prefix, 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)) { adj->router_address6 = prefix->u.prefix6; + } adjinfo2nexthop6(rinfo->nexthops6, adj); } } @@ -317,7 +321,9 @@ static int isis_route_info_same(struct isis_route_info *new, return 1; } -struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost, +struct isis_route_info *isis_route_create(struct prefix *prefix, + struct prefix_ipv6 *src_p, + uint32_t cost, uint32_t depth, struct list *adjacencies, struct isis_area *area, @@ -335,8 +341,9 @@ struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost, if (!table) return NULL; - rinfo_new = isis_route_info_new(prefix, cost, depth, adjacencies); - route_node = route_node_get(table, prefix); + rinfo_new = isis_route_info_new(prefix, src_p, cost, + depth, adjacencies); + route_node = srcdest_rnode_get(table, prefix, src_p); rinfo_old = route_node->info; if (!rinfo_old) { @@ -372,17 +379,18 @@ struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost, return route_info; } -static void isis_route_delete(struct prefix *prefix, struct route_table *table) +static void isis_route_delete(struct prefix *prefix, + struct prefix_ipv6 *src_p, + struct route_table *table) { struct route_node *rode; struct isis_route_info *rinfo; - char buff[PREFIX2STR_BUFFER]; + char buff[SRCDEST2STR_BUFFER]; /* for log */ - prefix2str(prefix, buff, sizeof(buff)); + srcdest2str(prefix, src_p, buff, sizeof(buff)); - - rode = route_node_get(table, prefix); + rode = srcdest_rnode_get(table, prefix, src_p); rinfo = rode->info; if (rinfo == NULL) { @@ -397,7 +405,7 @@ static void isis_route_delete(struct prefix *prefix, struct route_table *table) UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE); if (isis->debugs & DEBUG_RTE_EVENTS) zlog_debug("ISIS-Rte: route delete %s", buff); - isis_zebra_route_update(prefix, rinfo); + isis_zebra_route_update(prefix, src_p, rinfo); } isis_route_info_delete(rinfo); rode->info = NULL; @@ -411,15 +419,23 @@ static void _isis_route_verify_table(struct isis_area *area, { struct route_node *rnode, *drnode; struct isis_route_info *rinfo; - char buff[PREFIX2STR_BUFFER]; + char buff[SRCDEST2STR_BUFFER]; - for (rnode = route_top(table); rnode; rnode = route_next(rnode)) { + for (rnode = route_top(table); rnode; + rnode = srcdest_route_next(rnode)) { if (rnode->info == NULL) continue; rinfo = rnode->info; + struct prefix *dst_p; + struct prefix_ipv6 *src_p; + + srcdest_rnode_prefixes(rnode, + (const struct prefix **)&dst_p, + (const struct prefix **)&src_p); + if (isis->debugs & DEBUG_RTE_EVENTS) { - prefix2str(&rnode->p, buff, sizeof(buff)); + srcdest2str(dst_p, src_p, buff, sizeof(buff)); zlog_debug( "ISIS-Rte (%s): route validate: %s %s %s %s", area->area_tag, @@ -437,13 +453,13 @@ static void _isis_route_verify_table(struct isis_area *area, buff); } - isis_zebra_route_update(&rnode->p, rinfo); + isis_zebra_route_update(dst_p, src_p, rinfo); if (!CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) { /* Area is either L1 or L2 => we use level route tables * directly for * validating => no problems with deleting routes. */ if (!tables) { - isis_route_delete(&rnode->p, table); + isis_route_delete(dst_p, src_p, table); continue; } @@ -452,12 +468,13 @@ static void _isis_route_verify_table(struct isis_area *area, * delete node from level tables as well before deleting * route info. */ for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { - drnode = route_node_get(tables[level - 1], &rnode->p); + drnode = srcdest_rnode_get(tables[level - 1], + dst_p, src_p); if (drnode->info == rnode->info) drnode->info = NULL; } - isis_route_delete(&rnode->p, table); + isis_route_delete(dst_p, src_p, table); } } } @@ -485,16 +502,22 @@ void isis_route_verify_merge(struct isis_area *area, struct route_table *merge; struct route_node *rnode, *mrnode; - merge = route_table_init(); + merge = srcdest_table_init(); for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { for (rnode = route_top(tables[level - 1]); rnode; - rnode = route_next(rnode)) { + rnode = srcdest_route_next(rnode)) { struct isis_route_info *rinfo = rnode->info; if (!rinfo) continue; - mrnode = route_node_get(merge, &rnode->p); + struct prefix *prefix; + struct prefix_ipv6 *src_p; + + srcdest_rnode_prefixes(rnode, + (const struct prefix **)&prefix, + (const struct prefix **)&src_p); + mrnode = srcdest_rnode_get(merge, prefix, src_p); struct isis_route_info *mrinfo = mrnode->info; if (mrinfo) { route_unlock_node(mrnode); @@ -535,7 +558,7 @@ void isis_route_invalidate_table(struct isis_area *area, { struct route_node *rode; struct isis_route_info *rinfo; - for (rode = route_top(table); rode; rode = route_next(rode)) { + for (rode = route_top(table); rode; rode = srcdest_route_next(rode)) { if (rode->info == NULL) continue; rinfo = rode->info; diff --git a/isisd/isis_route.h b/isisd/isis_route.h index ae4b855cc7..9d6858586b 100644 --- a/isisd/isis_route.h +++ b/isisd/isis_route.h @@ -50,7 +50,9 @@ struct isis_route_info { struct list *nexthops6; }; -struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost, +struct isis_route_info *isis_route_create(struct prefix *prefix, + struct prefix_ipv6 *src_p, + uint32_t cost, uint32_t depth, struct list *adjacencies, struct isis_area *area, diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index fe5623ae5a..0a8b0e927e 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -37,6 +37,7 @@ #include "spf_backoff.h" #include "jhash.h" #include "skiplist.h" +#include "srcdest_table.h" #include "isis_constants.h" #include "isis_common.h" @@ -74,12 +75,17 @@ enum vertextype { #define VTYPE_ES(t) ((t) == VTYPE_ES) #define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL) +struct prefix_pair { + struct prefix dest; + struct prefix_ipv6 src; +}; + /* * Triple */ union isis_N { uint8_t id[ISIS_SYS_ID_LEN + 1]; - struct prefix prefix; + struct prefix_pair ip; }; struct isis_vertex { enum vertextype type; @@ -106,8 +112,13 @@ static unsigned isis_vertex_queue_hash_key(void *vp) { struct isis_vertex *vertex = vp; - if (VTYPE_IP(vertex->type)) - return prefix_hash_key(&vertex->N.prefix); + if (VTYPE_IP(vertex->type)) { + uint32_t key; + + key = prefix_hash_key(&vertex->N.ip.dest); + key = jhash_1word(prefix_hash_key(&vertex->N.ip.src), key); + return key; + } return jhash(vertex->N.id, ISIS_SYS_ID_LEN + 1, 0x55aa5a5a); } @@ -119,8 +130,13 @@ static int isis_vertex_queue_hash_cmp(const void *a, const void *b) if (va->type != vb->type) return 0; - if (VTYPE_IP(va->type)) - return prefix_cmp(&va->N.prefix, &vb->N.prefix) == 0; + if (VTYPE_IP(va->type)) { + if (prefix_cmp(&va->N.ip.dest, &vb->N.ip.dest)) + return 0; + + return prefix_cmp((struct prefix *)&va->N.ip.src, + (struct prefix *)&vb->N.ip.src) == 0; + } return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0; } @@ -394,6 +410,7 @@ static const char *vtype2string(enum vertextype vtype) return NULL; /* Not reached */ } +#define VID2STR_BUFFER SRCDEST2STR_BUFFER static const char *vid2string(struct isis_vertex *vertex, char *buff, int size) { if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) { @@ -401,7 +418,9 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size) } if (VTYPE_IP(vertex->type)) { - prefix2str((struct prefix *)&vertex->N.prefix, buff, size); + srcdest2str(&vertex->N.ip.dest, + &vertex->N.ip.src, + buff, size); return buff; } @@ -416,7 +435,7 @@ static void isis_vertex_id_init(struct isis_vertex *vertex, union isis_N *n, if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) { memcpy(vertex->N.id, n->id, ISIS_SYS_ID_LEN + 1); } else if (VTYPE_IP(vtype)) { - memcpy(&vertex->N.prefix, &n->prefix, sizeof(struct prefix)); + memcpy(&vertex->N.ip, &n->ip, sizeof(n->ip)); } else { zlog_err("WTF!"); } @@ -474,7 +493,7 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area) isis_vertex_queue_init(&tree->tents, "IS-IS SPF tents", true); isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths", false); - tree->route_table = route_table_init(); + tree->route_table = srcdest_table_init(); tree->area = area; tree->last_run_timestamp = 0; tree->last_run_monotime = 0; @@ -577,7 +596,7 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree, struct isis_vertex *vertex; struct isis_lsp *lsp; #ifdef EXTREME_DEBUG - char buff[PREFIX2STR_BUFFER]; + char buff[VID2STR_BUFFER]; #endif /* EXTREME_DEBUG */ union isis_N n; @@ -628,7 +647,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, struct listnode *node; struct isis_adjacency *parent_adj; #ifdef EXTREME_DEBUG - char buff[PREFIX2STR_BUFFER]; + char buff[VID2STR_BUFFER]; #endif assert(isis_find_vertex(&spftree->paths, id, vtype) == NULL); @@ -701,15 +720,16 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, { struct isis_vertex *vertex; #ifdef EXTREME_DEBUG - char buff[PREFIX2STR_BUFFER]; + char buff[VID2STR_BUFFER]; #endif assert(spftree && parent); - struct prefix p; + struct prefix_pair p; if (vtype >= VTYPE_IPREACH_INTERNAL) { - prefix_copy(&p, id); - apply_mask(&p); + memcpy(&p, id, sizeof(p)); + apply_mask(&p.dest); + apply_mask((struct prefix *)&p.src); id = &p; } @@ -796,6 +816,7 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree, enum vertextype vtype; static const uint8_t null_sysid[ISIS_SYS_ID_LEN]; struct isis_mt_router_info *mt_router_info = NULL; + struct prefix_pair ip_info; if (!lsp->tlvs) return ISIS_OK; @@ -889,12 +910,17 @@ lspfragloop: vtype = i ? VTYPE_IPREACH_EXTERNAL : VTYPE_IPREACH_INTERNAL; + memset(&ip_info, 0, sizeof(ip_info)); + ip_info.dest.family = AF_INET; + struct isis_oldstyle_ip_reach *r; for (r = (struct isis_oldstyle_ip_reach *)reachs[i] ->head; r; r = r->next) { dist = cost + r->metric; - process_N(spftree, vtype, (void *)&r->prefix, + ip_info.dest.u.prefix4 = r->prefix.prefix; + ip_info.dest.prefixlen = r->prefix.prefixlen; + process_N(spftree, vtype, &ip_info, dist, depth + 1, parent); } } @@ -908,6 +934,9 @@ lspfragloop: ipv4_reachs = isis_lookup_mt_items( &lsp->tlvs->mt_ip_reach, spftree->mtid); + memset(&ip_info, 0, sizeof(ip_info)); + ip_info.dest.family = AF_INET; + struct isis_extended_ip_reach *r; for (r = ipv4_reachs ? (struct isis_extended_ip_reach *) @@ -915,7 +944,9 @@ lspfragloop: : NULL; r; r = r->next) { dist = cost + r->metric; - process_N(spftree, VTYPE_IPREACH_TE, (void *)&r->prefix, + ip_info.dest.u.prefix4 = r->prefix.prefix; + ip_info.dest.prefixlen = r->prefix.prefixlen; + process_N(spftree, VTYPE_IPREACH_TE, &ip_info, dist, depth + 1, parent); } } @@ -936,7 +967,28 @@ lspfragloop: dist = cost + r->metric; vtype = r->external ? VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL; - process_N(spftree, vtype, (void *)&r->prefix, dist, + memset(&ip_info, 0, sizeof(ip_info)); + ip_info.dest.family = AF_INET6; + ip_info.dest.u.prefix6 = r->prefix.prefix; + ip_info.dest.prefixlen = r->prefix.prefixlen; + + if (r->subtlvs + && r->subtlvs->source_prefix + && r->subtlvs->source_prefix->prefixlen) { + if (spftree->tree_id != SPFTREE_DSTSRC) { + char buff[VID2STR_BUFFER]; + zlog_warn("Ignoring dest-src route %s in non dest-src topology", + srcdest2str( + &ip_info.dest, + r->subtlvs->source_prefix, + buff, sizeof(buff) + ) + ); + continue; + } + ip_info.src = *r->subtlvs->source_prefix; + } + process_N(spftree, vtype, &ip_info, dist, depth + 1, parent); } } @@ -965,7 +1017,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, struct list *adj_list; struct list *adjdb; struct prefix_ipv4 *ipv4; - struct prefix prefix; + struct prefix_pair ip_info; int retval = ISIS_OK; uint8_t lsp_id[ISIS_SYS_ID_LEN + 2]; static uint8_t null_lsp_id[ISIS_SYS_ID_LEN + 2]; @@ -989,27 +1041,29 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, * Add IP(v6) addresses of this circuit */ if (spftree->family == AF_INET) { - prefix.family = AF_INET; + memset(&ip_info, 0, sizeof(ip_info)); + ip_info.dest.family = AF_INET; for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode, ipv4)) { - prefix.u.prefix4 = ipv4->prefix; - prefix.prefixlen = ipv4->prefixlen; - apply_mask(&prefix); + ip_info.dest.u.prefix4 = ipv4->prefix; + ip_info.dest.prefixlen = ipv4->prefixlen; + apply_mask(&ip_info.dest); isis_spf_add_local(spftree, VTYPE_IPREACH_INTERNAL, - &prefix, NULL, 0, parent); + &ip_info, NULL, 0, parent); } } if (spftree->family == AF_INET6) { - prefix.family = AF_INET6; + memset(&ip_info, 0, sizeof(ip_info)); + ip_info.dest.family = AF_INET6; for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, ipnode, ipv6)) { - prefix.prefixlen = ipv6->prefixlen; - prefix.u.prefix6 = ipv6->prefix; - apply_mask(&prefix); + ip_info.dest.u.prefix6 = ipv6->prefix; + ip_info.dest.prefixlen = ipv6->prefixlen; + apply_mask(&ip_info.dest); isis_spf_add_local(spftree, VTYPE_IP6REACH_INTERNAL, - &prefix, NULL, 0, parent); + &ip_info, NULL, 0, parent); } } if (circuit->circ_type == CIRCUIT_T_BROADCAST) { @@ -1192,7 +1246,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, static void add_to_paths(struct isis_spftree *spftree, struct isis_vertex *vertex) { - char buff[PREFIX2STR_BUFFER]; + char buff[VID2STR_BUFFER]; if (isis_find_vertex(&spftree->paths, &vertex->N, vertex->type)) return; @@ -1207,7 +1261,8 @@ static void add_to_paths(struct isis_spftree *spftree, if (VTYPE_IP(vertex->type)) { if (listcount(vertex->Adj_N) > 0) - isis_route_create((struct prefix *)&vertex->N.prefix, + isis_route_create(&vertex->N.ip.dest, + &vertex->N.ip.src, vertex->d_N, vertex->depth, vertex->Adj_N, spftree->area, spftree->route_table); @@ -1263,6 +1318,10 @@ static int isis_run_spf(struct isis_area *area, int level, family = AF_INET6; mtid = isis_area_ipv6_topology(area); break; + case SPFTREE_DSTSRC: + family = AF_INET6; + mtid = ISIS_MT_IPV6_DSTSRC; + break; case SPFTREE_COUNT: assert(!"isis_run_spf should never be called with SPFTREE_COUNT as argument!"); return ISIS_WARNING; @@ -1377,6 +1436,10 @@ static int isis_run_spf_cb(struct thread *thread) if (area->ipv6_circuits) retval = isis_run_spf(area, level, SPFTREE_IPV6, isis->sysid, &thread->real); + if (area->ipv6_circuits + && isis_area_ipv6_dstsrc_enabled(area)) + retval = isis_run_spf(area, level, SPFTREE_DSTSRC, isis->sysid, + &thread->real); isis_area_verify_routes(area); @@ -1456,7 +1519,7 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue, { struct listnode *node; struct isis_vertex *vertex; - char buff[PREFIX2STR_BUFFER]; + char buff[VID2STR_BUFFER]; vty_out(vty, "Vertex Type Metric Next-Hop Interface Parent\n"); @@ -1522,6 +1585,39 @@ static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue, } } +static void isis_print_spftree(struct vty *vty, int level, + struct isis_area *area, + enum spf_tree_id tree_id) +{ + const char *tree_id_text = NULL; + + switch (tree_id) { + case SPFTREE_IPV4: + tree_id_text = "that speak IP"; + break; + case SPFTREE_IPV6: + tree_id_text = "that speak IPv6"; + break; + case SPFTREE_DSTSRC: + tree_id_text = "that support IPv6 dst-src routing"; + break; + case SPFTREE_COUNT: + assert(!"isis_print_spftree shouldn't be called with SPFTREE_COUNT as type"); + return; + } + + if (!area->spftree[tree_id][level - 1] + || !isis_vertex_queue_count( + &area->spftree[tree_id][level - 1]->paths)) + return; + + vty_out(vty, "IS-IS paths to level-%d routers %s\n", + level, tree_id_text); + isis_print_paths(vty, &area->spftree[tree_id][level - 1]->paths, + isis->sysid); + vty_out(vty, "\n"); +} + DEFUN (show_isis_topology, show_isis_topology_cmd, "show isis topology []", @@ -1553,25 +1649,17 @@ DEFUN (show_isis_topology, if ((level & levels) == 0) continue; - if (area->ip_circuits > 0 && area->spftree[SPFTREE_IPV4][level - 1] - && isis_vertex_queue_count(&area->spftree[SPFTREE_IPV4][level - 1]->paths) > 0) { - vty_out(vty, - "IS-IS paths to level-%d routers that speak IP\n", - level); - isis_print_paths( - vty, &area->spftree[SPFTREE_IPV4][level - 1]->paths, - isis->sysid); - vty_out(vty, "\n"); + if (area->ip_circuits > 0) { + isis_print_spftree(vty, level, area, + SPFTREE_IPV4); } - if (area->ipv6_circuits > 0 && area->spftree[SPFTREE_IPV6][level - 1] - && isis_vertex_queue_count(&area->spftree[SPFTREE_IPV6][level - 1]->paths) > 0) { - vty_out(vty, - "IS-IS paths to level-%d routers that speak IPv6\n", - level); - isis_print_paths( - vty, &area->spftree[SPFTREE_IPV6][level - 1]->paths, - isis->sysid); - vty_out(vty, "\n"); + if (area->ipv6_circuits > 0) { + isis_print_spftree(vty, level, area, + SPFTREE_IPV6); + } + if (isis_area_ipv6_dstsrc_enabled(area)) { + isis_print_spftree(vty, level, area, + SPFTREE_DSTSRC); } } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index b225af1060..9bc0f2ef35 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -247,6 +247,7 @@ static int isis_zebra_link_params(int command, struct zclient *zclient, } static void isis_zebra_route_add_route(struct prefix *prefix, + struct prefix_ipv6 *src_p, struct isis_route_info *route_info) { struct zapi_route api; @@ -264,6 +265,10 @@ static void isis_zebra_route_add_route(struct prefix *prefix, api.type = ZEBRA_ROUTE_ISIS; api.safi = SAFI_UNICAST; api.prefix = *prefix; + if (src_p && src_p->prefixlen) { + api.src_prefix = *src_p; + SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); + } SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); api.metric = route_info->cost; @@ -322,6 +327,7 @@ static void isis_zebra_route_add_route(struct prefix *prefix, } static void isis_zebra_route_del_route(struct prefix *prefix, + struct prefix_ipv6 *src_p, struct isis_route_info *route_info) { struct zapi_route api; @@ -334,21 +340,26 @@ static void isis_zebra_route_del_route(struct prefix *prefix, api.type = ZEBRA_ROUTE_ISIS; api.safi = SAFI_UNICAST; api.prefix = *prefix; + if (src_p && src_p->prefixlen) { + api.src_prefix = *src_p; + SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); + } zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); } void isis_zebra_route_update(struct prefix *prefix, + struct prefix_ipv6 *src_p, struct isis_route_info *route_info) { if (zclient->sock < 0) return; if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) - isis_zebra_route_add_route(prefix, route_info); + isis_zebra_route_add_route(prefix, src_p, route_info); else - isis_zebra_route_del_route(prefix, route_info); + isis_zebra_route_del_route(prefix, src_p, route_info); } static int isis_zebra_read(int command, struct zclient *zclient, diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index bd7bf2b5c5..4fbcf87217 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -28,6 +28,7 @@ void isis_zebra_init(struct thread_master *); void isis_zebra_stop(void); void isis_zebra_route_update(struct prefix *prefix, + struct prefix_ipv6 *src_p, struct isis_route_info *route_info); int isis_distribute_list_update(int routetype); void isis_zebra_redistribute_set(afi_t afi, int type); diff --git a/isisd/isisd.c b/isisd/isisd.c index ec71c224dd..a19f287453 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1325,6 +1325,10 @@ DEFUN (show_isis_summary, vty_out(vty, " IPv6 route computation:\n"); isis_spf_print(area->spftree[SPFTREE_IPV6][level - 1], vty); + + vty_out(vty, " IPv6 dst-src route computation:\n"); + isis_spf_print(area->spftree[SPFTREE_DSTSRC][level-1], + vty); } } vty_out(vty, "\n"); diff --git a/isisd/isisd.h b/isisd/isisd.h index fef18ed6fc..ce602e4402 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -66,6 +66,7 @@ DECLARE_QOBJ_TYPE(isis_area) enum spf_tree_id { SPFTREE_IPV4 = 0, SPFTREE_IPV6, + SPFTREE_DSTSRC, SPFTREE_COUNT }; diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c index 32f8e8ca5b..4497faf6fc 100644 --- a/lib/srcdest_table.c +++ b/lib/srcdest_table.c @@ -281,13 +281,12 @@ void srcdest_rnode_prefixes(struct route_node *rn, const struct prefix **p, } } -const char *srcdest_rnode2str(struct route_node *rn, char *str, int size) +const char *srcdest2str(const struct prefix *dst_p, + const struct prefix_ipv6 *src_p, + char *str, int size) { - const struct prefix *dst_p, *src_p; char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; - srcdest_rnode_prefixes(rn, &dst_p, &src_p); - snprintf(str, size, "%s%s%s", prefix2str(dst_p, dst_buf, sizeof(dst_buf)), (src_p && src_p->prefixlen) ? " from " : "", @@ -296,3 +295,11 @@ const char *srcdest_rnode2str(struct route_node *rn, char *str, int size) : ""); return str; } + +const char *srcdest_rnode2str(struct route_node *rn, char *str, int size) +{ + const struct prefix *dst_p, *src_p; + + srcdest_rnode_prefixes(rn, &dst_p, &src_p); + return srcdest2str(dst_p, (struct prefix_ipv6*)src_p, str, size); +} diff --git a/lib/srcdest_table.h b/lib/srcdest_table.h index 5f97f02bac..9ceb876f81 100644 --- a/lib/srcdest_table.h +++ b/lib/srcdest_table.h @@ -64,6 +64,9 @@ extern struct route_node *srcdest_rnode_lookup(struct route_table *table, extern void srcdest_rnode_prefixes(struct route_node *rn, const struct prefix **p, const struct prefix **src_p); +extern const char *srcdest2str(const struct prefix *dst_p, + const struct prefix_ipv6 *src_p, + char *str, int size); extern const char *srcdest_rnode2str(struct route_node *rn, char *str, int size); extern struct route_node *srcdest_route_next(struct route_node *rn); diff --git a/tests/isisd/test_isis_vertex_queue.c b/tests/isisd/test_isis_vertex_queue.c index fe528203aa..3e31b83351 100644 --- a/tests/isisd/test_isis_vertex_queue.c +++ b/tests/isisd/test_isis_vertex_queue.c @@ -17,21 +17,21 @@ static size_t vertex_count; static void setup_test_vertices(void) { union isis_N nid, nip = { - .prefix.family = AF_UNSPEC + .ip.dest.family = AF_UNSPEC }; vertices = XMALLOC(MTYPE_TMP, sizeof(*vertices) * 16); - nip.prefix.family = AF_INET; - nip.prefix.prefixlen = 24; - inet_pton(AF_INET, "192.168.1.0", &nip.prefix.u.prefix4); + nip.ip.dest.family = AF_INET; + nip.ip.dest.prefixlen = 24; + inet_pton(AF_INET, "192.168.1.0", &nip.ip.dest.u.prefix4); vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE); vertices[vertex_count]->d_N = 20; vertex_count++; - nip.prefix.family = AF_INET; - nip.prefix.prefixlen = 24; - inet_pton(AF_INET, "192.168.2.0", &nip.prefix.u.prefix4); + nip.ip.dest.family = AF_INET; + nip.ip.dest.prefixlen = 24; + inet_pton(AF_INET, "192.168.2.0", &nip.ip.dest.u.prefix4); vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE); vertices[vertex_count]->d_N = 20; vertex_count++; @@ -48,9 +48,9 @@ static void setup_test_vertices(void) vertices[vertex_count]->d_N = 15; vertex_count++; - nip.prefix.family = AF_INET; - nip.prefix.prefixlen = 24; - inet_pton(AF_INET, "192.168.3.0", &nip.prefix.u.prefix4); + nip.ip.dest.family = AF_INET; + nip.ip.dest.prefixlen = 24; + inet_pton(AF_INET, "192.168.3.0", &nip.ip.dest.u.prefix4); vertices[vertex_count] = isis_vertex_new(&nip, VTYPE_IPREACH_TE); vertices[vertex_count]->d_N = 20; vertex_count++;