The commit introduces the changes to be done to carry route type 5 EVPN
information in bgp extra attribute information. The commit also handles
the update processing for route type 5 information.

Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com>
---
 bgpd/bgp_attr.c  |  16 ++++-
 bgpd/bgp_attr.h  |  14 +++++
 bgpd/bgp_route.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 bgpd/bgp_route.h |   5 ++
 4 files changed, 205 insertions(+), 3 deletions(-)

diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 8741c4af3441..c7564ae49fb8 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -311,6 +311,18 @@ encap_same(struct bgp_attr_encap_subtlv *h1, struct 
bgp_attr_encap_subtlv *h2)
     return 1;
 }
 
+static bool
+overlay_index_same(const struct attr_extra *ae1, const struct attr_extra *ae2)
+{
+  if(!ae1 && ae2)
+    return false;
+  if(!ae2 && ae1)
+    return false;
+  if(!ae1 && !ae2)
+    return false;
+  return !memcmp(&(ae1->evpn_overlay), &(ae2->evpn_overlay), sizeof(struct 
overlay_index));
+}
+
 /* Unknown transit attribute. */
 static struct hash *transit_hash;
 
@@ -551,7 +563,9 @@ attrhash_cmp (const void *p1, const void *p2)
           && ae1->transit == ae2->transit
          && (ae1->encap_tunneltype == ae2->encap_tunneltype)
          && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs)
-          && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id))
+          && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id)
+          && ae1->eth_t_id == ae2->eth_t_id
+          && overlay_index_same(ae1, ae2))
         return 1;
       else if (ae1 || ae2)
         return 0;
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 3bd7aface174..64a7464177df 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -21,6 +21,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, 
Boston, MA
 #ifndef _QUAGGA_BGP_ATTR_H
 #define _QUAGGA_BGP_ATTR_H
 
+#include "bgp_attr_evpn.h"
+
 /* Simple bit mapping. */
 #define BITMAP_NBBY 8
 
@@ -54,6 +56,13 @@ struct bgp_attr_encap_subtlv {
     uint8_t                            value[1];       /* will be extended */
 };
 
+/* Overlay Index Info */
+struct overlay_index
+{
+  struct eth_segment_id eth_s_id;
+  union gw_addr gw_ip;
+};
+
 /* Additional/uncommon BGP attributes.
  * lazily allocated as and when a struct attr
  * requires it.
@@ -95,6 +104,11 @@ struct attr_extra
 
   /* route tag */
   route_tag_t tag;
+
+  /* EVPN */
+  uint32_t eth_t_id;
+  struct overlay_index evpn_overlay;
+  short use_gw;
 };
 
 /* BGP core attribute structure. */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 32577c299f6a..3c8ebcab8676 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -57,6 +57,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, 
Boston, MA
 #include "bgpd/bgp_vty.h"
 #include "bgpd/bgp_mpath.h"
 #include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_evpn.h"
 
 /* Extern from bgp_dump.c */
 extern const char *bgp_origin_str[];
@@ -2526,6 +2527,86 @@ info_make (int type, int sub_type, struct peer *peer, 
struct attr *attr,
   return new;
 }
 
+static void
+overlay_index_update(struct attr *attr, struct eth_segment_id *eth_s_id, union 
gw_addr *gw_ip)
+{
+  struct attr_extra *extra;
+
+  if(!attr)
+    return;
+  extra = bgp_attr_extra_get(attr);
+
+  if(eth_s_id == NULL)
+    {
+      memset(&(extra->evpn_overlay.eth_s_id),0, sizeof(struct eth_segment_id));
+    }
+  else
+    {
+      memcpy(&(extra->evpn_overlay.eth_s_id), eth_s_id, sizeof(struct 
eth_segment_id));
+    }
+  if(gw_ip == NULL)
+    {
+      memset(&(extra->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
+    }
+  else
+    {
+      memcpy(&(extra->evpn_overlay.gw_ip),gw_ip, sizeof(union gw_addr));
+    }
+}
+
+static bool
+eth_tag_id_equal(afi_t afi, struct bgp_info *info, uint32_t *eth_t_id)
+{
+  uint32_t local_eth_t_id;
+
+  if(afi != AFI_INTERNAL_L2VPN)
+    return true;
+  if (!info->attr || !info->attr->extra) {
+    local_eth_t_id = 0;
+    if(eth_t_id == NULL)
+      return true;
+  } else {
+    local_eth_t_id = info->attr->extra->eth_t_id;
+  }
+  if(eth_t_id && (local_eth_t_id == *eth_t_id))
+    return true;
+  if (local_eth_t_id == 0)
+    return true;
+  return false;
+}
+
+static bool
+overlay_index_equal(afi_t afi, struct bgp_info *info, struct eth_segment_id 
*eth_s_id, union gw_addr *gw_ip)
+{
+  struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote;
+  union gw_addr *info_gw_ip, *info_gw_ip_remote;
+  char temp[16];
+
+  if(afi != AFI_INTERNAL_L2VPN)
+    return true;
+  if (!info->attr || !info->attr->extra) {
+    memset(&temp, 0, 16);
+    info_eth_s_id = (struct eth_segment_id *)&temp;
+    info_gw_ip = (union gw_addr *)&temp;
+    if(eth_s_id == NULL && gw_ip == NULL)
+      return true;
+  } else {
+    info_eth_s_id = &(info->attr->extra->evpn_overlay.eth_s_id);
+    info_gw_ip = &(info->attr->extra->evpn_overlay.gw_ip);
+  }
+  if(gw_ip == NULL)
+    info_gw_ip_remote = (union gw_addr *)&temp;
+  else
+    info_gw_ip_remote = gw_ip;
+  if(eth_s_id == NULL)
+    info_eth_s_id_remote =  (struct eth_segment_id *)&temp;
+  else
+    info_eth_s_id_remote =  eth_s_id;
+  if(!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr)))
+    return false;
+  return !memcmp(info_eth_s_id, info_eth_s_id_remote, sizeof(struct 
eth_segment_id));
+}
+
 static bool
 labels_equal(struct bgp_info *info, uint32_t *labels, size_t nlabels)
 {
@@ -2640,7 +2721,11 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, 
safi_t safi,
       /* Same attribute comes in. */
       if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
           && attrhash_cmp (ri->attr, attr_new)
-          && labels_equal (ri, labels, nlabels))
+          && labels_equal (ri, labels, nlabels)
+          && eth_tag_id_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_t_id)
+          && (overlay_index_equal(afi, ri, 
+                                  evpn==NULL?NULL:&evpn->eth_s_id, 
+                                  evpn==NULL?NULL:&evpn->gw_ip)))
         {
 
 
@@ -2684,6 +2769,19 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, 
safi_t safi,
       else if (ri->extra)
         ri->extra->nlabels = 0;
 
+      /* Update Overlay Index */
+      if(afi == AFI_INTERNAL_L2VPN)
+        {
+          overlay_index_update(ri->attr, evpn==NULL?NULL:&evpn->eth_s_id, 
+                               evpn==NULL?NULL:&evpn->gw_ip);
+          if(ri->attr && ri->attr->extra)
+            {
+              if(evpn && evpn->eth_t_id)
+                ri->attr->extra->eth_t_id = evpn->eth_t_id;
+              else
+                ri->attr->extra->eth_t_id = 0;
+            }
+        }
       bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
 
       /* Process change. */
@@ -2713,6 +2811,19 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, 
safi_t safi,
       memcpy (ri->extra->labels, labels, sizeof(*labels) * nlabels);
     }
 
+  /* Update Overlay Index */
+  if(afi == AFI_INTERNAL_L2VPN)
+    {
+      overlay_index_update(new->attr, evpn==NULL?NULL:&evpn->eth_s_id,
+                           evpn==NULL?NULL:&evpn->gw_ip);
+      if(new->attr && new->attr->extra)
+        {
+          if(evpn && evpn->eth_t_id)
+            new->attr->extra->eth_t_id = evpn->eth_t_id;
+          else
+            new->attr->extra->eth_t_id = 0;
+        }
+    }
   bgp_info_set_flag (rn, new, BGP_INFO_VALID);
 
   /* Register new BGP information. */
@@ -2897,7 +3008,10 @@ bgp_update_main (struct peer *peer, struct prefix *p, 
struct attr *attr,
       /* Same attribute comes in. */
       if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) 
           && attrhash_cmp (ri->attr, attr_new)
-          && labels_equal (ri, labels, nlabels))
+          && labels_equal (ri, labels, nlabels)
+          && eth_tag_id_equal(afi, ri, evpn==NULL?0:&evpn->eth_t_id)
+          && (overlay_index_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_s_id,
+                                  evpn==NULL?NULL:&evpn->gw_ip)))
        {
          if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
              && peer->sort == BGP_PEER_EBGP
@@ -2992,6 +3106,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, 
struct attr *attr,
       else if (ri->extra)
         ri->extra->nlabels = 0;
 
+      /* Update Overlay Index */
+      if(afi == AFI_INTERNAL_L2VPN)
+        {
+          overlay_index_update(ri->attr, evpn==NULL?NULL:&evpn->eth_s_id,
+                               evpn==NULL?NULL:&evpn->gw_ip);
+          if(ri->attr && ri->attr->extra)
+            {
+              if(evpn && evpn->eth_t_id)
+                ri->attr->extra->eth_t_id = evpn->eth_t_id;
+              else
+                ri->attr->extra->eth_t_id = 0;
+            }
+        }
       bgp_attr_flush (&new_attr);
 
       /* Update bgp route dampening information.  */
@@ -3065,6 +3192,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, 
struct attr *attr,
       memcpy (new->extra->labels, labels, sizeof(*labels) * nlabels);
     }
 
+  /* Update Overlay Index */
+  if(afi == AFI_INTERNAL_L2VPN)
+    {
+      overlay_index_update(new->attr, evpn==NULL?NULL:&evpn->eth_s_id,
+                           evpn==NULL?NULL:&evpn->gw_ip);
+      if(new->attr && new->attr->extra)
+        {
+          if(evpn && evpn->eth_t_id)
+            new->attr->extra->eth_t_id = evpn->eth_t_id;
+          else
+            new->attr->extra->eth_t_id = 0;
+        }
+    }
   /* Nexthop reachability check. */
   if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
     {
@@ -4085,6 +4225,8 @@ bgp_static_free (struct bgp_static *bgp_static)
 {
   if (bgp_static->rmap.name)
     free (bgp_static->rmap.name);
+  if(bgp_static->eth_s_id)
+    XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
   XFREE (MTYPE_BGP_STATIC, bgp_static);
 }
 
@@ -4581,6 +4723,28 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix 
*p,
       bgp_attr_extra_get (&attr)->ecommunity = ecommunity_dup 
(bgp_static->ecomm);
       attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
     }
+  if(afi == AFI_INTERNAL_L2VPN)
+    {
+      if (bgp_static->igpnexthop.s_addr)
+        {
+          union gw_addr add;
+
+          memset(&add, 0, sizeof(union gw_addr));
+          add.ipv4.s_addr = bgp_static->igpnexthop.s_addr;
+          overlay_index_update(&attr, bgp_static->eth_s_id, &add);
+        }
+      else
+        {
+          overlay_index_update(&attr, bgp_static->eth_s_id, NULL);
+        }
+      if((&attr)->extra)
+        (&attr)->extra->eth_t_id = bgp_static->eth_t_id;
+    }
+  if (bgp_static->igpnexthop.s_addr)
+    {
+    bgp_attr_extra_get (&attr)->mp_nexthop_global_in = bgp_static->igpnexthop;
+    bgp_attr_extra_get (&attr)->mp_nexthop_len = IPV4_MAX_BYTELEN;
+    }
   /* Apply route-map. */
   if (bgp_static->rmap.name)
     {
@@ -4624,7 +4788,12 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix 
*p,
 
   if (ri)
     {
+      union gw_addr add;
+      memset(&add, 0, sizeof(union gw_addr));
+      add.ipv4.s_addr = bgp_static->igpnexthop.s_addr;
       if (attrhash_cmp (ri->attr, attr_new) &&
+          eth_tag_id_equal(afi, ri, &bgp_static->eth_t_id) &&
+          overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) &&
           !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
         {
           bgp_unlock_node (rn);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 5047b5c48b18..4301088fed3d 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -149,6 +149,11 @@ struct bgp_static
   /* MPLS label. */
   uint32_t labels[BGP_MAX_LABELS];
   size_t nlabels;
+
+  /* EVPN */
+  uint32_t eth_t_id;
+  struct eth_segment_id *eth_s_id;
+  char *router_mac;
 };
 
 #define BGP_INFO_COUNTABLE(BI) \
-- 
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to