summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn_mh.c130
-rw-r--r--bgpd/bgp_evpn_mh.h7
-rw-r--r--bgpd/bgp_evpn_vty.c2
-rw-r--r--bgpd/bgp_zebra.c11
4 files changed, 113 insertions, 37 deletions
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 2dec0863c0..0b02669211 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -1621,21 +1621,18 @@ static void bgp_evpn_es_remote_info_re_eval(struct bgp_evpn_es *es)
}
}
-/* Process ES link oper-down by withdrawing ES-EAD and ESR */
-static void bgp_evpn_local_es_down(struct bgp *bgp,
- struct bgp_evpn_es *es)
+static inline bool bgp_evpn_local_es_is_active(struct bgp_evpn_es *es)
+{
+ return (es->flags & BGP_EVPNES_OPER_UP)
+ && !(es->flags & BGP_EVPNES_BYPASS);
+}
+
+static void bgp_evpn_local_es_deactivate(struct bgp *bgp,
+ struct bgp_evpn_es *es)
{
struct prefix_evpn p;
int ret;
- if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP))
- return;
-
- UNSET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
-
- if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("local es %s down", es->esi_str);
-
/* withdraw ESR */
/* Delete and withdraw locally learnt ES route */
build_evpn_type4_prefix(&p, &es->esi, es->originator_ip);
@@ -1661,21 +1658,28 @@ static void bgp_evpn_local_es_down(struct bgp *bgp,
}
}
-/* Process ES link oper-up by generating ES-EAD and ESR */
-static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
- bool regen_esr)
+/* Process ES link oper-down by withdrawing ES-EAD and ESR */
+static void bgp_evpn_local_es_down(struct bgp *bgp, struct bgp_evpn_es *es)
{
- struct prefix_evpn p;
- bool regen_ead = false;
+ bool old_active;
- if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
- if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("local es %s up", es->esi_str);
+ if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP))
+ return;
- SET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
- regen_esr = true;
- regen_ead = true;
- }
+ old_active = bgp_evpn_local_es_is_active(es);
+ UNSET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
+
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("local es %s down", es->esi_str);
+
+ if (old_active)
+ bgp_evpn_local_es_deactivate(bgp, es);
+}
+
+static void bgp_evpn_local_es_activate(struct bgp *bgp, struct bgp_evpn_es *es,
+ bool regen_ead, bool regen_esr)
+{
+ struct prefix_evpn p;
if (regen_esr) {
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
@@ -1701,6 +1705,61 @@ static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
}
}
+/* Process ES link oper-up by generating ES-EAD and ESR */
+static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
+ bool regen_esr)
+{
+ bool regen_ead = false;
+ bool active = false;
+
+ if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("local es %s up", es->esi_str);
+
+ SET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
+ regen_esr = true;
+ regen_ead = true;
+ }
+
+ active = bgp_evpn_local_es_is_active(es);
+ if (active && (regen_ead || regen_esr))
+ bgp_evpn_local_es_activate(bgp, es, regen_ead, regen_esr);
+}
+
+/* If an ethernet segment is in LACP bypass we cannot advertise
+ * reachability to it i.e. EAD-per-ES and ESR is not advertised in
+ * bypass state.
+ * PS: EAD-per-EVI will continue to be advertised
+ */
+static void bgp_evpn_local_es_bypass_update(struct bgp *bgp,
+ struct bgp_evpn_es *es, bool bypass)
+{
+ bool old_bypass = !!(es->flags & BGP_EVPNES_BYPASS);
+ bool old_active;
+ bool new_active;
+
+ if (bypass == old_bypass)
+ return;
+
+ old_active = bgp_evpn_local_es_is_active(es);
+ if (bypass)
+ SET_FLAG(es->flags, BGP_EVPNES_BYPASS);
+ else
+ UNSET_FLAG(es->flags, BGP_EVPNES_BYPASS);
+
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("local es %s bypass %s", es->esi_str,
+ bypass ? "set" : "clear");
+
+ new_active = bgp_evpn_local_es_is_active(es);
+ if (old_active != new_active) {
+ if (new_active)
+ bgp_evpn_local_es_activate(bgp, es, true, true);
+ else
+ bgp_evpn_local_es_deactivate(bgp, es);
+ }
+}
+
static void bgp_evpn_local_es_do_del(struct bgp *bgp, struct bgp_evpn_es *es)
{
struct bgp_evpn_es_evi *es_evi;
@@ -1757,7 +1816,7 @@ int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi)
*/
int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
struct in_addr originator_ip, bool oper_up,
- uint16_t df_pref)
+ uint16_t df_pref, bool bypass)
{
char buf[ESI_STR_LEN];
struct bgp_evpn_es *es;
@@ -1780,8 +1839,9 @@ int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
}
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("add local es %s orig-ip %pI4 df_pref %u", es->esi_str,
- &originator_ip, df_pref);
+ zlog_debug("add local es %s orig-ip %pI4 df_pref %u %s",
+ es->esi_str, &originator_ip, df_pref,
+ bypass ? "bypass" : "");
es->originator_ip = originator_ip;
if (df_pref != es->df_pref) {
@@ -1802,6 +1862,8 @@ int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
if (bgp_mh_info->ead_evi_adv_for_down_links)
bgp_evpn_local_type1_evi_route_add(bgp, es);
+ bgp_evpn_local_es_bypass_update(bgp, es, bypass);
+
/* If the ES link is operationally up generate EAD-ES. EAD-EVI
* can be generated even if the link is inactive.
*/
@@ -1952,6 +2014,8 @@ static void bgp_evpn_es_show_entry(struct vty *vty,
char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
type_str[0] = '\0';
+ if (es->flags & BGP_EVPNES_BYPASS)
+ strlcat(type_str, "B", sizeof(type_str));
if (es->flags & BGP_EVPNES_LOCAL)
strlcat(type_str, "L", sizeof(type_str));
if (es->flags & BGP_EVPNES_REMOTE)
@@ -1986,13 +2050,17 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
/* Add the "brief" info first */
bgp_evpn_es_show_entry(vty, es, json);
- if (es->flags & (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI)) {
+ if (es->flags
+ & (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI
+ | BGP_EVPNES_BYPASS)) {
json_flags = json_object_new_array();
if (es->flags & BGP_EVPNES_OPER_UP)
json_array_string_add(json_flags, "up");
if (es->flags & BGP_EVPNES_ADV_EVI)
json_array_string_add(json_flags,
"advertiseEVI");
+ if (es->flags & BGP_EVPNES_BYPASS)
+ json_array_string_add(json_flags, "bypass");
json_object_object_add(json, "flags", json_flags);
}
json_object_string_add(json, "originator_ip",
@@ -2045,6 +2113,8 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
if (es->flags & BGP_EVPNES_LOCAL)
vty_out(vty, " Local ES DF preference: %u\n",
es->df_pref);
+ if (es->flags & BGP_EVPNES_BYPASS)
+ vty_out(vty, " LACP bypass: on\n");
vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
vty_out(vty, " Remote VNI Count: %d\n",
es->remote_es_evi_cnt);
@@ -2084,7 +2154,7 @@ void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail)
} else {
if (!detail) {
vty_out(vty,
- "ES Flags: L local, R remote, I inconsistent\n");
+ "ES Flags: B - bypass, L local, R remote, I inconsistent\n");
vty_out(vty,
"VTEP Flags: E ESR/Type-4, A active nexthop\n");
vty_out(vty,
@@ -2973,7 +3043,7 @@ static void bgp_evpn_local_es_evi_do_del(struct bgp_evpn_es_evi *es_evi)
if (bgp) {
/* update EAD-ES with new list of VNIs */
- if (CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
+ if (bgp_evpn_local_es_is_active(es)) {
build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG,
&es->esi, es->originator_ip);
if (bgp_evpn_type1_route_update(bgp, es, NULL, &p))
@@ -3098,7 +3168,7 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
/* update EAD-ES */
build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG,
&es->esi, es->originator_ip);
- if (CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
+ if (bgp_evpn_local_es_is_active(es)) {
if (bgp_evpn_type1_route_update(bgp, es, NULL, &p))
flog_err(EC_BGP_EVPN_ROUTE_CREATE,
"%u: EAD-ES route creation failure for ESI %s VNI %u",
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index 6199113e87..818fad2eb6 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -29,7 +29,6 @@
#define BGP_EVPN_AD_EVI_ETH_TAG 0
#define BGP_EVPNES_INCONS_STR_SZ 80
-#define BGP_EVPN_FLAG_STR_SZ 5
#define BGP_EVPN_VTEPS_FLAG_STR_SZ (BGP_EVPN_FLAG_STR_SZ * ES_VTEP_MAX_CNT)
#define BGP_EVPN_CONS_CHECK_INTERVAL 60
@@ -62,6 +61,10 @@ struct bgp_evpn_es {
#define BGP_EVPNES_ADV_EVI (1 << 3)
/* consistency checks pending */
#define BGP_EVPNES_CONS_CHECK_PEND (1 << 4)
+ /* ES is in LACP bypass mode - don't advertise EAD-ES or ESR */
+#define BGP_EVPNES_BYPASS (1 << 5)
+ /* bits needed for printing the flags + null */
+#define BGP_EVPN_FLAG_STR_SZ 7
/* memory used for adding the es to bgp->es_rb_tree */
RB_ENTRY(bgp_evpn_es) rb_node;
@@ -340,7 +343,7 @@ int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
uint32_t addpath_id);
extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
struct in_addr originator_ip, bool oper_up,
- uint16_t df_pref);
+ uint16_t df_pref, bool bypass);
extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi);
extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni);
extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni);
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 5b0b3bb6e5..73bce5df9a 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -4803,7 +4803,7 @@ DEFPY_HIDDEN(test_es_add,
vtep_ip = bgp->router_id;
ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
- EVPN_MH_DF_PREF_MIN);
+ EVPN_MH_DF_PREF_MIN, false);
if (ret == -1) {
vty_out(vty, "%%Failed to add ES\n");
return CMD_WARNING;
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index d397a5241a..3be721824e 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2660,6 +2660,7 @@ static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS)
char buf[ESI_STR_LEN];
struct in_addr originator_ip;
uint8_t active;
+ uint8_t bypass;
uint16_t df_pref;
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -2671,14 +2672,16 @@ static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS)
originator_ip.s_addr = stream_get_ipv4(s);
active = stream_getc(s);
df_pref = stream_getw(s);
+ bypass = stream_getc(s);
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug(
- "Rx add ESI %s originator-ip %pI4 active %u df_pref %u",
- esi_to_str(&esi, buf, sizeof(buf)),
- &originator_ip, active, df_pref);
+ "Rx add ESI %s originator-ip %pI4 active %u df_pref %u %s",
+ esi_to_str(&esi, buf, sizeof(buf)), &originator_ip,
+ active, df_pref, bypass ? "bypass" : "");
- bgp_evpn_local_es_add(bgp, &esi, originator_ip, active, df_pref);
+ bgp_evpn_local_es_add(bgp, &esi, originator_ip, active, df_pref,
+ !!bypass);
return 0;
}