summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_routemap.c11
-rw-r--r--bgpd/bgp_vty.c27
-rw-r--r--lib/log.c4
-rw-r--r--ospfd/ospf_flood.c25
-rw-r--r--ospfd/ospf_lsa.c160
-rw-r--r--ospfd/ospf_lsa.h4
-rw-r--r--ospfd/ospf_nsm.c28
-rw-r--r--ospfd/ospf_vty.c17
-rw-r--r--ospfd/ospf_zebra.c132
-rw-r--r--ospfd/ospfd.c32
-rw-r--r--ospfd/ospfd.h2
-rw-r--r--sharpd/sharp_zebra.c2
-rw-r--r--vrrpd/vrrp.c29
-rw-r--r--vrrpd/vrrp_zebra.c8
-rw-r--r--vtysh/vtysh_config.c38
-rw-r--r--yang/frr-filter.yang353
-rw-r--r--yang/frr-route-map.yang404
-rw-r--r--zebra/if_netlink.c6
-rw-r--r--zebra/zebra_rib.c5
-rw-r--r--zebra/zebra_vxlan.c69
20 files changed, 1014 insertions, 342 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 04043fdc8e..5ffc416dc5 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2091,12 +2091,19 @@ route_set_lcommunity_delete(void *rule, const struct prefix *pfx,
static void *route_set_lcommunity_delete_compile(const char *arg)
{
struct rmap_community *rcom;
+ char **splits;
+ int num;
- rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+ frrstr_split(arg, " ", &splits, &num);
- rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+ rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+ rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
rcom->name_hash = bgp_clist_hash_key(rcom->name);
+ for (int i = 0; i < num; i++)
+ XFREE(MTYPE_TMP, splits[i]);
+ XFREE(MTYPE_TMP, splits);
+
return rcom;
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 27042017dd..58a202d510 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -7770,7 +7770,7 @@ static void bgp_show_bestpath_json(struct bgp *bgp, json_object *json)
/* Show BGP peer's summary information. */
static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
- bool use_json, json_object *json)
+ bool use_json)
{
struct peer *peer;
struct listnode *node, *nnode;
@@ -7781,6 +7781,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
int len;
int max_neighbor_width = 0;
int pfx_rcd_safi;
+ json_object *json = NULL;
json_object *json_peer = NULL;
json_object *json_peers = NULL;
struct peer_af *paf;
@@ -7795,9 +7796,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
pfx_rcd_safi = safi;
if (use_json) {
- if (json == NULL)
- json = json_object_new_object();
-
+ json = json_object_new_object();
json_peers = json_object_new_object();
} else {
/* Loop over all neighbors that will be displayed to determine
@@ -8202,8 +8201,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
}
static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
- int safi, bool use_json,
- json_object *json)
+ int safi, bool use_json)
{
int is_first = 1;
int afi_wildcard = (afi == AFI_MAX);
@@ -8221,6 +8219,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
while (safi < SAFI_MAX) {
if (bgp_afi_safi_peer_exists(bgp, afi, safi)) {
nbr_output = true;
+
if (is_wildcard) {
/*
* So limit output to those afi/safi
@@ -8229,8 +8228,6 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
* them
*/
if (use_json) {
- json = json_object_new_object();
-
if (!is_first)
vty_out(vty, ",\n");
else
@@ -8245,8 +8242,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
safi));
}
}
- bgp_show_summary(vty, bgp, afi, safi, use_json,
- json);
+ bgp_show_summary(vty, bgp, afi, safi, use_json);
}
safi++;
if (!safi_wildcard)
@@ -8272,7 +8268,6 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
{
struct listnode *node, *nnode;
struct bgp *bgp;
- json_object *json = NULL;
int is_first = 1;
bool nbr_output = false;
@@ -8282,8 +8277,6 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
nbr_output = true;
if (use_json) {
- json = json_object_new_object();
-
if (!is_first)
vty_out(vty, ",\n");
else
@@ -8299,7 +8292,7 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
? VRF_DEFAULT_NAME
: bgp->name);
}
- bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, json);
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json);
}
if (use_json)
@@ -8330,8 +8323,8 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
return CMD_WARNING;
}
- bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json,
- NULL);
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi,
+ use_json);
return CMD_SUCCESS;
}
}
@@ -8339,7 +8332,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
bgp = bgp_get_default();
if (bgp)
- bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, NULL);
+ bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json);
else {
if (use_json)
vty_out(vty, "{}\n");
diff --git a/lib/log.c b/lib/log.c
index 48ee0f6adb..8e4d2bc600 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -387,10 +387,8 @@ void vzlog(int priority, const char *format, va_list args)
/* If it doesn't match on a filter, do nothing with the debug log */
if ((priority == LOG_DEBUG) && zlog_filter_count
- && vzlog_filter(zl, &tsctl, proto_str, priority, msg)) {
- pthread_mutex_unlock(&loglock);
+ && vzlog_filter(zl, &tsctl, proto_str, priority, msg))
goto out;
- }
/* call external hook */
hook_call(zebra_ext_log, priority, format, args);
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 6d1e44996e..1d85a04984 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -83,6 +83,9 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
struct as_external_lsa *al;
struct prefix_ipv4 p;
struct route_node *rn;
+ struct list *ext_list;
+ struct listnode *node;
+ struct ospf_external *ext;
int type;
al = (struct as_external_lsa *)lsa->data;
@@ -91,7 +94,7 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
p.prefix = lsa->data->id;
p.prefixlen = ip_masklen(al->mask);
- for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
int redist_on = 0;
redist_on =
@@ -105,10 +108,6 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
ospf->vrf_id));
// Pending: check for MI above.
if (redist_on) {
- struct list *ext_list;
- struct listnode *node;
- struct ospf_external *ext;
-
ext_list = ospf->external[type];
if (!ext_list)
continue;
@@ -129,6 +128,22 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
}
}
+ if (is_prefix_default(&p) && ospf->external[DEFAULT_ROUTE]) {
+ ext_list = ospf->external[DEFAULT_ROUTE];
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ if (!ext->external_info)
+ continue;
+
+ rn = route_node_lookup(ext->external_info,
+ (struct prefix *)&p);
+ if (!rn)
+ continue;
+ route_unlock_node(rn);
+ if (rn->info != NULL)
+ return (struct external_info *)rn->info;
+ }
+ }
return NULL;
}
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index bf46d22031..db41df7c47 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -1979,6 +1979,13 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
*/
+ if (ospf->router_id.s_addr == 0) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("LSA[Type5:%pI4]: deferring AS-external-LSA origination, router ID is zero",
+ &ei->p.prefix);
+ return NULL;
+ }
+
/* Check the AS-external-LSA should be originated. */
if (!ospf_redistribute_check(ospf, ei, NULL))
return NULL;
@@ -2019,50 +2026,6 @@ struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf,
return new;
}
-/* Originate AS-external-LSA from external info with initial flag. */
-int ospf_external_lsa_originate_timer(struct thread *thread)
-{
- struct ospf *ospf = THREAD_ARG(thread);
- struct route_node *rn;
- struct external_info *ei;
- struct route_table *rt;
- int type = THREAD_VAL(thread);
- struct list *ext_list;
- struct listnode *node;
- struct ospf_external *ext;
-
- ospf->t_external_lsa = NULL;
-
- ext_list = ospf->external[type];
- if (!ext_list)
- return 0;
-
- for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
- /* Originate As-external-LSA from all type of distribute source.
- */
- rt = ext->external_info;
- if (!rt)
- continue;
-
- for (rn = route_top(rt); rn; rn = route_next(rn)) {
- ei = rn->info;
-
- if (!ei)
- continue;
-
- if (is_prefix_default((struct prefix_ipv4 *)&ei->p))
- continue;
-
- if (!ospf_external_lsa_originate(ospf, ei))
- flog_warn(
- EC_OSPF_LSA_INSTALL_FAILURE,
- "LSA: AS-external-LSA was not originated.");
- }
- }
-
- return 0;
-}
-
static struct external_info *ospf_default_external_info(struct ospf *ospf)
{
int type;
@@ -2102,31 +2065,52 @@ static struct external_info *ospf_default_external_info(struct ospf *ospf)
return NULL;
}
-int ospf_default_originate_timer(struct thread *thread)
+void ospf_external_lsa_rid_change(struct ospf *ospf)
{
- struct prefix_ipv4 p;
- struct in_addr nexthop;
struct external_info *ei;
- struct ospf *ospf;
+ int type;
- ospf = THREAD_ARG(thread);
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
+ struct route_node *rn;
+ struct route_table *rt;
+ struct list *ext_list;
+ struct listnode *node;
+ struct ospf_external *ext;
- p.family = AF_INET;
- p.prefix.s_addr = 0;
- p.prefixlen = 0;
+ ext_list = ospf->external[type];
+ if (!ext_list)
+ continue;
- if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) {
- /* If there is no default route via redistribute,
- then originate AS-external-LSA with nexthop 0 (self). */
- nexthop.s_addr = 0;
- ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, p, 0, nexthop,
- 0);
- }
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
+ /* Originate As-external-LSA from all type of
+ * distribute source.
+ */
+ rt = ext->external_info;
+ if (!rt)
+ continue;
- if ((ei = ospf_default_external_info(ospf)))
- ospf_external_lsa_originate(ospf, ei);
+ for (rn = route_top(rt); rn; rn = route_next(rn)) {
+ ei = rn->info;
- return 0;
+ if (!ei)
+ continue;
+
+ if (is_prefix_default(
+ (struct prefix_ipv4 *)&ei->p))
+ continue;
+
+ if (!ospf_external_lsa_originate(ospf, ei))
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "LSA: AS-external-LSA was not originated.");
+ }
+ }
+ }
+
+ ei = ospf_default_external_info(ospf);
+ if (ei && !ospf_external_lsa_originate(ospf, ei)) {
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "LSA: AS-external-LSA for default route was not originated.");
+ }
}
/* Flush any NSSA LSAs for given prefix */
@@ -2218,44 +2202,20 @@ void ospf_external_lsa_refresh_default(struct ospf *ospf)
ei = ospf_default_external_info(ospf);
lsa = ospf_external_info_find_lsa(ospf, &p);
- if (ei) {
- if (lsa) {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
- (void *)lsa);
- ospf_external_lsa_refresh(ospf, lsa, ei,
- LSA_REFRESH_FORCE);
- } else {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
- ospf_external_lsa_originate(ospf, ei);
- }
- } else {
- if (lsa) {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
- ospf_refresher_unregister_lsa(ospf, lsa);
- ospf_lsa_flush_as(ospf, lsa);
- }
- }
-}
-
-void ospf_default_originate_lsa_update(struct ospf *ospf)
-{
- struct prefix_ipv4 p;
- struct ospf_lsa *lsa;
-
- p.family = AF_INET;
- p.prefixlen = 0;
- p.prefix.s_addr = 0;
-
- lsa = ospf_external_info_find_lsa(ospf, &p);
- if (lsa && IS_LSA_MAXAGE(lsa)) {
- ospf_discard_from_db(ospf, lsa->lsdb, lsa);
- ospf_lsdb_delete(lsa->lsdb, lsa);
+ if (ei && lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
+ (void *)lsa);
+ ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE);
+ } else if (ei && !lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
+ ospf_external_lsa_originate(ospf, ei);
+ } else if (lsa) {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
+ ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0);
}
}
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 5e3dabc27a..4033659bff 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -275,8 +275,7 @@ extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *);
extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *,
struct external_info *);
-extern int ospf_external_lsa_originate_timer(struct thread *);
-extern int ospf_default_originate_timer(struct thread *);
+extern void ospf_external_lsa_rid_change(struct ospf *ospf);
extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *,
uint32_t, struct in_addr,
struct in_addr);
@@ -301,7 +300,6 @@ extern int ospf_lsa_maxage_walker(struct thread *);
extern struct ospf_lsa *ospf_lsa_refresh(struct ospf *, struct ospf_lsa *);
extern void ospf_external_lsa_refresh_default(struct ospf *);
-extern void ospf_default_originate_lsa_update(struct ospf *ospf);
extern void ospf_external_lsa_refresh_type(struct ospf *, uint8_t,
unsigned short, int);
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index f7c73fee33..ee27ec0942 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -616,8 +616,6 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state)
struct ospf_interface *oi = nbr->oi;
struct ospf_area *vl_area = NULL;
uint8_t old_state;
- int x;
- int force = 1;
/* Preserve old status. */
old_state = nbr->state;
@@ -664,32 +662,6 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state)
if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area)
if (++vl_area->full_vls == 1)
ospf_schedule_abr_task(oi->ospf);
-
- /* kevinm: refresh any redistributions */
- for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++) {
- struct list *red_list;
- struct listnode *node;
- struct ospf_redist *red;
-
- if (x == ZEBRA_ROUTE_OSPF6)
- continue;
-
- red_list = oi->ospf->redist[x];
- if (!red_list)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
- ospf_external_lsa_refresh_type(
- oi->ospf, x, red->instance,
- force);
- }
- /* XXX: Clearly some thing is wrong with refresh of
- * external LSAs
- * this added to hack around defaults not refreshing
- * after a timer
- * jump.
- */
- ospf_external_lsa_refresh_default(oi->ospf);
} else {
oi->full_nbrs--;
oi->area->full_nbrs--;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 98ddd6a79e..2564c6f330 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -8487,22 +8487,8 @@ DEFUN (no_ospf_default_information_originate,
"Pointer to route-map entries\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- struct prefix_ipv4 p;
- struct ospf_external *ext;
struct ospf_redist *red;
- p.family = AF_INET;
- p.prefix.s_addr = 0;
- p.prefixlen = 0;
-
- ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0);
-
- ext = ospf_external_lookup(ospf, DEFAULT_ROUTE, 0);
- if (ext && EXTERNAL_INFO(ext)) {
- ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p);
- ospf_external_del(ospf, DEFAULT_ROUTE, 0);
- }
-
red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0);
if (!red)
return CMD_SUCCESS;
@@ -8510,7 +8496,8 @@ DEFUN (no_ospf_default_information_originate,
ospf_routemap_unset(red);
ospf_redist_del(ospf, DEFAULT_ROUTE, 0);
- return ospf_redistribute_default_unset(ospf);
+ return ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE,
+ 0, 0);
}
DEFUN (ospf_default_metric,
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 951402f47f..47438b985e 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -744,10 +744,10 @@ int ospf_redistribute_unset(struct ospf *ospf, int type,
int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
int mvalue)
{
- struct ospf_external *ext;
struct prefix_ipv4 p;
struct in_addr nexthop;
int cur_originate = ospf->default_originate;
+ const char *type_str = NULL;
nexthop.s_addr = 0;
p.family = AF_INET;
@@ -756,41 +756,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
ospf->default_originate = originate;
- ospf_external_add(ospf, DEFAULT_ROUTE, 0);
-
- if (cur_originate == DEFAULT_ORIGINATE_NONE) {
- /* First time configuration */
- if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
- zlog_debug("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
- metric_type(ospf, DEFAULT_ROUTE, 0),
- metric_value(ospf, DEFAULT_ROUTE, 0));
-
- if (ospf->router_id.s_addr == 0)
- ospf->external_origin |= (1 << DEFAULT_ROUTE);
- if ((originate == DEFAULT_ORIGINATE_ALWAYS)
- && (ospf->router_id.s_addr)) {
-
- /* always , so originate lsa even it doesn't
- * exist in RIB.
- */
- ospf_external_info_add(ospf, DEFAULT_ROUTE, 0,
- p, 0, nexthop, 0);
- ospf_external_lsa_refresh_default(ospf);
-
- } else if (originate == DEFAULT_ORIGINATE_ZEBRA) {
- /* Send msg to Zebra to validate default route
- * existance.
- */
- zclient_redistribute_default(
- ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, AFI_IP,
- ospf->vrf_id);
- }
-
- ospf_asbr_status_update(ospf, ++ospf->redistribute);
- return CMD_SUCCESS;
-
-
- } else if (originate == cur_originate) {
+ if (cur_originate == originate) {
/* Refresh the lsa since metric might different */
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
zlog_debug(
@@ -800,67 +766,51 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
metric_value(ospf, DEFAULT_ROUTE, 0));
ospf_external_lsa_refresh_default(ospf);
-
- } else {
- /* "default-info originate always" configured now,
- * where "default-info originate" configured previoulsly.
- */
- if (originate == DEFAULT_ORIGINATE_ALWAYS) {
-
- zclient_redistribute_default(
- ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
- zclient, AFI_IP, ospf->vrf_id);
- /* here , ex-info should be added since ex-info might
- * have not updated earlier if def route is not exist.
- * If ex-iinfo ex-info already exist , it will return
- * smoothly.
- */
- ospf_external_info_add(ospf, DEFAULT_ROUTE, 0,
- p, 0, nexthop, 0);
- ospf_external_lsa_refresh_default(ospf);
-
- } else {
- /* "default-info originate" configured now,where
- * "default-info originate always" configured
- * previoulsy.
- */
-
- ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0);
-
- ext = ospf_external_lookup(ospf, DEFAULT_ROUTE, 0);
- if (ext && EXTERNAL_INFO(ext))
- ospf_external_info_delete(ospf,
- DEFAULT_ROUTE, 0, p);
-
- zclient_redistribute_default(
- ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
- zclient, AFI_IP, ospf->vrf_id);
- }
+ return CMD_SUCCESS;
}
- return CMD_SUCCESS;
-}
-int ospf_redistribute_default_unset(struct ospf *ospf)
-{
- if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) {
- if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0))
- return CMD_SUCCESS;
+ switch (cur_originate) {
+ case DEFAULT_ORIGINATE_NONE:
+ break;
+ case DEFAULT_ORIGINATE_ZEBRA:
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
zclient, AFI_IP, ospf->vrf_id);
+ ospf->redistribute--;
+ break;
+ case DEFAULT_ORIGINATE_ALWAYS:
+ ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p);
+ ospf_external_del(ospf, DEFAULT_ROUTE, 0);
+ ospf->redistribute--;
+ break;
}
- ospf->default_originate = DEFAULT_ORIGINATE_NONE;
+ switch (originate) {
+ case DEFAULT_ORIGINATE_NONE:
+ type_str = "none";
+ break;
+ case DEFAULT_ORIGINATE_ZEBRA:
+ type_str = "normal";
+ ospf->redistribute++;
+ zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
+ zclient, AFI_IP, ospf->vrf_id);
+ break;
+ case DEFAULT_ORIGINATE_ALWAYS:
+ type_str = "always";
+ ospf->redistribute++;
+ ospf_external_add(ospf, DEFAULT_ROUTE, 0);
+ ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, p, 0, nexthop,
+ 0);
+ break;
+ }
if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
- zlog_debug("Redistribute[DEFAULT]: Stop");
-
- // Pending: how does the external_info cleanup work in this case?
-
- ospf_asbr_status_update(ospf, --ospf->redistribute);
-
- /* clean up maxage default originate external lsa */
- ospf_default_originate_lsa_update(ospf);
+ zlog_debug("Redistribute[DEFAULT]: %s Type[%d], Metric[%d]",
+ type_str,
+ metric_type(ospf, DEFAULT_ROUTE, 0),
+ metric_value(ospf, DEFAULT_ROUTE, 0));
+ ospf_external_lsa_refresh_default(ospf);
+ ospf_asbr_status_update(ospf, ospf->redistribute);
return CMD_SUCCESS;
}
@@ -1067,11 +1017,7 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
/* Nothing has changed, so nothing to do; return */
return 0;
}
- if (ospf->router_id.s_addr == 0)
- /* Set flags to generate AS-external-LSA originate event
- for each redistributed protocols later. */
- ospf->external_origin |= (1 << rt_type);
- else {
+ if (ospf->router_id.s_addr != 0) {
if (ei) {
if (is_prefix_default(&p))
ospf_external_lsa_refresh_default(ospf);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index a64ddbc3b7..b91a55f635 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -91,7 +91,6 @@ void ospf_router_id_update(struct ospf *ospf)
struct ospf_interface *oi;
struct interface *ifp;
struct listnode *node;
- int type;
if (!ospf->oi_running) {
if (IS_DEBUG_OSPF_EVENT)
@@ -135,24 +134,6 @@ void ospf_router_id_update(struct ospf *ospf)
ospf_nbr_self_reset(oi, router_id);
}
- /* If AS-external-LSA is queued, then flush those LSAs. */
- if (router_id_old.s_addr == 0 && ospf->external_origin) {
- /* Originate each redistributed external route. */
- for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
- if (ospf->external_origin & (1 << type))
- thread_add_event(
- master,
- ospf_external_lsa_originate_timer,
- ospf, type, NULL);
- /* Originate Deafult. */
- if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX))
- thread_add_event(master,
- ospf_default_originate_timer,
- ospf, 0, NULL);
-
- ospf->external_origin = 0;
- }
-
/* Flush (inline) all external LSAs based on the OSPF_LSA_SELF
* flag */
if (ospf->lsdb) {
@@ -196,20 +177,14 @@ void ospf_router_id_update(struct ospf *ospf)
}
}
- /* Originate each redistributed external route. */
- for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
- thread_add_event(master,
- ospf_external_lsa_originate_timer,
- ospf, type, NULL);
- thread_add_event(master, ospf_default_originate_timer, ospf, 0,
- NULL);
-
/* update router-lsa's for each area */
ospf_router_lsa_update(ospf);
/* update ospf_interface's */
FOR_ALL_INTERFACES (vrf, ifp)
ospf_if_update(ospf, ifp);
+
+ ospf_external_lsa_rid_change(ospf);
}
}
@@ -633,7 +608,7 @@ static void ospf_finish_final(struct ospf *ospf)
ospf_redist_del(ospf, i, red->instance);
}
}
- ospf_redistribute_default_unset(ospf);
+ ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE, 0, 0);
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
ospf_remove_vls_through_area(ospf, area);
@@ -702,7 +677,6 @@ static void ospf_finish_final(struct ospf *ospf)
/* Cancel all timers. */
OSPF_TIMER_OFF(ospf->t_read);
OSPF_TIMER_OFF(ospf->t_write);
- OSPF_TIMER_OFF(ospf->t_external_lsa);
OSPF_TIMER_OFF(ospf->t_spf_calc);
OSPF_TIMER_OFF(ospf->t_ase_calc);
OSPF_TIMER_OFF(ospf->t_maxage);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index cbea033b73..b31ad30375 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -202,7 +202,6 @@ struct ospf {
struct ospf_lsdb *lsdb;
/* Flags. */
- int external_origin; /* AS-external-LSA origin flag. */
int ase_calc; /* ASE calculation flag. */
struct list *opaque_lsa_self; /* Type-11 Opaque-LSAs */
@@ -233,7 +232,6 @@ struct ospf {
struct thread *t_distribute_update; /* Distirbute list update timer. */
struct thread *t_spf_calc; /* SPF calculation timer. */
struct thread *t_ase_calc; /* ASE calculation timer. */
- struct thread *t_external_lsa; /* AS-external-LSA origin timer. */
struct thread
*t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
struct thread *t_sr_update; /* Segment Routing update timer */
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index cd6f956580..6263f429ea 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -188,7 +188,7 @@ static void handle_repeated(bool installed)
sg.r.inst, sg.r.total_routes);
}
- if (installed) {
+ if (!installed) {
sg.r.installed_routes = 0;
sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
&sg.r.nhop_group,
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index 5213b27d32..951ad3f58f 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -196,9 +196,20 @@ static struct vrrp_vrouter *vrrp_lookup_by_if_mvl(struct interface *mvl_ifp)
{
struct interface *p;
- if (!mvl_ifp || !mvl_ifp->link_ifindex
- || !vrrp_ifp_has_vrrp_mac(mvl_ifp))
+ if (!mvl_ifp || mvl_ifp->link_ifindex == 0
+ || !vrrp_ifp_has_vrrp_mac(mvl_ifp)) {
+ if (mvl_ifp && mvl_ifp->link_ifindex == 0)
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Interface %s has no parent ifindex; disregarding",
+ mvl_ifp->name);
+ if (mvl_ifp && !vrrp_ifp_has_vrrp_mac(mvl_ifp))
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Interface %s has a non-VRRP MAC; disregarding",
+ mvl_ifp->name);
return NULL;
+ }
p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
uint8_t vrid = mvl_ifp->hw_addr[5];
@@ -2028,9 +2039,19 @@ static void vrrp_bind_pending(struct interface *mvl_ifp)
{
struct vrrp_vrouter *vr;
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Searching for instances that could use interface %s",
+ mvl_ifp->name);
+
vr = vrrp_lookup_by_if_mvl(mvl_ifp);
if (vr) {
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX VRRP_LOGPFX_VRID
+ "<-- This instance can probably use interface %s",
+ vr->vrid, mvl_ifp->name);
+
if (mvl_ifp->hw_addr[4] == 0x01 && !vr->v4->mvl_ifp)
vrrp_attach_interface(vr->v4);
else if (mvl_ifp->hw_addr[4] == 0x02 && !vr->v6->mvl_ifp)
@@ -2112,9 +2133,13 @@ void vrrp_if_down(struct interface *ifp)
struct listnode *ln;
struct list *vrs;
+ vrrp_bind_pending(ifp);
+
vrs = vrrp_lookup_by_if_any(ifp);
for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
+ vrrp_check_start(vr);
+
if (vr->ifp == ifp || vr->v4->mvl_ifp == ifp
|| vr->v6->mvl_ifp == ifp) {
DEBUGD(&vrrp_dbg_auto,
diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c
index dbfcbe945e..72b77c1313 100644
--- a/vrrpd/vrrp_zebra.c
+++ b/vrrpd/vrrp_zebra.c
@@ -38,9 +38,11 @@ static void vrrp_zebra_debug_if_state(struct interface *ifp, vrf_id_t vrf_id,
const char *func)
{
DEBUGD(&vrrp_dbg_zebra,
- "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
- func, ifp->name, ifp->ifindex, vrf_id, (long)ifp->flags,
- ifp->metric, ifp->mtu, if_is_operative(ifp));
+ "%s: %s index %d(%u) parent %d mac %02x:%02x:%02x:%02x:%02x:%02x flags %ld metric %d mtu %d operative %d",
+ func, ifp->name, vrf_id, ifp->link_ifindex, ifp->ifindex,
+ ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2],
+ ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5],
+ (long)ifp->flags, ifp->metric, ifp->mtu, if_is_operative(ifp));
}
static void vrrp_zebra_debug_if_dump_address(struct interface *ifp,
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index e357a60296..3ec2eb239d 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -23,6 +23,7 @@
#include "command.h"
#include "linklist.h"
#include "memory.h"
+#include "typesafe.h"
#include "vtysh/vtysh.h"
#include "vtysh/vtysh_user.h"
@@ -33,6 +34,8 @@ DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG_LINE, "Vtysh configuration line")
vector configvec;
+PREDECL_RBTREE_UNIQ(config_master);
+
struct config {
/* Configuration node name. */
char *name;
@@ -45,6 +48,9 @@ struct config {
/* Index of this config. */
uint32_t index;
+
+ /* Node entry for the typed Red-black tree */
+ struct config_master_item rbt_item;
};
struct list *config_top;
@@ -66,7 +72,7 @@ static struct config *config_new(void)
return config;
}
-static int config_cmp(struct config *c1, struct config *c2)
+static int config_cmp(const struct config *c1, const struct config *c2)
{
return strcmp(c1->name, c2->name);
}
@@ -78,28 +84,23 @@ static void config_del(struct config *config)
XFREE(MTYPE_VTYSH_CONFIG, config);
}
+DECLARE_RBTREE_UNIQ(config_master, struct config, rbt_item, config_cmp)
+
static struct config *config_get(int index, const char *line)
{
struct config *config;
- struct config *config_loop;
- struct list *master;
- struct listnode *node, *nnode;
-
- config = config_loop = NULL;
+ struct config_master_head *master;
master = vector_lookup_ensure(configvec, index);
if (!master) {
- master = list_new();
- master->del = (void (*)(void *))config_del;
- master->cmp = (int (*)(void *, void *))config_cmp;
+ master = XMALLOC(MTYPE_VTYSH_CONFIG, sizeof(struct config_master_head));
+ config_master_init(master);
vector_set_index(configvec, index, master);
}
- for (ALL_LIST_ELEMENTS(master, node, nnode, config_loop)) {
- if (strcmp(config_loop->name, line) == 0)
- config = config_loop;
- }
+ const struct config config_ref = { .name = (char *)line };
+ config = config_master_find(master, &config_ref);
if (!config) {
config = config_new();
@@ -108,7 +109,7 @@ static struct config *config_get(int index, const char *line)
config->line->cmp = (int (*)(void *, void *))line_cmp;
config->name = XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line);
config->index = index;
- listnode_add(master, config);
+ config_master_add(master, config);
}
return config;
}
@@ -432,7 +433,7 @@ void vtysh_config_dump(void)
struct listnode *node, *nnode;
struct listnode *mnode, *mnnode;
struct config *config;
- struct list *master;
+ struct config_master_head *master;
char *line;
unsigned int i;
@@ -443,7 +444,7 @@ void vtysh_config_dump(void)
for (i = 0; i < vector_active(configvec); i++)
if ((master = vector_slot(configvec, i)) != NULL) {
- for (ALL_LIST_ELEMENTS(master, node, nnode, config)) {
+ while ((config = config_master_pop(master))) {
/* Don't print empty sections for interface.
* Route maps on the
* other hand could have a legitimate empty
@@ -463,6 +464,8 @@ void vtysh_config_dump(void)
vty_out(vty, "%s\n", line);
if (!NO_DELIMITER(i))
vty_out(vty, "!\n");
+
+ config_del(config);
}
if (NO_DELIMITER(i))
vty_out(vty, "!\n");
@@ -470,7 +473,8 @@ void vtysh_config_dump(void)
for (i = 0; i < vector_active(configvec); i++)
if ((master = vector_slot(configvec, i)) != NULL) {
- list_delete(&master);
+ config_master_fini(master);
+ XFREE(MTYPE_VTYSH_CONFIG, master);
vector_slot(configvec, i) = NULL;
}
list_delete_all_node(config_top);
diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang
new file mode 100644
index 0000000000..e79ede87b7
--- /dev/null
+++ b/yang/frr-filter.yang
@@ -0,0 +1,353 @@
+module frr-filter {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/filter";
+ prefix frr-filter;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization "Free Range Routing";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description "This module defines filter settings";
+
+ revision 2019-07-04 {
+ description "Initial revision";
+ }
+
+ /*
+ * Types.
+ */
+ typedef access-list-standard {
+ description "Standard IPv4 access list (any, host or a prefix)";
+ type uint16 {
+ range "1..99 | 1300..1999";
+ }
+ }
+
+ typedef access-list-extended {
+ description
+ "Extended IPv4 access list (source / destination any, hosts or prefixes)";
+ type uint16 {
+ range "100..199 | 2000..2699";
+ }
+ }
+
+ typedef access-list-legacy {
+ description "Standard/Extended IPv4 access list";
+ type uint16 {
+ range "1..199 | 1300..2699";
+ }
+ }
+
+ typedef access-list-name {
+ description "Access list name formatting";
+ type string;
+ }
+
+ typedef access-list-sequence {
+ description "Access list sequence number";
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+
+ typedef access-list-action {
+ description "Access list return action on match";
+ type enumeration {
+ enum deny {
+ description "Deny an entry";
+ value 0;
+ }
+ enum permit {
+ description "Accept an entry";
+ value 1;
+ }
+ }
+ }
+
+ /*
+ * Configuration data.
+ */
+ container filter-list {
+ list access-list-legacy {
+ description "Access list legacy instance";
+
+ key "number sequence";
+
+ leaf number {
+ description "Access list sequence value";
+ type access-list-legacy;
+ }
+
+ leaf sequence {
+ description "Access list sequence value";
+ type access-list-sequence;
+ }
+
+ leaf action {
+ description "Access list action on match";
+ type access-list-action;
+ mandatory true;
+ }
+
+ leaf remark {
+ description "Access list remark";
+ type string;
+ }
+
+ choice value {
+ description
+ "Standard access list: value to match.
+ Extended access list: source value to match.";
+ mandatory true;
+
+ leaf host {
+ description "Host to match";
+ type inet:ipv4-address;
+ }
+ leaf network {
+ description "Network to match";
+ type inet:ipv4-prefix;
+ }
+ leaf any {
+ description "Match any";
+ type empty;
+ }
+ }
+
+ choice extended-value {
+ when "./sequence >= 100 and ./sequence <= 199 or
+ ./sequence >= 2000 and ./sequence <= 2699";
+ description "Destination value to match";
+
+ leaf destination-host {
+ description "Host to match";
+ type inet:ipv4-address;
+ }
+ leaf destination-network {
+ description "Network to match";
+ type inet:ipv4-prefix;
+ }
+ leaf destination-any {
+ description "Match any";
+ type empty;
+ }
+ }
+ }
+
+ list access-list {
+ description "Access list instance";
+
+ key "type identifier sequence";
+
+ leaf type {
+ description "Access list content type";
+ type enumeration {
+ enum ipv4 {
+ description "Internet Protocol address version 4";
+ value 0;
+ }
+ enum ipv6 {
+ description "Internet Protocol address version 6";
+ value 1;
+ }
+ enum mac {
+ description "Media Access Control address";
+ value 2;
+ }
+
+ /*
+ * Protocol YANG models should augment the parent node to
+ * contain the routing protocol specific value. The protocol
+ * must also augment `value` leaf to include its specific
+ * values or expand the `when` statement on the existing cases.
+ */
+ enum custom {
+ description "Custom data type";
+ value 100;
+ }
+ }
+ }
+
+ leaf identifier {
+ description "Access list identifier";
+ type access-list-name;
+ }
+
+ leaf sequence {
+ description "Access list sequence value";
+ type access-list-sequence;
+ }
+
+ leaf action {
+ description "Access list action on match";
+ type access-list-action;
+ mandatory true;
+ }
+
+ leaf remark {
+ description "Access list remark";
+ type string;
+ }
+
+ choice value {
+ description "Access list value to match";
+ mandatory true;
+
+ case ipv4-prefix {
+ when "./type = 'ipv4'";
+
+ leaf ipv4-prefix {
+ description "Configure IPv4 prefix to match";
+ type inet:ipv4-prefix;
+ }
+
+ leaf ipv4-exact-match {
+ description "Exact match of prefix";
+ type boolean;
+ default false;
+ }
+ }
+ case ipv6-prefix {
+ when "./type = 'ipv6'";
+
+ leaf ipv6-prefix {
+ description "Configure IPv6 prefix to match";
+ type inet:ipv6-prefix;
+ }
+
+ leaf ipv6-exact-match {
+ description "Exact match of prefix";
+ type boolean;
+ default false;
+ }
+ }
+ case mac {
+ when "./type = 'mac'";
+
+ leaf mac {
+ description "Configure MAC address to match";
+ type yang:mac-address;
+ }
+ }
+ case any {
+ leaf any {
+ description "Match anything";
+ type empty;
+ }
+ }
+ }
+ }
+
+ list prefix-list {
+ description "Prefix list instance";
+
+ key "type name sequence";
+
+ leaf type {
+ description "Prefix list type";
+ type enumeration {
+ enum ipv4 {
+ description "Internet Protocol address version 4";
+ value 0;
+ }
+ enum ipv6 {
+ description "Internet Protocol address version 6";
+ value 1;
+ }
+ }
+ }
+
+ leaf name {
+ description "Prefix list name";
+ type access-list-name;
+ }
+
+ leaf sequence {
+ description "Access list sequence value";
+ type access-list-sequence;
+ }
+
+ leaf action {
+ description "Prefix list action on match";
+ type access-list-action;
+ mandatory true;
+ }
+
+ leaf description {
+ description "Prefix list user description";
+ type string;
+ }
+
+ choice value {
+ description "Prefix list value to match";
+ mandatory true;
+
+ case ipv4-prefix {
+ when "./type = 'ipv4'";
+
+ leaf ipv4-prefix {
+ description "Configure IPv4 prefix to match";
+ type inet:ipv4-prefix;
+ }
+
+ leaf ipv4-prefix-length-greater-or-equal {
+ description
+ "Specifies if matching prefixes with length greater than
+ or equal to value";
+ type uint8 {
+ range "0..32";
+ }
+ }
+
+ leaf ipv4-prefix-length-lesser-or-equal {
+ description
+ "Specifies if matching prefixes with length lesser than
+ or equal to value";
+ type uint8 {
+ range "0..32";
+ }
+ }
+ }
+ case ipv6-prefix {
+ when "./type = 'ipv6'";
+
+ leaf ipv6-prefix {
+ description "Configure IPv6 prefix to match";
+ type inet:ipv6-prefix;
+ }
+
+ leaf ipv6-prefix-length-greater-or-equal {
+ description
+ "Specifies if matching prefixes with length greater than
+ or equal to value";
+ type uint8 {
+ range "0..128";
+ }
+ }
+
+ leaf ipv6-prefix-length-lesser-or-equal {
+ description
+ "Specifies if matching prefixes with length lesser than
+ or equal to value";
+ type uint8 {
+ range "0..128";
+ }
+ }
+ }
+ case any {
+ leaf any {
+ description "Match anything";
+ type empty;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
new file mode 100644
index 0000000000..0ce40b474b
--- /dev/null
+++ b/yang/frr-route-map.yang
@@ -0,0 +1,404 @@
+module frr-route-map {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/route-map";
+ prefix frr-route-map;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import frr-filter {
+ prefix filter;
+ }
+
+ organization "Free Range Routing";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description "This module defines route map settings";
+
+ revision 2019-07-01 {
+ description "Initial revision";
+ }
+
+ /*
+ * Types.
+ */
+ typedef route-map-sequence {
+ description "Route map valid sequence numbers";
+ type uint16 {
+ range "1..65535";
+ }
+ }
+
+ typedef route-map-name {
+ description "Route map name format";
+ type string;
+ }
+
+ /*
+ * Operational data.
+ */
+ container route-map {
+ list instance {
+ description "Route map instance";
+
+ key "name sequence";
+
+ leaf name {
+ description "Route map instance name";
+ type route-map-name;
+ }
+
+ leaf sequence {
+ description
+ "Route map instance priority (low number means higher priority)";
+ type route-map-sequence;
+ }
+
+ leaf description {
+ description "Route map description";
+ type string;
+ }
+
+ leaf action {
+ description
+ "Route map actions: permit (executes action), deny (quits evaluation)";
+ mandatory true;
+ type enumeration {
+ enum permit {
+ description
+ "Executes configured action and permits the prefix/route
+ if the conditions matched. An alternative exit action can
+ be configured to continue processing the route map list
+ or jump to process another route map.";
+ value 0;
+ }
+ enum deny {
+ description
+ "If all conditions are met the prefix/route is denied and
+ route map processing stops.";
+ value 1;
+ }
+ }
+ }
+
+ list match-condition {
+ description "Route map match conditions";
+
+ key "condition";
+
+ leaf condition {
+ description "Match condition";
+ type enumeration {
+ enum interface {
+ description "Match interface";
+ value 0;
+ }
+ enum ipv4-address-list {
+ description "Match an IPv4 access-list";
+ value 1;
+ }
+ enum ipv4-prefix-list {
+ description "Match an IPv4 prefix-list";
+ value 2;
+ }
+ enum ipv4-prefix-length {
+ description "Match an IPv4 prefix length";
+ value 3;
+ }
+ enum ipv4-next-hop-list {
+ description "Match an IPv4 next-hop";
+ value 4;
+ }
+ enum ipv4-next-hop-prefix-list {
+ description "Match an IPv4 next-hop prefix list";
+ value 5;
+ }
+ enum ipv4-next-hop-prefix-length {
+ description "Match an IPv4 next-hop prefix length";
+ value 6;
+ }
+ enum ipv4-next-hop-type {
+ description "Match an IPv4 next-hop type";
+ value 7;
+ }
+ enum ipv6-address-list {
+ description "Match an IPv6 access-list";
+ value 8;
+ }
+ enum ipv6-prefix-list {
+ description "Match an IPv6 prefix-list";
+ value 9;
+ }
+ enum ipv6-prefix-length {
+ description "Match an IPv6 prefix length";
+ value 10;
+ }
+ enum ipv6-next-hop {
+ description "Match an IPv6 next-hop";
+ value 11;
+ }
+ enum ipv6-next-hop-type {
+ description "Match an IPv6 next-hop type";
+ value 12;
+ }
+ enum metric {
+ description "Match a route metric";
+ value 13;
+ }
+ enum tag {
+ description "Match a route tag";
+ value 14;
+ }
+
+ /*
+ * Protocol YANG models should augment the parent node to
+ * contain the routing protocol specific value. The protocol
+ * must also augment `condition-value` to include its specific
+ * values or expand the `when` statement on the existing cases.
+ */
+ enum routing-protocol-specific {
+ description "Match a routing protocol specific type";
+ value 100;
+ }
+ }
+ }
+
+ choice condition-value {
+ description
+ "Value to match (interpretation depends on condition type)";
+ case access-list-num {
+ when "./condition = 'ipv4-address-list' or
+ ./condition = 'ipv4-next-hop-list'";
+ leaf access-list-num {
+ type filter:access-list-standard;
+ }
+ }
+ case access-list-num-extended {
+ when "./condition = 'ipv4-address-list' or
+ ./condition = 'ipv4-next-hop-list'";
+ leaf access-list-num-extended {
+ type filter:access-list-extended;
+ }
+ }
+ case list-name {
+ when "./condition = 'ipv4-address-list' or
+ ./condition = 'ipv4-prefix-list' or
+ ./condition = 'ipv4-next-hop-list' or
+ ./condition = 'ipv4-next-hop-prefix-list' or
+ ./condition = 'ipv6-address-list' or
+ ./condition = 'ipv6-prefix-list'";
+ leaf list-name {
+ type filter:access-list-name;
+ }
+ }
+ case ipv6-address {
+ when "./condition = 'ipv6-next-hop'";
+ leaf ipv6-address {
+ type inet:ipv6-address;
+ }
+ }
+ case ipv4-prefix-length {
+ when "./condition = 'ipv4-prefix-length' or
+ ./condition = 'ipv4-next-hop-prefix-length'";
+ leaf ipv4-prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ }
+ }
+ case ipv6-prefix-length {
+ when "./condition = 'ipv6-prefix-length'";
+ leaf ipv6-prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ }
+ }
+ case ipv4-next-hop-type {
+ when "./condition = 'ipv4-next-hop-type'";
+ leaf ipv4-next-hop-type {
+ type enumeration {
+ enum blackhole {
+ value 0;
+ }
+ }
+ }
+ }
+ case ipv6-next-hop-type {
+ when "./condition = 'ipv6-next-hop-type'";
+ leaf ipv6-next-hop-type {
+ type enumeration {
+ enum blackhole {
+ value 0;
+ }
+ }
+ }
+ }
+ case metric {
+ when "./condition = 'metric'";
+ leaf metric {
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+ }
+ case tag {
+ when "./condition = 'tag'";
+ leaf tag {
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+ }
+ }
+ }
+
+ list set-action {
+ description "Route map set actions";
+
+ key "action";
+
+ leaf action {
+ description "Action to do when the route map matches";
+ type enumeration {
+ enum ipv4-next-hop {
+ description "Set IPv4 address of the next hop";
+ value 0;
+ }
+ enum ipv6-next-hop {
+ description "Set IPv6 address of the next hop";
+ value 1;
+ }
+ enum metric {
+ description "Set prefix/route metric";
+ value 2;
+ }
+ enum tag {
+ description "Set tag";
+ value 3;
+ }
+
+ /*
+ * Protocol YANG models should augment the parent node to
+ * contain the routing protocol specific value. The protocol
+ * must also augment `action-value` to include its specific
+ * values or expand the `when` statement on the existing cases.
+ */
+ enum routing-protocol-specific {
+ description "Set a routing protocol specific action";
+ value 100;
+ }
+ }
+ }
+
+ choice action-value {
+ description
+ "Value to set (interpretation depends on action-type)";
+ case ipv4-address {
+ when "./action = 'ipv4-next-hop'";
+ leaf ipv4-address {
+ description "IPv4 address";
+ type inet:ipv4-address;
+ }
+ }
+ case ipv6-address {
+ when "./action = 'ipv6-next-hop'";
+ leaf ipv6-address {
+ description "IPv6 address";
+ type inet:ipv6-address;
+ }
+ }
+ case metric {
+ when "./action = 'metric'";
+ choice metric-value {
+ description "Metric to set or use";
+ case value {
+ leaf value {
+ description "Use the following metric value";
+ type uint32 {
+ range "0..4294967295";
+ }
+ }
+ }
+ case add-metric {
+ leaf add-metric {
+ description "Add unit to metric";
+ type boolean;
+ }
+ }
+ case subtract-metric {
+ leaf subtract-metric {
+ description "Subtract unit from metric";
+ type boolean;
+ }
+ }
+ case use-round-trip-time {
+ leaf use-round-trip-time {
+ description "Use the round trip time as metric";
+ type boolean;
+ }
+ }
+ case add-round-trip-time {
+ leaf add-round-trip-time {
+ description "Add round trip time to metric";
+ type boolean;
+ }
+ }
+ case subtract-round-trip-time {
+ leaf subtract-round-trip-time {
+ description "Subtract round trip time to metric";
+ type boolean;
+ }
+ }
+ }
+ }
+ case tag {
+ leaf tag {
+ description "Tag value";
+ type uint32 {
+ range "0..4294967295";
+ }
+ }
+ }
+ }
+ }
+
+ leaf call {
+ description
+ "Call another route map before calling `exit-policy`. If the
+ called route map returns deny then this route map will also
+ return deny";
+ type string;
+ }
+
+ leaf exit-policy {
+ description "What do to after route map successful match, set and call";
+ type enumeration {
+ enum permit-or-deny {
+ description "End route map evaluation and return";
+ value 0;
+ }
+ enum next {
+ description
+ "Proceed evaluating next route map entry per sequence";
+ value 1;
+ }
+ enum goto {
+ description
+ "Go to route map entry with the provided sequence number";
+ value 2;
+ }
+ }
+ default "permit-or-deny";
+ }
+
+ leaf goto-value {
+ when "../exit-policy = 'goto'";
+ description
+ "Sequence number to jump (when using `goto` exit policy)";
+ type route-map-sequence;
+ }
+ }
+ }
+}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index df8d4bfe15..63e72fed00 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1347,6 +1347,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
"Intf %s(%u) has come UP",
name, ifp->ifindex);
if_up(ifp);
+ } else {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "Intf %s(%u) has gone DOWN",
+ name, ifp->ifindex);
+ if_down(ifp);
}
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index f3721c478d..3608b887ee 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1926,6 +1926,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
goto done;
}
+ /* Ensure we clear the QUEUED flag */
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+
/* Is this a notification that ... matters? We only really care about
* the route that is currently selected for installation.
*/
@@ -1990,7 +1993,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_vrf(ctx), dest_str);
/* We expect this to be the selected route, so we want
- * to tell others about this transistion.
+ * to tell others about this transition.
*/
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 359585df73..2e8c81bddd 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -3403,6 +3403,39 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
return 0;
}
+static bool zvni_check_mac_del_from_db(struct mac_walk_ctx *wctx,
+ zebra_mac_t *mac)
+{
+ if ((wctx->flags & DEL_LOCAL_MAC) &&
+ (mac->flags & ZEBRA_MAC_LOCAL))
+ return true;
+ else if ((wctx->flags & DEL_REMOTE_MAC) &&
+ (mac->flags & ZEBRA_MAC_REMOTE))
+ return true;
+ else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) &&
+ (mac->flags & ZEBRA_MAC_REMOTE) &&
+ IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
+ return true;
+ else if ((wctx->flags & DEL_LOCAL_MAC) &&
+ (mac->flags & ZEBRA_MAC_AUTO) &&
+ !listcount(mac->neigh_list)) {
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char buf[ETHER_ADDR_STRLEN];
+
+ zlog_debug("%s: Del MAC %s flags 0x%x",
+ __PRETTY_FUNCTION__,
+ prefix_mac2str(&mac->macaddr,
+ buf, sizeof(buf)),
+ mac->flags);
+ }
+ wctx->uninstall = 0;
+
+ return true;
+ }
+
+ return false;
+}
+
/*
* Free MAC hash entry (callback)
*/
@@ -3411,18 +3444,11 @@ static void zvni_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
struct mac_walk_ctx *wctx = arg;
zebra_mac_t *mac = bucket->data;
- if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
- || ((wctx->flags & DEL_REMOTE_MAC)
- && (mac->flags & ZEBRA_MAC_REMOTE))
- || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
- && (mac->flags & ZEBRA_MAC_REMOTE)
- && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
- &wctx->r_vtep_ip))) {
+ if (zvni_check_mac_del_from_db(wctx, mac)) {
if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
zvni_mac_send_del_to_client(wctx->zvni->vni,
&mac->macaddr);
}
-
if (wctx->uninstall)
zvni_mac_uninstall(wctx->zvni, mac);
@@ -5332,8 +5358,6 @@ static void process_remote_macip_add(vni_t vni,
if (ipa_len)
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
} else {
- const char *mac_type;
-
/* When host moves but changes its (MAC,IP)
* binding, BGP may install a MACIP entry that
* corresponds to "older" location of the host
@@ -5342,16 +5366,14 @@ static void process_remote_macip_add(vni_t vni,
* the sequence number and ignore this update
* if appropriate.
*/
- if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
tmp_seq = mac->loc_seq;
- mac_type = "local";
- } else {
+ else
tmp_seq = mac->rem_seq;
- mac_type = "remote";
- }
+
if (seq < tmp_seq) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
+ zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x",
vni,
prefix_mac2str(macaddr,
buf, sizeof(buf)),
@@ -5359,8 +5381,7 @@ static void process_remote_macip_add(vni_t vni,
ipa_len ?
ipaddr2str(ipaddr,
buf1, sizeof(buf1)) : "",
- mac_type,
- tmp_seq);
+ tmp_seq, mac->flags);
return;
}
}
@@ -7274,8 +7295,13 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
* of a VxLAN bridge.
*/
zvni = zvni_from_svi(ifp, link_if);
- if (!zvni)
+ if (!zvni) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%s: Del neighbor %s VNI is not present for interface %s",
+ __PRETTY_FUNCTION__,
+ ipaddr2str(ip, buf, sizeof(buf)), ifp->name);
return 0;
+ }
if (!zvni->vxlan_if) {
zlog_debug(
@@ -7672,9 +7698,10 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
return 0;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
+ zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u",
prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
- ifp->ifindex, vid, zvni->vni, mac->flags);
+ ifp->ifindex, vid, zvni->vni, mac->loc_seq,
+ mac->flags, listcount(mac->neigh_list));
/* Update all the neigh entries associated with this mac */
zvni_process_neigh_on_local_mac_del(zvni, mac);