summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c7
-rw-r--r--bgpd/bgp_attr.h31
-rw-r--r--bgpd/bgp_attr_evpn.c13
-rw-r--r--bgpd/bgp_attr_evpn.h3
-rw-r--r--bgpd/bgp_ecommunity.c5
-rw-r--r--bgpd/bgp_ecommunity.h6
-rw-r--r--bgpd/bgp_evpn_mh.c9
-rw-r--r--bgpd/bgp_evpn_mh.h43
8 files changed, 107 insertions, 10 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 50a2dd3d28..948055e375 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -719,6 +719,8 @@ bool attrhash_cmp(const void *p1, const void *p2)
&attr2->originator_id)
&& overlay_index_same(attr1, attr2)
&& !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t))
+ && attr1->es_flags == attr2->es_flags
+ && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum
&& attr1->nh_ifindex == attr2->nh_ifindex
&& attr1->nh_lla_ifindex == attr2->nh_lla_ifindex
&& attr1->distance == attr2->distance
@@ -2187,6 +2189,7 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
uint8_t sticky = 0;
+ bool proxy = false;
if (length == 0) {
attr->ecommunity = NULL;
@@ -2224,7 +2227,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
attr->router_flag = 1;
/* Check EVPN Neighbor advertisement flags, R-bit */
- bgp_attr_evpn_na_flag(attr, &attr->router_flag);
+ bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
+ if (proxy)
+ attr->es_flags |= ATTR_ES_PROXY_ADVERT;
/* Extract the Rmac, if any */
if (bgp_attr_rmac(attr, &attr->rmac)) {
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 4d67194e10..1b2c75fbef 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -215,6 +215,30 @@ struct attr {
/* NA router flag (R-bit) support in EVPN */
uint8_t router_flag;
+ /* ES info */
+ uint8_t es_flags;
+ /* Path is not "locally-active" on the advertising VTEP. This is
+ * translated into an ARP-ND ECOM.
+ */
+#define ATTR_ES_PROXY_ADVERT (1 << 0)
+ /* Destination ES is present locally. This flag is set on local
+ * paths and sync paths
+ */
+#define ATTR_ES_IS_LOCAL (1 << 1)
+ /* There are one or more non-best paths from ES peers. Note that
+ * this flag is only set on the local MAC-IP paths in the VNI
+ * route table (not set in the global routing table). And only
+ * non-proxy advertisements from an ES peer can result in this
+ * flag being set.
+ */
+#define ATTR_ES_PEER_ACTIVE (1 << 2)
+ /* There are one or more non-best proxy paths from ES peers */
+#define ATTR_ES_PEER_PROXY (1 << 3)
+ /* An ES peer has router bit set - only applicable if
+ * ATTR_ES_PEER_ACTIVE is set
+ */
+#define ATTR_ES_PEER_ROUTER (1 << 4)
+
/* route tag */
route_tag_t tag;
@@ -241,6 +265,13 @@ struct attr {
/* EVPN MAC Mobility sequence number, if any. */
uint32_t mm_seqnum;
+ /* highest MM sequence number rxed in a MAC-IP route from an
+ * ES peer (this includes both proxy and non-proxy MAC-IP
+ * advertisements from ES peers).
+ * This is only applicable to local paths in the VNI routing
+ * table and derived from other imported/non-best paths.
+ */
+ uint32_t mm_sync_seqnum;
/* EVPN local router-mac */
struct ethaddr rmac;
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index e81ef79fbb..aa0c59f3a7 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -195,7 +195,8 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
/*
* return true if attr contains router flag extended community
*/
-void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag)
+void bgp_attr_evpn_na_flag(struct attr *attr,
+ uint8_t *router_flag, bool *proxy)
{
struct ecommunity *ecom;
int i;
@@ -217,10 +218,14 @@ void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag)
if (type == ECOMMUNITY_ENCODE_EVPN &&
sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
val = *pnt++;
- if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) {
+
+ if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG)
*router_flag = 1;
- break;
- }
+
+ if (val & ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG)
+ *proxy = true;
+
+ break;
}
}
}
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index e878634610..19c028a826 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -46,7 +46,8 @@ extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
uint8_t *sticky);
extern uint8_t bgp_attr_default_gw(struct attr *attr);
-extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag);
+extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag,
+ bool *proxy);
extern bool is_zero_gw_ip(const union gw_addr *gw_ip, afi_t afi);
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 0990d0b872..f2aac3646c 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -810,6 +810,11 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG))
strlcpy(encbuf, "ND:Router Flag",
sizeof(encbuf));
+ if (CHECK_FLAG(
+ flags,
+ ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG))
+ strlcpy(encbuf, "ND:Proxy",
+ sizeof(encbuf));
} else if (*pnt
== ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT) {
struct ethaddr mac;
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 1e9ffcb678..812bcc46e7 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -73,8 +73,10 @@
#define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01
-#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01
-#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02
+
+#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01
+#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02
+#define ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG 0x04
#define ECOMMUNITY_EVPN_SUBTYPE_ESI_SA_FLAG (1 << 0) /* single-active */
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 6e6dda7aa7..bb870e04b2 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -1469,6 +1469,15 @@ static void bgp_evpn_local_es_do_del(struct bgp *bgp, struct bgp_evpn_es *es)
bgp_evpn_es_local_info_clear(es);
}
+bool bgp_evpn_is_esi_local(esi_t *esi)
+{
+ struct bgp_evpn_es *es = NULL;
+
+ /* Lookup ESI hash - should exist. */
+ es = bgp_evpn_es_find(esi);
+ return es ? !!(es->flags & BGP_EVPNES_LOCAL) : false;
+}
+
int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi)
{
struct bgp_evpn_es *es = NULL;
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index 1dcdfc3cf1..93355d495a 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -215,15 +215,53 @@ struct bgp_evpn_mh_info {
};
/****************************************************************************/
-static inline int is_es_local(struct bgp_evpn_es *es)
+static inline int bgp_evpn_is_es_local(struct bgp_evpn_es *es)
{
return CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) ? 1 : 0;
}
extern esi_t *zero_esi;
+static inline bool bgp_evpn_is_esi_valid(esi_t *esi)
+{
+ return !!memcmp(esi, zero_esi, sizeof(esi_t));
+}
+
static inline esi_t *bgp_evpn_attr_get_esi(struct attr *attr)
{
- return (attr) ? &attr->esi : zero_esi;
+ return attr ? &attr->esi : zero_esi;
+}
+
+static inline bool bgp_evpn_attr_is_sync(struct attr *attr)
+{
+ return attr ? !!(attr->es_flags &
+ (ATTR_ES_PEER_PROXY | ATTR_ES_PEER_ACTIVE)) : false;
+}
+
+static inline uint32_t bgp_evpn_attr_get_sync_seq(struct attr *attr)
+{
+ return attr ? attr->mm_sync_seqnum : 0;
+}
+
+static inline bool bgp_evpn_attr_is_active_on_peer(struct attr *attr)
+{
+ return attr ?
+ !!(attr->es_flags & ATTR_ES_PEER_ACTIVE) : false;
+}
+
+static inline bool bgp_evpn_attr_is_router_on_peer(struct attr *attr)
+{
+ return attr ?
+ !!(attr->es_flags & ATTR_ES_PEER_ROUTER) : false;
+}
+
+static inline bool bgp_evpn_attr_is_proxy(struct attr *attr)
+{
+ return attr ? !!(attr->es_flags & ATTR_ES_PROXY_ADVERT) : false;
+}
+
+static inline bool bgp_evpn_attr_is_local_es(struct attr *attr)
+{
+ return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false;
}
/****************************************************************************/
@@ -256,5 +294,6 @@ void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni,
bool uj, bool detail);
void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail);
struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi);
+extern bool bgp_evpn_is_esi_local(esi_t *esi);
#endif /* _FRR_BGP_EVPN_MH_H */