summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgpd.c4
-rw-r--r--eigrpd/eigrp_packet.c5
-rw-r--r--lib/routemap.h10
-rw-r--r--lib/table.c1
-rw-r--r--lib/thread.c76
-rw-r--r--lib/thread.h1
-rw-r--r--ospfd/ospf_abr.c2
-rw-r--r--ospfd/ospf_interface.c2
-rw-r--r--ospfd/ospf_route.c1
-rw-r--r--ospfd/ospf_routemap.c21
-rw-r--r--pimd/pim_instance.c4
-rw-r--r--ripd/rip_routemap.c40
-rw-r--r--ripngd/ripng_routemap.c42
-rw-r--r--vtysh/vtysh_main.c4
-rw-r--r--zebra/rt_netlink.c63
-rw-r--r--zebra/zebra_rib.c64
-rw-r--r--zebra/zebra_static.c18
-rw-r--r--zebra/zebra_static.h14
-rw-r--r--zebra/zebra_vty.c34
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)\