]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: basic support for EVPN
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 5 Sep 2016 08:53:51 +0000 (10:53 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 14 Feb 2017 12:58:57 +0000 (13:58 +0100)
To handle BGP NLRI EVPN messages, bgp is modified to handle AFI_L2VPN
and SAFI_EVPN values.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_open.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_updgrp_adv.c
bgpd/bgp_vty.c
bgpd/bgpd.c

index 7dbb439be1b7342706f716eb51bd6c41aeeb4040..51079f31e03b77be43d733e250f41177cf1226b2 100644 (file)
@@ -93,6 +93,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
                   case AFI_IP6:
                     json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv6");
                   break;
+                  case AFI_L2VPN:
+                    json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "L2VPN");
+                  break;
                   default:
                     json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi));
                   break;
@@ -111,6 +114,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
                   case SAFI_ENCAP:
                     json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "encap");
                   break;
+                  case SAFI_EVPN:
+                    json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "EVPN");
+                  break;
                   default:
                     json_object_int_add(json_cap, "capabilityErrorMultiProtocolSafiUnknown", mpc.safi);
                   break;
@@ -127,6 +133,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
                   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;
@@ -145,6 +154,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
                   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;
@@ -1136,7 +1148,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_L2VPN][SAFI_EVPN])
        {
          zlog_err ("%s [Error] Configured AFI/SAFIs do not "
                    "overlap with received MP capabilities",
index 2df22ab568e9fcbb1c1c648f7f80d8c365c50c02..c7453509faa2caa8e901967982d349133bb3f42b 100644 (file)
@@ -246,13 +246,13 @@ bgp_write_packet (struct peer *peer)
                if (!(PAF_SUBGRP(paf))->t_coalesce &&
                    peer->afc_nego[afi][safi] && peer->synctime
                    && ! CHECK_FLAG (peer->af_sflags[afi][safi],
-                                    PEER_STATUS_EOR_SEND))
+                                    PEER_STATUS_EOR_SEND)
+                    && safi != SAFI_EVPN)
                  {
                    SET_FLAG (peer->af_sflags[afi][safi],
                              PEER_STATUS_EOR_SEND);
                    return bgp_update_packet_eor (peer, afi, safi);
                  }
-
              }
            continue;
          }
index 0123ed17eaa360087cd20f2b1545406adcd92e6f..84c0ee1021cb3752f4208cf03d634967f185a302 100644 (file)
@@ -84,7 +84,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_EVPN))
     {
       prn = bgp_node_get (table, (struct prefix *) prd);
 
@@ -97,7 +98,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_EVPN))
     rn->prn = prn;
 
   return rn;
@@ -3067,7 +3069,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_EVPN))
     bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL);
   else
     for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
@@ -3288,7 +3290,7 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
   if (!peer->clear_node_queue->thread)
     peer_lock (peer);
 
-  if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP)
+  if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
     bgp_clear_route_table (peer, afi, safi, NULL);
   else
     for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
@@ -3421,40 +3423,56 @@ void
 bgp_cleanup_routes (struct bgp *bgp)
 {
   afi_t afi;
+  struct bgp_node *rn;
 
   for (afi = AFI_IP; afi < AFI_MAX; ++afi)
     {
-      struct bgp_node *rn;
-
+      if (afi == AFI_L2VPN)
+        continue;
       bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST);
-
       /*
-       * VPN and ENCAP tables are two-level (RD is top level)
+       * VPN and ENCAP and EVPN tables are two-level (RD is top level)
        */
-      for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn;
-          rn = bgp_route_next (rn))
-       {
-         if (rn->info)
-           {
-             bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_MPLS_VPN);
-             bgp_table_finish ((struct bgp_table **)&(rn->info));
-             rn->info = NULL;
-             bgp_unlock_node(rn);
-           }
-       }
-
-      for (rn = bgp_table_top(bgp->rib[afi][SAFI_ENCAP]); rn;
-          rn = bgp_route_next (rn))
-       {
-         if (rn->info)
-           {
-             bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_ENCAP);
-             bgp_table_finish ((struct bgp_table **)&(rn->info));
-             rn->info = NULL;
-             bgp_unlock_node(rn);
-           }
+      if (afi != AFI_L2VPN)
+        {
+          safi_t safi;
+          safi = SAFI_MPLS_VPN;
+          for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
+               rn = bgp_route_next (rn))
+            {
+              if (rn->info)
+                {
+                  bgp_cleanup_table((struct bgp_table *)(rn->info), safi);
+                  bgp_table_finish ((struct bgp_table **)&(rn->info));
+                  rn->info = NULL;
+                  bgp_unlock_node(rn);
+                }
+            }
+          safi = SAFI_ENCAP;
+          for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
+               rn = bgp_route_next (rn))
+            {
+              if (rn->info)
+                {
+                  bgp_cleanup_table((struct bgp_table *)(rn->info), safi);
+                  bgp_table_finish ((struct bgp_table **)&(rn->info));
+                  rn->info = NULL;
+                  bgp_unlock_node(rn);
+                }
+            }
        }
     }
+  for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn;
+       rn = bgp_route_next (rn))
+    {
+      if (rn->info)
+        {
+          bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_EVPN);
+          bgp_table_finish ((struct bgp_table **)&(rn->info));
+          rn->info = NULL;
+          bgp_unlock_node(rn);
+        }
+    }
 }
 
 void
@@ -4209,7 +4227,7 @@ bgp_static_add (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)
+           if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN))
              {
                table = rn->info;
 
@@ -4243,7 +4261,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_EVPN))
              {
                table = rn->info;
 
@@ -5099,7 +5117,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_EVPN))
     return;
 
   table = bgp->aggregate[afi][safi];
@@ -5136,7 +5154,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_EVPN))
     return;
 
   table = bgp->aggregate[afi][safi];
@@ -5924,7 +5942,7 @@ route_vty_out (struct vty *vty, struct prefix *p,
        * neccessarily the same as the prefix address family.
        * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
        */
-      if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN))
+      if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN))
         {
          if (attr->extra)
             {
@@ -5956,7 +5974,7 @@ route_vty_out (struct vty *vty, struct prefix *p,
             {
               json_nexthop_global = json_object_new_object();
 
-             if (safi == SAFI_MPLS_VPN)
+             if ((safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN))
                 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in));
               else
                 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop));
@@ -5966,7 +5984,7 @@ route_vty_out (struct vty *vty, struct prefix *p,
             }
           else
             {
-             if (safi == SAFI_MPLS_VPN)
+             if ((safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN))
                vty_out (vty, "%-16s",
                          inet_ntoa (attr->extra->mp_nexthop_global_in));
              else
@@ -6180,9 +6198,10 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t
           if (p->family == AF_INET &&
               (safi == SAFI_MPLS_VPN ||
                safi == SAFI_ENCAP ||
+               safi == SAFI_EVPN ||
                !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
             {
-              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
+              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
                 json_object_string_add(json_net, "nextHop", inet_ntoa (attr->extra->mp_nexthop_global_in));
               else
                 json_object_string_add(json_net, "nextHop", inet_ntoa (attr->nexthop));
@@ -6218,9 +6237,10 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t
           if (p->family == AF_INET &&
               (safi == SAFI_MPLS_VPN ||
                safi == SAFI_ENCAP ||
+               safi == SAFI_EVPN ||
                !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
             {
-              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
+              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
                 vty_out (vty, "%-16s",
                          inet_ntoa (attr->extra->mp_nexthop_global_in));
               else
@@ -6307,7 +6327,7 @@ route_vty_out_tag (struct vty *vty, struct prefix *p,
       if (p->family == AF_INET
           && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
        {
-         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
+         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
             {
               if (json)
                 json_object_string_add(json_out, "mpNexthopGlobalIn", inet_ntoa (attr->extra->mp_nexthop_global_in));
@@ -6717,9 +6737,10 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
       if (p->family == AF_INET &&
           (safi == SAFI_MPLS_VPN ||
            safi == SAFI_ENCAP ||
+           safi == SAFI_EVPN ||
            !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
        {
-          if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
+          if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
             {
               if (json_paths)
                 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in));
@@ -7657,9 +7678,9 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
   else
     {
       vty_out (vty, "BGP routing table entry for %s%s%s/%d%s",
-              ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) ?
+              ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) ?
               prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""),
-              safi == SAFI_MPLS_VPN ? ":" : "",
+              ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "",
               inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN),
               p->prefixlen, VTY_NEWLINE);
     }
@@ -7779,7 +7800,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
       json_paths = json_object_new_array();
     }
 
-  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
+  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
     {
       for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn))
         {
@@ -10054,7 +10075,7 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name,
 
   match.family = afi2family (afi);
 
-  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN))
     {
       for (rn = bgp_table_top (bgp->rib[AFI_IP][safi]); rn; rn = bgp_route_next (rn))
         {
index 48f56a29b24fca6591ea522110a6624fad5ecc00..efb2046e1256a7b8e2e6655e0544cc809c1e7ffe 100644 (file)
@@ -605,6 +605,7 @@ subgroup_announce_table (struct update_subgroup *subgrp,
 
   if (safi != SAFI_MPLS_VPN
       && safi != SAFI_ENCAP
+      && safi != SAFI_EVPN
       && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
     subgroup_default_originate (subgrp, 0);
 
@@ -668,7 +669,8 @@ subgroup_announce_route (struct update_subgroup *subgrp)
     return;
 
   if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN &&
-      SUBGRP_SAFI (subgrp) != SAFI_ENCAP)
+      SUBGRP_SAFI (subgrp) != SAFI_ENCAP &&
+      SUBGRP_SAFI (subgrp) != SAFI_EVPN)
     subgroup_announce_table (subgrp, NULL);
   else
     for (rn = bgp_table_top (update_subgroup_rib (subgrp)); rn;
index cca34d0a8569894c1741741e750116b6ad7a6a17..881173d382986ae0a0a982203c14b392ede38637 100644 (file)
@@ -6834,6 +6834,8 @@ afi_safi_print (afi_t afi, safi_t safi)
     return "IPv6 VPN";
   else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
     return "IPv6 Encap";
+  else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
+    return "L2VPN EVPN";
   else
     return "Unknown";
 }
@@ -6857,6 +6859,8 @@ afi_safi_json (afi_t afi, safi_t safi)
     return "IPv6VPN";
   else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
     return "IPv6Encap";
+  else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
+    return "L2VPN EVPN";
   else
     return "Unknown";
 }
index fc6968e9d9a4ce103d9d14740a04d4ab7665e259..1cad7c5a152c0d0ff9ef33d5c1c1d0e4be2e8900 100644 (file)
@@ -1643,6 +1643,8 @@ peer_as_change (struct peer *peer, as_t as, int as_specified)
                  PEER_FLAG_REFLECTOR_CLIENT);
       UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
                  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_L2VPN][SAFI_EVPN],
+                 PEER_FLAG_REFLECTOR_CLIENT);
     }
 
   /* local-as reset */
@@ -7217,7 +7219,11 @@ bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
       else if (safi == SAFI_ENCAP)
         vty_out (vty, "ipv6 encap");
     }
-
+  else if (afi == AFI_L2VPN)
+    {
+      if (safi == SAFI_EVPN)
+       vty_out (vty, "evpn");
+    }
   vty_out (vty, "%s", VTY_NEWLINE);
 
   *write = 1;
@@ -7518,6 +7524,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_L2VPN, SAFI_EVPN);
+
 #if ENABLE_BGP_VNC
       write += bgp_rfapi_cfg_write(vty, bgp);
 #endif