mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 01:15:12 +00:00
isisd: make spf code dst-src aware
Take the source-prefix sub-TLV into consideration when running SPF and support creation/deletion of dst-src routes as result. Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
parent
6d38d0785c
commit
321c1bbb94
@ -33,6 +33,7 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "if.h"
|
#include "if.h"
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
#include "srcdest_table.h"
|
||||||
|
|
||||||
#include "isis_constants.h"
|
#include "isis_constants.h"
|
||||||
#include "isis_common.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,
|
static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
|
||||||
|
struct prefix_ipv6 *src_p,
|
||||||
uint32_t cost,
|
uint32_t cost,
|
||||||
uint32_t depth,
|
uint32_t depth,
|
||||||
struct list *adjacencies)
|
struct list *adjacencies)
|
||||||
@ -232,8 +234,10 @@ static struct isis_route_info *isis_route_info_new(struct prefix *prefix,
|
|||||||
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 */
|
||||||
if (depth == 2 && prefix->prefixlen == 128)
|
if (depth == 2 && prefix->prefixlen == 128
|
||||||
|
&& (!src_p || !src_p->prefixlen)) {
|
||||||
adj->router_address6 = prefix->u.prefix6;
|
adj->router_address6 = prefix->u.prefix6;
|
||||||
|
}
|
||||||
adjinfo2nexthop6(rinfo->nexthops6, adj);
|
adjinfo2nexthop6(rinfo->nexthops6, adj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -317,7 +321,9 @@ static int isis_route_info_same(struct isis_route_info *new,
|
|||||||
return 1;
|
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,
|
uint32_t depth,
|
||||||
struct list *adjacencies,
|
struct list *adjacencies,
|
||||||
struct isis_area *area,
|
struct isis_area *area,
|
||||||
@ -335,8 +341,9 @@ struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost,
|
|||||||
if (!table)
|
if (!table)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rinfo_new = isis_route_info_new(prefix, cost, depth, adjacencies);
|
rinfo_new = isis_route_info_new(prefix, src_p, cost,
|
||||||
route_node = route_node_get(table, prefix);
|
depth, adjacencies);
|
||||||
|
route_node = srcdest_rnode_get(table, prefix, src_p);
|
||||||
|
|
||||||
rinfo_old = route_node->info;
|
rinfo_old = route_node->info;
|
||||||
if (!rinfo_old) {
|
if (!rinfo_old) {
|
||||||
@ -372,17 +379,18 @@ struct isis_route_info *isis_route_create(struct prefix *prefix, uint32_t cost,
|
|||||||
return route_info;
|
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 route_node *rode;
|
||||||
struct isis_route_info *rinfo;
|
struct isis_route_info *rinfo;
|
||||||
char buff[PREFIX2STR_BUFFER];
|
char buff[SRCDEST2STR_BUFFER];
|
||||||
|
|
||||||
/* for log */
|
/* for log */
|
||||||
prefix2str(prefix, buff, sizeof(buff));
|
srcdest2str(prefix, src_p, buff, sizeof(buff));
|
||||||
|
|
||||||
|
rode = srcdest_rnode_get(table, prefix, src_p);
|
||||||
rode = route_node_get(table, prefix);
|
|
||||||
rinfo = rode->info;
|
rinfo = rode->info;
|
||||||
|
|
||||||
if (rinfo == NULL) {
|
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);
|
UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
|
||||||
if (isis->debugs & DEBUG_RTE_EVENTS)
|
if (isis->debugs & DEBUG_RTE_EVENTS)
|
||||||
zlog_debug("ISIS-Rte: route delete %s", buff);
|
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);
|
isis_route_info_delete(rinfo);
|
||||||
rode->info = NULL;
|
rode->info = NULL;
|
||||||
@ -411,15 +419,23 @@ static void _isis_route_verify_table(struct isis_area *area,
|
|||||||
{
|
{
|
||||||
struct route_node *rnode, *drnode;
|
struct route_node *rnode, *drnode;
|
||||||
struct isis_route_info *rinfo;
|
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)
|
if (rnode->info == NULL)
|
||||||
continue;
|
continue;
|
||||||
rinfo = rnode->info;
|
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) {
|
if (isis->debugs & DEBUG_RTE_EVENTS) {
|
||||||
prefix2str(&rnode->p, buff, sizeof(buff));
|
srcdest2str(dst_p, src_p, buff, sizeof(buff));
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"ISIS-Rte (%s): route validate: %s %s %s %s",
|
"ISIS-Rte (%s): route validate: %s %s %s %s",
|
||||||
area->area_tag,
|
area->area_tag,
|
||||||
@ -437,13 +453,13 @@ static void _isis_route_verify_table(struct isis_area *area,
|
|||||||
buff);
|
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)) {
|
if (!CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) {
|
||||||
/* Area is either L1 or L2 => we use level route tables
|
/* Area is either L1 or L2 => we use level route tables
|
||||||
* directly for
|
* directly for
|
||||||
* validating => no problems with deleting routes. */
|
* validating => no problems with deleting routes. */
|
||||||
if (!tables) {
|
if (!tables) {
|
||||||
isis_route_delete(&rnode->p, table);
|
isis_route_delete(dst_p, src_p, table);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,12 +468,13 @@ static void _isis_route_verify_table(struct isis_area *area,
|
|||||||
* delete node from level tables as well before deleting
|
* delete node from level tables as well before deleting
|
||||||
* route info. */
|
* route info. */
|
||||||
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
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)
|
if (drnode->info == rnode->info)
|
||||||
drnode->info = NULL;
|
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_table *merge;
|
||||||
struct route_node *rnode, *mrnode;
|
struct route_node *rnode, *mrnode;
|
||||||
|
|
||||||
merge = route_table_init();
|
merge = srcdest_table_init();
|
||||||
|
|
||||||
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
||||||
for (rnode = route_top(tables[level - 1]); rnode;
|
for (rnode = route_top(tables[level - 1]); rnode;
|
||||||
rnode = route_next(rnode)) {
|
rnode = srcdest_route_next(rnode)) {
|
||||||
struct isis_route_info *rinfo = rnode->info;
|
struct isis_route_info *rinfo = rnode->info;
|
||||||
if (!rinfo)
|
if (!rinfo)
|
||||||
continue;
|
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;
|
struct isis_route_info *mrinfo = mrnode->info;
|
||||||
if (mrinfo) {
|
if (mrinfo) {
|
||||||
route_unlock_node(mrnode);
|
route_unlock_node(mrnode);
|
||||||
@ -535,7 +558,7 @@ void isis_route_invalidate_table(struct isis_area *area,
|
|||||||
{
|
{
|
||||||
struct route_node *rode;
|
struct route_node *rode;
|
||||||
struct isis_route_info *rinfo;
|
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)
|
if (rode->info == NULL)
|
||||||
continue;
|
continue;
|
||||||
rinfo = rode->info;
|
rinfo = rode->info;
|
||||||
|
@ -50,7 +50,9 @@ struct isis_route_info {
|
|||||||
struct list *nexthops6;
|
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,
|
uint32_t depth,
|
||||||
struct list *adjacencies,
|
struct list *adjacencies,
|
||||||
struct isis_area *area,
|
struct isis_area *area,
|
||||||
|
186
isisd/isis_spf.c
186
isisd/isis_spf.c
@ -37,6 +37,7 @@
|
|||||||
#include "spf_backoff.h"
|
#include "spf_backoff.h"
|
||||||
#include "jhash.h"
|
#include "jhash.h"
|
||||||
#include "skiplist.h"
|
#include "skiplist.h"
|
||||||
|
#include "srcdest_table.h"
|
||||||
|
|
||||||
#include "isis_constants.h"
|
#include "isis_constants.h"
|
||||||
#include "isis_common.h"
|
#include "isis_common.h"
|
||||||
@ -74,12 +75,17 @@ enum vertextype {
|
|||||||
#define VTYPE_ES(t) ((t) == VTYPE_ES)
|
#define VTYPE_ES(t) ((t) == VTYPE_ES)
|
||||||
#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
|
#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL)
|
||||||
|
|
||||||
|
struct prefix_pair {
|
||||||
|
struct prefix dest;
|
||||||
|
struct prefix_ipv6 src;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Triple <N, d(N), {Adj(N)}>
|
* Triple <N, d(N), {Adj(N)}>
|
||||||
*/
|
*/
|
||||||
union isis_N {
|
union isis_N {
|
||||||
uint8_t id[ISIS_SYS_ID_LEN + 1];
|
uint8_t id[ISIS_SYS_ID_LEN + 1];
|
||||||
struct prefix prefix;
|
struct prefix_pair ip;
|
||||||
};
|
};
|
||||||
struct isis_vertex {
|
struct isis_vertex {
|
||||||
enum vertextype type;
|
enum vertextype type;
|
||||||
@ -106,8 +112,13 @@ static unsigned isis_vertex_queue_hash_key(void *vp)
|
|||||||
{
|
{
|
||||||
struct isis_vertex *vertex = vp;
|
struct isis_vertex *vertex = vp;
|
||||||
|
|
||||||
if (VTYPE_IP(vertex->type))
|
if (VTYPE_IP(vertex->type)) {
|
||||||
return prefix_hash_key(&vertex->N.prefix);
|
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);
|
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)
|
if (va->type != vb->type)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (VTYPE_IP(va->type))
|
if (VTYPE_IP(va->type)) {
|
||||||
return prefix_cmp(&va->N.prefix, &vb->N.prefix) == 0;
|
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;
|
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 */
|
return NULL; /* Not reached */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VID2STR_BUFFER SRCDEST2STR_BUFFER
|
||||||
static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
|
static const char *vid2string(struct isis_vertex *vertex, char *buff, int size)
|
||||||
{
|
{
|
||||||
if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) {
|
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)) {
|
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;
|
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)) {
|
if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) {
|
||||||
memcpy(vertex->N.id, n->id, ISIS_SYS_ID_LEN + 1);
|
memcpy(vertex->N.id, n->id, ISIS_SYS_ID_LEN + 1);
|
||||||
} else if (VTYPE_IP(vtype)) {
|
} else if (VTYPE_IP(vtype)) {
|
||||||
memcpy(&vertex->N.prefix, &n->prefix, sizeof(struct prefix));
|
memcpy(&vertex->N.ip, &n->ip, sizeof(n->ip));
|
||||||
} else {
|
} else {
|
||||||
zlog_err("WTF!");
|
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->tents, "IS-IS SPF tents", true);
|
||||||
isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths", false);
|
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->area = area;
|
||||||
tree->last_run_timestamp = 0;
|
tree->last_run_timestamp = 0;
|
||||||
tree->last_run_monotime = 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_vertex *vertex;
|
||||||
struct isis_lsp *lsp;
|
struct isis_lsp *lsp;
|
||||||
#ifdef EXTREME_DEBUG
|
#ifdef EXTREME_DEBUG
|
||||||
char buff[PREFIX2STR_BUFFER];
|
char buff[VID2STR_BUFFER];
|
||||||
#endif /* EXTREME_DEBUG */
|
#endif /* EXTREME_DEBUG */
|
||||||
union isis_N n;
|
union isis_N n;
|
||||||
|
|
||||||
@ -628,7 +647,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree,
|
|||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct isis_adjacency *parent_adj;
|
struct isis_adjacency *parent_adj;
|
||||||
#ifdef EXTREME_DEBUG
|
#ifdef EXTREME_DEBUG
|
||||||
char buff[PREFIX2STR_BUFFER];
|
char buff[VID2STR_BUFFER];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(isis_find_vertex(&spftree->paths, id, vtype) == NULL);
|
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;
|
struct isis_vertex *vertex;
|
||||||
#ifdef EXTREME_DEBUG
|
#ifdef EXTREME_DEBUG
|
||||||
char buff[PREFIX2STR_BUFFER];
|
char buff[VID2STR_BUFFER];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(spftree && parent);
|
assert(spftree && parent);
|
||||||
|
|
||||||
struct prefix p;
|
struct prefix_pair p;
|
||||||
if (vtype >= VTYPE_IPREACH_INTERNAL) {
|
if (vtype >= VTYPE_IPREACH_INTERNAL) {
|
||||||
prefix_copy(&p, id);
|
memcpy(&p, id, sizeof(p));
|
||||||
apply_mask(&p);
|
apply_mask(&p.dest);
|
||||||
|
apply_mask((struct prefix *)&p.src);
|
||||||
id = &p;
|
id = &p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,6 +816,7 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
|
|||||||
enum vertextype vtype;
|
enum vertextype vtype;
|
||||||
static const uint8_t null_sysid[ISIS_SYS_ID_LEN];
|
static const uint8_t null_sysid[ISIS_SYS_ID_LEN];
|
||||||
struct isis_mt_router_info *mt_router_info = NULL;
|
struct isis_mt_router_info *mt_router_info = NULL;
|
||||||
|
struct prefix_pair ip_info;
|
||||||
|
|
||||||
if (!lsp->tlvs)
|
if (!lsp->tlvs)
|
||||||
return ISIS_OK;
|
return ISIS_OK;
|
||||||
@ -889,12 +910,17 @@ lspfragloop:
|
|||||||
vtype = i ? VTYPE_IPREACH_EXTERNAL
|
vtype = i ? VTYPE_IPREACH_EXTERNAL
|
||||||
: VTYPE_IPREACH_INTERNAL;
|
: VTYPE_IPREACH_INTERNAL;
|
||||||
|
|
||||||
|
memset(&ip_info, 0, sizeof(ip_info));
|
||||||
|
ip_info.dest.family = AF_INET;
|
||||||
|
|
||||||
struct isis_oldstyle_ip_reach *r;
|
struct isis_oldstyle_ip_reach *r;
|
||||||
for (r = (struct isis_oldstyle_ip_reach *)reachs[i]
|
for (r = (struct isis_oldstyle_ip_reach *)reachs[i]
|
||||||
->head;
|
->head;
|
||||||
r; r = r->next) {
|
r; r = r->next) {
|
||||||
dist = cost + r->metric;
|
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);
|
dist, depth + 1, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -908,6 +934,9 @@ lspfragloop:
|
|||||||
ipv4_reachs = isis_lookup_mt_items(
|
ipv4_reachs = isis_lookup_mt_items(
|
||||||
&lsp->tlvs->mt_ip_reach, spftree->mtid);
|
&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;
|
struct isis_extended_ip_reach *r;
|
||||||
for (r = ipv4_reachs
|
for (r = ipv4_reachs
|
||||||
? (struct isis_extended_ip_reach *)
|
? (struct isis_extended_ip_reach *)
|
||||||
@ -915,7 +944,9 @@ lspfragloop:
|
|||||||
: NULL;
|
: NULL;
|
||||||
r; r = r->next) {
|
r; r = r->next) {
|
||||||
dist = cost + r->metric;
|
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);
|
dist, depth + 1, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -936,7 +967,28 @@ lspfragloop:
|
|||||||
dist = cost + r->metric;
|
dist = cost + r->metric;
|
||||||
vtype = r->external ? VTYPE_IP6REACH_EXTERNAL
|
vtype = r->external ? VTYPE_IP6REACH_EXTERNAL
|
||||||
: VTYPE_IP6REACH_INTERNAL;
|
: 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);
|
depth + 1, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -965,7 +1017,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
|
|||||||
struct list *adj_list;
|
struct list *adj_list;
|
||||||
struct list *adjdb;
|
struct list *adjdb;
|
||||||
struct prefix_ipv4 *ipv4;
|
struct prefix_ipv4 *ipv4;
|
||||||
struct prefix prefix;
|
struct prefix_pair ip_info;
|
||||||
int retval = ISIS_OK;
|
int retval = ISIS_OK;
|
||||||
uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
|
uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
|
||||||
static uint8_t null_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
|
* Add IP(v6) addresses of this circuit
|
||||||
*/
|
*/
|
||||||
if (spftree->family == AF_INET) {
|
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,
|
for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode,
|
||||||
ipv4)) {
|
ipv4)) {
|
||||||
prefix.u.prefix4 = ipv4->prefix;
|
ip_info.dest.u.prefix4 = ipv4->prefix;
|
||||||
prefix.prefixlen = ipv4->prefixlen;
|
ip_info.dest.prefixlen = ipv4->prefixlen;
|
||||||
apply_mask(&prefix);
|
apply_mask(&ip_info.dest);
|
||||||
isis_spf_add_local(spftree,
|
isis_spf_add_local(spftree,
|
||||||
VTYPE_IPREACH_INTERNAL,
|
VTYPE_IPREACH_INTERNAL,
|
||||||
&prefix, NULL, 0, parent);
|
&ip_info, NULL, 0, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (spftree->family == AF_INET6) {
|
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,
|
for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
|
||||||
ipnode, ipv6)) {
|
ipnode, ipv6)) {
|
||||||
prefix.prefixlen = ipv6->prefixlen;
|
ip_info.dest.u.prefix6 = ipv6->prefix;
|
||||||
prefix.u.prefix6 = ipv6->prefix;
|
ip_info.dest.prefixlen = ipv6->prefixlen;
|
||||||
apply_mask(&prefix);
|
apply_mask(&ip_info.dest);
|
||||||
isis_spf_add_local(spftree,
|
isis_spf_add_local(spftree,
|
||||||
VTYPE_IP6REACH_INTERNAL,
|
VTYPE_IP6REACH_INTERNAL,
|
||||||
&prefix, NULL, 0, parent);
|
&ip_info, NULL, 0, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
|
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,
|
static void add_to_paths(struct isis_spftree *spftree,
|
||||||
struct isis_vertex *vertex)
|
struct isis_vertex *vertex)
|
||||||
{
|
{
|
||||||
char buff[PREFIX2STR_BUFFER];
|
char buff[VID2STR_BUFFER];
|
||||||
|
|
||||||
if (isis_find_vertex(&spftree->paths, &vertex->N, vertex->type))
|
if (isis_find_vertex(&spftree->paths, &vertex->N, vertex->type))
|
||||||
return;
|
return;
|
||||||
@ -1207,7 +1261,8 @@ static void add_to_paths(struct isis_spftree *spftree,
|
|||||||
|
|
||||||
if (VTYPE_IP(vertex->type)) {
|
if (VTYPE_IP(vertex->type)) {
|
||||||
if (listcount(vertex->Adj_N) > 0)
|
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->d_N, vertex->depth,
|
||||||
vertex->Adj_N, spftree->area,
|
vertex->Adj_N, spftree->area,
|
||||||
spftree->route_table);
|
spftree->route_table);
|
||||||
@ -1263,6 +1318,10 @@ static int isis_run_spf(struct isis_area *area, int level,
|
|||||||
family = AF_INET6;
|
family = AF_INET6;
|
||||||
mtid = isis_area_ipv6_topology(area);
|
mtid = isis_area_ipv6_topology(area);
|
||||||
break;
|
break;
|
||||||
|
case SPFTREE_DSTSRC:
|
||||||
|
family = AF_INET6;
|
||||||
|
mtid = ISIS_MT_IPV6_DSTSRC;
|
||||||
|
break;
|
||||||
case SPFTREE_COUNT:
|
case SPFTREE_COUNT:
|
||||||
assert(!"isis_run_spf should never be called with SPFTREE_COUNT as argument!");
|
assert(!"isis_run_spf should never be called with SPFTREE_COUNT as argument!");
|
||||||
return ISIS_WARNING;
|
return ISIS_WARNING;
|
||||||
@ -1377,6 +1436,10 @@ static int isis_run_spf_cb(struct thread *thread)
|
|||||||
if (area->ipv6_circuits)
|
if (area->ipv6_circuits)
|
||||||
retval = isis_run_spf(area, level, SPFTREE_IPV6, isis->sysid,
|
retval = isis_run_spf(area, level, SPFTREE_IPV6, isis->sysid,
|
||||||
&thread->real);
|
&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);
|
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 listnode *node;
|
||||||
struct isis_vertex *vertex;
|
struct isis_vertex *vertex;
|
||||||
char buff[PREFIX2STR_BUFFER];
|
char buff[VID2STR_BUFFER];
|
||||||
|
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"Vertex Type Metric Next-Hop Interface Parent\n");
|
"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,
|
DEFUN (show_isis_topology,
|
||||||
show_isis_topology_cmd,
|
show_isis_topology_cmd,
|
||||||
"show isis topology [<level-1|level-2>]",
|
"show isis topology [<level-1|level-2>]",
|
||||||
@ -1553,25 +1649,17 @@ DEFUN (show_isis_topology,
|
|||||||
if ((level & levels) == 0)
|
if ((level & levels) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (area->ip_circuits > 0 && area->spftree[SPFTREE_IPV4][level - 1]
|
if (area->ip_circuits > 0) {
|
||||||
&& isis_vertex_queue_count(&area->spftree[SPFTREE_IPV4][level - 1]->paths) > 0) {
|
isis_print_spftree(vty, level, area,
|
||||||
vty_out(vty,
|
SPFTREE_IPV4);
|
||||||
"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->ipv6_circuits > 0 && area->spftree[SPFTREE_IPV6][level - 1]
|
if (area->ipv6_circuits > 0) {
|
||||||
&& isis_vertex_queue_count(&area->spftree[SPFTREE_IPV6][level - 1]->paths) > 0) {
|
isis_print_spftree(vty, level, area,
|
||||||
vty_out(vty,
|
SPFTREE_IPV6);
|
||||||
"IS-IS paths to level-%d routers that speak IPv6\n",
|
}
|
||||||
level);
|
if (isis_area_ipv6_dstsrc_enabled(area)) {
|
||||||
isis_print_paths(
|
isis_print_spftree(vty, level, area,
|
||||||
vty, &area->spftree[SPFTREE_IPV6][level - 1]->paths,
|
SPFTREE_DSTSRC);
|
||||||
isis->sysid);
|
|
||||||
vty_out(vty, "\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
static void isis_zebra_route_add_route(struct prefix *prefix,
|
||||||
|
struct prefix_ipv6 *src_p,
|
||||||
struct isis_route_info *route_info)
|
struct isis_route_info *route_info)
|
||||||
{
|
{
|
||||||
struct zapi_route api;
|
struct zapi_route api;
|
||||||
@ -264,6 +265,10 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
|
|||||||
api.type = ZEBRA_ROUTE_ISIS;
|
api.type = ZEBRA_ROUTE_ISIS;
|
||||||
api.safi = SAFI_UNICAST;
|
api.safi = SAFI_UNICAST;
|
||||||
api.prefix = *prefix;
|
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_NEXTHOP);
|
||||||
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
|
||||||
api.metric = route_info->cost;
|
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,
|
static void isis_zebra_route_del_route(struct prefix *prefix,
|
||||||
|
struct prefix_ipv6 *src_p,
|
||||||
struct isis_route_info *route_info)
|
struct isis_route_info *route_info)
|
||||||
{
|
{
|
||||||
struct zapi_route api;
|
struct zapi_route api;
|
||||||
@ -334,21 +340,26 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
|
|||||||
api.type = ZEBRA_ROUTE_ISIS;
|
api.type = ZEBRA_ROUTE_ISIS;
|
||||||
api.safi = SAFI_UNICAST;
|
api.safi = SAFI_UNICAST;
|
||||||
api.prefix = *prefix;
|
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);
|
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
||||||
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void isis_zebra_route_update(struct prefix *prefix,
|
void isis_zebra_route_update(struct prefix *prefix,
|
||||||
|
struct prefix_ipv6 *src_p,
|
||||||
struct isis_route_info *route_info)
|
struct isis_route_info *route_info)
|
||||||
{
|
{
|
||||||
if (zclient->sock < 0)
|
if (zclient->sock < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
|
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
|
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,
|
static int isis_zebra_read(int command, struct zclient *zclient,
|
||||||
|
@ -28,6 +28,7 @@ void isis_zebra_init(struct thread_master *);
|
|||||||
void isis_zebra_stop(void);
|
void isis_zebra_stop(void);
|
||||||
|
|
||||||
void isis_zebra_route_update(struct prefix *prefix,
|
void isis_zebra_route_update(struct prefix *prefix,
|
||||||
|
struct prefix_ipv6 *src_p,
|
||||||
struct isis_route_info *route_info);
|
struct isis_route_info *route_info);
|
||||||
int isis_distribute_list_update(int routetype);
|
int isis_distribute_list_update(int routetype);
|
||||||
void isis_zebra_redistribute_set(afi_t afi, int type);
|
void isis_zebra_redistribute_set(afi_t afi, int type);
|
||||||
|
@ -1325,6 +1325,10 @@ DEFUN (show_isis_summary,
|
|||||||
vty_out(vty, " IPv6 route computation:\n");
|
vty_out(vty, " IPv6 route computation:\n");
|
||||||
isis_spf_print(area->spftree[SPFTREE_IPV6][level - 1],
|
isis_spf_print(area->spftree[SPFTREE_IPV6][level - 1],
|
||||||
vty);
|
vty);
|
||||||
|
|
||||||
|
vty_out(vty, " IPv6 dst-src route computation:\n");
|
||||||
|
isis_spf_print(area->spftree[SPFTREE_DSTSRC][level-1],
|
||||||
|
vty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
|
@ -66,6 +66,7 @@ DECLARE_QOBJ_TYPE(isis_area)
|
|||||||
enum spf_tree_id {
|
enum spf_tree_id {
|
||||||
SPFTREE_IPV4 = 0,
|
SPFTREE_IPV4 = 0,
|
||||||
SPFTREE_IPV6,
|
SPFTREE_IPV6,
|
||||||
|
SPFTREE_DSTSRC,
|
||||||
SPFTREE_COUNT
|
SPFTREE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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];
|
char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN];
|
||||||
|
|
||||||
srcdest_rnode_prefixes(rn, &dst_p, &src_p);
|
|
||||||
|
|
||||||
snprintf(str, size, "%s%s%s",
|
snprintf(str, size, "%s%s%s",
|
||||||
prefix2str(dst_p, dst_buf, sizeof(dst_buf)),
|
prefix2str(dst_p, dst_buf, sizeof(dst_buf)),
|
||||||
(src_p && src_p->prefixlen) ? " from " : "",
|
(src_p && src_p->prefixlen) ? " from " : "",
|
||||||
@ -296,3 +295,11 @@ const char *srcdest_rnode2str(struct route_node *rn, char *str, int size)
|
|||||||
: "");
|
: "");
|
||||||
return str;
|
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);
|
||||||
|
}
|
||||||
|
@ -64,6 +64,9 @@ extern struct route_node *srcdest_rnode_lookup(struct route_table *table,
|
|||||||
extern void srcdest_rnode_prefixes(struct route_node *rn,
|
extern void srcdest_rnode_prefixes(struct route_node *rn,
|
||||||
const struct prefix **p,
|
const struct prefix **p,
|
||||||
const struct prefix **src_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,
|
extern const char *srcdest_rnode2str(struct route_node *rn, char *str,
|
||||||
int size);
|
int size);
|
||||||
extern struct route_node *srcdest_route_next(struct route_node *rn);
|
extern struct route_node *srcdest_route_next(struct route_node *rn);
|
||||||
|
@ -17,21 +17,21 @@ static size_t vertex_count;
|
|||||||
static void setup_test_vertices(void)
|
static void setup_test_vertices(void)
|
||||||
{
|
{
|
||||||
union isis_N nid, nip = {
|
union isis_N nid, nip = {
|
||||||
.prefix.family = AF_UNSPEC
|
.ip.dest.family = AF_UNSPEC
|
||||||
};
|
};
|
||||||
|
|
||||||
vertices = XMALLOC(MTYPE_TMP, sizeof(*vertices) * 16);
|
vertices = XMALLOC(MTYPE_TMP, sizeof(*vertices) * 16);
|
||||||
|
|
||||||
nip.prefix.family = AF_INET;
|
nip.ip.dest.family = AF_INET;
|
||||||
nip.prefix.prefixlen = 24;
|
nip.ip.dest.prefixlen = 24;
|
||||||
inet_pton(AF_INET, "192.168.1.0", &nip.prefix.u.prefix4);
|
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] = isis_vertex_new(&nip, VTYPE_IPREACH_TE);
|
||||||
vertices[vertex_count]->d_N = 20;
|
vertices[vertex_count]->d_N = 20;
|
||||||
vertex_count++;
|
vertex_count++;
|
||||||
|
|
||||||
nip.prefix.family = AF_INET;
|
nip.ip.dest.family = AF_INET;
|
||||||
nip.prefix.prefixlen = 24;
|
nip.ip.dest.prefixlen = 24;
|
||||||
inet_pton(AF_INET, "192.168.2.0", &nip.prefix.u.prefix4);
|
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] = isis_vertex_new(&nip, VTYPE_IPREACH_TE);
|
||||||
vertices[vertex_count]->d_N = 20;
|
vertices[vertex_count]->d_N = 20;
|
||||||
vertex_count++;
|
vertex_count++;
|
||||||
@ -48,9 +48,9 @@ static void setup_test_vertices(void)
|
|||||||
vertices[vertex_count]->d_N = 15;
|
vertices[vertex_count]->d_N = 15;
|
||||||
vertex_count++;
|
vertex_count++;
|
||||||
|
|
||||||
nip.prefix.family = AF_INET;
|
nip.ip.dest.family = AF_INET;
|
||||||
nip.prefix.prefixlen = 24;
|
nip.ip.dest.prefixlen = 24;
|
||||||
inet_pton(AF_INET, "192.168.3.0", &nip.prefix.u.prefix4);
|
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] = isis_vertex_new(&nip, VTYPE_IPREACH_TE);
|
||||||
vertices[vertex_count]->d_N = 20;
|
vertices[vertex_count]->d_N = 20;
|
||||||
vertex_count++;
|
vertex_count++;
|
||||||
|
Loading…
Reference in New Issue
Block a user