diff options
| -rw-r--r-- | bgpd/bgpd.c | 4 | ||||
| -rw-r--r-- | eigrpd/eigrp_packet.c | 5 | ||||
| -rw-r--r-- | lib/routemap.h | 10 | ||||
| -rw-r--r-- | lib/table.c | 1 | ||||
| -rw-r--r-- | lib/thread.c | 76 | ||||
| -rw-r--r-- | lib/thread.h | 1 | ||||
| -rw-r--r-- | ospfd/ospf_abr.c | 2 | ||||
| -rw-r--r-- | ospfd/ospf_interface.c | 2 | ||||
| -rw-r--r-- | ospfd/ospf_route.c | 1 | ||||
| -rw-r--r-- | ospfd/ospf_routemap.c | 21 | ||||
| -rw-r--r-- | pimd/pim_instance.c | 4 | ||||
| -rw-r--r-- | ripd/rip_routemap.c | 40 | ||||
| -rw-r--r-- | ripngd/ripng_routemap.c | 42 | ||||
| -rw-r--r-- | vtysh/vtysh_main.c | 4 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 63 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 64 | ||||
| -rw-r--r-- | zebra/zebra_static.c | 18 | ||||
| -rw-r--r-- | zebra/zebra_static.h | 14 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 34 |
19 files changed, 267 insertions, 139 deletions
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d147055749..86eea1b220 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3187,6 +3187,7 @@ void bgp_free(struct bgp *bgp) safi_t safi; struct bgp_table *table; struct bgp_node *rn; + struct bgp_rmap *rmap; QOBJ_UNREG(bgp); @@ -3215,6 +3216,9 @@ void bgp_free(struct bgp *bgp) bgp_table_finish(&bgp->aggregate[afi][safi]); if (bgp->rib[afi][safi]) bgp_table_finish(&bgp->rib[afi][safi]); + rmap = &bgp->table_map[afi][safi]; + if (rmap->name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); } bgp_scan_finish(bgp); diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 8a7d4d9587..d2bff74a54 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -272,6 +272,7 @@ int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s, if (!key) { zlog_warn("Interface %s: Expected key value not found in config", ei->ifp->name); + eigrp_authTLV_SHA256_free(auth_TLV); return 0; } @@ -622,8 +623,8 @@ int eigrp_read(struct thread *thread) if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) { char src[PREFIX_STRLEN], dst[PREFIX_STRLEN]; - strncpy(src, inet_ntoa(iph->ip_src), PREFIX_STRLEN); - strncpy(dst, inet_ntoa(iph->ip_dst), PREFIX_STRLEN); + strlcpy(src, inet_ntoa(iph->ip_src), sizeof(src)); + strlcpy(dst, inet_ntoa(iph->ip_dst), sizeof(dst)); zlog_debug("Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]", lookup_msg(eigrp_packet_type_str, opcode, NULL), ntohl(eigrph->sequence), ntohl(eigrph->ack), length, diff --git a/lib/routemap.h b/lib/routemap.h index b166de1e09..8c00e8104c 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -194,7 +194,15 @@ extern int route_map_delete_set(struct route_map_index *index, /* Install rule command to the match list. */ extern void route_map_install_match(struct route_map_rule_cmd *cmd); -/* Install rule command to the set list. */ +/* + * Install rule command to the set list. + * + * When installing a particular item, Allow a difference of handling + * of bad cli inputted(return NULL) -vs- this particular daemon cannot use + * this form of the command(return a pointer and handle it appropriately + * in the apply command). See 'set metric' command + * as it is handled in ripd/ripngd and ospfd. + */ extern void route_map_install_set(struct route_map_rule_cmd *cmd); /* Lookup route map by name. */ diff --git a/lib/table.c b/lib/table.c index 67cf6aeec3..b0b0d24ea0 100644 --- a/lib/table.c +++ b/lib/table.c @@ -281,6 +281,7 @@ struct route_node *route_node_get(struct route_table *const table, u_char prefixlen = p->prefixlen; const u_char *prefix = &p->u.prefix; + apply_mask((struct prefix *)p); node = hash_get(table->hash, (void *)p, NULL); if (node && node->info) return route_lock_node(node); diff --git a/lib/thread.c b/lib/thread.c index 4a5c61d036..b39f2d55c2 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -47,9 +47,6 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") write(m->io_pipe[1], &wakebyte, 1); \ } while (0); -/* max # of thread_fetch() calls before we force a poll() */ -#define MAX_TICK_IO 1000 - /* control variable for initializer */ pthread_once_t init_once = PTHREAD_ONCE_INIT; pthread_key_t thread_current; @@ -552,7 +549,7 @@ void thread_master_free(struct thread_master *m) { listnode_delete(masters, m); if (masters->count == 0) { - list_free (masters); + list_free(masters); masters = NULL; } } @@ -1320,6 +1317,20 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch) do_thread_cancel(m); /* + * Attempt to flush ready queue before going into poll(). + * This is performance-critical. Think twice before modifying. + */ + if ((thread = thread_trim_head(&m->ready))) { + fetch = thread_run(m, thread, fetch); + if (fetch->ref) + *fetch->ref = NULL; + pthread_mutex_unlock(&m->mtx); + break; + } + + /* otherwise, tick through scheduling sequence */ + + /* * Post events to ready queue. This must come before the * following block since events should occur immediately */ @@ -1362,44 +1373,26 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch) memcpy(m->handler.copy, m->handler.pfds, m->handler.copycount * sizeof(struct pollfd)); - /* - * Attempt to flush ready queue before going into poll(). - * This is performance-critical. Think twice before modifying. - */ - if (m->ready.count == 0 || m->tick_since_io >= MAX_TICK_IO) { - pthread_mutex_unlock(&m->mtx); - { - m->tick_since_io = 0; - num = fd_poll(m, m->handler.copy, - m->handler.pfdsize, - m->handler.copycount, tw); - } - pthread_mutex_lock(&m->mtx); - - /* Handle any errors received in poll() */ - if (num < 0) { - if (errno == EINTR) { - pthread_mutex_unlock(&m->mtx); - /* loop around to signal handler */ - continue; - } + pthread_mutex_unlock(&m->mtx); + { + num = fd_poll(m, m->handler.copy, m->handler.pfdsize, + m->handler.copycount, tw); + } + pthread_mutex_lock(&m->mtx); - /* else die */ - zlog_warn("poll() error: %s", - safe_strerror(errno)); + /* Handle any errors received in poll() */ + if (num < 0) { + if (errno == EINTR) { pthread_mutex_unlock(&m->mtx); - fetch = NULL; - break; + /* loop around to signal handler */ + continue; } - /* - * Since we could have received more cancellation - * requests during poll(), process those - */ - do_thread_cancel(m); - - } else { - m->tick_since_io++; + /* else die */ + zlog_warn("poll() error: %s", safe_strerror(errno)); + pthread_mutex_unlock(&m->mtx); + fetch = NULL; + break; } /* Post timers to ready queue. */ @@ -1410,13 +1403,6 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch) if (num > 0) thread_process_io(m, num); - /* have a ready task ==> return it to caller */ - if ((thread = thread_trim_head(&m->ready))) { - fetch = thread_run(m, thread, fetch); - if (fetch->ref) - *fetch->ref = NULL; - } - pthread_mutex_unlock(&m->mtx); } while (!thread && m->spin); diff --git a/lib/thread.h b/lib/thread.h index 86bf4df7c0..c830446e10 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -70,7 +70,6 @@ struct cancel_req { struct thread_master { char *name; - int tick_since_io; struct thread **read; struct thread **write; struct pqueue *timer; diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index c6d4364fa3..968461b4d0 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -76,6 +76,7 @@ static void ospf_area_range_add(struct ospf_area *area, p.family = AF_INET; p.prefixlen = range->masklen; p.prefix = range->addr; + apply_mask_ipv4(&p); rn = route_node_get(area->ranges, (struct prefix *)&p); if (rn->info) @@ -123,6 +124,7 @@ struct ospf_area_range *ospf_area_range_lookup_next(struct ospf_area *area, p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; p.prefix = *range_net; + apply_mask_ipv4(&p); if (first) rn = route_top(area->ranges); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 54639afd6c..422e1a2a6b 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -171,6 +171,7 @@ static void ospf_add_to_if(struct interface *ifp, struct ospf_interface *oi) p = *oi->address; p.prefixlen = IPV4_MAX_PREFIXLEN; + apply_mask(&p); rn = route_node_get(IF_OIFS(ifp), &p); /* rn->info should either be NULL or equal to this oi @@ -562,6 +563,7 @@ struct ospf_if_params *ospf_get_if_params(struct interface *ifp, p.family = AF_INET; p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefix = addr; + apply_mask_ipv4(&p); rn = route_node_get(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 9c4dca2e2f..89ea331b52 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -356,6 +356,7 @@ void ospf_intra_add_router(struct route_table *rt, struct vertex *v, p.family = AF_INET; p.prefix = v->id; p.prefixlen = IPV4_MAX_BITLEN; + apply_mask_ipv4(&p); if (IS_DEBUG_OSPF_EVENT) zlog_debug("ospf_intra_add_router: talking about %s/%d", diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index 547e1e8f53..f47e2b6f1e 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -336,6 +336,10 @@ static struct route_map_rule_cmd route_match_tag_cmd = { route_map_rule_tag_free, }; +struct ospf_metric { + bool used; + u_int32_t metric; +}; /* `set metric METRIC' */ /* Set metric to attribute. */ @@ -343,7 +347,7 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - u_int32_t *metric; + struct ospf_metric *metric; struct external_info *ei; if (type == RMAP_OSPF) { @@ -352,7 +356,8 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, ei = object; /* Set metric out value. */ - ei->route_map_set.metric = *metric; + if (metric->used) + ei->route_map_set.metric = metric->metric; } return RMAP_OKAY; } @@ -360,7 +365,10 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, /* set metric compilation. */ static void *route_set_metric_compile(const char *arg) { - u_int32_t *metric; + struct ospf_metric *metric; + + metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); + metric->used = false; /* OSPF doesn't support the +/- in set metric <+/-metric> check @@ -373,11 +381,12 @@ static void *route_set_metric_compile(const char *arg) if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt")) zlog_warn( "OSPF does not support 'set metric +rtt / -rtt'"); - return NULL; + + return metric; } } - metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); - *metric = strtoul(arg, NULL, 10); + metric->metric = strtoul(arg, NULL, 10); + metric->used = true; return metric; } diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index d1f8085b48..5a59342947 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -202,9 +202,9 @@ static int pim_vrf_config_write(struct vty *vty) if (vrf->vrf_id == VRF_DEFAULT) continue; - vty_out(vty, "vrf %s\n", vrf->name); + vty_frame(vty, "vrf %s\n", vrf->name); pim_global_config_write_worker(pim, vty); - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); } return 0; diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 7255df5e67..ad9f8cf80b 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -36,8 +36,8 @@ struct rip_metric_modifier { enum { metric_increment, metric_decrement, metric_absolute } type; - - u_char metric; + bool used; + u_int8_t metric; }; /* Hook function for updating route_map assignment. */ @@ -365,6 +365,9 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, mod = rule; rinfo = object; + if (!mod->used) + return RMAP_OKAY; + if (mod->type == metric_increment) rinfo->metric_out += mod->metric; else if (mod->type == metric_decrement) @@ -387,43 +390,48 @@ static void *route_set_metric_compile(const char *arg) { int len; const char *pnt; - int type; long metric; char *endptr = NULL; struct rip_metric_modifier *mod; + mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rip_metric_modifier)); + mod->used = false; + len = strlen(arg); pnt = arg; if (len == 0) - return NULL; + return mod; /* Examine first character. */ if (arg[0] == '+') { - type = metric_increment; + mod->type = metric_increment; pnt++; } else if (arg[0] == '-') { - type = metric_decrement; + mod->type = metric_decrement; pnt++; } else - type = metric_absolute; + mod->type = metric_absolute; /* Check beginning with digit string. */ if (*pnt < '0' || *pnt > '9') - return NULL; + return mod; /* Convert string to integer. */ metric = strtol(pnt, &endptr, 10); - if (metric == LONG_MAX || *endptr != '\0') - return NULL; - if (metric < 0 || metric > RIP_METRIC_INFINITY) - return NULL; + if (*endptr != '\0' || metric < 0) { + return mod; + } + if (metric > RIP_METRIC_INFINITY) { + zlog_info("%s: Metric specified: %ld is greater than RIP_METRIC_INFINITY, using INFINITY instead", + __PRETTY_FUNCTION__, metric); + mod->metric = RIP_METRIC_INFINITY; + } else + mod->metric = metric; - mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, - sizeof(struct rip_metric_modifier)); - mod->type = type; - mod->metric = metric; + mod->used = true; return mod; } diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index 3080801fb3..e518585c74 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -32,8 +32,8 @@ struct rip_metric_modifier { enum { metric_increment, metric_decrement, metric_absolute } type; - - u_char metric; + bool used; + u_int8_t metric; }; /* `match metric METRIC' */ @@ -168,6 +168,9 @@ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, mod = rule; rinfo = object; + if (!mod->used) + return RMAP_OKAY; + if (mod->type == metric_increment) rinfo->metric_out += mod->metric; else if (mod->type == metric_decrement) @@ -190,7 +193,6 @@ static void *route_set_metric_compile(const char *arg) { int len; const char *pnt; - int type; long metric; char *endptr = NULL; struct rip_metric_modifier *mod; @@ -198,38 +200,42 @@ static void *route_set_metric_compile(const char *arg) len = strlen(arg); pnt = arg; + mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rip_metric_modifier)); + mod->used = false; + if (len == 0) - return NULL; + return mod; /* Examine first character. */ if (arg[0] == '+') { - type = metric_increment; + mod->type = metric_increment; pnt++; } else if (arg[0] == '-') { - type = metric_decrement; + mod->type = metric_decrement; pnt++; } else - type = metric_absolute; + mod->type = metric_absolute; /* Check beginning with digit string. */ if (*pnt < '0' || *pnt > '9') - return NULL; + return mod; /* Convert string to integer. */ metric = strtol(pnt, &endptr, 10); - if (metric == LONG_MAX || *endptr != '\0') - return NULL; - /* Commented out by Hasso Tepper, to avoid problems in vtysh. */ - /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */ - if (metric < 0) - return NULL; + if (*endptr != '\0' || metric < 0) + return mod; - mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, - sizeof(struct rip_metric_modifier)); - mod->type = type; - mod->metric = metric; + if (metric > RIPNG_METRIC_INFINITY) { + zlog_info("%s: Metric specified: %ld is being converted into METRIC_INFINITY", + __PRETTY_FUNCTION__, + metric); + mod->metric = RIPNG_METRIC_INFINITY; + } else + mod->metric = metric; + mod->used = true; return mod; } diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index f4c21e69cd..003853571f 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -179,7 +179,7 @@ struct option longopts[] = { {"noerror", no_argument, NULL, 'n'}, {"mark", no_argument, NULL, 'm'}, {"writeconfig", no_argument, NULL, 'w'}, - {"pathspace", no_argument, NULL, 'N'}, + {"pathspace", required_argument, NULL, 'N'}, {0}}; /* Read a string, and return a pointer to it. Returns NULL on EOF. */ @@ -318,7 +318,7 @@ int main(int argc, char **argv, char **env) /* Option handling. */ while (1) { - opt = getopt_long(argc, argv, "be:c:d:nf:mEhCw", longopts, 0); + opt = getopt_long(argc, argv, "be:c:d:nf:mEhCwN:", longopts, 0); if (opt == EOF) break; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index f05025e630..12b6185395 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -148,14 +148,15 @@ static inline int is_selfroute(int proto) || (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA) || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG) || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) - || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) { + || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL) + || (proto == RTPROT_RIP)) { return 1; } return 0; } -static inline int get_rt_proto(int proto) +static inline int zebra2proto(int proto) { switch (proto) { case ZEBRA_ROUTE_BABEL: @@ -197,6 +198,47 @@ static inline int get_rt_proto(int proto) return proto; } +static inline int proto2zebra(int proto, int family) +{ + switch (proto) { + case RTPROT_BABEL: + proto = ZEBRA_ROUTE_BABEL; + break; + case RTPROT_BGP: + proto = ZEBRA_ROUTE_BGP; + break; + case RTPROT_OSPF: + proto = (family == AFI_IP) ? + ZEBRA_ROUTE_OSPF : ZEBRA_ROUTE_OSPF6; + break; + case RTPROT_ISIS: + proto = ZEBRA_ROUTE_ISIS; + break; + case RTPROT_RIP: + proto = ZEBRA_ROUTE_RIP; + break; + case RTPROT_RIPNG: + proto = ZEBRA_ROUTE_RIPNG; + break; + case RTPROT_NHRP: + proto = ZEBRA_ROUTE_NHRP; + break; + case RTPROT_EIGRP: + proto = ZEBRA_ROUTE_EIGRP; + break; + case RTPROT_LDP: + proto = ZEBRA_ROUTE_LDP; + break; + case RTPROT_STATIC: + proto = ZEBRA_ROUTE_STATIC; + break; + default: + proto = ZEBRA_ROUTE_KERNEL; + break; + } + return proto; +} + /* Pending: create an efficient table_id (in a tree/hash) based lookup) */ @@ -231,6 +273,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, char anyaddr[16] = {0}; + int proto = ZEBRA_ROUTE_KERNEL; int index = 0; int table; int metric = 0; @@ -300,9 +343,10 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, } /* Route which inserted by Zebra. */ - if (is_selfroute(rtm->rtm_protocol)) + if (is_selfroute(rtm->rtm_protocol)) { flags |= ZEBRA_FLAG_SELFROUTE; - + proto = proto2zebra(rtm->rtm_protocol, rtm->rtm_family); + } if (tb[RTA_OIF]) index = *(int *)RTA_DATA(tb[RTA_OIF]); @@ -409,7 +453,8 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, memcpy(&nh.src, prefsrc, sz); if (gate) memcpy(&nh.gate, gate, sz); - rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + + rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, NULL, &nh, table, metric, mtu, 0); } else { /* This is a multipath route */ @@ -421,7 +466,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); - re->type = ZEBRA_ROUTE_KERNEL; + re->type = proto; re->distance = 0; re->flags = flags; re->metric = metric; @@ -515,13 +560,13 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, if (gate) memcpy(&nh.gate, gate, sz); rib_delete(afi, SAFI_UNICAST, vrf_id, - ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, &nh, + proto, 0, flags, &p, NULL, &nh, table, metric); } else { /* XXX: need to compare the entire list of nexthops * here for NLM_F_APPEND stupidity */ rib_delete(afi, SAFI_UNICAST, vrf_id, - ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, NULL, + proto, 0, flags, &p, NULL, NULL, table, metric); } } @@ -1272,7 +1317,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p, req.r.rtm_family = family; req.r.rtm_dst_len = p->prefixlen; req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; - req.r.rtm_protocol = get_rt_proto(re->type); + req.r.rtm_protocol = zebra2proto(re->type); req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index deb434bd35..d74f84a1f6 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2072,8 +2072,9 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, for (ALL_NEXTHOPS(re->nexthop, nexthop)) { inet_ntop(p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN); - zlog_debug("%s: %s %s with flags %s%s%s", func, + zlog_debug("%s: %s %s[%u] with flags %s%s%s", func, (nexthop->rparent ? " NH" : "NH"), straddr, + nexthop->ifindex, (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""), @@ -2644,23 +2645,50 @@ static void rib_sweep_table(struct route_table *table) struct route_node *rn; struct route_entry *re; struct route_entry *next; + struct nexthop *nexthop; int ret = 0; - if (table) - for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) - RNODE_FOREACH_RE_SAFE(rn, re, next) - { - if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) - continue; + if (!table) + return; - if (re->type == ZEBRA_ROUTE_KERNEL - && CHECK_FLAG(re->flags, - ZEBRA_FLAG_SELFROUTE)) { - ret = rib_uninstall_kernel(rn, re); - if (!ret) - rib_delnode(rn, re); - } - } + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (IS_ZEBRA_DEBUG_RIB) + route_entry_dump(&rn->p, NULL, re); + + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE)) + continue; + + /* + * So we are starting up and have received + * routes from the kernel that we have installed + * from a previous run of zebra but not cleaned + * up ( say a kill -9 ) + * But since we haven't actually installed + * them yet( we received them from the kernel ) + * we don't think they are active. + * So let's pretend they are active to actually + * remove them. + * In all honesty I'm not sure if we should + * mark them as active when we receive them + * This is startup only so probably ok. + * + * If we ever decide to move rib_sweep_table + * to a different spot (ie startup ) + * this decision needs to be revisited + */ + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + + ret = rib_uninstall_kernel(rn, re); + if (!ret) + rib_delnode(rn, re); + } + } } /* Sweep all RIB tables. */ @@ -2669,8 +2697,10 @@ void rib_sweep_route(void) struct vrf *vrf; struct zebra_vrf *zvrf; - RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) { + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) { + if ((zvrf = vrf->info) == NULL) + continue; + rib_sweep_table(zvrf->table[AFI_IP][SAFI_UNICAST]); rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]); } diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index ec6d406325..658f060fff 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -45,6 +45,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p, struct route_table *table; struct prefix nh_p; struct nexthop *nexthop = NULL; + enum blackhole_type bh_type = 0; /* Lookup table. */ table = zebra_vrf_table(afi, safi, si->vrf_id); @@ -52,6 +53,17 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p, return; memset(&nh_p, 0, sizeof(nh_p)); + if (si->type == STATIC_BLACKHOLE) { + switch (si->bh_type) { + case STATIC_BLACKHOLE_DROP: + case STATIC_BLACKHOLE_NULL: + bh_type = BLACKHOLE_NULL; + break; + case STATIC_BLACKHOLE_REJECT: + bh_type = BLACKHOLE_REJECT; + break; + } + } /* Lookup existing route */ rn = srcdest_rnode_get(table, p, src_p); @@ -92,7 +104,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p, break; case STATIC_BLACKHOLE: nexthop = route_entry_nexthop_blackhole_add( - re, si->bh_type); + re, bh_type); break; case STATIC_IPV6_GATEWAY: nexthop = route_entry_nexthop_ipv6_add(re, @@ -168,7 +180,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p, break; case STATIC_BLACKHOLE: nexthop = route_entry_nexthop_blackhole_add( - re, si->bh_type); + re, bh_type); break; case STATIC_IPV6_GATEWAY: nexthop = route_entry_nexthop_ipv6_add(re, @@ -363,7 +375,7 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p, struct prefix_ipv6 *src_p, union g_addr *gate, - const char *ifname, enum blackhole_type bh_type, + const char *ifname, enum static_blackhole_type bh_type, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label) { diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 458594a289..68fe73b0a3 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -31,6 +31,12 @@ struct static_nh_label { mpls_label_t label[MPLS_MAX_LABELS]; }; +enum static_blackhole_type { + STATIC_BLACKHOLE_DROP = 0, + STATIC_BLACKHOLE_NULL, + STATIC_BLACKHOLE_REJECT +}; + typedef enum { STATIC_IFNAME, STATIC_IPV4_GATEWAY, @@ -61,7 +67,7 @@ struct static_route { /* * Nexthop value. */ - enum blackhole_type bh_type; + enum static_blackhole_type bh_type; union g_addr addr; ifindex_t ifindex; @@ -80,9 +86,9 @@ extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p, struct prefix_ipv6 *src_p, union g_addr *gate, - const char *ifname, enum blackhole_type bh_type, - route_tag_t tag, u_char distance, - struct zebra_vrf *zvrf, + const char *ifname, + enum static_blackhole_type bh_type, route_tag_t tag, + u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label); extern int static_delete_route(afi_t, safi_t safi, u_char type, diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 95ba19b1f6..1573646adc 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -74,7 +74,7 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi, union g_addr gate; union g_addr *gatep = NULL; struct in_addr mask; - enum blackhole_type bh_type = 0; + enum static_blackhole_type bh_type = 0; route_tag_t tag = 0; struct zebra_vrf *zvrf; u_char type; @@ -165,18 +165,21 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi, } } + /* Null0 static route. */ + if ((ifname != NULL) + && (strncasecmp(ifname, "Null0", strlen(ifname)) == 0)) { + bh_type = STATIC_BLACKHOLE_NULL; + ifname = NULL; + } + /* Route flags */ if (flag_str) { switch (flag_str[0]) { case 'r': - case 'R': /* XXX */ - bh_type = BLACKHOLE_REJECT; + bh_type = STATIC_BLACKHOLE_REJECT; break; - case 'n': - case 'N' /* XXX */: case 'b': - case 'B': /* XXX */ - bh_type = BLACKHOLE_NULL; + bh_type = STATIC_BLACKHOLE_DROP; break; default: vty_out(vty, "%% Malformed flag %s \n", flag_str); @@ -335,7 +338,8 @@ DEFPY(ip_route, ip_route_cmd, <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>\ <\ {A.B.C.D$gate|INTERFACE$ifname}\ - |<null0|reject|blackhole>$flag\ + |null0$ifname\ + |<reject|blackhole>$flag\ >\ [{\ tag (1-4294967295)\ @@ -1712,12 +1716,15 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi, break; case STATIC_BLACKHOLE: switch (si->bh_type) { - case BLACKHOLE_REJECT: - vty_out(vty, " reject"); - break; - default: + case STATIC_BLACKHOLE_DROP: vty_out(vty, " blackhole"); break; + case STATIC_BLACKHOLE_NULL: + vty_out(vty, " Null0"); + break; + case STATIC_BLACKHOLE_REJECT: + vty_out(vty, " reject"); + break; } break; case STATIC_IPV4_GATEWAY_IFNAME: @@ -1770,7 +1777,8 @@ DEFPY(ipv6_route, "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\ <\ {X:X::X:X$gate|INTERFACE$ifname}\ - |<null0|reject|blackhole>$flag\ + |null0$ifname\ + |<reject|blackhole>$flag\ >\ [{\ tag (1-4294967295)\ |
