summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_community_alias.c29
-rw-r--r--bgpd/bgp_community_alias.h1
-rw-r--r--bgpd/bgp_route.c156
-rw-r--r--bgpd/bgp_vty.c6
-rw-r--r--doc/user/bgp.rst16
-rw-r--r--lib/route_types.txt4
-rw-r--r--tests/topotests/bgp_conditional_advertisement/r1/bgpd.conf1
-rw-r--r--tests/topotests/bgp_conditional_advertisement/r2/bgpd.conf1
-rw-r--r--tests/topotests/bgp_conditional_advertisement/r3/bgpd.conf1
-rwxr-xr-xtests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py8
-rw-r--r--tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json191
-rw-r--r--tests/topotests/lib/bgp.py412
-rw-r--r--tests/topotests/lib/common_config.py117
-rwxr-xr-xtools/frr-reload.py46
-rw-r--r--zebra/rib.h45
-rw-r--r--zebra/rt.h4
-rw-r--r--zebra/rt_netlink.c14
-rw-r--r--zebra/rt_netlink.h5
-rw-r--r--zebra/rtread_netlink.c6
-rw-r--r--zebra/rtread_sysctl.c4
-rw-r--r--zebra/zapi_msg.c18
-rw-r--r--zebra/zebra_dplane.c10
-rw-r--r--zebra/zebra_evpn.c29
-rw-r--r--zebra/zebra_evpn.h10
-rw-r--r--zebra/zebra_evpn_mac.c44
-rw-r--r--zebra/zebra_evpn_mac.h42
-rw-r--r--zebra/zebra_evpn_mh.c23
-rw-r--r--zebra/zebra_evpn_mh.h9
-rw-r--r--zebra/zebra_evpn_neigh.c44
-rw-r--r--zebra/zebra_evpn_neigh.h36
-rw-r--r--zebra/zebra_nhg.c9
-rw-r--r--zebra/zebra_rib.c403
-rw-r--r--zebra/zebra_rnh.c3
-rw-r--r--zebra/zebra_rnh.h3
-rw-r--r--zebra/zebra_vxlan.c280
-rw-r--r--zebra/zebra_vxlan.h12
36 files changed, 1376 insertions, 666 deletions
diff --git a/bgpd/bgp_community_alias.c b/bgpd/bgp_community_alias.c
index 6e510a0a04..f770ebdd5d 100644
--- a/bgpd/bgp_community_alias.c
+++ b/bgpd/bgp_community_alias.c
@@ -152,3 +152,32 @@ const char *bgp_community2alias(char *community)
return community;
}
+
+static int bgp_community_alias_vector_walker(struct hash_bucket *bucket,
+ void *data)
+{
+ vector *comps = data;
+ struct community_alias *alias = bucket->data;
+
+ vector_set(*comps, XSTRDUP(MTYPE_COMPLETION, alias->alias));
+
+ return 1;
+}
+
+static void bgp_community_alias_cmd_completion(vector comps,
+ struct cmd_token *token)
+{
+ hash_walk(bgp_ca_alias_hash, bgp_community_alias_vector_walker, &comps);
+}
+
+static const struct cmd_variable_handler community_alias_handlers[] = {
+ {.varname = "alias_name",
+ .completions = bgp_community_alias_cmd_completion},
+ {.tokenname = "ALIAS_NAME",
+ .completions = bgp_community_alias_cmd_completion},
+ {.completions = NULL}};
+
+void bgp_community_alias_command_completion_setup(void)
+{
+ cmd_variable_handler_register(community_alias_handlers);
+}
diff --git a/bgpd/bgp_community_alias.h b/bgpd/bgp_community_alias.h
index c84119a0d6..ab8ed06ee6 100644
--- a/bgpd/bgp_community_alias.h
+++ b/bgpd/bgp_community_alias.h
@@ -42,5 +42,6 @@ extern void bgp_ca_community_delete(struct community_alias *ca);
extern void bgp_ca_alias_delete(struct community_alias *ca);
extern int bgp_community_alias_write(struct vty *vty);
extern const char *bgp_community2alias(char *community);
+extern void bgp_community_alias_command_completion_setup(void);
#endif /* FRR_BGP_COMMUNITY_ALIAS_H */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index bd45314350..e9cbf22882 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3663,7 +3663,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (aspath_loop_check(attr->aspath, peer->change_local_as)
> aspath_loop_count) {
peer->stat_pfx_aspath_loop++;
- reason = "as-path contains our own AS A;";
+ reason = "as-path contains our own AS;";
goto filtered;
}
}
@@ -9519,14 +9519,18 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
afi_t afi, safi_t safi, bool use_json,
- json_object *json)
+ json_object *json_paths)
{
- struct attr *attr;
+ struct attr *attr = path->attr;
int len;
char timebuf[BGP_UPTIME_LEN];
+ json_object *json_path = NULL;
+
+ if (use_json)
+ json_path = json_object_new_object();
/* short status lead text */
- route_vty_short_status_out(vty, path, p, json);
+ route_vty_short_status_out(vty, path, p, json_path);
/* print prefix and mask */
if (!use_json) {
@@ -9534,147 +9538,125 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
route_vty_out_route(path->net, p, vty, NULL, false);
else
vty_out(vty, "%*s", 17, " ");
- }
- len = vty_out(vty, "%s", path->peer->host);
- len = 17 - len;
- if (len < 1) {
- if (!use_json)
+ len = vty_out(vty, "%s", path->peer->host);
+ len = 17 - len;
+
+ if (len < 1)
vty_out(vty, "\n%*s", 34, " ");
- } else {
- if (use_json)
- json_object_int_add(json, "peerHost", len);
else
vty_out(vty, "%*s", len, " ");
- }
- if (use_json)
- bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
- safi, use_json, json);
- else
vty_out(vty, "%s ",
bgp_damp_reuse_time_vty(vty, path, timebuf,
BGP_UPTIME_LEN, afi, safi,
- use_json, json));
-
- /* Print attribute */
- attr = path->attr;
+ use_json, NULL));
- /* Print aspath */
- if (attr->aspath) {
- if (use_json)
- json_object_string_add(json, "asPath",
- attr->aspath->str);
- else
+ if (attr->aspath)
aspath_print_vty(vty, "%s", attr->aspath, " ");
- }
- /* Print origin */
- if (use_json)
- json_object_string_add(json, "origin",
- bgp_origin_str[attr->origin]);
- else
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
- if (!use_json)
vty_out(vty, "\n");
+ } else {
+ bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
+ safi, use_json, json_path);
+
+ if (attr->aspath)
+ json_object_string_add(json_path, "asPath",
+ attr->aspath->str);
+
+ json_object_string_add(json_path, "origin",
+ bgp_origin_str[attr->origin]);
+ json_object_string_add(json_path, "peerHost", path->peer->host);
+
+ json_object_array_add(json_paths, json_path);
+ }
}
/* flap route */
static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
afi_t afi, safi_t safi, bool use_json,
- json_object *json)
+ json_object *json_paths)
{
- struct attr *attr;
+ struct attr *attr = path->attr;
struct bgp_damp_info *bdi;
char timebuf[BGP_UPTIME_LEN];
int len;
+ json_object *json_path = NULL;
if (!path->extra)
return;
+ if (use_json)
+ json_path = json_object_new_object();
+
bdi = path->extra->damp_info;
/* short status lead text */
- route_vty_short_status_out(vty, path, p, json);
+ route_vty_short_status_out(vty, path, p, json_path);
- /* print prefix and mask */
if (!use_json) {
if (!display)
route_vty_out_route(path->net, p, vty, NULL, false);
else
vty_out(vty, "%*s", 17, " ");
- }
- len = vty_out(vty, "%s", path->peer->host);
- len = 16 - len;
- if (len < 1) {
- if (!use_json)
+ len = vty_out(vty, "%s", path->peer->host);
+ len = 16 - len;
+ if (len < 1)
vty_out(vty, "\n%*s", 33, " ");
- } else {
- if (use_json)
- json_object_int_add(json, "peerHost", len);
else
vty_out(vty, "%*s", len, " ");
- }
- len = vty_out(vty, "%d", bdi->flap);
- len = 5 - len;
- if (len < 1) {
- if (!use_json)
+ len = vty_out(vty, "%d", bdi->flap);
+ len = 5 - len;
+ if (len < 1)
vty_out(vty, " ");
- } else {
- if (use_json)
- json_object_int_add(json, "bdiFlap", len);
else
vty_out(vty, "%*s", len, " ");
- }
- if (use_json)
- peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
- json);
- else
vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
BGP_UPTIME_LEN, 0, NULL));
- if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
- && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
- if (use_json)
- bgp_damp_reuse_time_vty(vty, path, timebuf,
- BGP_UPTIME_LEN, afi, safi,
- use_json, json);
- else
+ if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
+ && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
vty_out(vty, "%s ",
bgp_damp_reuse_time_vty(vty, path, timebuf,
BGP_UPTIME_LEN, afi,
- safi, use_json, json));
- } else {
- if (!use_json)
+ safi, use_json, NULL));
+ else
vty_out(vty, "%*s ", 8, " ");
- }
-
- /* Print attribute */
- attr = path->attr;
- /* Print aspath */
- if (attr->aspath) {
- if (use_json)
- json_object_string_add(json, "asPath",
- attr->aspath->str);
- else
+ if (attr->aspath)
aspath_print_vty(vty, "%s", attr->aspath, " ");
- }
- /* Print origin */
- if (use_json)
- json_object_string_add(json, "origin",
- bgp_origin_str[attr->origin]);
- else
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
- if (!use_json)
vty_out(vty, "\n");
+ } else {
+ json_object_string_add(json_path, "peerHost", path->peer->host);
+ json_object_int_add(json_path, "bdiFlap", bdi->flap);
+
+ peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
+ json_path);
+
+ if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
+ && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
+ bgp_damp_reuse_time_vty(vty, path, timebuf,
+ BGP_UPTIME_LEN, afi, safi,
+ use_json, json_path);
+
+ if (attr->aspath)
+ json_object_string_add(json_path, "asPath",
+ attr->aspath->str);
+
+ json_object_string_add(json_path, "origin",
+ bgp_origin_str[attr->origin]);
+
+ json_object_array_add(json_paths, json_path);
+ }
}
static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
@@ -12196,7 +12178,7 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
|route-filter-translated-v4] [exact-match]\
|rpki <invalid|valid|notfound>\
|version (1-4294967295)\
- |alias WORD\
+ |alias ALIAS_NAME\
] [json$uj [detail$detail] | wide$wide]",
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 576ced3473..dfdfab79a5 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1565,7 +1565,7 @@ void cli_show_router_bgp_router_id(struct vty *vty, struct lyd_node *dnode,
}
DEFPY(bgp_community_alias, bgp_community_alias_cmd,
- "[no$no] bgp community alias WORD$community WORD$alias",
+ "[no$no] bgp community alias WORD$community ALIAS_NAME$alias_name",
NO_STR BGP_STR
"Add community specific parameters\n"
"Create an alias for a community\n"
@@ -1585,7 +1585,7 @@ DEFPY(bgp_community_alias, bgp_community_alias_cmd,
memset(&ca1, 0, sizeof(ca1));
memset(&ca2, 0, sizeof(ca2));
strlcpy(ca1.community, community, sizeof(ca1.community));
- strlcpy(ca1.alias, alias, sizeof(ca1.alias));
+ strlcpy(ca1.alias, alias_name, sizeof(ca1.alias));
lookup_community = bgp_ca_community_lookup(&ca1);
lookup_alias = bgp_ca_alias_lookup(&ca1);
@@ -20970,4 +20970,6 @@ void community_alias_vty(void)
/* Community-list. */
install_element(CONFIG_NODE, &bgp_community_alias_cmd);
+
+ bgp_community_alias_command_completion_setup();
}
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index ac17328325..6b5a008761 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -401,6 +401,22 @@ Route Selection
paths learned from any of eBGP, iBGP, or confederation neighbors will
be multipath if they are otherwise considered equal cost.
+.. clicmd:: maximum-paths (1-128)
+
+ Sets the maximum-paths value used for ecmp calculations for this
+ bgp instance in EBGP. The maximum value listed, 128, can be limited by
+ the ecmp cli for bgp or if the daemon was compiled with a lower
+ ecmp value. This value can also be set in ipv4/ipv6 unicast/labeled
+ unicast to only affect those particular afi/safi's.
+
+.. clicmd:: maximum-paths ibgp (1-128) [equal-cluster-length]
+
+ Sets the maximum-paths value used for ecmp calculations for this
+ bgp instance in IBGP. The maximum value listed, 128, can be limited by
+ the ecmp cli for bgp or if the daemon was compiled with a lower
+ ecmp value. This value can also be set in ipv4/ipv6 unicast/labeled
+ unicast to only affect those particular afi/safi's.
+
.. _bgp-distance:
Administrative Distance Metrics
diff --git a/lib/route_types.txt b/lib/route_types.txt
index c48391545d..77639070c9 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -1,4 +1,4 @@
-# Canonical Zserv route types information registry for Quagga.
+# Canonical Zserv route types information registry for FRR.
#
# Used to construct route_types.c and route_types.h
#
@@ -60,7 +60,7 @@ ZEBRA_ROUTE_PIM, pim, pimd, 'P', 0, 0, 0, "PIM", pimd
ZEBRA_ROUTE_EIGRP, eigrp, eigrpd, 'E', 1, 0, 1, "EIGRP", eigrpd
ZEBRA_ROUTE_NHRP, nhrp, nhrpd, 'N', 1, 1, 1, "NHRP", nhrpd
# HSLS and OLSR both are AFI independent (so: 1, 1), however
-# we want to disable for them for general Quagga distribution.
+# we want to disable for them for general FRR distribution.
# This at least makes it trivial for users of these protocols
# to 'switch on' redist support (direct numeric entry remaining
# possible).
diff --git a/tests/topotests/bgp_conditional_advertisement/r1/bgpd.conf b/tests/topotests/bgp_conditional_advertisement/r1/bgpd.conf
index 633d1832fd..293b38c7e8 100644
--- a/tests/topotests/bgp_conditional_advertisement/r1/bgpd.conf
+++ b/tests/topotests/bgp_conditional_advertisement/r1/bgpd.conf
@@ -17,6 +17,7 @@ route-map DEF permit 10
!
router bgp 1
bgp log-neighbor-changes
+ bgp conditional-advertisement timer 5
no bgp ebgp-requires-policy
neighbor 10.10.10.2 remote-as 2
!
diff --git a/tests/topotests/bgp_conditional_advertisement/r2/bgpd.conf b/tests/topotests/bgp_conditional_advertisement/r2/bgpd.conf
index c6147fe658..82525fac64 100644
--- a/tests/topotests/bgp_conditional_advertisement/r2/bgpd.conf
+++ b/tests/topotests/bgp_conditional_advertisement/r2/bgpd.conf
@@ -32,6 +32,7 @@ route-map RMAP-2 deny 10
!
router bgp 2
bgp log-neighbor-changes
+ bgp conditional-advertisement timer 5
no bgp ebgp-requires-policy
neighbor 10.10.10.1 remote-as 1
neighbor 10.10.20.3 remote-as 3
diff --git a/tests/topotests/bgp_conditional_advertisement/r3/bgpd.conf b/tests/topotests/bgp_conditional_advertisement/r3/bgpd.conf
index 2f4f5068d8..f389f309a6 100644
--- a/tests/topotests/bgp_conditional_advertisement/r3/bgpd.conf
+++ b/tests/topotests/bgp_conditional_advertisement/r3/bgpd.conf
@@ -1,6 +1,7 @@
!
router bgp 3
bgp log-neighbor-changes
+ bgp conditional-advertisement timer 5
no bgp ebgp-requires-policy
neighbor 10.10.20.2 remote-as 2
!
diff --git a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
index 086bad6481..fd5bb38b98 100755
--- a/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
+++ b/tests/topotests/bgp_evpn_vxlan_topo1/test_bgp_evpn_vxlan.py
@@ -365,6 +365,10 @@ def test_ip_pe1_learn():
"run the IP learn test for PE1"
tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
host1 = tgen.gears["host1"]
pe1 = tgen.gears["PE1"]
pe2 = tgen.gears["PE2"]
@@ -380,6 +384,10 @@ def test_ip_pe2_learn():
"run the IP learn test for PE2"
tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
host2 = tgen.gears["host2"]
pe1 = tgen.gears["PE1"]
pe2 = tgen.gears["PE2"]
diff --git a/tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json b/tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json
index 14842da326..dd412708bb 100644
--- a/tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json
+++ b/tests/topotests/evpn_type5_test_topo1/evpn_type5_topo1.json
@@ -41,7 +41,10 @@
"neighbor": {
"e1": {
"dest_link": {
- "r1": {}
+ "r1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -55,7 +58,10 @@
"neighbor": {
"e1": {
"dest_link": {
- "r1": {}
+ "r1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -106,7 +112,10 @@
"neighbor": {
"e1": {
"dest_link": {
- "r2-link1": {}
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -120,7 +129,10 @@
"neighbor": {
"e1": {
"dest_link": {
- "r2-link1": {}
+ "r2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -140,7 +152,10 @@
"neighbor": {
"e1": {
"dest_link": {
- "r2-link2": {}
+ "r2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -154,7 +169,10 @@
"neighbor": {
"e1": {
"dest_link": {
- "r2-link2": {}
+ "r2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -222,7 +240,10 @@
"neighbor": {
"r1": {
"dest_link": {
- "e1": {}
+ "e1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -233,7 +254,10 @@
"neighbor": {
"r1": {
"dest_link": {
- "e1": {}
+ "e1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -262,7 +286,10 @@
"neighbor": {
"r2": {
"dest_link": {
- "e1-link1": {}
+ "e1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -273,7 +300,10 @@
"neighbor": {
"r2": {
"dest_link": {
- "e1-link1": {}
+ "e1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -302,7 +332,10 @@
"neighbor": {
"r2": {
"dest_link": {
- "e1-link2": {}
+ "e1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -313,7 +346,10 @@
"neighbor": {
"r2": {
"dest_link": {
- "e1-link2": {}
+ "e1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -342,6 +378,8 @@
"d1": {
"dest_link": {
"e1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
"deactivate": "ipv4"
}
}
@@ -349,6 +387,8 @@
"d2": {
"dest_link": {
"e1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
"deactivate": "ipv4"
}
}
@@ -412,6 +452,8 @@
"e1": {
"dest_link": {
"d1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3,
"deactivate": "ipv4"
}
}
@@ -442,7 +484,10 @@
"neighbor": {
"r3": {
"dest_link": {
- "d1": {}
+ "d1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -453,7 +498,10 @@
"neighbor": {
"r3": {
"dest_link": {
- "d1": {}
+ "d1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -482,7 +530,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d1-link1": {}
+ "d1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -493,7 +544,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d1-link1": {}
+ "d1-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -522,7 +576,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d1-link2": {}
+ "d1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -533,7 +590,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d1-link2": {}
+ "d1-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -590,7 +650,9 @@
"e1": {
"dest_link": {
"d2-link1": {
- "deactivate": "ipv4"
+ "deactivate": "ipv4",
+ "keepalivetimer": 1,
+ "holddowntimer": 3
}
}
}
@@ -620,7 +682,10 @@
"neighbor": {
"r3": {
"dest_link": {
- "d2": {}
+ "d2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -631,7 +696,10 @@
"neighbor": {
"r3": {
"dest_link": {
- "d2": {}
+ "d2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -660,7 +728,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d2-link1": {}
+ "d2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -671,7 +742,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d2-link1": {}
+ "d2-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -700,7 +774,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d2-link2": {}
+ "d2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -711,7 +788,10 @@
"neighbor": {
"r4": {
"dest_link": {
- "d2-link2": {}
+ "d2-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -755,12 +835,18 @@
"neighbor": {
"d1": {
"dest_link": {
- "r3": {}
+ "r3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
},
"d2": {
"dest_link": {
- "r3": {}
+ "r3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -771,12 +857,18 @@
"neighbor": {
"d1": {
"dest_link": {
- "r3": {}
+ "r3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
},
"d2": {
"dest_link": {
- "r3": {}
+ "r3": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -814,12 +906,18 @@
"neighbor": {
"d1": {
"dest_link": {
- "r4-link1": {}
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
},
"d2": {
"dest_link": {
- "r4-link1": {}
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -830,12 +928,18 @@
"neighbor": {
"d1": {
"dest_link": {
- "r4-link1": {}
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
},
"d2": {
"dest_link": {
- "r4-link1": {}
+ "r4-link1": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -852,12 +956,18 @@
"neighbor": {
"d1": {
"dest_link": {
- "r4-link2": {}
+ "r4-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
},
"d2": {
"dest_link": {
- "r4-link2": {}
+ "r4-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -868,12 +978,18 @@
"neighbor": {
"d1": {
"dest_link": {
- "r4-link2": {}
+ "r4-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
},
"d2": {
"dest_link": {
- "r4-link2": {}
+ "r4-link2": {
+ "keepalivetimer": 1,
+ "holddowntimer": 3
+ }
}
}
}
@@ -885,3 +1001,4 @@
}
}
}
+
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index a236a916b5..2f1f67439f 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -44,6 +44,7 @@ from lib.common_config import (
FRRCFG_FILE,
retry,
get_ipv6_linklocal_address,
+ get_frr_ipv6_linklocal
)
LOGDIR = "/tmp/topotests/"
@@ -265,6 +266,11 @@ def __create_bgp_global(tgen, input_dict, router, build=False):
config_data.append("bgp router-id {}".format(router_id))
config_data.append("no bgp network import-check")
+ bgp_peer_grp_data = bgp_data.setdefault("peer-group", {})
+
+ if "peer-group" in bgp_data and bgp_peer_grp_data:
+ peer_grp_data = __create_bgp_peer_group(tgen, bgp_peer_grp_data, router)
+ config_data.extend(peer_grp_data)
bst_path = bgp_data.setdefault("bestpath", None)
if bst_path:
@@ -380,6 +386,7 @@ def __create_bgp_unicast_neighbor(
addr_data = addr_dict["unicast"]
if addr_data:
config_data.append("address-family {} unicast".format(addr_type))
+
advertise_network = addr_data.setdefault("advertise_networks", [])
for advertise_network_dict in advertise_network:
network = advertise_network_dict["network"]
@@ -404,14 +411,29 @@ def __create_bgp_unicast_neighbor(
config_data.append(cmd)
+ import_cmd = addr_data.setdefault("import", {})
+ if import_cmd:
+ try:
+ if import_cmd["delete"]:
+ config_data.append("no import vrf {}".format(import_cmd["vrf"]))
+ except KeyError:
+ config_data.append("import vrf {}".format(import_cmd["vrf"]))
+
max_paths = addr_data.setdefault("maximum_paths", {})
if max_paths:
ibgp = max_paths.setdefault("ibgp", None)
ebgp = max_paths.setdefault("ebgp", None)
+ del_cmd = max_paths.setdefault("delete", False)
if ibgp:
- config_data.append("maximum-paths ibgp {}".format(ibgp))
+ if del_cmd:
+ config_data.append("no maximum-paths ibgp {}".format(ibgp))
+ else:
+ config_data.append("maximum-paths ibgp {}".format(ibgp))
if ebgp:
- config_data.append("maximum-paths {}".format(ebgp))
+ if del_cmd:
+ config_data.append("no maximum-paths {}".format(ebgp))
+ else:
+ config_data.append("maximum-paths {}".format(ebgp))
aggregate_addresses = addr_data.setdefault("aggregate_address", [])
for aggregate_address in aggregate_addresses:
@@ -649,6 +671,38 @@ def __create_l2vpn_evpn_address_family(
return config_data
+def __create_bgp_peer_group(topo, input_dict, router):
+ """
+ Helper API to create neighbor specific configuration
+
+ Parameters
+ ----------
+ * `topo` : json file data
+ * `input_dict` : Input dict data, required when configuring from testcase
+ * `router` : router id to be configured
+ """
+ config_data = []
+ logger.debug("Entering lib API: __create_bgp_peer_group()")
+
+ for grp, grp_dict in input_dict.items():
+ config_data.append("neighbor {} peer-group".format(grp))
+ neigh_cxt = "neighbor {} ".format(grp)
+ update_source = grp_dict.setdefault("update-source", None)
+ remote_as = grp_dict.setdefault("remote-as", None)
+ capability = grp_dict.setdefault("capability", None)
+ if update_source:
+ config_data.append("{} update-source {}".format(neigh_cxt, update_source))
+
+ if remote_as:
+ config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
+
+ if capability:
+ config_data.append("{} capability {}".format(neigh_cxt, capability))
+
+ logger.debug("Exiting lib API: __create_bgp_peer_group()")
+ return config_data
+
+
def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
"""
Helper API to create neighbor specific configuration
@@ -660,10 +714,9 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
* `input_dict` : Input dict data, required when configuring from testcase
* `router` : router id to be configured
"""
-
config_data = []
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
-
+ tgen = get_topogen()
bgp_data = input_dict["address_family"]
neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
@@ -672,35 +725,91 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
nh_details = topo[name]
if "vrfs" in topo[router] or type(nh_details["bgp"]) is list:
- remote_as = nh_details["bgp"][0]["local_as"]
+ for vrf_data in nh_details["bgp"]:
+ if "vrf" in nh_details["links"][dest_link] and "vrf" in vrf_data:
+ if nh_details["links"][dest_link]["vrf"] == vrf_data["vrf"]:
+ remote_as = vrf_data["local_as"]
+ break
+ else:
+ if "vrf" not in vrf_data:
+ remote_as = vrf_data["local_as"]
+ break
+
else:
remote_as = nh_details["bgp"]["local_as"]
update_source = None
- if dest_link in nh_details["links"].keys():
- ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0]
- # Loopback interface
- if "source_link" in peer and peer["source_link"] == "lo":
- update_source = topo[router]["links"]["lo"][addr_type].split("/")[0]
+ if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
+ ip_addr = nh_details["links"][dest_link]["peer-interface"]
+ elif "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
+ intf = topo[name]["links"][dest_link]["interface"]
+ ip_addr = get_frr_ipv6_linklocal(tgen, name, intf)
+ elif dest_link in nh_details["links"].keys():
+ try:
+ ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0]
+ except KeyError:
+ intf = topo[name]["links"][dest_link]["interface"]
+ ip_addr = get_frr_ipv6_linklocal(tgen, name, intf)
+ if "delete" in peer and peer["delete"]:
+ neigh_cxt = "no neighbor {}".format(ip_addr)
+ config_data.append("{}".format(neigh_cxt))
+ return config_data
+ else:
+ neigh_cxt = "neighbor {}".format(ip_addr)
- neigh_cxt = "neighbor {}".format(ip_addr)
+ if "peer-group" in peer:
+ config_data.append(
+ "neighbor {} interface peer-group {}".format(
+ ip_addr, peer["peer-group"]
+ )
+ )
+
+ # Loopback interface
+ if "source_link" in peer:
+ if peer["source_link"] == "lo":
+ update_source = topo[router]["links"]["lo"][addr_type].split("/")[0]
+ else:
+ update_source = topo[router]["links"][peer["source_link"]][
+ "interface"
+ ]
+ if "peer-group" not in peer:
+ if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
+ config_data.append(
+ "{} interface remote-as {}".format(neigh_cxt, remote_as)
+ )
+ elif add_neigh:
+ config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
- if add_neigh:
- config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
if addr_type == "ipv6":
config_data.append("address-family ipv6 unicast")
config_data.append("{} activate".format(neigh_cxt))
+ if "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
+ config_data.append(
+ "{} update-source {}".format(
+ neigh_cxt, nh_details["links"][dest_link]["peer-interface"]
+ )
+ )
+ config_data.append(
+ "{} interface {}".format(
+ neigh_cxt, nh_details["links"][dest_link]["peer-interface"]
+ )
+ )
+
disable_connected = peer.setdefault("disable_connected_check", False)
keep_alive = peer.setdefault("keepalivetimer", 3)
hold_down = peer.setdefault("holddowntimer", 10)
password = peer.setdefault("password", None)
no_password = peer.setdefault("no_password", None)
+ capability = peer.setdefault("capability", None)
max_hop_limit = peer.setdefault("ebgp_multihop", 1)
+
graceful_restart = peer.setdefault("graceful-restart", None)
graceful_restart_helper = peer.setdefault("graceful-restart-helper", None)
graceful_restart_disable = peer.setdefault("graceful-restart-disable", None)
+ if capability:
+ config_data.append("{} capability {}".format(neigh_cxt, capability))
if update_source:
config_data.append(
@@ -718,7 +827,6 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
config_data.append(
"{} timers {} {}".format(neigh_cxt, keep_alive, hold_down)
)
-
if graceful_restart:
config_data.append("{} graceful-restart".format(neigh_cxt))
elif graceful_restart == False:
@@ -768,7 +876,7 @@ def __create_bgp_unicast_address_family(
config_data = []
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
-
+ tgen = get_topogen()
bgp_data = input_dict["address_family"]
neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
@@ -784,16 +892,34 @@ def __create_bgp_unicast_address_family(
for destRouterLink, data in sorted(nh_details["links"].items()):
if "type" in data and data["type"] == "loopback":
if dest_link == destRouterLink:
- ip_addr = nh_details["links"][destRouterLink][
- addr_type
- ].split("/")[0]
+ ip_addr = (
+ nh_details["links"][destRouterLink][addr_type]
+ .split("/")[0]
+ .lower()
+ )
# Physical interface
else:
- if dest_link in nh_details["links"].keys():
-
- ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0]
- if addr_type == "ipv4" and bgp_data["ipv6"]:
+ # check the neighbor type if un numbered nbr, use interface.
+ if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
+ ip_addr = nh_details["links"][dest_link]["peer-interface"]
+ elif "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
+ intf = topo[peer_name]["links"][dest_link]["interface"]
+ ip_addr = get_frr_ipv6_linklocal(tgen, peer_name, intf)
+ elif dest_link in nh_details["links"].keys():
+ try:
+ ip_addr = nh_details["links"][dest_link][addr_type].split("/")[
+ 0
+ ]
+ except KeyError:
+ intf = topo[peer_name]["links"][dest_link]["interface"]
+ ip_addr = get_frr_ipv6_linklocal(tgen, peer_name, intf)
+ if (
+ addr_type == "ipv4"
+ and bgp_data["ipv6"]
+ and check_address_types("ipv6")
+ and "ipv6" in nh_details["links"][dest_link]
+ ):
deactivate = nh_details["links"][dest_link]["ipv6"].split("/")[
0
]
@@ -822,6 +948,7 @@ def __create_bgp_unicast_address_family(
prefix_lists = peer.setdefault("prefix_lists", {})
route_maps = peer.setdefault("route_maps", {})
no_send_community = peer.setdefault("no_send_community", None)
+ capability = peer.setdefault("capability", None)
allowas_in = peer.setdefault("allowas-in", None)
# next-hop-self
@@ -841,6 +968,11 @@ def __create_bgp_unicast_address_family(
"no {} send-community {}".format(neigh_cxt, no_send_community)
)
+ # capability_ext_nh
+ if capability and addr_type == "ipv6":
+ config_data.append("address-family ipv4 unicast")
+ config_data.append("{} activate".format(neigh_cxt))
+
if "allowas_in" in peer:
allow_as_in = peer["allowas_in"]
config_data.append("{} allowas-in {}".format(neigh_cxt, allow_as_in))
@@ -1067,33 +1199,37 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
API will verify if BGP is converged with in the given time frame.
Running "show bgp summary json" command and verify bgp neighbor
state is established,
+
Parameters
----------
* `tgen`: topogen object
* `topo`: input json file data
* `dut`: device under test
- * `expected` : expected results from API, by-default True
Usage
-----
# To veriry is BGP is converged for all the routers used in
topology
results = verify_bgp_convergence(tgen, topo, dut="r1")
+
Returns
-------
errormsg(str) or True
"""
- logger.debug("Entering lib API: verify_bgp_convergence()")
+ result = False
+ logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+ tgen = get_topogen()
for router, rnode in tgen.routers().items():
- if dut is not None and dut != router:
+ if 'bgp' not in topo['routers'][router]:
continue
- if "bgp" not in topo["routers"][router]:
+ if dut is not None and dut != router:
continue
logger.info("Verifying BGP Convergence on router %s:", router)
- show_bgp_json = run_frr_cmd(rnode, "show bgp vrf all summary json", isjson=True)
+ show_bgp_json = run_frr_cmd(rnode, "show bgp vrf all summary json",
+ isjson=True)
# Verifying output dictionary show_bgp_json is empty or not
if not bool(show_bgp_json):
errormsg = "BGP is not running"
@@ -1115,100 +1251,6 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
# To find neighbor ip type
bgp_addr_type = bgp_data["address_family"]
- if "ipv4" in bgp_addr_type or "ipv6" in bgp_addr_type:
- for addr_type in bgp_addr_type.keys():
- if not check_address_types(addr_type):
- continue
- total_peer = 0
-
- bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"]
-
- for bgp_neighbor in bgp_neighbors:
- total_peer += len(bgp_neighbors[bgp_neighbor]["dest_link"])
-
- for addr_type in bgp_addr_type.keys():
- if not check_address_types(addr_type):
- continue
- bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"]
-
- no_of_peer = 0
- for bgp_neighbor, peer_data in bgp_neighbors.items():
- for dest_link in peer_data["dest_link"].keys():
- data = topo["routers"][bgp_neighbor]["links"]
- if dest_link in data:
- peer_details = peer_data["dest_link"][dest_link]
- # for link local neighbors
- if (
- "neighbor_type" in peer_details
- and peer_details["neighbor_type"] == "link-local"
- ):
- neighbor_ip = get_ipv6_linklocal_address(
- topo["routers"], bgp_neighbor, dest_link
- )
- elif "source_link" in peer_details:
- neighbor_ip = topo["routers"][bgp_neighbor][
- "links"
- ][peer_details["source_link"]][addr_type].split(
- "/"
- )[
- 0
- ]
- elif (
- "neighbor_type" in peer_details
- and peer_details["neighbor_type"] == "unnumbered"
- ):
- neighbor_ip = data[dest_link]["peer-interface"]
- else:
- neighbor_ip = data[dest_link][addr_type].split("/")[
- 0
- ]
- nh_state = None
-
- if addr_type == "ipv4":
- if "ipv4Unicast" in show_bgp_json[vrf]:
- ipv4_data = show_bgp_json[vrf]["ipv4Unicast"][
- "peers"
- ]
- nh_state = ipv4_data[neighbor_ip]["state"]
- else:
- if "ipv6Unicast" in show_bgp_json[vrf]:
- ipv6_data = show_bgp_json[vrf]["ipv6Unicast"][
- "peers"
- ]
- nh_state = ipv6_data[neighbor_ip]["state"]
- if nh_state == "Established":
- no_of_peer += 1
-
- if "l2vpn" in bgp_addr_type:
- if "neighbor" not in bgp_addr_type["l2vpn"]["evpn"]:
- if no_of_peer == total_peer:
- logger.info(
- "[DUT: %s] VRF: %s, BGP is Converged for %s address-family",
- router,
- vrf,
- addr_type,
- )
- else:
- errormsg = (
- "[DUT: %s] VRF: %s, BGP is not converged for %s address-family"
- % (router, vrf, addr_type)
- )
- return errormsg
- else:
- if no_of_peer == total_peer:
- logger.info(
- "[DUT: %s] VRF: %s, BGP is Converged for %s address-family",
- router,
- vrf,
- addr_type,
- )
- else:
- errormsg = (
- "[DUT: %s] VRF: %s, BGP is not converged for %s address-family"
- % (router, vrf, addr_type)
- )
- return errormsg
-
if "l2vpn" in bgp_addr_type:
total_evpn_peer = 0
@@ -1224,46 +1266,120 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
data = topo["routers"][bgp_neighbor]["links"]
for dest_link in dest_link_dict.keys():
if dest_link in data:
- peer_details = peer_data[_addr_type][dest_link]
+ peer_details = \
+ peer_data[_addr_type][dest_link]
- neighbor_ip = data[dest_link][_addr_type].split("/")[0]
+ neighbor_ip = \
+ data[dest_link][_addr_type].split(
+ "/")[0]
nh_state = None
- if (
- "ipv4Unicast" in show_bgp_json[vrf]
- or "ipv6Unicast" in show_bgp_json[vrf]
- ):
- errormsg = (
- "[DUT: %s] VRF: %s, "
- "ipv4Unicast/ipv6Unicast"
- " address-family present"
- " under l2vpn" % (router, vrf)
- )
+ if "ipv4Unicast" in show_bgp_json[vrf] or \
+ "ipv6Unicast" in show_bgp_json[vrf]:
+ errormsg = ("[DUT: %s] VRF: %s, "
+ "ipv4Unicast/ipv6Unicast"
+ " address-family present"
+ " under l2vpn" % (router,
+ vrf))
return errormsg
- l2VpnEvpn_data = show_bgp_json[vrf]["l2VpnEvpn"][
- "peers"
- ]
- nh_state = l2VpnEvpn_data[neighbor_ip]["state"]
+ l2VpnEvpn_data = \
+ show_bgp_json[vrf]["l2VpnEvpn"][
+ "peers"]
+ nh_state = \
+ l2VpnEvpn_data[neighbor_ip]["state"]
if nh_state == "Established":
no_of_evpn_peer += 1
if no_of_evpn_peer == total_evpn_peer:
- logger.info(
- "[DUT: %s] VRF: %s, BGP is Converged for " "epvn peers",
- router,
- vrf,
- )
+ logger.info("[DUT: %s] VRF: %s, BGP is Converged for "
+ "epvn peers", router, vrf)
+ result = True
else:
- errormsg = (
- "[DUT: %s] VRF: %s, BGP is not converged "
- "for evpn peers" % (router, vrf)
- )
+ errormsg = ("[DUT: %s] VRF: %s, BGP is not converged "
+ "for evpn peers" % (router, vrf))
return errormsg
+ else:
+ total_peer = 0
+ for addr_type in bgp_addr_type.keys():
+ if not check_address_types(addr_type):
+ continue
- logger.debug("Exiting API: verify_bgp_convergence()")
- return True
+ bgp_neighbors = \
+ bgp_addr_type[addr_type]["unicast"]["neighbor"]
+
+ for bgp_neighbor in bgp_neighbors:
+ total_peer += \
+ len(bgp_neighbors[bgp_neighbor]["dest_link"])
+
+ no_of_peer = 0
+ for addr_type in bgp_addr_type.keys():
+ if not check_address_types(addr_type):
+ continue
+ bgp_neighbors = \
+ bgp_addr_type[addr_type]["unicast"]["neighbor"]
+
+ for bgp_neighbor, peer_data in bgp_neighbors.items():
+ for dest_link in peer_data["dest_link"].\
+ keys():
+ data = \
+ topo["routers"][bgp_neighbor]["links"]
+ if dest_link in data:
+ peer_details = \
+ peer_data['dest_link'][dest_link]
+ # for link local neighbors
+ if "neighbor_type" in peer_details and \
+ peer_details["neighbor_type"] == \
+ 'link-local':
+ intf = topo["routers"][bgp_neighbor][
+ "links"][dest_link]["interface"]
+ neighbor_ip = get_frr_ipv6_linklocal(
+ tgen, bgp_neighbor, intf)
+ elif "source_link" in peer_details:
+ neighbor_ip = \
+ topo["routers"][bgp_neighbor][
+ "links"][peer_details[
+ 'source_link']][
+ addr_type].\
+ split("/")[0]
+ elif "neighbor_type" in peer_details and \
+ peer_details["neighbor_type"] == \
+ 'unnumbered':
+ neighbor_ip = \
+ data[dest_link]["peer-interface"]
+ else:
+ neighbor_ip = \
+ data[dest_link][addr_type].split(
+ "/")[0]
+ nh_state = None
+ neighbor_ip = neighbor_ip.lower()
+ if addr_type == "ipv4":
+ ipv4_data = show_bgp_json[vrf][
+ "ipv4Unicast"]["peers"]
+ nh_state = \
+ ipv4_data[neighbor_ip]["state"]
+ else:
+ ipv6_data = show_bgp_json[vrf][
+ "ipv6Unicast"]["peers"]
+ if neighbor_ip in ipv6_data:
+ nh_state = \
+ ipv6_data[neighbor_ip]["state"]
+
+ if nh_state == "Established":
+ no_of_peer += 1
+
+ if no_of_peer == total_peer and no_of_peer > 0:
+ logger.info("[DUT: %s] VRF: %s, BGP is Converged",
+ router, vrf)
+ result = True
+ else:
+ errormsg = ("[DUT: %s] VRF: %s, BGP is not converged"
+ % (router, vrf))
+ return errormsg
+
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return result
@retry(retry_timeout=16)
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 9e60e523d3..6a02e50127 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -497,7 +497,7 @@ def reset_config_on_routers(tgen, routerName=None):
f.close()
run_cfg_file = "{}/{}/frr.sav".format(TMPDIR, rname)
init_cfg_file = "{}/{}/frr_json_initial.conf".format(TMPDIR, rname)
- command = "/usr/lib/frr/frr-reload.py --input {} --test {} > {}".format(
+ command = "/usr/lib/frr/frr-reload.py --test --test-reset --input {} {} > {}".format(
run_cfg_file, init_cfg_file, dname
)
result = call(command, shell=True, stderr=SUB_STDOUT, stdout=SUB_PIPE)
@@ -527,37 +527,9 @@ def reset_config_on_routers(tgen, routerName=None):
raise InvalidCLIError(out_data)
raise InvalidCLIError("Unknown error in %s", output)
- f = open(dname, "r")
delta = StringIO()
- delta.write("configure terminal\n")
- t_delta = f.read()
-
- # Don't disable debugs
- check_debug = True
-
- for line in t_delta.split("\n"):
- line = line.strip()
- if line == "Lines To Delete" or line == "===============" or not line:
- continue
-
- if line == "Lines To Add":
- check_debug = False
- continue
-
- if line == "============" or not line:
- continue
-
- # Leave debugs and log output alone
- if check_debug:
- if "debug" in line or "log file" in line:
- continue
-
- delta.write(line)
- delta.write("\n")
-
- f.close()
-
- delta.write("end\n")
+ with open(dname, "r") as f:
+ delta.write(f.read())
output = router.vtysh_multicmd(delta.getvalue(), pretty_output=False)
@@ -637,6 +609,7 @@ def load_config_to_router(tgen, routerName, save_bkup=False):
return True
+
def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
"""
API to get the link local ipv6 address of a particular interface using
@@ -669,38 +642,48 @@ def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
else:
cmd = "show interface"
- ifaces = router_list[router].run('vtysh -c "{}"'.format(cmd))
-
- # Fix newlines (make them all the same)
- ifaces = ("\n".join(ifaces.splitlines()) + "\n").splitlines()
-
- interface = None
- ll_per_if_count = 0
- for line in ifaces:
- # Interface name
- m = re_search("Interface ([a-zA-Z0-9-]+) is", line)
- if m:
- interface = m.group(1).split(" ")[0]
- ll_per_if_count = 0
-
- # Interface ip
- m1 = re_search("inet6 (fe80[:a-fA-F0-9]+[/0-9]+)", line)
- if m1:
- local = m1.group(1)
- ll_per_if_count += 1
- if ll_per_if_count > 1:
- linklocal += [["%s-%s" % (interface, ll_per_if_count), local]]
- else:
- linklocal += [[interface, local]]
-
- if linklocal:
- if intf:
- return [_linklocal[1] for _linklocal in linklocal if _linklocal[0] == intf][
- 0
- ].split("/")[0]
- return linklocal
- else:
- errormsg = "Link local ip missing on router {}"
+ linklocal = []
+ if vrf:
+ cmd = "show interface vrf {}".format(vrf)
+ else:
+ cmd = "show interface"
+ for chk_ll in range(0, 60):
+ sleep(1/4)
+ ifaces = router_list[router].run('vtysh -c "{}"'.format(cmd))
+ # Fix newlines (make them all the same)
+ ifaces = ('\n'.join(ifaces.splitlines()) + '\n').splitlines()
+
+ interface = None
+ ll_per_if_count = 0
+ for line in ifaces:
+ # Interface name
+ m = re_search('Interface ([a-zA-Z0-9-]+) is', line)
+ if m:
+ interface = m.group(1).split(" ")[0]
+ ll_per_if_count = 0
+
+ # Interface ip
+ m1 = re_search('inet6 (fe80[:a-fA-F0-9]+[\/0-9]+)',
+ line)
+ if m1:
+ local = m1.group(1)
+ ll_per_if_count += 1
+ if ll_per_if_count > 1:
+ linklocal += [["%s-%s" %
+ (interface, ll_per_if_count), local]]
+ else:
+ linklocal += [[interface, local]]
+
+ try:
+ if linklocal:
+ if intf:
+ return [_linklocal[1] for _linklocal in linklocal if _linklocal[0]==intf][0].\
+ split("/")[0]
+ return linklocal
+ except IndexError:
+ continue
+
+ errormsg = "Link local ip missing on router {}".format(router)
return errormsg
@@ -1846,6 +1829,14 @@ def create_interfaces_cfg(tgen, topo, build=False):
else:
interface_data.append("ipv6 address {}".format(intf_addr))
+ # Wait for vrf interfaces to get link local address once they are up
+ if not destRouterLink == 'lo' and 'vrf' in topo[c_router][
+ 'links'][destRouterLink]:
+ vrf = topo[c_router]['links'][destRouterLink]['vrf']
+ intf = topo[c_router]['links'][destRouterLink]['interface']
+ ll = get_frr_ipv6_linklocal(tgen, c_router, intf=intf,
+ vrf = vrf)
+
if "ipv6-link-local" in data:
intf_addr = c_data["links"][destRouterLink]["ipv6-link-local"]
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index eb8753fd08..9d41305ec3 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -2012,6 +2012,11 @@ if __name__ == "__main__":
parser.add_argument(
"--daemon", help="daemon for which want to replace the config", default=""
)
+ parser.add_argument(
+ "--test-reset",
+ action="store_true",
+ help="Used by topotest to not delete debug or log file commands",
+ )
args = parser.parse_args()
@@ -2125,7 +2130,7 @@ if __name__ == "__main__":
service_integrated_vtysh_config = False
break
- if not service_integrated_vtysh_config and not args.daemon:
+ if not args.test and not service_integrated_vtysh_config and not args.daemon:
log.error(
"'service integrated-vtysh-config' is not configured, this is required for 'service frr reload'"
)
@@ -2153,35 +2158,56 @@ if __name__ == "__main__":
running.load_from_show_running(args.daemon)
(lines_to_add, lines_to_del) = compare_context_objects(newconf, running)
- lines_to_configure = []
if lines_to_del:
- print("\nLines To Delete")
- print("===============")
+ if not args.test_reset:
+ print("\nLines To Delete")
+ print("===============")
for (ctx_keys, line) in lines_to_del:
if line == "!":
continue
- cmd = "\n".join(lines_to_config(ctx_keys, line, True))
- lines_to_configure.append(cmd)
+ nolines = lines_to_config(ctx_keys, line, True)
+
+ if args.test_reset:
+ # For topotests the original code stripped the lines, and ommitted blank lines
+ # after, do that here
+ nolines = [x.strip() for x in nolines]
+ # For topotests leave these lines in (don't delete them)
+ # [chopps: why is "log file" more special than other "log" commands?]
+ nolines = [x for x in nolines if "debug" not in x and "log file" not in x]
+ if not nolines:
+ continue
+
+ cmd = "\n".join(nolines)
print(cmd)
if lines_to_add:
- print("\nLines To Add")
- print("============")
+ if not args.test_reset:
+ print("\nLines To Add")
+ print("============")
for (ctx_keys, line) in lines_to_add:
if line == "!":
continue
- cmd = "\n".join(lines_to_config(ctx_keys, line, False))
- lines_to_configure.append(cmd)
+ lines = lines_to_config(ctx_keys, line, False)
+
+ if args.test_reset:
+ # For topotests the original code stripped the lines, and ommitted blank lines
+ # after, do that here
+ lines = [x.strip() for x in lines if x.strip()]
+ if not lines:
+ continue
+
+ cmd = "\n".join(lines)
print(cmd)
elif args.reload:
+ lines_to_configure = []
# We will not be able to do anything, go ahead and exit(1)
if not vtysh.is_config_available():
diff --git a/zebra/rib.h b/zebra/rib.h
index b7ffb9ce8d..31d9dfd265 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -177,15 +177,16 @@ struct route_entry {
/* meta-queue structure:
* sub-queue 0: nexthop group objects
- * sub-queue 1: connected
- * sub-queue 2: kernel
- * sub-queue 3: static
- * sub-queue 4: RIP, RIPng, OSPF, OSPF6, IS-IS, EIGRP, NHRP
- * sub-queue 5: iBGP, eBGP
- * sub-queue 6: any other origin (if any) typically those that
+ * sub-queue 1: EVPN/VxLAN objects
+ * sub-queue 2: connected
+ * sub-queue 3: kernel
+ * sub-queue 4: static
+ * sub-queue 5: RIP, RIPng, OSPF, OSPF6, IS-IS, EIGRP, NHRP
+ * sub-queue 6: iBGP, eBGP
+ * sub-queue 7: any other origin (if any) typically those that
* don't generate routes
*/
-#define MQ_SIZE 7
+#define MQ_SIZE 8
struct meta_queue {
struct list *subq[MQ_SIZE];
uint32_t size; /* sum of lengths of all subqueues */
@@ -446,6 +447,36 @@ extern int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx);
/* Enqueue incoming nhg from proto daemon for processing */
extern int rib_queue_nhe_add(struct nhg_hash_entry *nhe);
+/* Enqueue evpn route for processing */
+int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
+ const struct ipaddr *vtep_ip,
+ const struct prefix *host_prefix);
+int zebra_rib_queue_evpn_route_del(vrf_id_t vrf_id,
+ const struct ipaddr *vtep_ip,
+ const struct prefix *host_prefix);
+/* Enqueue EVPN remote ES for processing */
+int zebra_rib_queue_evpn_rem_es_add(const esi_t *esi,
+ const struct in_addr *vtep_ip,
+ bool esr_rxed, uint8_t df_alg,
+ uint16_t df_pref);
+int zebra_rib_queue_evpn_rem_es_del(const esi_t *esi,
+ const struct in_addr *vtep_ip);
+/* Enqueue EVPN remote macip update for processing */
+int zebra_rib_queue_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
+ const struct ipaddr *ip,
+ struct in_addr vtep_ip);
+int zebra_rib_queue_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
+ const struct ipaddr *ipaddr,
+ uint8_t flags, uint32_t seq,
+ struct in_addr vtep_ip,
+ const esi_t *esi);
+/* Enqueue VXLAN remote vtep update for processing */
+int zebra_rib_queue_evpn_rem_vtep_add(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip,
+ int flood_control);
+int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip);
+
extern void meta_queue_free(struct meta_queue *mq);
extern int zebra_rib_labeled_unicast(struct route_entry *re);
extern struct route_table *rib_table_ipv6;
diff --git a/zebra/rt.h b/zebra/rt.h
index f79ddbe958..929a44ade7 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -93,10 +93,10 @@ extern void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
struct interface *br_if);
extern void macfdb_read_specific_mac(struct zebra_ns *zns,
struct interface *br_if,
- struct ethaddr *mac, vlanid_t vid);
+ const struct ethaddr *mac, vlanid_t vid);
extern void neigh_read(struct zebra_ns *zns);
extern void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *ifp);
-extern void neigh_read_specific_ip(struct ipaddr *ip,
+extern void neigh_read_specific_ip(const struct ipaddr *ip,
struct interface *vlan_if);
extern void route_read(struct zebra_ns *zns);
extern int kernel_upd_mac_nh(uint32_t nh_id, struct in_addr vtep_ip);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 38f8140db2..a64ec52dda 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -3466,10 +3466,9 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
/* Request for MAC FDB for a specific MAC address in VLAN from the kernel */
static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
- int family,
- int type,
+ int family, int type,
struct interface *br_if,
- struct ethaddr *mac,
+ const struct ethaddr *mac,
vlanid_t vid)
{
struct {
@@ -3506,7 +3505,7 @@ static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
struct interface *br_if,
- struct ethaddr *mac, vlanid_t vid)
+ const struct ethaddr *mac, vlanid_t vid)
{
int ret = 0;
struct zebra_dplane_info dp_info;
@@ -3946,7 +3945,8 @@ int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
* read using netlink interface.
*/
static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns,
- int type, struct ipaddr *ip,
+ int type,
+ const struct ipaddr *ip,
ifindex_t ifindex)
{
struct {
@@ -3983,8 +3983,8 @@ static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns,
return netlink_request(&zns->netlink_cmd, &req);
}
-int netlink_neigh_read_specific_ip(struct ipaddr *ip,
- struct interface *vlan_if)
+int netlink_neigh_read_specific_ip(const struct ipaddr *ip,
+ struct interface *vlan_if)
{
int ret = 0;
struct zebra_ns *zns;
diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h
index 4e41ff984b..93c06e555b 100644
--- a/zebra/rt_netlink.h
+++ b/zebra/rt_netlink.h
@@ -99,8 +99,9 @@ extern int netlink_neigh_read_for_vlan(struct zebra_ns *zns,
struct interface *vlan_if);
extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
struct interface *br_if,
- struct ethaddr *mac, uint16_t vid);
-extern int netlink_neigh_read_specific_ip(struct ipaddr *ip,
+ const struct ethaddr *mac,
+ uint16_t vid);
+extern int netlink_neigh_read_specific_ip(const struct ipaddr *ip,
struct interface *vlan_if);
extern vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id);
diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c
index fbca47351d..f70b006acd 100644
--- a/zebra/rtread_netlink.c
+++ b/zebra/rtread_netlink.c
@@ -46,9 +46,9 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
}
void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
- struct ethaddr *mac, vlanid_t vid)
+ const struct ethaddr *mac, vlanid_t vid)
{
-netlink_macfdb_read_specific_mac(zns, br_if, mac, vid);
+ netlink_macfdb_read_specific_mac(zns, br_if, mac, vid);
}
void neigh_read(struct zebra_ns *zns)
@@ -61,7 +61,7 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
netlink_neigh_read_for_vlan(zns, vlan_if);
}
-void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if)
+void neigh_read_specific_ip(const struct ipaddr *ip, struct interface *vlan_if)
{
netlink_neigh_read_specific_ip(ip, vlan_if);
}
diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c
index 74c6825ba1..594f7c2dd9 100644
--- a/zebra/rtread_sysctl.c
+++ b/zebra/rtread_sysctl.c
@@ -88,7 +88,7 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp,
}
void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if,
- struct ethaddr *mac, vlanid_t vid)
+ const struct ethaddr *mac, vlanid_t vid)
{
}
@@ -100,7 +100,7 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if)
{
}
-void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if)
+void neigh_read_specific_ip(const struct ipaddr *ip, struct interface *vlan_if)
{
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 8f2aa2fb09..a53e388062 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -682,6 +682,8 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
stream_put_in_addr(s, &addr);
if (re) {
+ struct nexthop_group *nhg;
+
stream_putc(s, re->distance);
stream_putl(s, re->metric);
num = 0;
@@ -689,15 +691,11 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
nump = stream_get_endp(s);
/* reserve room for nexthop_num */
stream_putc(s, 0);
- /*
- * Only non-recursive routes are elegible to resolve the
- * nexthop we are looking up. Therefore, we will just iterate
- * over the top chain of nexthops.
- */
- for (nexthop = re->nhe->nhg.nexthop; nexthop;
- nexthop = nexthop->next)
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ nhg = rib_get_fib_nhg(re);
+ for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
+ if (rnh_nexthop_valid(re, nexthop))
num += zserv_encode_nexthop(s, nexthop);
+ }
/* store nexthop_num */
stream_putc_at(s, nump, num);
@@ -3655,8 +3653,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni,
[ZEBRA_REMOTE_ES_VTEP_ADD] = zebra_evpn_proc_remote_es,
[ZEBRA_REMOTE_ES_VTEP_DEL] = zebra_evpn_proc_remote_es,
- [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add,
- [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del,
+ [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add_zapi,
+ [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del_zapi,
[ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add,
[ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del,
[ZEBRA_DUPLICATE_ADDR_DETECTION] = zebra_vxlan_dup_addr_detection,
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 04411fa0d2..1217ed915a 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -3640,14 +3640,10 @@ enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op,
uint16_t state = 0;
uint32_t update_flags;
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- char buf1[PREFIX_STRLEN], buf2[PREFIX_STRLEN];
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%s: init link ctx %s: ifp %s, link_ip %pIA ip %pIA",
+ __func__, dplane_op2str(op), ifp->name, link_ip, ip);
- ipaddr2str(link_ip, buf1, sizeof(buf1));
- ipaddr2str(ip, buf2, sizeof(buf2));
- zlog_debug("init link ctx %s: ifp %s, ip %s link %s",
- dplane_op2str(op), ifp->name, buf1, buf2);
- }
if (ndm_state == ZEBRA_NEIGH_STATE_REACHABLE)
state = DPLANE_NUD_REACHABLE;
else if (ndm_state == ZEBRA_NEIGH_STATE_FAILED)
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index 816f46bac9..2c9f1dca59 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -1330,10 +1330,12 @@ void zebra_evpn_cleanup_all(struct hash_bucket *bucket, void *arg)
zebra_evpn_del(zevpn);
}
-static void
-zebra_evpn_process_sync_macip_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
- uint16_t ipa_len, struct ipaddr *ipaddr,
- uint8_t flags, uint32_t seq, esi_t *esi)
+static void zebra_evpn_process_sync_macip_add(zebra_evpn_t *zevpn,
+ const struct ethaddr *macaddr,
+ uint16_t ipa_len,
+ const struct ipaddr *ipaddr,
+ uint8_t flags, uint32_t seq,
+ const esi_t *esi)
{
struct sync_mac_ip_ctx ctx;
char ipbuf[INET6_ADDRSTRLEN];
@@ -1380,10 +1382,10 @@ zebra_evpn_process_sync_macip_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
/************************** remote mac-ip handling **************************/
/* Process a remote MACIP add from BGP. */
-void process_remote_macip_add(vni_t vni, struct ethaddr *macaddr,
- uint16_t ipa_len, struct ipaddr *ipaddr,
+void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
+ uint16_t ipa_len, const struct ipaddr *ipaddr,
uint8_t flags, uint32_t seq,
- struct in_addr vtep_ip, esi_t *esi)
+ struct in_addr vtep_ip, const esi_t *esi)
{
zebra_evpn_t *zevpn;
zebra_vtep_t *zvtep;
@@ -1447,18 +1449,19 @@ void process_remote_macip_add(vni_t vni, struct ethaddr *macaddr,
return;
- if (process_mac_remote_macip_add(zevpn, zvrf, macaddr, ipa_len, ipaddr,
- &mac, vtep_ip, flags, seq, esi)
+ if (zebra_evpn_mac_remote_macip_add(zevpn, zvrf, macaddr, ipa_len,
+ ipaddr, &mac, vtep_ip, flags, seq,
+ esi)
!= 0)
return;
- process_neigh_remote_macip_add(zevpn, zvrf, ipaddr, mac, vtep_ip, flags,
- seq);
+ zebra_evpn_neigh_remote_macip_add(zevpn, zvrf, ipaddr, mac, vtep_ip,
+ flags, seq);
}
/* Process a remote MACIP delete from BGP. */
-void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr,
- uint16_t ipa_len, struct ipaddr *ipaddr,
+void zebra_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
+ uint16_t ipa_len, const struct ipaddr *ipaddr,
struct in_addr vtep_ip)
{
zebra_evpn_t *zevpn;
diff --git a/zebra/zebra_evpn.h b/zebra/zebra_evpn.h
index ee9e1406e4..774627a15d 100644
--- a/zebra/zebra_evpn.h
+++ b/zebra/zebra_evpn.h
@@ -204,12 +204,12 @@ int zebra_evpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip);
void zebra_evpn_handle_flooding_remote_vteps(struct hash_bucket *bucket,
void *zvrf);
void zebra_evpn_cleanup_all(struct hash_bucket *bucket, void *arg);
-void process_remote_macip_add(vni_t vni, struct ethaddr *macaddr,
- uint16_t ipa_len, struct ipaddr *ipaddr,
+void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
+ uint16_t ipa_len, const struct ipaddr *ipaddr,
uint8_t flags, uint32_t seq,
- struct in_addr vtep_ip, esi_t *esi);
-void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr,
- uint16_t ipa_len, struct ipaddr *ipaddr,
+ struct in_addr vtep_ip, const esi_t *esi);
+void zebra_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
+ uint16_t ipa_len, const struct ipaddr *ipaddr,
struct in_addr vtep_ip);
void zebra_evpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt);
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index fe3167dc29..cf2aa67269 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -986,8 +986,9 @@ void zebra_evpn_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
/*
* Inform BGP about local MACIP.
*/
-int zebra_evpn_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
- struct ipaddr *ip, uint8_t flags,
+int zebra_evpn_macip_send_msg_to_client(vni_t vni,
+ const struct ethaddr *macaddr,
+ const struct ipaddr *ip, uint8_t flags,
uint32_t seq, int state,
struct zebra_evpn_es *es, uint16_t cmd)
{
@@ -1095,7 +1096,8 @@ static void *zebra_evpn_mac_alloc(void *p)
/*
* Add MAC entry.
*/
-zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr)
+zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevpn,
+ const struct ethaddr *macaddr)
{
zebra_mac_t tmp_mac;
zebra_mac_t *mac = NULL;
@@ -1254,7 +1256,8 @@ void zebra_evpn_mac_del_all(zebra_evpn_t *zevpn, int uninstall, int upd_client,
/*
* Look up MAC hash entry.
*/
-zebra_mac_t *zebra_evpn_mac_lookup(zebra_evpn_t *zevpn, struct ethaddr *mac)
+zebra_mac_t *zebra_evpn_mac_lookup(zebra_evpn_t *zevpn,
+ const struct ethaddr *mac)
{
zebra_mac_t tmp;
zebra_mac_t *pmac;
@@ -1269,7 +1272,7 @@ zebra_mac_t *zebra_evpn_mac_lookup(zebra_evpn_t *zevpn, struct ethaddr *mac)
/*
* Inform BGP about local MAC addition.
*/
-int zebra_evpn_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
+int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr,
uint32_t mac_flags, uint32_t seq,
struct zebra_evpn_es *es)
{
@@ -1303,7 +1306,7 @@ int zebra_evpn_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
/*
* Inform BGP about local MAC deletion.
*/
-int zebra_evpn_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
+int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr,
uint32_t flags, bool force)
{
if (!force) {
@@ -1563,7 +1566,7 @@ void zebra_evpn_sync_mac_del(zebra_mac_t *mac)
static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
zebra_mac_t *mac, uint32_t seq,
uint16_t ipa_len,
- struct ipaddr *ipaddr,
+ const struct ipaddr *ipaddr,
bool sync)
{
char ipbuf[INET6_ADDRSTRLEN];
@@ -1627,11 +1630,10 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
return true;
}
-zebra_mac_t *
-zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
- uint16_t ipa_len, struct ipaddr *ipaddr,
- uint8_t flags, uint32_t seq, esi_t *esi,
- struct sync_mac_ip_ctx *ctx)
+zebra_mac_t *zebra_evpn_proc_sync_mac_update(
+ zebra_evpn_t *zevpn, const struct ethaddr *macaddr, uint16_t ipa_len,
+ const struct ipaddr *ipaddr, uint8_t flags, uint32_t seq,
+ const esi_t *esi, struct sync_mac_ip_ctx *ctx)
{
zebra_mac_t *mac;
bool inform_bgp = false;
@@ -1958,11 +1960,13 @@ void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket,
zebra_evpn_print_mac_hash_detail(bucket, ctxt);
}
-int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
- struct ethaddr *macaddr, uint16_t ipa_len,
- struct ipaddr *ipaddr, zebra_mac_t **macp,
- struct in_addr vtep_ip, uint8_t flags,
- uint32_t seq, esi_t *esi)
+int zebra_evpn_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
+ const struct ethaddr *macaddr,
+ uint16_t ipa_len,
+ const struct ipaddr *ipaddr,
+ zebra_mac_t **macp, struct in_addr vtep_ip,
+ uint8_t flags, uint32_t seq,
+ const esi_t *esi)
{
char buf1[INET6_ADDRSTRLEN];
bool sticky;
@@ -2127,7 +2131,7 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
struct interface *ifp,
- struct ethaddr *macaddr, vlanid_t vid,
+ const struct ethaddr *macaddr, vlanid_t vid,
bool sticky, bool local_inactive,
bool dp_static, zebra_mac_t *mac)
{
@@ -2447,8 +2451,8 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac,
}
int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
- struct ipaddr *ip, zebra_mac_t **macp,
- struct ethaddr *macaddr, vlanid_t vlan_id,
+ const struct ipaddr *ip, zebra_mac_t **macp,
+ const struct ethaddr *macaddr, vlanid_t vlan_id,
bool def_gw)
{
zebra_mac_t *mac;
diff --git a/zebra/zebra_evpn_mac.h b/zebra/zebra_evpn_mac.h
index fb162f1a93..e90082e50b 100644
--- a/zebra/zebra_evpn_mac.h
+++ b/zebra/zebra_evpn_mac.h
@@ -229,11 +229,14 @@ int zebra_evpn_rem_mac_uninstall(zebra_evpn_t *zevi, zebra_mac_t *mac,
int zebra_evpn_rem_mac_install(zebra_evpn_t *zevi, zebra_mac_t *mac,
bool was_static);
void zebra_evpn_deref_ip2mac(zebra_evpn_t *zevi, zebra_mac_t *mac);
-zebra_mac_t *zebra_evpn_mac_lookup(zebra_evpn_t *zevi, struct ethaddr *mac);
-zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevi, struct ethaddr *macaddr);
+zebra_mac_t *zebra_evpn_mac_lookup(zebra_evpn_t *zevi,
+ const struct ethaddr *mac);
+zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevi,
+ const struct ethaddr *macaddr);
int zebra_evpn_mac_del(zebra_evpn_t *zevi, zebra_mac_t *mac);
-int zebra_evpn_macip_send_msg_to_client(uint32_t id, struct ethaddr *macaddr,
- struct ipaddr *ip, uint8_t flags,
+int zebra_evpn_macip_send_msg_to_client(uint32_t id,
+ const struct ethaddr *macaddr,
+ const struct ipaddr *ip, uint8_t flags,
uint32_t seq, int state,
struct zebra_evpn_es *es, uint16_t cmd);
void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json);
@@ -246,38 +249,39 @@ void zebra_evpn_mac_send_add_del_to_client(zebra_mac_t *mac, bool old_bgp_ready,
void zebra_evpn_mac_del_all(zebra_evpn_t *zevi, int uninstall, int upd_client,
uint32_t flags);
-int zebra_evpn_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
+int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr,
uint32_t mac_flags, uint32_t seq,
struct zebra_evpn_es *es);
-int zebra_evpn_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
+int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr,
uint32_t flags, bool force);
void zebra_evpn_send_mac_list_to_client(zebra_evpn_t *zevi);
-zebra_mac_t *
-zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevi, struct ethaddr *macaddr,
- uint16_t ipa_len, struct ipaddr *ipaddr,
- uint8_t flags, uint32_t seq, esi_t *esi,
- struct sync_mac_ip_ctx *ctx);
+zebra_mac_t *zebra_evpn_proc_sync_mac_update(
+ zebra_evpn_t *zevi, const struct ethaddr *macaddr, uint16_t ipa_len,
+ const struct ipaddr *ipaddr, uint8_t flags, uint32_t seq,
+ const esi_t *esi, struct sync_mac_ip_ctx *ctx);
void zebra_evpn_sync_mac_del(zebra_mac_t *mac);
void zebra_evpn_rem_mac_del(zebra_evpn_t *zevi, zebra_mac_t *mac);
void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket,
void *ctxt);
-int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
- struct ethaddr *macaddr, uint16_t ipa_len,
- struct ipaddr *ipaddr, zebra_mac_t **macp,
- struct in_addr vtep_ip, uint8_t flags,
- uint32_t seq, esi_t *esi);
+int zebra_evpn_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
+ const struct ethaddr *macaddr,
+ uint16_t ipa_len,
+ const struct ipaddr *ipaddr,
+ zebra_mac_t **macp, struct in_addr vtep_ip,
+ uint8_t flags, uint32_t seq,
+ const esi_t *esi);
int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
struct interface *ifp,
- struct ethaddr *macaddr, vlanid_t vid,
+ const struct ethaddr *macaddr, vlanid_t vid,
bool sticky, bool local_inactive,
bool dp_static, zebra_mac_t *mac);
int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac,
bool clear_static);
int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
- struct ipaddr *ip, zebra_mac_t **macp,
- struct ethaddr *macaddr, vlanid_t vlan_id,
+ const struct ipaddr *ip, zebra_mac_t **macp,
+ const struct ethaddr *macaddr, vlanid_t vlan_id,
bool def_gw);
void zebra_evpn_mac_svi_add(struct interface *ifp, zebra_evpn_t *zevpn);
void zebra_evpn_mac_svi_del(struct interface *ifp, zebra_evpn_t *zevpn);
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index d6ae92a03d..05947faf4f 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -1747,7 +1747,7 @@ static int zebra_es_rb_cmp(const struct zebra_evpn_es *es1,
RB_GENERATE(zebra_es_rb_head, zebra_evpn_es, rb_node, zebra_es_rb_cmp);
/* Lookup ES */
-struct zebra_evpn_es *zebra_evpn_es_find(esi_t *esi)
+struct zebra_evpn_es *zebra_evpn_es_find(const esi_t *esi)
{
struct zebra_evpn_es tmp;
@@ -1758,7 +1758,7 @@ struct zebra_evpn_es *zebra_evpn_es_find(esi_t *esi)
/* A new local es is created when a local-es-id and sysmac is configured
* against an interface.
*/
-static struct zebra_evpn_es *zebra_evpn_es_new(esi_t *esi)
+static struct zebra_evpn_es *zebra_evpn_es_new(const esi_t *esi)
{
struct zebra_evpn_es *es;
@@ -2392,7 +2392,7 @@ static int zebra_evpn_type3_esi_update(struct zebra_if *zif, uint32_t lid,
return zebra_evpn_local_es_update(zif, &esi);
}
-static int zebra_evpn_remote_es_del(esi_t *esi, struct in_addr vtep_ip)
+int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip)
{
char buf[ESI_STR_LEN];
struct zebra_evpn_es *es;
@@ -2432,9 +2432,8 @@ static void zebra_evpn_remote_es_flush(struct zebra_evpn_es **esp)
zebra_evpn_es_remote_info_re_eval(esp);
}
-static int zebra_evpn_remote_es_add(esi_t *esi, struct in_addr vtep_ip,
- bool esr_rxed, uint8_t df_alg,
- uint16_t df_pref)
+int zebra_evpn_remote_es_add(const esi_t *esi, struct in_addr vtep_ip,
+ bool esr_rxed, uint8_t df_alg, uint16_t df_pref)
{
char buf[ESI_STR_LEN];
struct zebra_evpn_es *es;
@@ -2498,10 +2497,10 @@ void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS)
: false;
STREAM_GETC(s, df_alg);
STREAM_GETW(s, df_pref);
- zebra_evpn_remote_es_add(&esi, vtep_ip, esr_rxed, df_alg,
- df_pref);
+ zebra_rib_queue_evpn_rem_es_add(&esi, &vtep_ip, esr_rxed,
+ df_alg, df_pref);
} else {
- zebra_evpn_remote_es_del(&esi, vtep_ip);
+ zebra_rib_queue_evpn_rem_es_del(&esi, &vtep_ip);
}
stream_failure:
@@ -2542,7 +2541,7 @@ bool zebra_evpn_es_mac_ref_entry(zebra_mac_t *mac, struct zebra_evpn_es *es)
return true;
}
-bool zebra_evpn_es_mac_ref(zebra_mac_t *mac, esi_t *esi)
+bool zebra_evpn_es_mac_ref(zebra_mac_t *mac, const esi_t *esi)
{
struct zebra_evpn_es *es;
@@ -3901,12 +3900,12 @@ void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS)
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("evpn remote nh %d %pIA rmac %pEA add",
vrf_id, &nh, &rmac);
- zebra_vxlan_evpn_vrf_route_add(vrf_id, &rmac, &nh,
+ zebra_rib_queue_evpn_route_add(vrf_id, &rmac, &nh,
(struct prefix *)&dummy_prefix);
} else {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("evpn remote nh %d %pIA del", vrf_id, &nh);
- zebra_vxlan_evpn_vrf_route_del(vrf_id, &nh,
+ zebra_rib_queue_evpn_route_del(vrf_id, &nh,
(struct prefix *)&dummy_prefix);
}
}
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index 8861e80cee..a828056f1f 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -330,14 +330,17 @@ extern void zebra_evpn_es_show_detail(struct vty *vty, bool uj);
extern void zebra_evpn_es_show_esi(struct vty *vty, bool uj, esi_t *esi);
extern void zebra_evpn_update_all_es(zebra_evpn_t *zevpn);
extern void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS);
+int zebra_evpn_remote_es_add(const esi_t *esi, struct in_addr vtep_ip,
+ bool esr_rxed, uint8_t df_alg, uint16_t df_pref);
+int zebra_evpn_remote_es_del(const esi_t *esi, struct in_addr vtep_ip);
extern void zebra_evpn_es_evi_show(struct vty *vty, bool uj, int detail);
extern void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj,
vni_t vni, int detail);
extern void zebra_evpn_es_mac_deref_entry(zebra_mac_t *mac);
extern bool zebra_evpn_es_mac_ref_entry(zebra_mac_t *mac,
- struct zebra_evpn_es *es);
-extern bool zebra_evpn_es_mac_ref(zebra_mac_t *mac, esi_t *esi);
-extern struct zebra_evpn_es *zebra_evpn_es_find(esi_t *esi);
+ struct zebra_evpn_es *es);
+extern bool zebra_evpn_es_mac_ref(zebra_mac_t *mac, const esi_t *esi);
+extern struct zebra_evpn_es *zebra_evpn_es_find(const esi_t *esi);
extern void zebra_evpn_interface_init(void);
extern int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp);
extern void zebra_evpn_acc_vl_show(struct vty *vty, bool uj);
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
index 4c7a1542fc..839e8d9ebc 100644
--- a/zebra/zebra_evpn_neigh.c
+++ b/zebra/zebra_evpn_neigh.c
@@ -204,7 +204,7 @@ static void *zebra_evpn_neigh_alloc(void *p)
}
static void zebra_evpn_local_neigh_ref_mac(zebra_neigh_t *n,
- struct ethaddr *macaddr,
+ const struct ethaddr *macaddr,
zebra_mac_t *mac,
bool send_mac_update)
{
@@ -284,8 +284,8 @@ static void zebra_evpn_sync_neigh_dp_install(zebra_neigh_t *n,
/*
* Inform BGP about local neighbor addition.
*/
-int zebra_evpn_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
- struct ethaddr *macaddr,
+int zebra_evpn_neigh_send_add_to_client(vni_t vni, const struct ipaddr *ip,
+ const struct ethaddr *macaddr,
zebra_mac_t *zmac, uint32_t neigh_flags,
uint32_t seq)
{
@@ -497,7 +497,7 @@ static void zebra_evpn_local_neigh_deref_mac(zebra_neigh_t *n,
}
bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
- struct ethaddr *macaddr, uint32_t seq,
+ const struct ethaddr *macaddr, uint32_t seq,
bool sync)
{
uint32_t tmp_seq;
@@ -543,8 +543,8 @@ bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
* Add neighbor entry.
*/
static zebra_neigh_t *zebra_evpn_neigh_add(zebra_evpn_t *zevpn,
- struct ipaddr *ip,
- struct ethaddr *mac,
+ const struct ipaddr *ip,
+ const struct ethaddr *mac,
zebra_mac_t *zmac, uint32_t n_flags)
{
zebra_neigh_t tmp_n;
@@ -615,8 +615,8 @@ void zebra_evpn_sync_neigh_del(zebra_neigh_t *n)
zebra_neigh_t *
zebra_evpn_proc_sync_neigh_update(zebra_evpn_t *zevpn, zebra_neigh_t *n,
- uint16_t ipa_len, struct ipaddr *ipaddr,
- uint8_t flags, uint32_t seq, esi_t *esi,
+ uint16_t ipa_len, const struct ipaddr *ipaddr,
+ uint8_t flags, uint32_t seq, const esi_t *esi,
struct sync_mac_ip_ctx *ctx)
{
struct interface *ifp = NULL;
@@ -895,7 +895,8 @@ void zebra_evpn_neigh_del_all(zebra_evpn_t *zevpn, int uninstall,
/*
* Look up neighbor hash entry.
*/
-zebra_neigh_t *zebra_evpn_neigh_lookup(zebra_evpn_t *zevpn, struct ipaddr *ip)
+zebra_neigh_t *zebra_evpn_neigh_lookup(zebra_evpn_t *zevpn,
+ const struct ipaddr *ip)
{
zebra_neigh_t tmp;
zebra_neigh_t *n;
@@ -1254,9 +1255,9 @@ zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr,
}
int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
- struct ipaddr *ip, struct ethaddr *macaddr,
- bool is_router, bool local_inactive,
- bool dp_static)
+ const struct ipaddr *ip,
+ const struct ethaddr *macaddr, bool is_router,
+ bool local_inactive, bool dp_static)
{
struct zebra_vrf *zvrf;
zebra_neigh_t *n = NULL;
@@ -1596,7 +1597,8 @@ int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
}
int zebra_evpn_remote_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
- struct ipaddr *ip, struct ethaddr *macaddr,
+ const struct ipaddr *ip,
+ const struct ethaddr *macaddr,
uint16_t state)
{
zebra_neigh_t *n = NULL;
@@ -2046,10 +2048,11 @@ void zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket *bucket,
zebra_evpn_print_neigh_hash_detail(bucket, ctxt);
}
-void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
- struct ipaddr *ipaddr, zebra_mac_t *mac,
- struct in_addr vtep_ip, uint8_t flags,
- uint32_t seq)
+void zebra_evpn_neigh_remote_macip_add(zebra_evpn_t *zevpn,
+ struct zebra_vrf *zvrf,
+ const struct ipaddr *ipaddr,
+ zebra_mac_t *mac, struct in_addr vtep_ip,
+ uint8_t flags, uint32_t seq)
{
zebra_neigh_t *n;
int update_neigh = 0;
@@ -2240,7 +2243,8 @@ int zebra_evpn_neigh_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
void zebra_evpn_neigh_remote_uninstall(zebra_evpn_t *zevpn,
struct zebra_vrf *zvrf, zebra_neigh_t *n,
- zebra_mac_t *mac, struct ipaddr *ipaddr)
+ zebra_mac_t *mac,
+ const struct ipaddr *ipaddr)
{
if (zvrf->dad_freeze && CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)
&& CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
@@ -2273,7 +2277,7 @@ void zebra_evpn_neigh_remote_uninstall(zebra_evpn_t *zevpn,
}
}
-int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
+int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, const struct ipaddr *ip)
{
zebra_neigh_t *n;
zebra_mac_t *zmac;
@@ -2298,7 +2302,7 @@ int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
}
/* If it is a remote entry, the kernel has aged this out or someone has
- * deleted it, it needs to be re-installed as Quagga is the owner.
+ * deleted it, it needs to be re-installed as FRR is the owner.
*/
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
zebra_evpn_rem_neigh_install(zevpn, n, false /*was_static*/);
diff --git a/zebra/zebra_evpn_neigh.h b/zebra/zebra_evpn_neigh.h
index 05156c1255..3735a833fd 100644
--- a/zebra/zebra_evpn_neigh.h
+++ b/zebra/zebra_evpn_neigh.h
@@ -217,26 +217,27 @@ int remote_neigh_count(zebra_mac_t *zmac);
int zebra_evpn_rem_neigh_install(zebra_evpn_t *zevpn, zebra_neigh_t *n,
bool was_static);
void zebra_evpn_install_neigh_hash(struct hash_bucket *bucket, void *ctxt);
-int zebra_evpn_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
- struct ethaddr *macaddr,
+int zebra_evpn_neigh_send_add_to_client(vni_t vni, const struct ipaddr *ip,
+ const struct ethaddr *macaddr,
zebra_mac_t *zmac, uint32_t neigh_flags,
uint32_t seq);
int zebra_evpn_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
struct ethaddr *macaddr, uint32_t flags,
int state, bool force);
bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
- struct ethaddr *macaddr, uint32_t seq,
+ const struct ethaddr *macaddr, uint32_t seq,
bool sync);
int zebra_evpn_neigh_del(zebra_evpn_t *zevpn, zebra_neigh_t *n);
void zebra_evpn_sync_neigh_del(zebra_neigh_t *n);
zebra_neigh_t *
zebra_evpn_proc_sync_neigh_update(zebra_evpn_t *zevpn, zebra_neigh_t *n,
- uint16_t ipa_len, struct ipaddr *ipaddr,
- uint8_t flags, uint32_t seq, esi_t *esi,
+ uint16_t ipa_len, const struct ipaddr *ipaddr,
+ uint8_t flags, uint32_t seq, const esi_t *esi,
struct sync_mac_ip_ctx *ctx);
void zebra_evpn_neigh_del_all(zebra_evpn_t *zevpn, int uninstall,
int upd_client, uint32_t flags);
-zebra_neigh_t *zebra_evpn_neigh_lookup(zebra_evpn_t *zevpn, struct ipaddr *ip);
+zebra_neigh_t *zebra_evpn_neigh_lookup(zebra_evpn_t *zevpn,
+ const struct ipaddr *ip);
int zebra_evpn_rem_neigh_install(zebra_evpn_t *zevpn, zebra_neigh_t *n,
bool was_static);
@@ -251,11 +252,12 @@ void zebra_evpn_process_neigh_on_local_mac_change(zebra_evpn_t *zevpn,
void zebra_evpn_process_neigh_on_remote_mac_del(zebra_evpn_t *zevpn,
zebra_mac_t *zmac);
int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
- struct ipaddr *ip, struct ethaddr *macaddr,
- bool is_router, bool local_inactive,
- bool dp_static);
+ const struct ipaddr *ip,
+ const struct ethaddr *macaddr, bool is_router,
+ bool local_inactive, bool dp_static);
int zebra_evpn_remote_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
- struct ipaddr *ip, struct ethaddr *macaddr,
+ const struct ipaddr *ip,
+ const struct ethaddr *macaddr,
uint16_t state);
void zebra_evpn_send_neigh_to_client(zebra_evpn_t *zevpn);
void zebra_evpn_clear_dup_neigh_hash(struct hash_bucket *bucket, void *ctxt);
@@ -266,16 +268,18 @@ void zebra_evpn_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket *bucket,
void *ctxt);
-void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
- struct ipaddr *ipaddr, zebra_mac_t *mac,
- struct in_addr vtep_ip, uint8_t flags,
- uint32_t seq);
+void zebra_evpn_neigh_remote_macip_add(zebra_evpn_t *zevpn,
+ struct zebra_vrf *zvrf,
+ const struct ipaddr *ipaddr,
+ zebra_mac_t *mac, struct in_addr vtep_ip,
+ uint8_t flags, uint32_t seq);
int zebra_evpn_neigh_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
struct ipaddr *ip, zebra_mac_t *mac);
void zebra_evpn_neigh_remote_uninstall(zebra_evpn_t *zevpn,
struct zebra_vrf *zvrf, zebra_neigh_t *n,
- zebra_mac_t *mac, struct ipaddr *ipaddr);
-int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip);
+ zebra_mac_t *mac,
+ const struct ipaddr *ipaddr);
+int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, const struct ipaddr *ip);
#ifdef __cplusplus
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index af86263a16..46d5164127 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -453,8 +453,13 @@ static void *zebra_nhg_hash_alloc(void *arg)
/* Mark duplicate nexthops in a group at creation time. */
nexthop_group_mark_duplicates(&(nhe->nhg));
- /* Add the ifp now if it's not a group or recursive and has ifindex */
- if (nhe->nhg.nexthop && nhe->nhg.nexthop->ifindex) {
+ /*
+ * Add the ifp now if it's not a group or recursive and has ifindex.
+ *
+ * A proto-owned ID is always a group.
+ */
+ if (!PROTO_OWNED(nhe) && nhe->nhg.nexthop && !nhe->nhg.nexthop->next
+ && !nhe->nhg.nexthop->resolved && nhe->nhg.nexthop->ifindex) {
struct interface *ifp = NULL;
ifp = if_lookup_by_index(nhe->nhg.nexthop->ifindex,
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 12cc0b4e8a..c51dd759a6 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -56,13 +56,14 @@
#include "zebra/zebra_vxlan.h"
#include "zebra/zapi_msg.h"
#include "zebra/zebra_dplane.h"
+#include "zebra/zebra_evpn_mh.h"
DEFINE_MGROUP(ZEBRA, "zebra");
DEFINE_MTYPE(ZEBRA, RE, "Route Entry");
DEFINE_MTYPE_STATIC(ZEBRA, RIB_DEST, "RIB destination");
DEFINE_MTYPE_STATIC(ZEBRA, RIB_UPDATE_CTX, "Rib update context object");
-DEFINE_MTYPE_STATIC(ZEBRA, WQ_NHG_WRAPPER, "WQ nhg wrapper");
+DEFINE_MTYPE_STATIC(ZEBRA, WQ_WRAPPER, "WQ wrapper");
/*
* Event, list, and mutex for delivery of dataplane results
@@ -74,7 +75,7 @@ static struct dplane_ctx_q rib_dplane_q;
DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
-/* Should we allow non Quagga processes to delete our routes */
+/* Should we allow non FRR processes to delete our routes */
extern int allow_delete;
/* Each route type's string and default distance value. */
@@ -83,41 +84,44 @@ static const struct {
uint8_t distance;
uint8_t meta_q_map;
} route_info[ZEBRA_ROUTE_MAX] = {
- [ZEBRA_ROUTE_NHG] = {ZEBRA_ROUTE_NHG, 255 /* Uneeded for nhg's */, 0},
- [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, 6},
- [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0, 2},
- [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0, 1},
- [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1, 3},
- [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120, 4},
- [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120, 4},
- [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110, 4},
- [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110, 4},
- [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115, 4},
- [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */, 5},
- [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255, 6},
- [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90, 4},
- [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10, 4},
- [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255, 6},
- [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255, 6},
- [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150, 3},
- [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150, 6},
- [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20, 5},
- [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20, 5},
- [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20, 5},
- [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20, 5},
- [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20, 5},
- [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, 4},
- [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, 6},
- [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 6},
- [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 6},
- [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 4},
- [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 6},
- [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, 6},
+ [ZEBRA_ROUTE_NHG] = {ZEBRA_ROUTE_NHG, 255 /* Unneeded for nhg's */, 0},
+ [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, 7},
+ [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0, 3},
+ [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0, 2},
+ [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1, 4},
+ [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120, 5},
+ [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120, 5},
+ [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110, 5},
+ [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110, 5},
+ [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115, 5},
+ [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */, 6},
+ [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255, 7},
+ [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90, 5},
+ [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10, 5},
+ [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255, 7},
+ [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255, 7},
+ [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150, 4},
+ [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150, 7},
+ [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20, 6},
+ [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20, 6},
+ [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20, 6},
+ [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20, 6},
+ [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20, 6},
+ [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, 5},
+ [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, 7},
+ [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 7},
+ [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 7},
+ [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 5},
+ [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 7},
+ [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, 7},
/* Any new route type added to zebra, should be mirrored here */
/* no entry/default: 150 */
};
+/* EVPN/VXLAN subqueue is number 1 */
+#define META_QUEUE_EVPN 1
+
/* Wrapper struct for nhg workqueue items; a 'ctx' is an incoming update
* from the OS, and an 'nhe' is a nhe update.
*/
@@ -132,6 +136,29 @@ struct wq_nhg_wrapper {
#define WQ_NHG_WRAPPER_TYPE_CTX 0x01
#define WQ_NHG_WRAPPER_TYPE_NHG 0x02
+/* Wrapper structs for evpn/vxlan workqueue items. */
+struct wq_evpn_wrapper {
+ int type;
+ bool add_p;
+ vrf_id_t vrf_id;
+ bool esr_rxed;
+ uint8_t df_alg;
+ uint16_t df_pref;
+ uint32_t flags;
+ uint32_t seq;
+ esi_t esi;
+ vni_t vni;
+ struct ipaddr ip;
+ struct ethaddr macaddr;
+ struct prefix prefix;
+ struct in_addr vtep_ip;
+};
+
+#define WQ_EVPN_WRAPPER_TYPE_VRFROUTE 0x01
+#define WQ_EVPN_WRAPPER_TYPE_REM_ES 0x02
+#define WQ_EVPN_WRAPPER_TYPE_REM_MACIP 0x03
+#define WQ_EVPN_WRAPPER_TYPE_REM_VTEP 0x04
+
/* %pRN is already a printer for route_nodes that just prints the prefix */
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pZN" (struct route_node *)
@@ -2316,6 +2343,62 @@ done:
}
/*
+ * Process a node from the EVPN/VXLAN subqueue.
+ */
+static void process_subq_evpn(struct listnode *lnode)
+{
+ struct wq_evpn_wrapper *w;
+
+ /* In general, the list node points to a wrapper object
+ * holding the info necessary to make some update.
+ */
+ w = listgetdata(lnode);
+ if (!w)
+ return;
+
+ if (w->type == WQ_EVPN_WRAPPER_TYPE_VRFROUTE) {
+ if (w->add_p)
+ zebra_vxlan_evpn_vrf_route_add(w->vrf_id, &w->macaddr,
+ &w->ip, &w->prefix);
+ else
+ zebra_vxlan_evpn_vrf_route_del(w->vrf_id, &w->ip,
+ &w->prefix);
+ } else if (w->type == WQ_EVPN_WRAPPER_TYPE_REM_ES) {
+ if (w->add_p)
+ zebra_evpn_remote_es_add(&w->esi, w->ip.ipaddr_v4,
+ w->esr_rxed, w->df_alg,
+ w->df_pref);
+ else
+ zebra_evpn_remote_es_del(&w->esi, w->ip.ipaddr_v4);
+ } else if (w->type == WQ_EVPN_WRAPPER_TYPE_REM_MACIP) {
+ uint16_t ipa_len = 0;
+
+ if (w->ip.ipa_type == IPADDR_V4)
+ ipa_len = IPV4_MAX_BYTELEN;
+ else if (w->ip.ipa_type == IPADDR_V6)
+ ipa_len = IPV6_MAX_BYTELEN;
+
+ if (w->add_p)
+ zebra_evpn_rem_macip_add(w->vni, &w->macaddr, ipa_len,
+ &w->ip, w->flags, w->seq,
+ w->vtep_ip, &w->esi);
+ else
+ zebra_evpn_rem_macip_del(w->vni, &w->macaddr, ipa_len,
+ &w->ip, w->vtep_ip);
+ } else if (w->type == WQ_EVPN_WRAPPER_TYPE_REM_VTEP) {
+ if (w->add_p)
+ zebra_vxlan_remote_vtep_add(w->vrf_id, w->vni,
+ w->vtep_ip, w->flags);
+ else
+ zebra_vxlan_remote_vtep_del(w->vrf_id, w->vni,
+ w->vtep_ip);
+ }
+
+
+ XFREE(MTYPE_WQ_WRAPPER, w);
+}
+
+/*
* Process the nexthop-group workqueue subqueue
*/
static void process_subq_nhg(struct listnode *lnode)
@@ -2355,8 +2438,7 @@ static void process_subq_nhg(struct listnode *lnode)
/* Process incoming nhg update, probably from a proto daemon */
newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
nhe->zapi_instance,
- nhe->zapi_session,
- &nhe->nhg, 0);
+ nhe->zapi_session, &nhe->nhg, 0);
/* Report error to daemon via ZAPI */
if (newnhe == NULL)
@@ -2368,7 +2450,7 @@ static void process_subq_nhg(struct listnode *lnode)
zebra_nhg_free(nhe);
}
- XFREE(MTYPE_WQ_NHG_WRAPPER, w);
+ XFREE(MTYPE_WQ_WRAPPER, w);
}
static void process_subq_route(struct listnode *lnode, uint8_t qindex)
@@ -2411,9 +2493,9 @@ static void process_subq_route(struct listnode *lnode, uint8_t qindex)
route_unlock_node(rnode);
}
-/* Take a list of route_node structs and return 1, if there was a record
- * picked from it and processed by rib_process(). Don't process more,
- * than one RN record; operate only in the specified sub-queue.
+/*
+ * Examine the specified subqueue; process one entry and return 1 if
+ * there is a node, return 0 otherwise.
*/
static unsigned int process_subq(struct list *subq, uint8_t qindex)
{
@@ -2422,7 +2504,9 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex)
if (!lnode)
return 0;
- if (qindex == route_info[ZEBRA_ROUTE_NHG].meta_q_map)
+ if (qindex == META_QUEUE_EVPN)
+ process_subq_evpn(lnode);
+ else if (qindex == route_info[ZEBRA_ROUTE_NHG].meta_q_map)
process_subq_nhg(lnode);
else
process_subq_route(lnode, qindex);
@@ -2432,7 +2516,7 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex)
return 1;
}
-/* Dispatch the meta queue by picking, processing and unlocking the next RN from
+/* Dispatch the meta queue by picking and processing the next node from
* a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
* data is pointed to the meta queue structure.
*/
@@ -2538,7 +2622,7 @@ static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
if (!ctx)
return -1;
- w = XCALLOC(MTYPE_WQ_NHG_WRAPPER, sizeof(struct wq_nhg_wrapper));
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_nhg_wrapper));
w->type = WQ_NHG_WRAPPER_TYPE_CTX;
w->u.ctx = ctx;
@@ -2564,7 +2648,7 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
if (!nhe)
return -1;
- w = XCALLOC(MTYPE_WQ_NHG_WRAPPER, sizeof(struct wq_nhg_wrapper));
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_nhg_wrapper));
w->type = WQ_NHG_WRAPPER_TYPE_NHG;
w->u.nhe = nhe;
@@ -2579,6 +2663,14 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
return 0;
}
+static int rib_meta_queue_evpn_add(struct meta_queue *mq, void *data)
+{
+ listnode_add(mq->subq[META_QUEUE_EVPN], data);
+ mq->size++;
+
+ return 0;
+}
+
static int mq_add_handler(void *data,
int (*mq_add_func)(struct meta_queue *mq, void *data))
{
@@ -2640,6 +2732,225 @@ int rib_queue_nhe_add(struct nhg_hash_entry *nhe)
return mq_add_handler(nhe, rib_meta_queue_nhg_add);
}
+/*
+ * Enqueue evpn route for processing
+ */
+int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
+ const struct ipaddr *vtep_ip,
+ const struct prefix *host_prefix)
+{
+ struct wq_evpn_wrapper *w;
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_VRFROUTE;
+ w->add_p = true;
+ w->vrf_id = vrf_id;
+ w->macaddr = *rmac;
+ w->ip = *vtep_ip;
+ w->prefix = *host_prefix;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("%s: (%u)%pIA, host prefix %pFX enqueued", __func__,
+ vrf_id, vtep_ip, host_prefix);
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+int zebra_rib_queue_evpn_route_del(vrf_id_t vrf_id,
+ const struct ipaddr *vtep_ip,
+ const struct prefix *host_prefix)
+{
+ struct wq_evpn_wrapper *w;
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_VRFROUTE;
+ w->add_p = false;
+ w->vrf_id = vrf_id;
+ w->ip = *vtep_ip;
+ w->prefix = *host_prefix;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("%s: (%u)%pIA, host prefix %pFX enqueued", __func__,
+ vrf_id, vtep_ip, host_prefix);
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+/* Enqueue EVPN remote ES for processing */
+int zebra_rib_queue_evpn_rem_es_add(const esi_t *esi,
+ const struct in_addr *vtep_ip,
+ bool esr_rxed, uint8_t df_alg,
+ uint16_t df_pref)
+{
+ struct wq_evpn_wrapper *w;
+ char buf[ESI_STR_LEN];
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_REM_ES;
+ w->add_p = true;
+ w->esi = *esi;
+ w->ip.ipa_type = IPADDR_V4;
+ w->ip.ipaddr_v4 = *vtep_ip;
+ w->esr_rxed = esr_rxed;
+ w->df_alg = df_alg;
+ w->df_pref = df_pref;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("%s: vtep %pI4, esi %s enqueued", __func__, vtep_ip,
+ esi_to_str(esi, buf, sizeof(buf)));
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+int zebra_rib_queue_evpn_rem_es_del(const esi_t *esi,
+ const struct in_addr *vtep_ip)
+{
+ struct wq_evpn_wrapper *w;
+ char buf[ESI_STR_LEN];
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_REM_ES;
+ w->add_p = false;
+ w->esi = *esi;
+ w->ip.ipa_type = IPADDR_V4;
+ w->ip.ipaddr_v4 = *vtep_ip;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ if (memcmp(esi, zero_esi, sizeof(esi_t)) != 0)
+ esi_to_str(esi, buf, sizeof(buf));
+ else
+ strlcpy(buf, "-", sizeof(buf));
+
+ zlog_debug("%s: vtep %pI4, esi %s enqueued", __func__, vtep_ip,
+ buf);
+ }
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+/*
+ * Enqueue EVPN remote macip update for processing
+ */
+int zebra_rib_queue_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
+ const struct ipaddr *ipaddr,
+ uint8_t flags, uint32_t seq,
+ struct in_addr vtep_ip, const esi_t *esi)
+{
+ struct wq_evpn_wrapper *w;
+ char buf[ESI_STR_LEN];
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_REM_MACIP;
+ w->add_p = true;
+ w->vni = vni;
+ w->macaddr = *macaddr;
+ w->ip = *ipaddr;
+ w->flags = flags;
+ w->seq = seq;
+ w->vtep_ip = vtep_ip;
+ w->esi = *esi;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ if (memcmp(esi, zero_esi, sizeof(esi_t)) != 0)
+ esi_to_str(esi, buf, sizeof(buf));
+ else
+ strlcpy(buf, "-", sizeof(buf));
+
+ zlog_debug("%s: mac %pEA, vtep %pI4, esi %s enqueued", __func__,
+ macaddr, &vtep_ip, buf);
+ }
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+int zebra_rib_queue_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
+ const struct ipaddr *ip,
+ struct in_addr vtep_ip)
+{
+ struct wq_evpn_wrapper *w;
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_REM_MACIP;
+ w->add_p = false;
+ w->vni = vni;
+ w->macaddr = *macaddr;
+ w->ip = *ip;
+ w->vtep_ip = vtep_ip;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("%s: mac %pEA, vtep %pI4 enqueued", __func__,
+ macaddr, &vtep_ip);
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+/*
+ * Enqueue remote VTEP address for processing
+ */
+int zebra_rib_queue_evpn_rem_vtep_add(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip, int flood_control)
+{
+ struct wq_evpn_wrapper *w;
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_REM_VTEP;
+ w->add_p = true;
+ w->vrf_id = vrf_id;
+ w->vni = vni;
+ w->vtep_ip = vtep_ip;
+ w->flags = flood_control;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("%s: vrf %u, vtep %pI4 enqueued", __func__, vrf_id,
+ &vtep_ip);
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip)
+{
+ struct wq_evpn_wrapper *w;
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+ w->type = WQ_EVPN_WRAPPER_TYPE_REM_VTEP;
+ w->add_p = false;
+ w->vrf_id = vrf_id;
+ w->vni = vni;
+ w->vtep_ip = vtep_ip;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("%s: vrf %u, vtep %pI4 enqueued", __func__, vrf_id,
+ &vtep_ip);
+
+ return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+/* Clean up the EVPN meta-queue list */
+static void evpn_meta_queue_free(struct list *l)
+{
+ struct listnode *node;
+ struct wq_evpn_wrapper *w;
+
+ /* Free the node wrapper object, and the struct it wraps */
+ while ((node = listhead(l)) != NULL) {
+ w = node->data;
+ node->data = NULL;
+
+ XFREE(MTYPE_WQ_WRAPPER, w);
+
+ list_delete_node(l, node);
+ }
+}
+
/* Clean up the nhg meta-queue list */
static void nhg_meta_queue_free(struct list *l)
{
@@ -2656,7 +2967,7 @@ static void nhg_meta_queue_free(struct list *l)
else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG)
zebra_nhg_free(w->u.nhe);
- XFREE(MTYPE_WQ_NHG_WRAPPER, w);
+ XFREE(MTYPE_WQ_WRAPPER, w);
list_delete_node(l, node);
}
@@ -2688,6 +2999,8 @@ void meta_queue_free(struct meta_queue *mq)
/* Some subqueues may need cleanup - nhgs for example */
if (i == route_info[ZEBRA_ROUTE_NHG].meta_q_map)
nhg_meta_queue_free(mq->subq[i]);
+ else if (i == META_QUEUE_EVPN)
+ evpn_meta_queue_free(mq->subq[i]);
list_delete(&mq->subq[i]);
}
@@ -2763,7 +3076,7 @@ rib_dest_t *zebra_rib_create_dest(struct route_node *rn)
* dest is created on-demand by rib_link() and is kept around at least
* as long as there are ribs hanging off it (@see rib_gc_dest()).
*
- * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
+ * Refcounting (aka "locking" throughout the Zebra and FRR code):
*
* - route_nodes: refcounted by:
* - dest attached to route_node:
@@ -3518,7 +3831,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
&(tmp_nh->gate.ipv6),
sizeof(struct in6_addr));
}
- zebra_vxlan_evpn_vrf_route_del(re->vrf_id,
+ zebra_rib_queue_evpn_route_del(re->vrf_id,
&vtep_ip, p);
}
}
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 41d55c2e6c..017a4aae7f 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -598,8 +598,7 @@ static const int RNH_INVALID_NH_FLAGS = (NEXTHOP_FLAG_RECURSIVE |
NEXTHOP_FLAG_DUPLICATE |
NEXTHOP_FLAG_RNH_FILTERED);
-static bool rnh_nexthop_valid(const struct route_entry *re,
- const struct nexthop *nh)
+bool rnh_nexthop_valid(const struct route_entry *re, const struct nexthop *nh)
{
return (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
&& CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)
diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h
index 4897a6af30..24ee6d0bd9 100644
--- a/zebra/zebra_rnh.h
+++ b/zebra/zebra_rnh.h
@@ -64,6 +64,9 @@ extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
extern int rnh_resolve_via_default(struct zebra_vrf *zvrf, int family);
+extern bool rnh_nexthop_valid(const struct route_entry *re,
+ const struct nexthop *nh);
+
/* UI control to avoid notifications if backup nexthop status changes */
void rnh_set_hide_backups(bool hide_p);
bool rnh_get_hide_backups(void);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 2f3ea7475a..2b46929acb 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -3820,10 +3820,6 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
uint16_t l = 0, ipa_len;
char buf1[INET6_ADDRSTRLEN];
- memset(&macaddr, 0, sizeof(struct ethaddr));
- memset(&ip, 0, sizeof(struct ipaddr));
- memset(&vtep_ip, 0, sizeof(struct in_addr));
-
s = msg;
while (l < hdr->length) {
@@ -3844,7 +3840,8 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
&vtep_ip, zebra_route_string(client->proto));
- process_remote_macip_del(vni, &macaddr, ipa_len, &ip, vtep_ip);
+ /* Enqueue to workqueue for processing */
+ zebra_rib_queue_evpn_rem_macip_del(vni, &macaddr, &ip, vtep_ip);
}
stream_failure:
@@ -3870,10 +3867,6 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
esi_t esi;
char esi_buf[ESI_STR_LEN];
- memset(&macaddr, 0, sizeof(struct ethaddr));
- memset(&ip, 0, sizeof(struct ipaddr));
- memset(&vtep_ip, 0, sizeof(struct in_addr));
-
if (!EVPN_ENABLED(zvrf)) {
zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
return;
@@ -3882,6 +3875,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
s = msg;
while (l < hdr->length) {
+
int res_length = zebra_vxlan_remote_macip_helper(
true, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip,
&flags, &seq, &esi);
@@ -3907,8 +3901,9 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
zebra_route_string(client->proto));
}
- process_remote_macip_add(vni, &macaddr, ipa_len, &ip,
- flags, seq, vtep_ip, &esi);
+ /* Enqueue to workqueue for processing */
+ zebra_rib_queue_evpn_rem_macip_add(vni, &macaddr, &ip, flags,
+ seq, vtep_ip, &esi);
}
stream_failure:
@@ -4204,27 +4199,23 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
/*
* Handle message from client to delete a remote VTEP for an EVPN.
*/
-void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
+void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS)
{
struct stream *s;
unsigned short l = 0;
vni_t vni;
struct in_addr vtep_ip;
- zebra_evpn_t *zevpn;
- zebra_vtep_t *zvtep;
- struct interface *ifp;
- struct zebra_if *zif;
if (!is_evpn_enabled()) {
zlog_debug(
- "%s: EVPN is not enabled yet we have received a vtep del command",
+ "%s: EVPN is not enabled yet we have received a VTEP DEL msg",
__func__);
return;
}
if (!EVPN_ENABLED(zvrf)) {
- zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
- zvrf_id(zvrf));
+ zlog_debug("Recv VTEP DEL zapi for non-EVPN VRF %u",
+ zvrf_id(zvrf));
return;
}
@@ -4244,76 +4235,182 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
l += 4;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Recv VTEP_DEL %pI4 VNI %u from %s",
+ zlog_debug("Recv VTEP DEL %pI4 VNI %u from %s",
&vtep_ip, vni,
zebra_route_string(client->proto));
- /* Locate VNI hash entry - expected to exist. */
- zevpn = zebra_evpn_lookup(vni);
- if (!zevpn) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Failed to locate VNI hash upon remote VTEP DEL, VNI %u",
- vni);
- continue;
- }
+ /* Enqueue for processing */
+ zebra_rib_queue_evpn_rem_vtep_del(zvrf_id(zvrf), vni, vtep_ip);
+ }
- ifp = zevpn->vxlan_if;
- if (!ifp) {
+stream_failure:
+ return;
+}
+
+/*
+ * Handle message from client to delete a remote VTEP for an EVPN.
+ */
+void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip)
+{
+ zebra_evpn_t *zevpn;
+ zebra_vtep_t *zvtep;
+ struct interface *ifp;
+ struct zebra_if *zif;
+ struct zebra_vrf *zvrf;
+
+ if (!is_evpn_enabled()) {
+ zlog_debug("%s: Can't process vtep del: EVPN is not enabled",
+ __func__);
+ return;
+ }
+
+ zvrf = zebra_vrf_lookup_by_id(vrf_id);
+ if (!zvrf)
+ return;
+
+ if (!EVPN_ENABLED(zvrf)) {
+ zlog_debug("Can't process VTEP DEL for non-EVPN VRF %u",
+ zvrf_id(zvrf));
+ return;
+ }
+
+ /* Locate VNI hash entry - expected to exist. */
+ zevpn = zebra_evpn_lookup(vni);
+ if (!zevpn) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
- zevpn->vni, zevpn);
- continue;
- }
- zif = ifp->info;
+ "Failed to locate VNI hash for remote VTEP DEL, VNI %u",
+ vni);
+ return;
+ }
- /* If down or not mapped to a bridge, we're done. */
- if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
- continue;
+ ifp = zevpn->vxlan_if;
+ if (!ifp) {
+ zlog_debug(
+ "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
+ zevpn->vni, zevpn);
+ return;
+ }
+ zif = ifp->info;
- /* If the remote VTEP does not exist, there's nothing more to
- * do.
- * Otherwise, uninstall any remote MACs pointing to this VTEP
- * and
- * then, the VTEP entry itself and remove it.
- */
- zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
- if (!zvtep)
- continue;
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return;
+
+ /* If the remote VTEP does not exist, there's nothing more to
+ * do.
+ * Otherwise, uninstall any remote MACs pointing to this VTEP
+ * and then, the VTEP entry itself and remove it.
+ */
+ zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
+ if (!zvtep)
+ return;
- zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
- zebra_evpn_vtep_del(zevpn, zvtep);
+ zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
+ zebra_evpn_vtep_del(zevpn, zvtep);
+}
+
+/*
+ * Handle message from client to add a remote VTEP for an EVPN.
+ */
+void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip, int flood_control)
+{
+ zebra_evpn_t *zevpn;
+ struct interface *ifp;
+ struct zebra_if *zif;
+ zebra_vtep_t *zvtep;
+ struct zebra_vrf *zvrf;
+
+ if (!is_evpn_enabled()) {
+ zlog_debug("%s: EVPN not enabled: can't process a VTEP ADD",
+ __func__);
+ return;
}
-stream_failure:
- return;
+ zvrf = zebra_vrf_lookup_by_id(vrf_id);
+ if (!zvrf)
+ return;
+
+ if (!EVPN_ENABLED(zvrf)) {
+ zlog_debug("Can't process VTEP ADD for non-EVPN VRF %u",
+ zvrf_id(zvrf));
+ return;
+ }
+
+ /* Locate VNI hash entry - expected to exist. */
+ zevpn = zebra_evpn_lookup(vni);
+ if (!zevpn) {
+ flog_err(
+ EC_ZEBRA_VTEP_ADD_FAILED,
+ "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
+ vni);
+ return;
+ }
+
+ ifp = zevpn->vxlan_if;
+ if (!ifp) {
+ flog_err(
+ EC_ZEBRA_VTEP_ADD_FAILED,
+ "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
+ zevpn->vni, zevpn);
+ return;
+ }
+
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return;
+
+ zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
+ if (zvtep) {
+ /* If the remote VTEP already exists check if
+ * the flood mode has changed
+ */
+ if (zvtep->flood_control != flood_control) {
+ if (zvtep->flood_control == VXLAN_FLOOD_DISABLED)
+ /* old mode was head-end-replication but
+ * is no longer; get rid of the HER fdb
+ * entry installed before
+ */
+ zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
+ zvtep->flood_control = flood_control;
+ zebra_evpn_vtep_install(zevpn, zvtep);
+ }
+ } else {
+ zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, flood_control);
+ if (zvtep)
+ zebra_evpn_vtep_install(zevpn, zvtep);
+ else
+ flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
+ "Failed to add remote VTEP, VNI %u zevpn %p",
+ vni, zevpn);
+ }
}
/*
* Handle message from client to add a remote VTEP for an EVPN.
*/
-void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
+void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS)
{
struct stream *s;
unsigned short l = 0;
vni_t vni;
struct in_addr vtep_ip;
- zebra_evpn_t *zevpn;
- struct interface *ifp;
- struct zebra_if *zif;
int flood_control;
- zebra_vtep_t *zvtep;
if (!is_evpn_enabled()) {
zlog_debug(
- "%s: EVPN not enabled yet we received a vtep_add zapi call",
+ "%s: EVPN not enabled yet we received a VTEP ADD zapi msg",
__func__);
return;
}
if (!EVPN_ENABLED(zvrf)) {
- zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
- zvrf_id(zvrf));
+ zlog_debug("Recv VTEP ADD zapi for non-EVPN VRF %u",
+ zvrf_id(zvrf));
return;
}
@@ -4328,62 +4425,13 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
l += IPV4_MAX_BYTELEN + 4;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Recv VTEP_ADD %pI4 VNI %u flood %d from %s",
- &vtep_ip, vni, flood_control,
- zebra_route_string(client->proto));
-
- /* Locate VNI hash entry - expected to exist. */
- zevpn = zebra_evpn_lookup(vni);
- if (!zevpn) {
- flog_err(
- EC_ZEBRA_VTEP_ADD_FAILED,
- "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
- vni);
- continue;
- }
-
- ifp = zevpn->vxlan_if;
- if (!ifp) {
- flog_err(
- EC_ZEBRA_VTEP_ADD_FAILED,
- "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
- zevpn->vni, zevpn);
- continue;
- }
-
- zif = ifp->info;
-
- /* If down or not mapped to a bridge, we're done. */
- if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
- continue;
+ zlog_debug("Recv VTEP ADD %pI4 VNI %u flood %d from %s",
+ &vtep_ip, vni, flood_control,
+ zebra_route_string(client->proto));
- zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
- if (zvtep) {
- /* If the remote VTEP already exists check if
- * the flood mode has changed
- */
- if (zvtep->flood_control != flood_control) {
- if (zvtep->flood_control
- == VXLAN_FLOOD_DISABLED)
- /* old mode was head-end-replication but
- * is no longer; get rid of the HER fdb
- * entry installed before
- */
- zebra_evpn_vtep_uninstall(zevpn,
- &vtep_ip);
- zvtep->flood_control = flood_control;
- zebra_evpn_vtep_install(zevpn, zvtep);
- }
- } else {
- zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip,
- flood_control);
- if (zvtep)
- zebra_evpn_vtep_install(zevpn, zvtep);
- else
- flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
- "Failed to add remote VTEP, VNI %u zevpn %p",
- vni, zevpn);
- }
+ /* Enqueue for processing */
+ zebra_rib_queue_evpn_rem_vtep_add(zvrf_id(zvrf), vni, vtep_ip,
+ flood_control);
}
stream_failure:
@@ -4398,7 +4446,7 @@ stream_failure:
* 3. vrr interface (MACVLAN) associated to a SVI
* We advertise macip routes for an interface if it is associated to VxLan vlan
*/
-int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
+int zebra_vxlan_add_del_gw_macip(struct interface *ifp, const struct prefix *p,
int add)
{
struct ipaddr ip;
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 24de8ff04e..915e987b6b 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -72,8 +72,12 @@ is_vxlan_flooding_head_end(void)
/* ZAPI message handlers */
extern void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS);
-extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS);
-extern void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS);
+void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip, int flood_control);
+extern void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id, vni_t vni,
+ struct in_addr vtep_ip);
extern void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS);
@@ -157,8 +161,8 @@ extern void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json);
extern void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json);
extern void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
json_object *json_vrfs);
-extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
- int add);
+extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp,
+ const struct prefix *p, int add);
extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
extern int zebra_vxlan_svi_down(struct interface *ifp,
struct interface *link_if);