To handle BGP NLRI EVPN messages, bgp is modified to handle AFI_L2VPN
and SAFI_EVPN values.

Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com>
---
 bgpd/bgp_attr.c   | 25 ++++++++++++++++++-----
 bgpd/bgp_open.c   | 29 ++++++++++++++++++++++++++-
 bgpd/bgp_packet.c | 28 ++++++++++++++++++++------
 bgpd/bgp_route.c  | 60 ++++++++++++++++++++++++++++++++++++++-----------------
 bgpd/bgp_vty.c    |  2 ++
 bgpd/bgpd.c       | 20 +++++++++++++++----
 6 files changed, 130 insertions(+), 34 deletions(-)

diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index b46e7a30e3f7..8741c4af3441 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2396,9 +2396,16 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, 
safi_t safi,
   sizep = stream_get_endp (s);
   stream_putw (s, 0);  /* Marker: Attribute length. */
 
-  stream_putw (s, afi);
-  stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
-
+  if(afi == AFI_INTERNAL_L2VPN)
+    stream_putw (s, AFI_L2VPN);
+  else
+    stream_putw (s, afi);
+  if(safi == SAFI_MPLS_VPN)
+    stream_putc (s, SAFI_MPLS_LABELED_VPN);
+  else if(safi == SAFI_INTERNAL_EVPN)
+    stream_putc (s, SAFI_EVPN);
+  else
+    stream_putc (s, safi);
   /* Nexthop */
   switch (afi)
     {
@@ -2987,8 +2994,16 @@ bgp_packet_mpunreach_start (struct stream *s, afi_t afi, 
safi_t safi)
   attrlen_pnt = stream_get_endp (s);
   stream_putw (s, 0);          /* Length of this attribute. */
 
-  stream_putw (s, afi);
-  stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
+  if(afi == AFI_INTERNAL_L2VPN)
+    stream_putw (s, AFI_L2VPN);
+  else
+    stream_putw (s, afi);
+  if(safi == SAFI_MPLS_VPN)
+    stream_putc (s, SAFI_MPLS_LABELED_VPN);
+  else if(safi == SAFI_INTERNAL_EVPN)
+    stream_putc (s, SAFI_EVPN);
+  else
+    stream_putc (s, safi);
   return attrlen_pnt;
 }
 
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 7b8b6577e078..5ce838b899dc 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -82,6 +82,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer)
            case AFI_IP6:
              vty_out (vty, "AFI IPv6, ");
              break;
+           case AFI_L2VPN:
+             vty_out (vty, "AFI L2VPN, ");
+             break;
            default:
              vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
              break;
@@ -100,6 +103,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer)
            case SAFI_ENCAP:
              vty_out (vty, "SAFI ENCAP");
              break;
+           case SAFI_EVPN:
+             vty_out (vty, "SAFI EVPN");
+             break;
            default:
              vty_out (vty, "SAFI Unknown %d ", mpc.safi);
              break;
@@ -143,6 +149,12 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
        case SAFI_ENCAP:
          return 1;
        }
+    case AFI_INTERNAL_L2VPN:
+      switch (*safi)
+       {
+        case SAFI_INTERNAL_EVPN:
+          return 1;
+        }
       break;
     }
 
@@ -849,7 +861,8 @@ bgp_open_option_parse (struct peer *peer, u_char length, 
int *mp_capability)
          && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
          && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
          && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
-         && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
+         && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP]
+         && ! peer->afc_nego[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN])
        {
          plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
                    "overlap with received MP capabilities",
@@ -884,6 +897,8 @@ bgp_open_capability_orf (struct stream *s, struct peer 
*peer,
 
   if (safi == SAFI_MPLS_VPN)
     safi = SAFI_MPLS_LABELED_VPN;
+  else if (safi == SAFI_INTERNAL_EVPN)
+    safi = SAFI_EVPN;
 
   stream_putc (s, BGP_OPEN_OPT_CAP);
   capp = stream_get_endp (s);           /* Set Capability Len Pointer */
@@ -1054,6 +1069,18 @@ bgp_open_capability (struct stream *s, struct peer *peer)
       stream_putc (s, 0);
       stream_putc (s, SAFI_ENCAP);
     }
+  /* IPv6 ENCAP. */
+  if (peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN])
+    {
+      peer->afc_adv[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN] = 1;
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_MP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN);
+      stream_putw (s, AFI_L2VPN);
+      stream_putc (s, 0);
+      stream_putc (s, SAFI_EVPN);
+    }
 
   /* Route refresh. */
   SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 8e315d1dbc80..db569b876424 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -650,7 +650,8 @@ bgp_write_packet (struct peer *peer)
                          CHECK_FLAG (adv->binfo->peer->cap,
                                       PEER_CAP_RESTART_BIT_ADV))
                    && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
-                   && safi != SAFI_MPLS_VPN)
+                   && safi != SAFI_MPLS_VPN
+                    && safi != SAFI_INTERNAL_EVPN)
                  {
                    if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
                        PEER_STATUS_EOR_RECEIVED))
@@ -668,7 +669,8 @@ bgp_write_packet (struct peer *peer)
          {
            if (peer->afc_nego[afi][safi] && peer->synctime
                && ! CHECK_FLAG (peer->af_sflags[afi][safi], 
PEER_STATUS_EOR_SEND)
-               && safi != SAFI_MPLS_VPN)
+               && safi != SAFI_MPLS_VPN
+                && safi != SAFI_INTERNAL_EVPN)
              {
                SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
                return bgp_update_packet_eor (peer, afi, safi);
@@ -1077,7 +1079,11 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, 
safi_t safi,
   /* Adjust safi code. */
   if (safi == SAFI_MPLS_VPN)
     safi = SAFI_MPLS_LABELED_VPN;
-  
+  else if (safi == SAFI_INTERNAL_EVPN)
+    safi = SAFI_EVPN;
+  if (afi == AFI_INTERNAL_L2VPN)
+    afi = AFI_L2VPN;
+
   s = stream_new (BGP_MAX_PACKET_SIZE);
 
   /* Make BGP update packet. */
@@ -1159,9 +1165,15 @@ bgp_capability_send (struct peer *peer, afi_t afi, 
safi_t safi,
   struct stream *s;
   int length;
 
+  /* Adjust afi code. */
+  if (afi == AFI_INTERNAL_L2VPN)
+    afi = AFI_L2VPN;
+
   /* Adjust safi code. */
   if (safi == SAFI_MPLS_VPN)
     safi = SAFI_MPLS_LABELED_VPN;
+  if (safi == SAFI_INTERNAL_EVPN)
+    safi = SAFI_EVPN;
 
   s = stream_new (BGP_MAX_PACKET_SIZE);
 
@@ -2079,9 +2091,9 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t 
size)
               peer->host, afi, safi);
 
   /* Check AFI and SAFI. */
-  if ((afi != AFI_IP && afi != AFI_IP6)
+  if ((afi != AFI_IP && afi != AFI_IP6 && afi != AFI_L2VPN)
       || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
-         && safi != SAFI_MPLS_LABELED_VPN))
+         && safi != SAFI_MPLS_LABELED_VPN && safi != SAFI_EVPN))
     {
       if (BGP_DEBUG (normal, NORMAL))
        {
@@ -2094,7 +2106,11 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t 
size)
   /* Adjust safi code. */
   if (safi == SAFI_MPLS_LABELED_VPN)
     safi = SAFI_MPLS_VPN;
-
+  else if (safi == SAFI_EVPN)
+    safi = SAFI_INTERNAL_EVPN;
+  if (afi == AFI_L2VPN)
+      afi = AFI_INTERNAL_L2VPN;
+      
   if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
     {
       u_char *end;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index e83f292162ba..a958a2e42fba 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -91,7 +91,8 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t 
safi, struct prefix
   if (!table)
     return NULL;
   
-  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) ||
+      (safi == SAFI_INTERNAL_EVPN))
     {
       prn = bgp_node_get (table, (struct prefix *) prd);
 
@@ -108,7 +109,8 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, 
safi_t safi, struct prefix
 
   rn = bgp_node_get (table, p);
 
-  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) ||
+      (safi == SAFI_INTERNAL_EVPN))
     rn->prn = prn;
 
   return rn;
@@ -1562,8 +1564,12 @@ void bgp_vrf_clean_tables (struct bgp_vrf *vrf)
         if (rn->info)
           {
             struct bgp_static *bs = rn->info;
-            bgp_static_withdraw_safi (vrf->bgp, &rn->p, afi, SAFI_MPLS_VPN,
-                                      &vrf->outbound_rd, NULL, 0);
+            if(afi == AFI_INTERNAL_L2VPN)
+              bgp_static_withdraw_safi (vrf->bgp, &rn->p, afi, 
SAFI_INTERNAL_EVPN,
+                                        &vrf->outbound_rd, NULL, 0);
+            else
+              bgp_static_withdraw_safi (vrf->bgp, &rn->p, afi, SAFI_MPLS_VPN,
+                                        &vrf->outbound_rd, NULL, 0);
             bgp_static_free (bs);
             rn->info = NULL;
             bgp_unlock_node (rn);
@@ -2408,8 +2414,15 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t 
afi,
        u_int8_t ndata[7];
 
        if (safi == SAFI_MPLS_VPN)
-         safi = SAFI_MPLS_LABELED_VPN;
-         
+         ndata[2]  = SAFI_MPLS_LABELED_VPN;
+       else if (safi == SAFI_INTERNAL_EVPN)
+         ndata[2] = SAFI_EVPN;
+       else
+         ndata[2] = safi;
+       if (afi == AFI_INTERNAL_L2VPN)
+         ndata[1] = AFI_L2VPN;
+       else
+         ndata[1] = afi;
        ndata[0] = (afi >>  8);
        ndata[1] = afi;
        ndata[2] = safi;
@@ -3324,11 +3337,10 @@ bgp_announce_table (struct peer *peer, afi_t afi, 
safi_t safi,
   struct attr_extra extra;
 
   memset(&extra, 0, sizeof(extra));
-
   if (! table)
     table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi];
 
-  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
+  if (((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != 
SAFI_INTERNAL_EVPN))
       && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
     bgp_default_originate (peer, afi, safi, 0);
 
@@ -3366,7 +3378,7 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t 
safi)
   if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
     return;
 
-  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP))
+  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && ( safi != 
SAFI_INTERNAL_EVPN))
     bgp_announce_table (peer, afi, safi, NULL, 0);
   else
     for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
@@ -3417,7 +3429,7 @@ bgp_soft_reconfig_rsclient (struct peer *rsclient, afi_t 
afi, safi_t safi)
   struct bgp_table *table;
   struct bgp_node *rn;
   
-  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP))
+  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != 
SAFI_INTERNAL_EVPN))
     bgp_soft_reconfig_table_rsclient (rsclient, afi, safi, NULL, NULL);
 
   else
@@ -3477,7 +3489,7 @@ bgp_soft_reconfig_in (struct peer *peer, afi_t afi, 
safi_t safi)
   if (peer->status != Established)
     return;
 
-  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP))
+  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != 
SAFI_INTERNAL_EVPN))
     bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL);
   else
     for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
@@ -3694,7 +3706,8 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t 
safi,
   switch (purpose)
     {
     case BGP_CLEAR_ROUTE_NORMAL:
-      if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP))
+      if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) &&
+          (safi != SAFI_INTERNAL_EVPN))
         bgp_clear_route_table (peer, afi, safi, NULL, NULL, purpose);
       else
         for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
@@ -3859,10 +3872,11 @@ bgp_cleanup_routes (void)
 
   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
     {
+      struct bgp_node *rn;
       for (afi = AFI_IP; afi < AFI_MAX; ++afi)
        {
-         struct bgp_node *rn;
-
+          if(afi == AFI_INTERNAL_L2VPN)
+            continue;
          bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST);
 
          /*
@@ -3892,6 +3906,17 @@ bgp_cleanup_routes (void)
                }
            }
        }
+      for (rn = 
bgp_table_top(bgp->rib[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]); rn;
+           rn = bgp_route_next (rn))
+        {
+          if (rn->info)
+            {
+              bgp_cleanup_table((struct bgp_table *)(rn->info), 
SAFI_INTERNAL_EVPN);
+              bgp_table_finish ((struct bgp_table **)&(rn->info));
+              rn->info = NULL;
+              bgp_unlock_node(rn);
+            }
+        }
     }
 }
 
@@ -4539,7 +4564,6 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
   assert (bgp_static);
 
   rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, &bgp_static->prd);
-
   bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
 
   attr.nexthop = bgp_static->igpnexthop;
@@ -4810,7 +4834,7 @@ bgp_static_delete (struct bgp *bgp)
       for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next 
(rn))
        if (rn->info != NULL)
          {      
-           if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
+           if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == 
SAFI_INTERNAL_EVPN))
              {
                table = rn->info;
 
@@ -5673,7 +5697,7 @@ bgp_aggregate_increment (struct bgp *bgp, struct prefix 
*p,
   struct bgp_table *table;
 
   /* MPLS-VPN aggregation is not yet supported. */
-  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == 
SAFI_INTERNAL_EVPN))
     return;
 
   table = bgp->aggregate[afi][safi];
@@ -5710,7 +5734,7 @@ bgp_aggregate_decrement (struct bgp *bgp, struct prefix 
*p,
   struct bgp_table *table;
 
   /* MPLS-VPN aggregation is not yet supported. */
-  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == 
SAFI_INTERNAL_EVPN))
     return;
 
   table = bgp->aggregate[afi][safi];
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 5fbec0f1a85b..1720fafe9d0a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -8103,6 +8103,8 @@ afi_safi_print (afi_t afi, safi_t safi)
     return "VPN-IPv6 Unicast";
   else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
     return "ENCAP-IPv6 Unicast";
+  else if (afi == AFI_INTERNAL_L2VPN && safi == SAFI_INTERNAL_EVPN)
+    return "EVPN";
   else
     return "Unknown";
 }
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 9e091dd2e04b..bd8ee96c1ce1 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1021,6 +1021,8 @@ peer_as_change (struct peer *peer, as_t as)
                  PEER_FLAG_REFLECTOR_CLIENT);
       UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
                  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN],
+                 PEER_FLAG_REFLECTOR_CLIENT);
     }
 
   /* local-as reset */
@@ -1455,7 +1457,8 @@ peer_group_active (struct peer *peer)
       || peer->af_group[AFI_IP6][SAFI_UNICAST]
       || peer->af_group[AFI_IP6][SAFI_MULTICAST]
       || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
-      || peer->af_group[AFI_IP6][SAFI_ENCAP])
+      || peer->af_group[AFI_IP6][SAFI_ENCAP]
+      || peer->af_group[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN])
     return 1;
   return 0;
 }
@@ -2606,7 +2609,8 @@ peer_active (struct peer *peer)
       || peer->afc[AFI_IP6][SAFI_UNICAST]
       || peer->afc[AFI_IP6][SAFI_MULTICAST]
       || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
-      || peer->afc[AFI_IP6][SAFI_ENCAP])
+      || peer->afc[AFI_IP6][SAFI_ENCAP]
+      || peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN])
     return 1;
   return 0;
 }
@@ -2622,7 +2626,8 @@ peer_active_nego (struct peer *peer)
       || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
       || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
       || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
-      || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
+      || peer->afc_nego[AFI_IP6][SAFI_ENCAP]
+      || peer->afc_nego[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN])
     return 1;
   return 0;
 }
@@ -5577,7 +5582,11 @@ bgp_config_write_family_header (struct vty *vty, afi_t 
afi, safi_t safi,
             vty_out (vty, " multicast");
         }
     }
-
+  else if (afi == AFI_INTERNAL_L2VPN)
+    {
+      if (safi == SAFI_INTERNAL_EVPN)
+       vty_out (vty, "evpn");
+    }
   vty_out (vty, "%s", VTY_NEWLINE);
 
   *write = 1;
@@ -5864,6 +5873,9 @@ bgp_config_write (struct vty *vty)
       /* ENCAPv6 configuration.  */
       write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
 
+      /* EVPN configuration.  */
+      write += bgp_config_write_family (vty, bgp, AFI_INTERNAL_L2VPN, 
SAFI_INTERNAL_EVPN);
+
       vty_out (vty, " exit%s", VTY_NEWLINE);
 
       write++;
-- 
2.1.4


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

Reply via email to