diff options
| -rw-r--r-- | bgpd/bgp_open.c | 2 | ||||
| -rw-r--r-- | isisd/dict.c | 6 | ||||
| -rw-r--r-- | isisd/isis_misc.c | 21 | ||||
| -rw-r--r-- | isisd/isis_misc.h | 1 | ||||
| -rw-r--r-- | isisd/isis_spf.c | 330 | ||||
| -rw-r--r-- | isisd/isis_spf.h | 49 | ||||
| -rw-r--r-- | isisd/isisd.c | 45 | ||||
| -rw-r--r-- | isisd/isisd.h | 2 | ||||
| -rw-r--r-- | lib/hash.c | 41 | ||||
| -rw-r--r-- | lib/prefix.c | 13 | ||||
| -rw-r--r-- | lib/prefix.h | 2 | ||||
| -rw-r--r-- | lib/table.c | 15 | ||||
| -rw-r--r-- | nhrpd/nhrp_cache.c | 2 | ||||
| -rw-r--r-- | nhrpd/nhrp_main.c | 2 | ||||
| -rw-r--r-- | nhrpd/nhrp_route.c | 38 | ||||
| -rw-r--r-- | watchfrr/watchfrr.c | 2 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 5 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 8 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 13 | ||||
| -rw-r--r-- | zebra/zebra_rnh.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_routemap.c | 12 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 9 |
22 files changed, 360 insertions, 262 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 2c988f86cc..3ee865e3ba 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -271,7 +271,7 @@ static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr) } static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi, - safi_t safi, u_char type, + iana_safi_t safi, u_char type, u_char mode) { if (bgp_debug_neighbor_events(peer)) diff --git a/isisd/dict.c b/isisd/dict.c index f09a8152a8..2ea86d1b68 100644 --- a/isisd/dict.c +++ b/isisd/dict.c @@ -174,6 +174,7 @@ static int verify_bintree(dict_t *dict) * subtree is not red-black. */ +#ifdef EXTREME_DICT_DEBUG static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) { unsigned height_left, height_right; @@ -198,6 +199,7 @@ static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) } return 1; } +#endif /* * Compute the actual count of nodes by traversing the tree and @@ -205,6 +207,7 @@ static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) * detect a mismatch. */ +#ifdef EXTREME_DICT_DEBUG static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) { if (root == nil) @@ -213,6 +216,7 @@ static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) return 1 + verify_node_count(nil, root->left) + verify_node_count(nil, root->right); } +#endif /* * Verify that the tree contains the given node. This is done by @@ -369,6 +373,7 @@ static void dict_clear(dict_t *dict) int dict_verify(dict_t *dict) { +#ifdef EXTREME_DICT_DEBUG dnode_t *nil = dict_nil(dict), *root = dict_root(dict); /* check that the sentinel node and root node are black */ @@ -389,6 +394,7 @@ int dict_verify(dict_t *dict) return 0; if (verify_node_count(nil, root) != dict_count(dict)) return 0; +#endif return 1; } diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 4d7b4c381a..c872774da8 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -601,3 +601,24 @@ void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...) XFREE(MTYPE_TMP, p); } + +void vty_out_timestr(struct vty *vty, time_t uptime) +{ + struct tm *tm; + time_t difftime = time(NULL); + difftime -= uptime; + tm = gmtime(&difftime); + +#define ONE_DAY_SECOND 60*60*24 +#define ONE_WEEK_SECOND 60*60*24*7 + if (difftime < ONE_DAY_SECOND) + vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (difftime < ONE_WEEK_SECOND) + vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else + vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + vty_out(vty, " ago"); +} diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h index 7de534ec7b..5a19a1ffa0 100644 --- a/isisd/isis_misc.h +++ b/isisd/isis_misc.h @@ -84,4 +84,5 @@ void log_multiline(int priority, const char *prefix, const char *format, ...) struct vty; void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); +void vty_out_timestr(struct vty *vty, time_t uptime); #endif diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 740f087ee7..9acbc21838 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -35,6 +35,7 @@ #include "if.h" #include "table.h" #include "spf_backoff.h" +#include "jhash.h" #include "isis_constants.h" #include "isis_common.h" @@ -55,6 +56,160 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info"); +enum vertextype { + VTYPE_PSEUDO_IS = 1, + VTYPE_PSEUDO_TE_IS, + VTYPE_NONPSEUDO_IS, + VTYPE_NONPSEUDO_TE_IS, + VTYPE_ES, + VTYPE_IPREACH_INTERNAL, + VTYPE_IPREACH_EXTERNAL, + VTYPE_IPREACH_TE, + VTYPE_IP6REACH_INTERNAL, + VTYPE_IP6REACH_EXTERNAL +}; + +#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS) +#define VTYPE_ES(t) ((t) == VTYPE_ES) +#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL) + +/* + * Triple <N, d(N), {Adj(N)}> + */ +struct isis_vertex { + enum vertextype type; + + union { + u_char id[ISIS_SYS_ID_LEN + 1]; + struct prefix prefix; + } N; + + u_int32_t d_N; /* d(N) Distance from this IS */ + u_int16_t depth; /* The depth in the imaginary tree */ + struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */ + struct list *parents; /* list of parents for ECMP */ + struct list *children; /* list of children used for tree dump */ +}; + +/* Vertex Queue and associated functions */ + +struct isis_vertex_queue { + struct list *list; + struct hash *hash; +}; + +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); + + return jhash(vertex->N.id, ISIS_SYS_ID_LEN + 1, 0x55aa5a5a); +} + +static int isis_vertex_queue_hash_cmp(const void *a, const void *b) +{ + const struct isis_vertex *va = a, *vb = b; + + if (va->type != vb->type) + return 0; + + if (VTYPE_IP(va->type)) + return prefix_cmp(&va->N.prefix, &vb->N.prefix) == 0; + + return memcmp(va->N.id, vb->N.id, ISIS_SYS_ID_LEN + 1) == 0; +} + +static void isis_vertex_queue_init(struct isis_vertex_queue *queue, const char *name) +{ + queue->list = list_new(); + queue->hash = hash_create(isis_vertex_queue_hash_key, + isis_vertex_queue_hash_cmp, + name); +} + +static void isis_vertex_del(struct isis_vertex *vertex); + +static void isis_vertex_queue_clear(struct isis_vertex_queue *queue) +{ + hash_clean(queue->hash, NULL); + + queue->list->del = (void (*)(void *))isis_vertex_del; + list_delete_all_node(queue->list); + queue->list->del = NULL; +} + +static void isis_vertex_queue_free(struct isis_vertex_queue *queue) +{ + isis_vertex_queue_clear(queue); + + hash_free(queue->hash); + queue->hash = NULL; + + list_delete(queue->list); + queue->list = NULL; +} + +static unsigned int isis_vertex_queue_count(struct isis_vertex_queue *queue) +{ + return listcount(queue->list); +} + +static void isis_vertex_queue_add(struct isis_vertex_queue *queue, + struct isis_vertex *vertex) +{ + listnode_add(queue->list, vertex); + + struct isis_vertex *inserted; + + inserted = hash_get(queue->hash, vertex, hash_alloc_intern); + assert(inserted == vertex); +} + +static struct isis_vertex *isis_vertex_queue_pop(struct isis_vertex_queue *queue) +{ + struct listnode *node; + + node = listhead(queue->list); + if (!node) + return NULL; + + struct isis_vertex *rv = listgetdata(node); + + list_delete_node(queue->list, node); + hash_release(queue->hash, rv); + + return rv; +} + +static void isis_vertex_queue_delete(struct isis_vertex_queue *queue, + struct isis_vertex *vertex) +{ + listnode_delete(queue->list, vertex); + hash_release(queue->hash, vertex); +} + +#define ALL_QUEUE_ELEMENTS_RO(queue, node, data) \ + ALL_LIST_ELEMENTS_RO((queue)->list, node, data) + + +/* End of vertex queue definitions */ + +struct isis_spftree { + struct isis_vertex_queue paths; /* the SPT */ + struct isis_vertex_queue tents; /* TENT */ + struct isis_area *area; /* back pointer to area */ + unsigned int runcount; /* number of runs since uptime */ + time_t last_run_timestamp; /* last run timestamp for scheduling */ + time_t last_run_duration; /* last run duration in msec */ + + uint16_t mtid; + int family; + int level; +}; + + /* * supports the given af ? */ @@ -174,12 +329,8 @@ static const char *vid2string(struct isis_vertex *vertex, char *buff, int size) return "UNKNOWN"; } -static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype) +static void isis_vertex_id_init(struct isis_vertex *vertex, void *id, enum vertextype vtype) { - struct isis_vertex *vertex; - - vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex)); - vertex->type = vtype; if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) { @@ -190,6 +341,15 @@ static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype) } else { zlog_err("WTF!"); } +} + +static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype) +{ + struct isis_vertex *vertex; + + vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex)); + + isis_vertex_id_init(vertex, id, vtype); vertex->Adj_N = list_new(); vertex->parents = list_new(); @@ -237,8 +397,8 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area) return NULL; } - tree->tents = list_new(); - tree->paths = list_new(); + isis_vertex_queue_init(&tree->tents, "IS-IS SPF tents"); + isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths"); tree->area = area; tree->last_run_timestamp = 0; tree->last_run_duration = 0; @@ -248,15 +408,8 @@ struct isis_spftree *isis_spftree_new(struct isis_area *area) void isis_spftree_del(struct isis_spftree *spftree) { - - spftree->tents->del = (void (*)(void *))isis_vertex_del; - list_delete(spftree->tents); - spftree->tents = NULL; - - spftree->paths->del = (void (*)(void *))isis_vertex_del; - list_delete(spftree->paths); - spftree->paths = NULL; - + isis_vertex_queue_free(&spftree->tents); + isis_vertex_queue_free(&spftree->paths); XFREE(MTYPE_ISIS_SPFTREE, spftree); return; @@ -266,12 +419,13 @@ static void isis_spftree_adj_del(struct isis_spftree *spftree, struct isis_adjacency *adj) { struct listnode *node; + struct isis_vertex *v; if (!adj) return; - for (node = listhead(spftree->tents); node; node = listnextnode(node)) - isis_vertex_adj_del(listgetdata(node), adj); - for (node = listhead(spftree->paths); node; node = listnextnode(node)) - isis_vertex_adj_del(listgetdata(node), adj); + for (ALL_QUEUE_ELEMENTS_RO(&spftree->tents, node, v)) + isis_vertex_adj_del(v, adj); + for (ALL_QUEUE_ELEMENTS_RO(&spftree->paths, node, v)) + isis_vertex_adj_del(v, adj); return; } @@ -384,7 +538,7 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree, spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS : VTYPE_NONPSEUDO_TE_IS); - listnode_add(spftree->paths, vertex); + isis_vertex_queue_add(&spftree->paths, vertex); #ifdef EXTREME_DEBUG zlog_debug("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS", @@ -396,35 +550,13 @@ static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree, return vertex; } -static struct isis_vertex *isis_find_vertex(struct list *list, void *id, +static struct isis_vertex *isis_find_vertex(struct isis_vertex_queue *queue, void *id, enum vertextype vtype) { - struct listnode *node; - struct isis_vertex *vertex; - struct prefix *p1, *p2; + struct isis_vertex querier; - for (ALL_LIST_ELEMENTS_RO(list, node, vertex)) { - if (vertex->type != vtype) - continue; - if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) { - if (memcmp((u_char *)id, vertex->N.id, - ISIS_SYS_ID_LEN + 1) - == 0) - return vertex; - } - if (VTYPE_IP(vertex->type)) { - p1 = (struct prefix *)id; - p2 = (struct prefix *)&vertex->N.id; - if (p1->family == p2->family - && p1->prefixlen == p2->prefixlen - && !memcmp(&p1->u.prefix, &p2->u.prefix, - PSIZE(p1->prefixlen))) { - return vertex; - } - } - } - - return NULL; + isis_vertex_id_init(&querier, id, vtype); + return hash_lookup(queue->hash, &querier); } /* @@ -442,6 +574,30 @@ static bool tent_cmp(struct isis_vertex *current, struct isis_vertex *candidate) return false; } +static void isis_vertex_queue_insert(struct isis_vertex_queue *queue, + struct isis_vertex *vertex) +{ + struct listnode *node; + struct isis_vertex *v; + + /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */ + for (node = listhead(queue->list); node; node = listnextnode(node)) { + v = listgetdata(node); + if (tent_cmp(v, vertex)) { + listnode_add_before(queue->list, node, vertex); + break; + } + } + + if (node == NULL) + listnode_add(queue->list, vertex); + + struct isis_vertex *inserted; + + inserted = hash_get(queue->hash, vertex, hash_alloc_intern); + assert(inserted == vertex); +} + /* * Add a vertex to TENT sorted by cost and by vertextype on tie break situation */ @@ -451,15 +607,15 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, struct isis_adjacency *adj, struct isis_vertex *parent) { - struct isis_vertex *vertex, *v; + struct isis_vertex *vertex; struct listnode *node; struct isis_adjacency *parent_adj; #ifdef EXTREME_DEBUG char buff[PREFIX2STR_BUFFER]; #endif - assert(isis_find_vertex(spftree->paths, id, vtype) == NULL); - assert(isis_find_vertex(spftree->tents, id, vtype) == NULL); + assert(isis_find_vertex(&spftree->paths, id, vtype) == NULL); + assert(isis_find_vertex(&spftree->tents, id, vtype) == NULL); vertex = isis_vertex_new(id, vtype); vertex->d_N = cost; vertex->depth = depth; @@ -485,23 +641,7 @@ static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, vertex->d_N, listcount(vertex->Adj_N)); #endif /* EXTREME_DEBUG */ - if (list_isempty(spftree->tents)) { - listnode_add(spftree->tents, vertex); - return vertex; - } - - /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */ - for (node = listhead(spftree->tents); node; node = listnextnode(node)) { - v = listgetdata(node); - if (tent_cmp(v, vertex)) { - listnode_add_before(spftree->tents, node, vertex); - break; - } - } - - if (node == NULL) - listnode_add(spftree->tents, vertex); - + isis_vertex_queue_insert(&spftree->tents, vertex); return vertex; } @@ -512,7 +652,7 @@ static void isis_spf_add_local(struct isis_spftree *spftree, { struct isis_vertex *vertex; - vertex = isis_find_vertex(spftree->tents, id, vtype); + vertex = isis_find_vertex(&spftree->tents, id, vtype); if (vertex) { /* C.2.5 c) */ @@ -536,7 +676,7 @@ static void isis_spf_add_local(struct isis_spftree *spftree, /* f) */ struct listnode *pnode, *pnextnode; struct isis_vertex *pvertex; - listnode_delete(spftree->tents, vertex); + isis_vertex_queue_delete(&spftree->tents, vertex); assert(listcount(vertex->children) == 0); for (ALL_LIST_ELEMENTS(vertex->parents, pnode, pnextnode, pvertex)) @@ -579,7 +719,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, } /* c) */ - vertex = isis_find_vertex(spftree->paths, id, vtype); + vertex = isis_find_vertex(&spftree->paths, id, vtype); if (vertex) { #ifdef EXTREME_DEBUG zlog_debug( @@ -591,7 +731,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, return; } - vertex = isis_find_vertex(spftree->tents, id, vtype); + vertex = isis_find_vertex(&spftree->tents, id, vtype); /* d) */ if (vertex) { /* 1) */ @@ -626,7 +766,7 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype, } else { struct listnode *pnode, *pnextnode; struct isis_vertex *pvertex; - listnode_delete(spftree->tents, vertex); + isis_vertex_queue_delete(&spftree->tents, vertex); assert(listcount(vertex->children) == 0); for (ALL_LIST_ELEMENTS(vertex->parents, pnode, pnextnode, pvertex)) @@ -1056,9 +1196,9 @@ static void add_to_paths(struct isis_spftree *spftree, { char buff[PREFIX2STR_BUFFER]; - if (isis_find_vertex(spftree->paths, vertex->N.id, vertex->type)) + if (isis_find_vertex(&spftree->paths, vertex->N.id, vertex->type)) return; - listnode_add(spftree->paths, vertex); + isis_vertex_queue_add(&spftree->paths, vertex); #ifdef EXTREME_DEBUG zlog_debug("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS", @@ -1087,11 +1227,8 @@ static void add_to_paths(struct isis_spftree *spftree, static void init_spt(struct isis_spftree *spftree, int mtid, int level, int family) { - spftree->tents->del = spftree->paths->del = - (void (*)(void *))isis_vertex_del; - list_delete_all_node(spftree->tents); - list_delete_all_node(spftree->paths); - spftree->tents->del = spftree->paths->del = NULL; + isis_vertex_queue_clear(&spftree->tents); + isis_vertex_queue_clear(&spftree->paths); spftree->mtid = mtid; spftree->level = level; @@ -1103,7 +1240,6 @@ static int isis_run_spf(struct isis_area *area, int level, int family, u_char *sysid) { int retval = ISIS_OK; - struct listnode *node; struct isis_vertex *vertex; struct isis_vertex *root_vertex; struct isis_spftree *spftree = NULL; @@ -1158,15 +1294,14 @@ static int isis_run_spf(struct isis_area *area, int level, int family, /* * C.2.7 Step 2 */ - if (listcount(spftree->tents) == 0) { + if (isis_vertex_queue_count(&spftree->tents) == 0) { zlog_warn("ISIS-Spf: TENT is empty SPF-root:%s", print_sys_hostname(sysid)); goto out; } - while (listcount(spftree->tents) > 0) { - node = listhead(spftree->tents); - vertex = listgetdata(node); + while (isis_vertex_queue_count(&spftree->tents)) { + vertex = isis_vertex_queue_pop(&spftree->tents); #ifdef EXTREME_DEBUG zlog_debug( @@ -1175,8 +1310,6 @@ static int isis_run_spf(struct isis_area *area, int level, int family, vtype2string(vertex->type), vertex->depth, vertex->d_N); #endif /* EXTREME_DEBUG */ - /* Remove from tent list and add to paths list */ - list_delete_node(spftree->tents, node); add_to_paths(spftree, vertex); if (VTYPE_IS(vertex->type)) { memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); @@ -1303,7 +1436,7 @@ int isis_spf_schedule(struct isis_area *area, int level) return ISIS_OK; } -static void isis_print_paths(struct vty *vty, struct list *paths, +static void isis_print_paths(struct vty *vty, struct isis_vertex_queue *queue, u_char *root_sysid) { struct listnode *node; @@ -1315,7 +1448,7 @@ static void isis_print_paths(struct vty *vty, struct list *paths, vty_out(vty, "Vertex Type Metric Next-Hop Interface Parent\n"); - for (ALL_LIST_ELEMENTS_RO(paths, node, vertex)) { + for (ALL_QUEUE_ELEMENTS_RO(queue, node, vertex)) { if (memcmp(vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) { vty_out(vty, "%-20s %-12s %-6s", print_sys_hostname(root_sysid), "", ""); @@ -1399,22 +1532,22 @@ DEFUN (show_isis_topology, continue; if (area->ip_circuits > 0 && area->spftree[level - 1] - && area->spftree[level - 1]->paths->count > 0) { + && isis_vertex_queue_count(&area->spftree[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[level - 1]->paths, + vty, &area->spftree[level - 1]->paths, isis->sysid); vty_out(vty, "\n"); } if (area->ipv6_circuits > 0 && area->spftree6[level - 1] - && area->spftree6[level - 1]->paths->count > 0) { + && isis_vertex_queue_count(&area->spftree6[level - 1]->paths) > 0) { vty_out(vty, "IS-IS paths to level-%d routers that speak IPv6\n", level); isis_print_paths( - vty, area->spftree6[level - 1]->paths, + vty, &area->spftree6[level - 1]->paths, isis->sysid); vty_out(vty, "\n"); } @@ -1430,3 +1563,16 @@ void isis_spf_cmds_init() { install_element(VIEW_NODE, &show_isis_topology_cmd); } + +void isis_spf_print(struct isis_spftree *spftree, struct vty *vty) +{ + vty_out(vty, " last run elapsed : "); + vty_out_timestr(vty, spftree->last_run_timestamp); + vty_out(vty, "\n"); + + vty_out(vty, " last run duration : %u usec\n", + (u_int32_t)spftree->last_run_duration); + + vty_out(vty, " run count : %u\n", + spftree->runcount); +} diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index c7a505489f..84e07861d2 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -24,53 +24,7 @@ #ifndef _ZEBRA_ISIS_SPF_H #define _ZEBRA_ISIS_SPF_H -enum vertextype { - VTYPE_PSEUDO_IS = 1, - VTYPE_PSEUDO_TE_IS, - VTYPE_NONPSEUDO_IS, - VTYPE_NONPSEUDO_TE_IS, - VTYPE_ES, - VTYPE_IPREACH_INTERNAL, - VTYPE_IPREACH_EXTERNAL, - VTYPE_IPREACH_TE, - VTYPE_IP6REACH_INTERNAL, - VTYPE_IP6REACH_EXTERNAL -}; - -#define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS) -#define VTYPE_ES(t) ((t) == VTYPE_ES) -#define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL) - -/* - * Triple <N, d(N), {Adj(N)}> - */ -struct isis_vertex { - enum vertextype type; - - union { - u_char id[ISIS_SYS_ID_LEN + 1]; - struct prefix prefix; - } N; - - u_int32_t d_N; /* d(N) Distance from this IS */ - u_int16_t depth; /* The depth in the imaginary tree */ - struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */ - struct list *parents; /* list of parents for ECMP */ - struct list *children; /* list of children used for tree dump */ -}; - -struct isis_spftree { - struct list *paths; /* the SPT */ - struct list *tents; /* TENT */ - struct isis_area *area; /* back pointer to area */ - unsigned int runcount; /* number of runs since uptime */ - time_t last_run_timestamp; /* last run timestamp for scheduling */ - time_t last_run_duration; /* last run duration in msec */ - - uint16_t mtid; - int family; - int level; -}; +struct isis_spftree; struct isis_spftree *isis_spftree_new(struct isis_area *area); void isis_spftree_del(struct isis_spftree *spftree); @@ -79,4 +33,5 @@ void spftree_area_del(struct isis_area *area); void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj); int isis_spf_schedule(struct isis_area *area, int level); void isis_spf_cmds_init(void); +void isis_spf_print(struct isis_spftree *spftree, struct vty *vty); #endif /* _ZEBRA_ISIS_SPF_H */ diff --git a/isisd/isisd.c b/isisd/isisd.c index 05797fb73a..60b9367da9 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1231,27 +1231,6 @@ DEFUN (show_hostname, return CMD_SUCCESS; } -static void vty_out_timestr(struct vty *vty, time_t uptime) -{ - struct tm *tm; - time_t difftime = time(NULL); - difftime -= uptime; - tm = gmtime(&difftime); - -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND 60*60*24*7 - if (difftime < ONE_DAY_SECOND) - vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, - tm->tm_sec); - else if (difftime < ONE_WEEK_SECOND) - vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, - tm->tm_min); - else - vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7, - tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); - vty_out(vty, " ago"); -} - DEFUN (show_isis_spf_ietf, show_isis_spf_ietf_cmd, "show isis spf-delay-ietf", @@ -1308,7 +1287,6 @@ DEFUN (show_isis_summary, { struct listnode *node, *node2; struct isis_area *area; - struct isis_spftree *spftree; int level; if (isis == NULL) { @@ -1349,7 +1327,6 @@ DEFUN (show_isis_summary, continue; vty_out(vty, " Level-%d:\n", level); - spftree = area->spftree[level - 1]; if (area->spf_timer[level - 1]) vty_out(vty, " SPF: (pending)\n"); else @@ -1363,28 +1340,10 @@ DEFUN (show_isis_summary, vty_out(vty, "\n"); vty_out(vty, " IPv4 route computation:\n"); - vty_out(vty, " last run elapsed : "); - vty_out_timestr(vty, spftree->last_run_timestamp); - vty_out(vty, "\n"); - - vty_out(vty, " last run duration : %u usec\n", - (u_int32_t)spftree->last_run_duration); + isis_spf_print(area->spftree[level - 1], vty); - vty_out(vty, " run count : %d\n", - spftree->runcount); - - spftree = area->spftree6[level - 1]; vty_out(vty, " IPv6 route computation:\n"); - - vty_out(vty, " last run elapsed : "); - vty_out_timestr(vty, spftree->last_run_timestamp); - vty_out(vty, "\n"); - - vty_out(vty, " last run duration : %llu msec\n", - (unsigned long long)spftree->last_run_duration); - - vty_out(vty, " run count : %d\n", - spftree->runcount); + isis_spf_print(area->spftree6[level - 1], vty); } } vty_out(vty, "\n"); diff --git a/isisd/isisd.h b/isisd/isisd.h index 1aacea881f..da02854f5c 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -37,7 +37,7 @@ /* uncomment if you are a developer in bug hunt */ /* #define EXTREME_DEBUG */ -/* #define EXTREME_TLV_DEBUG */ +/* #define EXTREME_DICT_DEBUG */ struct isis { u_long process_id; diff --git a/lib/hash.c b/lib/hash.c index e74e4355dc..801871f839 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -358,33 +358,26 @@ DEFUN(show_hash_stats, /* Summary statistics calculated are: * - * - Load factor: This is the number of elements in the table divided by - * the - * number of buckets. Since this hash table implementation uses - * chaining, - * this value can be greater than 1. This number provides information - * on - * how 'full' the table is, but does not provide information on how - * evenly - * distributed the elements are. Notably, a load factor >= 1 does not - * imply - * that every bucket has an element; with a pathological hash - * function, all - * elements could be in a single bucket. + * - Load factor: This is the number of elements in the table divided + * by the number of buckets. Since this hash table implementation + * uses chaining, this value can be greater than 1. + * This number provides information on how 'full' the table is, but + * does not provide information on how evenly distributed the + * elements are. + * Notably, a load factor >= 1 does not imply that every bucket has + * an element; with a pathological hash function, all elements could + * be in a single bucket. * * - Full load factor: this is the number of elements in the table - * divided by - * the number of buckets that have some elements in them. + * divided by the number of buckets that have some elements in them. * * - Std. Dev.: This is the standard deviation calculated from the - * relevant - * load factor. If the load factor is the mean of number of elements - * per - * bucket, the standard deviation measures how much any particular - * bucket - * is likely to deviate from the mean. As a rule of thumb this number - * should be less than 2, and ideally <= 1 for optimal performance. A - * number larger than 3 generally indicates a poor hash function. + * relevant load factor. If the load factor is the mean of number of + * elements per bucket, the standard deviation measures how much any + * particular bucket is likely to deviate from the mean. + * As a rule of thumb this number should be less than 2, and ideally + * <= 1 for optimal performance. A number larger than 3 generally + * indicates a poor hash function. */ double lf; // load factor @@ -411,7 +404,7 @@ DEFUN(show_hash_stats, continue; ssq = (long double)h->stats.ssq; - x2 = powl(h->count, 2.0); + x2 = h->count * h->count; ldc = (long double)h->count; full = h->size - h->stats.empty; lf = h->count / (double)h->size; diff --git a/lib/prefix.c b/lib/prefix.c index 0ba0025c68..47e16dbf8b 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -26,6 +26,7 @@ #include "sockunion.h" #include "memory.h" #include "log.h" +#include "jhash.h" DEFINE_MTYPE_STATIC(LIB, PREFIX, "Prefix") @@ -1335,3 +1336,15 @@ char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size) (uint8_t)mac->octet[4], (uint8_t)mac->octet[5]); return ptr; } + +unsigned prefix_hash_key(void *pp) +{ + struct prefix copy; + + /* make sure *all* unused bits are zero, particularly including + * alignment / + * padding and unused prefix bytes. */ + memset(©, 0, sizeof(copy)); + prefix_copy(©, (struct prefix *)pp); + return jhash(©, sizeof(copy), 0x55aa5a5a); +} diff --git a/lib/prefix.h b/lib/prefix.h index ce13dcfa0a..4f1f0b22d7 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -323,6 +323,8 @@ extern const char *inet6_ntoa(struct in6_addr); extern int prefix_str2mac(const char *str, struct ethaddr *mac); extern char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size); +extern unsigned prefix_hash_key(void *pp); + static inline int ipv6_martian(struct in6_addr *addr) { struct in6_addr localhost_addr; diff --git a/lib/table.c b/lib/table.c index 007d41778e..833adb9a37 100644 --- a/lib/table.c +++ b/lib/table.c @@ -27,7 +27,6 @@ #include "table.h" #include "memory.h" #include "sockunion.h" -#include "jhash.h" DEFINE_MTYPE(LIB, ROUTE_TABLE, "Route table") DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node") @@ -35,18 +34,6 @@ DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node") static void route_node_delete(struct route_node *); static void route_table_free(struct route_table *); -static unsigned route_table_hash_key(void *pp) -{ - struct prefix copy; - - /* make sure *all* unused bits are zero, particularly including - * alignment / - * padding and unused prefix bytes. */ - memset(©, 0, sizeof(copy)); - prefix_copy(©, (struct prefix *)pp); - return jhash(©, sizeof(copy), 0x55aa5a5a); -} - static int route_table_hash_cmp(const void *a, const void *b) { const struct prefix *pa = a, *pb = b; @@ -63,7 +50,7 @@ route_table_init_with_delegate(route_table_delegate_t *delegate) rt = XCALLOC(MTYPE_ROUTE_TABLE, sizeof(struct route_table)); rt->delegate = delegate; - rt->hash = hash_create(route_table_hash_key, route_table_hash_cmp, + rt->hash = hash_create(prefix_hash_key, route_table_hash_cmp, "route table hash"); return rt; } diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c index bd884bbc51..3ebdbf27ba 100644 --- a/nhrpd/nhrp_cache.c +++ b/nhrpd/nhrp_cache.c @@ -289,7 +289,7 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type, i if (holding_time > 0) c->new.expires = monotime(NULL) + holding_time; else if (holding_time < 0) - c->new.type = NHRP_CACHE_INVALID; + nhrp_cache_reset_new(c); if (c->new.type == NHRP_CACHE_INVALID || c->new.type >= NHRP_CACHE_STATIC || diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index 7c5d80336c..012d5cd87c 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -128,8 +128,8 @@ int main(int argc, char **argv) /* Library inits. */ master = frr_init(); - nhrp_interface_init(); vrf_init(NULL, NULL, NULL, NULL); + nhrp_interface_init(); resolver_init(); /* Run with elevated capabilities, as for all netlink activity diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 89972f8f98..c8a608c657 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -205,17 +205,18 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i /* Type, flags, message. */ /*type =*/ stream_getc(s); - /*flags =*/ stream_getc(s); + /*instance =*/ stream_getw(s); + /*flags =*/ stream_getl(s); message = stream_getc(s); /* Prefix */ switch (cmd) { - case ZEBRA_IPV4_ROUTE_ADD: - case ZEBRA_IPV4_ROUTE_DELETE: + case ZEBRA_REDISTRIBUTE_IPV4_ADD: + case ZEBRA_REDISTRIBUTE_IPV4_DEL: prefix.family = AF_INET; break; - case ZEBRA_IPV6_ROUTE_ADD: - case ZEBRA_IPV6_ROUTE_DELETE: + case ZEBRA_REDISTRIBUTE_IPV6_ADD: + case ZEBRA_REDISTRIBUTE_IPV6_DEL: prefix.family = AF_INET6; break; default: @@ -244,7 +245,7 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) /*metric =*/ stream_getl(s); - added = (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV6_ROUTE_ADD); + added = (cmd == ZEBRA_REDISTRIBUTE_IPV4_ADD || cmd == ZEBRA_REDISTRIBUTE_IPV6_ADD); debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s", added ? "add" : "del", prefix2str(&prefix, buf[0], sizeof buf[0]), @@ -342,12 +343,23 @@ enum nhrp_route_type nhrp_route_address(struct interface *in_ifp, union sockunio return NHRP_ROUTE_BLACKHOLE; } +static void +nhrp_zebra_connected (struct zclient *zclient) +{ + zclient_send_reg_requests(zclient, VRF_DEFAULT); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, + ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, + ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); +} + void nhrp_zebra_init(void) { zebra_rib[AFI_IP] = route_table_init(); zebra_rib[AFI_IP6] = route_table_init(); zclient = zclient_new(master); + zclient->zebra_connected = nhrp_zebra_connected; zclient->interface_add = nhrp_interface_add; zclient->interface_delete = nhrp_interface_delete; zclient->interface_up = nhrp_interface_up; @@ -360,20 +372,6 @@ void nhrp_zebra_init(void) zclient->redistribute_route_ipv6_del = nhrp_route_read; zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_KERNEL, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_CONNECT, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_STATIC, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_RIP, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_OSPF, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_ISIS, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, ZEBRA_ROUTE_BGP, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_KERNEL, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_CONNECT, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_STATIC, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_RIP, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_OSPF, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_ISIS, 0, VRF_DEFAULT); - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, ZEBRA_ROUTE_BGP, 0, VRF_DEFAULT); } void nhrp_zebra_terminate(void) diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 1aa25b41d0..6adb25f322 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -684,9 +684,11 @@ static void daemon_send_ready(void) fp = fopen(DAEMON_VTY_DIR "/watchfrr.started", "w"); fclose(fp); +#if defined HAVE_SYSTEMD zlog_notice( "Watchfrr: Notifying Systemd we are up and running"); systemd_send_started(master, 0); +#endif sent = 1; } } diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index dfc3f6211d..015e11b3a5 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -262,8 +262,9 @@ static int netlink_information_fetch(struct sockaddr_nl *snl, return netlink_neigh_change(snl, h, ns_id); break; default: - zlog_warn("Unknown netlink nlmsg_type %d vrf %u\n", - h->nlmsg_type, ns_id); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Unknown netlink nlmsg_type %d vrf %u\n", + h->nlmsg_type, ns_id); break; } return 0; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 9b31e467c7..887ea4794d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1706,11 +1706,11 @@ static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h, if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) { zlog_warn( - "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld", + "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu", nl_msg_type_to_str(h->nlmsg_type), nl_family_to_str(ndm->ndm_family), ifp->name, ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex, - RTA_PAYLOAD(tb[NDA_LLADDR])); + (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR])); return 0; } @@ -2035,11 +2035,11 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, if (tb[NDA_LLADDR]) { if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) { zlog_warn( - "%s family %s IF %s(%u) - LLADDR is not MAC, len %ld", + "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu", nl_msg_type_to_str(h->nlmsg_type), nl_family_to_str(ndm->ndm_family), ifp->name, ndm->ndm_ifindex, - RTA_PAYLOAD(tb[NDA_LLADDR])); + (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR])); return 0; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 98508aaa89..e61c2e7b0e 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -505,6 +505,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re, } resolved = 1; } + if (resolved && set) + re->nexthop_mtu = match->mtu; return resolved; } else if (re->type == ZEBRA_ROUTE_STATIC) { resolved = 0; @@ -2237,13 +2239,12 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, continue; if (same->type == re->type && same->instance == re->instance - && same->table == re->table - && same->type != ZEBRA_ROUTE_CONNECT) + && same->table == re->table && !RIB_SYSTEM_ROUTE(same)) break; } /* If this route is kernel route, set FIB flag to the route. */ - if (re->type == ZEBRA_ROUTE_KERNEL || re->type == ZEBRA_ROUTE_CONNECT) + if (RIB_SYSTEM_ROUTE(re)) for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); @@ -2467,11 +2468,11 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, continue; if (re->instance != instance) continue; - if (re->type != ZEBRA_ROUTE_CONNECT) { + if (!RIB_SYSTEM_ROUTE(re)) { same = re; break; } - /* Duplicate connected route comes in. */ + /* Duplicate system route comes in. */ else if ((nexthop = re->nexthop) && nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex @@ -2515,7 +2516,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, route_entry_nexthop_ifindex_add(re, ifindex); /* If this route is kernel route, set FIB flag to the route. */ - if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) + if (RIB_SYSTEM_ROUTE(re)) for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 8a326c27fc..8ab46f683c 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -815,6 +815,7 @@ static void copy_state(struct rnh *rnh, struct route_entry *re, state = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); state->type = re->type; + state->distance = re->distance; state->metric = re->metric; route_entry_copy_nexthops(state, re->nexthop); @@ -830,6 +831,9 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2) if ((!r1 && r2) || (r1 && !r2)) return 1; + if (r1->distance != r2->distance) + return 1; + if (r1->metric != r2->metric) return 1; diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 0176b36840..c738cde0ac 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -256,7 +256,7 @@ DEFUN (no_match_ip_nexthop_prefix_len, DEFUN (match_source_protocol, match_source_protocol_cmd, - "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>", + "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>", MATCH_STR "Match protocol via which the route was learnt\n" "BGP protocol\n" @@ -265,6 +265,10 @@ DEFUN (match_source_protocol, "RIPNG protocol\n" "ISIS protocol\n" "OSPF6 protocol\n" + "PIM protocol\n" + "NHRP protocol\n" + "EIGRP protocol\n" + "BABEL protocol\n" "Routes from directly connected peer\n" "Routes from system configuration\n" "Routes from kernel\n" @@ -284,7 +288,7 @@ DEFUN (match_source_protocol, DEFUN (no_match_source_protocol, no_match_source_protocol_cmd, - "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|connected|system|kernel|static>]", + "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>]", NO_STR MATCH_STR "No match protocol via which the route was learnt\n" @@ -294,6 +298,10 @@ DEFUN (no_match_source_protocol, "RIPNG protocol\n" "ISIS protocol\n" "OSPF6 protocol\n" + "PIM protocol\n" + "NHRP protocol\n" + "EIGRP protocol\n" + "BABEL protocol\n" "Routes from directly connected peer\n" "Routes from system configuration\n" "Routes from kernel\n" diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index e8b82ecf90..13c4429d6a 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -540,6 +540,9 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, break; } + if (re->nexthop_mtu) + vty_out(vty, ", mtu %u", re->nexthop_mtu); + /* Label information */ if (nexthop->nh_label && nexthop->nh_label->num_labels) { @@ -586,8 +589,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) json_object_boolean_true_add(json_route, "selected"); - if (re->type != ZEBRA_ROUTE_CONNECT - && re->type != ZEBRA_ROUTE_KERNEL) { + if (re->type != ZEBRA_ROUTE_CONNECT) { json_object_int_add(json_route, "distance", re->distance); json_object_int_add(json_route, "metric", re->metric); @@ -774,8 +776,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, srcdest_rnode2str(rn, buf, sizeof buf)); /* Distance and metric display. */ - if (re->type != ZEBRA_ROUTE_CONNECT - && re->type != ZEBRA_ROUTE_KERNEL) + if (re->type != ZEBRA_ROUTE_CONNECT) len += vty_out(vty, " [%d/%d]", re->distance, re->metric); } else |
