]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: encap: add encap SAFI (RFC5512)
authorLou Berger <lberger@labn.net>
Tue, 12 Jan 2016 18:42:02 +0000 (13:42 -0500)
committervivek <vivek@cumulusnetworks.com>
Sat, 11 Jun 2016 22:36:42 +0000 (15:36 -0700)
Adds RFC5512 and Encapsulation Attribute.

Signed-off-by: Lou Berger <lberger@labn.net>
(cherry picked from commit 298cc2f688dbadf0a447fcd06ae8e20fa5006ce4)

Conflicts:
bgpd/Makefile.am
bgpd/bgp_attr.c
bgpd/bgp_open.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_vty.c
bgpd/bgpd.c

13 files changed:
bgpd/Makefile.am
bgpd/bgp_attr.c
bgpd/bgp_encap.c [new file with mode: 0644]
bgpd/bgp_encap.h [new file with mode: 0644]
bgpd/bgp_encap_tlv.c
bgpd/bgp_encap_types.h
bgpd/bgp_open.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_updgrp_adv.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 9183734a3c5992bc51c0a0d7d899d5b536b4ba32..5176a8e048494221430e6d78590ec84285a9de92 100644 (file)
@@ -17,7 +17,7 @@ libbgp_a_SOURCES = \
        bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
        bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
         bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
-       bgp_encap_tlv.c
+       bgp_encap.c bgp_encap_tlv.c
 
 noinst_HEADERS = \
        bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
@@ -25,7 +25,7 @@ noinst_HEADERS = \
        bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
        bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
        bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \
-        bgp_updgrp.h bgp_bfd.h bgp_encap_tlv.h bgp_encap_types.h
+        bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h
 
 bgpd_SOURCES = bgp_main.c
 bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
index 0d828dc7dcda60481b22f09e22199fc5c0964a44..ef1d02ecaf2fe69d9e84af6cc93b990d1b74ac20 100644 (file)
@@ -1950,9 +1950,11 @@ bgp_attr_encap(
     uint16_t   sublength;
     struct bgp_attr_encap_subtlv *tlv;
 
-    subtype = stream_getw (BGP_INPUT (peer));
-    sublength = stream_getw (BGP_INPUT (peer));
-    length -= 4;
+    if (BGP_ATTR_ENCAP == type) {
+        subtype   = stream_getc (BGP_INPUT (peer));
+        sublength = stream_getc (BGP_INPUT (peer));
+        length   -= 2;
+    }
 
     if (sublength > length) {
       zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
@@ -2470,6 +2472,10 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
          stream_putl (s, 0);
          stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
          break;
+       case SAFI_ENCAP:
+         stream_putc (s, 4);
+         stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
+         break;
        default:
          break;
        }
@@ -2512,6 +2518,11 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
           }
         }
        break;
+       case SAFI_ENCAP:
+          assert (attr->extra);
+          stream_putc (s, IPV6_MAX_BYTELEN);
+         stream_put (s, &attr->extra->mp_nexthop_global, IPV6_MAX_BYTELEN);
+         break;
       default:
        break;
       }
@@ -2555,7 +2566,6 @@ bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
   return size;
 }
 
-#if 0
 /*
  * Encodes the tunnel encapsulation attribute
  */
@@ -2568,6 +2578,7 @@ bgp_packet_mpattr_tea(
     uint8_t            attrtype)
 {
     unsigned int                       attrlenfield = 0;
+    unsigned int                       attrhdrlen   = 0;
     struct bgp_attr_encap_subtlv       *subtlvs;
     struct bgp_attr_encap_subtlv       *st;
     const char                         *attrname;
@@ -2587,6 +2598,7 @@ bgp_packet_mpattr_tea(
             * V = concatenated subtlvs.
             */
            attrlenfield = 2 + 2;       /* T + L */
+            attrhdrlen   = 1 + 1;      /* subTLV T + L */
            break;
 
        default:
@@ -2594,15 +2606,15 @@ bgp_packet_mpattr_tea(
     }
 
 
+    /* if no tlvs, don't make attr */
+    if (subtlvs == NULL)
+       return;
+
     /* compute attr length */
     for (st = subtlvs; st; st = st->next) {
-       attrlenfield += (4 + st->length);
+       attrlenfield += (attrhdrlen + st->length);
     }
 
-    /* if no tlvs, don't make attr */
-    if (!attrlenfield)
-       return;
-
     if (attrlenfield > 0xffff) {
        zlog_info ("%s attribute is too long (length=%d), can't send it",
            attrname,
@@ -2631,12 +2643,13 @@ bgp_packet_mpattr_tea(
 
     /* write each sub-tlv */
     for (st = subtlvs; st; st = st->next) {
-       stream_putw (s, st->type);
-       stream_putw (s, st->length);
+        if (attrtype == BGP_ATTR_ENCAP) {
+            stream_putc (s, st->type);
+            stream_putc (s, st->length);
+        }
        stream_put (s, st->value, st->length);
     }
 }
-#endif
 
 void
 bgp_packet_mpattr_end (struct stream *s, size_t sizep)
@@ -3016,7 +3029,14 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
       stream_putl (s, attr->extra->aggregator_as);
       stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr);
     }
-  
+
+  if ((afi == AFI_IP || afi == AFI_IP6) &&
+      (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
+    {
+       /* Tunnel Encap attribute */
+       bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
+    }
+
   /* Unknown transit attribute. */
   if (attr->extra && attr->extra->transit)
     stream_put (s, attr->extra->transit->val, attr->extra->transit->length);
diff --git a/bgpd/bgp_encap.c b/bgpd/bgp_encap.c
new file mode 100644 (file)
index 0000000..2186b21
--- /dev/null
@@ -0,0 +1,992 @@
+
+/*
+ * This file created by LabN Consulting, L.L.C.
+ *
+ *
+ * This file is based on bgp_mplsvpn.c which is Copyright (C) 2000
+ * Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ */
+
+/* 
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "prefix.h"
+#include "log.h"
+#include "memory.h"
+#include "stream.h"
+#include "filter.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_encap.h"
+
+static u_int16_t
+decode_rd_type (u_char *pnt)
+{
+  u_int16_t v;
+  
+  v = ((u_int16_t) *pnt++ << 8);
+  v |= (u_int16_t) *pnt;
+  return v;
+}
+
+
+static void
+decode_rd_as (u_char *pnt, struct rd_as *rd_as)
+{
+  rd_as->as  = (u_int16_t) *pnt++ << 8;
+  rd_as->as |= (u_int16_t) *pnt++;
+  
+  rd_as->val  = ((u_int32_t) *pnt++) << 24;
+  rd_as->val |= ((u_int32_t) *pnt++) << 16;
+  rd_as->val |= ((u_int32_t) *pnt++) << 8;
+  rd_as->val |= (u_int32_t) *pnt;
+}
+
+static void
+decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
+{
+  rd_as->as  = (u_int32_t) *pnt++ << 24;
+  rd_as->as |= (u_int32_t) *pnt++ << 16;
+  rd_as->as |= (u_int32_t) *pnt++ << 8;
+  rd_as->as |= (u_int32_t) *pnt++;
+  
+  rd_as->val  = ((u_int32_t) *pnt++ << 8);
+  rd_as->val |= (u_int32_t) *pnt;
+}
+
+static void
+decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
+{
+  memcpy (&rd_ip->ip, pnt, 4);
+  pnt += 4;
+  
+  rd_ip->val = ((u_int16_t) *pnt++ << 8);
+  rd_ip->val |= (u_int16_t) *pnt;
+}
+
+static void
+ecom2prd(struct ecommunity *ecom, struct prefix_rd *prd)
+{
+    int        i;
+
+    memset(prd, 0, sizeof(struct prefix_rd));
+    prd->family = AF_UNSPEC;
+    prd->prefixlen = 64;
+
+    if (!ecom)
+       return;
+
+    for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE) {
+
+       uint8_t *ep;
+
+       ep = ecom->val + i;
+
+       switch (ep[0]) {
+           default:
+               continue;
+
+           case 0x80:
+           case 0x81:
+           case 0x82:
+               if (ep[1] == 0x0) {
+                   prd->val[1] = ep[0] & 0x03;
+                   memcpy(prd->val + 2, ep + 2, 6);
+                   return;
+               }
+       }
+    }
+}
+
+int
+bgp_nlri_parse_encap(
+    afi_t              afi,
+    struct peer                *peer,
+    struct attr                *attr,          /* Need even for withdraw */
+    struct bgp_nlri    *packet,
+    int                        withdraw)       /* 0=update, !0 = withdraw */
+{
+  u_char *pnt;
+  u_char *lim;
+  struct prefix p;
+  int psize = 0;
+  int prefixlen;
+  struct rd_as rd_as;
+  struct rd_ip rd_ip;
+  struct prefix_rd prd;
+  struct ecommunity *pEcom = NULL;
+  u_int16_t rdtype = 0xffff;
+  char buf[BUFSIZ];
+
+  /* Check peer status. */
+  if (peer->status != Established)
+    return 0;
+  
+  /* Make prefix_rd */
+  if (attr && attr->extra && attr->extra->ecommunity)
+      pEcom = attr->extra->ecommunity;
+
+  ecom2prd(pEcom, &prd);
+  memset(&rd_as, 0, sizeof(rd_as));
+  memset(&rd_ip, 0, sizeof(rd_ip));
+
+  if (pEcom) {
+
+      rdtype = (prd.val[0] << 8) | prd.val[1];
+
+      /* Decode RD value. */
+      if (rdtype == RD_TYPE_AS)
+       decode_rd_as (prd.val + 2, &rd_as);
+      else if (rdtype == RD_TYPE_IP)
+       decode_rd_ip (prd.val + 2, &rd_ip);
+      else if (rdtype == RD_TYPE_AS4)
+       decode_rd_as4 (prd.val + 2, &rd_as);
+      else
+       {
+         zlog_err ("Invalid RD type %d", rdtype);
+       }
+
+  }
+
+  /*
+   * NB: this code was based on the MPLS VPN code, which supported RDs.
+   * For the moment we are retaining the underlying RIB structure that
+   * keeps a per-RD radix tree, but since the RDs are not carried over
+   * the wire, we set the RD internally to 0.
+   */
+  prd.family = AF_UNSPEC;
+  prd.prefixlen = 64;
+  memset(prd.val, 0, sizeof(prd.val));
+
+  pnt = packet->nlri;
+  lim = pnt + packet->length;
+
+  for (; pnt < lim; pnt += psize)
+    {
+      /* Clear prefix structure. */
+      memset (&p, 0, sizeof (struct prefix));
+
+      /* Fetch prefix length. */
+      prefixlen = *pnt++;
+      p.family = afi2family(afi);
+      if (p.family == 0) {
+       /* bad afi, shouldn't happen */
+       zlog_warn("%s: bad afi %d, dropping incoming route", __func__, afi);
+       continue;
+      }
+      psize = PSIZE (prefixlen);
+
+      p.prefixlen = prefixlen;
+      memcpy (&p.u.prefix, pnt, psize);
+
+      if (pnt + psize > lim)
+       return -1;
+
+
+      if (rdtype == RD_TYPE_AS)
+       zlog_info ("rd-as %u:%u prefix %s/%d", rd_as.as, rd_as.val,
+                  inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
+                  p.prefixlen);
+      else if (rdtype == RD_TYPE_IP)
+       zlog_info ("rd-ip %s:%u prefix %s/%d", inet_ntoa (rd_ip.ip),
+                  rd_ip.val,
+                  inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
+                  p.prefixlen);
+      else if (rdtype == RD_TYPE_AS4)
+       zlog_info ("rd-as4 %u:%u prefix %s/%d", rd_as.as, rd_as.val,
+                  inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
+                  p.prefixlen);
+      else
+       zlog_info ("rd unknown, default to 0:0 prefix %s/%d",
+           inet_ntop (p.family, &p.u.prefix, buf, BUFSIZ),
+           p.prefixlen);
+
+      if (!withdraw) {
+       bgp_update (peer, &p, 0, attr, afi, SAFI_ENCAP,
+                   ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0);
+      } else {
+       bgp_withdraw (peer, &p, 0, attr, afi, SAFI_ENCAP,
+                     ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL);
+      }
+    }
+
+  /* Packet length consistency check. */
+  if (pnt != lim)
+    return -1;
+
+  return 0;
+}
+
+
+/* TBD: these routes should probably all be host routes */
+
+/* For testing purpose, static route of ENCAP. */
+DEFUN (encap_network,
+       encap_network_cmd,
+       "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify Route Distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "BGP tag\n"
+       "tag value\n")
+{
+  return bgp_static_set_safi (SAFI_ENCAP, vty, argv[0], argv[1], argv[2], NULL);
+}
+
+/* For testing purpose, static route of ENCAP. */
+DEFUN (no_encap_network,
+       no_encap_network_cmd,
+       "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify Route Distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "BGP tag\n"
+       "tag value\n")
+{
+  return bgp_static_unset_safi (SAFI_ENCAP, vty, argv[0], argv[1], argv[2]);
+}
+
+static int
+show_adj_route_encap (struct vty *vty, struct peer *peer, struct prefix_rd *prd)
+{
+  struct bgp *bgp;
+  struct bgp_table *table;
+  struct bgp_node *rn;
+  struct bgp_node *rm;
+  struct attr *attr;
+  int rd_header;
+  int header = 1;
+  char v4_header[] = "   Network          Next Hop            Metric LocPrf Weight Path%s";
+
+  bgp = bgp_get_default ();
+  if (bgp == NULL)
+    {
+      vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_ENCAP]); rn;
+       rn = bgp_route_next (rn))
+    {
+      if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+        continue;
+
+      if ((table = rn->info) != NULL)
+        {
+          rd_header = 1;
+
+          for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
+            if ((attr = rm->info) != NULL)
+              {
+                if (header)
+                  {
+                    vty_out (vty, "BGP table version is 0, local router ID is %s%s",
+                             inet_ntoa (bgp->router_id), VTY_NEWLINE);
+                    vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
+                             VTY_NEWLINE);
+                    vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
+                             VTY_NEWLINE, VTY_NEWLINE);
+                    vty_out (vty, v4_header, VTY_NEWLINE);
+                    header = 0;
+                  }
+
+                if (rd_header)
+                  {
+                    u_int16_t type;
+                    struct rd_as rd_as;
+                    struct rd_ip rd_ip;
+                    u_char *pnt;
+
+                    pnt = rn->p.u.val;
+
+                    vty_out (vty, "Route Distinguisher: ");
+
+                    /* Decode RD type. */
+                    type = decode_rd_type (pnt);
+
+                   switch (type) {
+
+                   case RD_TYPE_AS:
+                      decode_rd_as (pnt + 2, &rd_as);
+                      vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
+                     break;
+
+                   case RD_TYPE_IP:
+                      decode_rd_ip (pnt + 2, &rd_ip);
+                      vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
+                     break;
+
+                   default:
+                      vty_out (vty, "unknown RD type");
+                   }
+
+
+                    vty_out (vty, "%s", VTY_NEWLINE);
+                    rd_header = 0;
+                  }
+                route_vty_out_tmp (vty, &rm->p, attr, SAFI_ENCAP, 0, NULL);
+              }
+        }
+    }
+  return CMD_SUCCESS;
+}
+
+enum bgp_show_type
+{
+  bgp_show_type_normal,
+  bgp_show_type_regexp,
+  bgp_show_type_prefix_list,
+  bgp_show_type_filter_list,
+  bgp_show_type_neighbor,
+  bgp_show_type_cidr_only,
+  bgp_show_type_prefix_longer,
+  bgp_show_type_community_all,
+  bgp_show_type_community,
+  bgp_show_type_community_exact,
+  bgp_show_type_community_list,
+  bgp_show_type_community_list_exact
+};
+
+static int
+bgp_show_encap (
+    struct vty *vty,
+    afi_t afi,
+    struct prefix_rd *prd,
+    enum bgp_show_type type,
+    void *output_arg,
+    int tags)
+{
+  struct bgp *bgp;
+  struct bgp_table *table;
+  struct bgp_node *rn;
+  struct bgp_node *rm;
+  struct bgp_info *ri;
+  int rd_header;
+  int header = 1;
+  char v4_header[] = "   Network          Next Hop            Metric LocPrf Weight Path%s";
+  char v4_header_tag[] = "   Network          Next Hop      In tag/Out tag%s";
+
+  unsigned long output_count = 0;
+  unsigned long total_count  = 0;
+
+  bgp = bgp_get_default ();
+  if (bgp == NULL)
+    {
+      vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if ((afi != AFI_IP) && (afi != AFI_IP6)) {
+      vty_out (vty, "Afi %d not supported%s", afi, VTY_NEWLINE);
+      return CMD_WARNING;
+  }
+  
+  for (rn = bgp_table_top (bgp->rib[afi][SAFI_ENCAP]); rn; rn = bgp_route_next (rn))
+    {
+      if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+       continue;
+
+      if ((table = rn->info) != NULL)
+       {
+         rd_header = 1;
+
+         for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
+           for (ri = rm->info; ri; ri = ri->next)
+             {
+                total_count++;
+               if (type == bgp_show_type_neighbor)
+                 {
+                   union sockunion *su = output_arg;
+
+                   if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
+                     continue;
+                 }
+               if (header)
+                 {
+                   if (tags)
+                     vty_out (vty, v4_header_tag, VTY_NEWLINE);
+                   else
+                     {
+                       vty_out (vty, "BGP table version is 0, local router ID is %s%s",
+                                inet_ntoa (bgp->router_id), VTY_NEWLINE);
+                       vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
+                                VTY_NEWLINE);
+                       vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
+                                VTY_NEWLINE, VTY_NEWLINE);
+                       vty_out (vty, v4_header, VTY_NEWLINE);
+                     }
+                   header = 0;
+                 }
+
+               if (rd_header)
+                 {
+                   u_int16_t type;
+                   struct rd_as rd_as;
+                   struct rd_ip rd_ip;
+                   u_char *pnt;
+
+                   pnt = rn->p.u.val;
+
+                   /* Decode RD type. */
+                   type = decode_rd_type (pnt);
+
+                   vty_out (vty, "Route Distinguisher: ");
+
+                   switch (type) {
+
+                   case RD_TYPE_AS:
+                     decode_rd_as (pnt + 2, &rd_as);
+                     vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
+                     break;
+
+                   case RD_TYPE_IP:
+                     decode_rd_ip (pnt + 2, &rd_ip);
+                     vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
+                     break;
+
+                   default:
+                     vty_out (vty, "Unknown RD type");
+                     break;
+                   }
+
+                   vty_out (vty, "%s", VTY_NEWLINE);             
+                   rd_header = 0;
+                 }
+               if (tags)
+                 route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_ENCAP, NULL);
+               else
+                 route_vty_out (vty, &rm->p, ri, 0, SAFI_ENCAP, NULL);
+                output_count++;
+             }
+        }
+    }
+
+  if (output_count == 0)
+    {
+        vty_out (vty, "No prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE);
+    }
+  else
+    vty_out (vty, "%sDisplayed %ld out of %ld total prefixes%s",
+            VTY_NEWLINE, output_count, total_count, VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_bgp_ipv4_encap,
+       show_bgp_ipv4_encap_cmd,
+       "show bgp ipv4 encap",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n")
+{
+  return bgp_show_encap (vty, AFI_IP, NULL, bgp_show_type_normal, NULL, 0);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap,
+       show_bgp_ipv6_encap_cmd,
+       "show bgp ipv6 encap",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n")
+{
+  return bgp_show_encap (vty, AFI_IP6, NULL, bgp_show_type_normal, NULL, 0);
+}
+#endif
+
+DEFUN (show_bgp_ipv4_encap_rd,
+       show_bgp_ipv4_encap_rd_cmd,
+       "show bgp ipv4 encap rd ASN:nn_or_IP-address:nn",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_encap (vty, AFI_IP, &prd, bgp_show_type_normal, NULL, 0);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap_rd,
+       show_bgp_ipv6_encap_rd_cmd,
+       "show bgp ipv6 encap rd ASN:nn_or_IP-address:nn",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "Display BGP tags for prefixes\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_encap (vty, AFI_IP6, &prd, bgp_show_type_normal, NULL, 0);
+}
+#endif
+
+DEFUN (show_bgp_ipv4_encap_tags,
+       show_bgp_ipv4_encap_tags_cmd,
+       "show bgp ipv4 encap tags",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display BGP tags for prefixes\n")
+{
+  return bgp_show_encap (vty, AFI_IP, NULL, bgp_show_type_normal, NULL,  1);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap_tags,
+       show_bgp_ipv6_encap_tags_cmd,
+       "show bgp ipv6 encap tags",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display BGP tags for prefixes\n")
+{
+  return bgp_show_encap (vty, AFI_IP6, NULL, bgp_show_type_normal, NULL,  1);
+}
+#endif
+
+DEFUN (show_bgp_ipv4_encap_rd_tags,
+       show_bgp_ipv4_encap_rd_tags_cmd,
+       "show bgp ipv4 encap rd ASN:nn_or_IP-address:nn tags",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "Display BGP tags for prefixes\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_encap (vty, AFI_IP, &prd, bgp_show_type_normal, NULL, 1);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap_rd_tags,
+       show_bgp_ipv6_encap_rd_tags_cmd,
+       "show bgp ipv6 encap rd ASN:nn_or_IP-address:nn tags",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "Display BGP tags for prefixes\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_encap (vty, AFI_IP6, &prd, bgp_show_type_normal, NULL, 1);
+}
+#endif
+
+DEFUN (show_bgp_ipv4_encap_neighbor_routes,
+       show_bgp_ipv4_encap_neighbor_routes_cmd,
+       "show bgp ipv4 encap neighbors A.B.C.D routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  union sockunion *su;
+  struct peer *peer;
+  
+  su = sockunion_str2su (argv[0]);
+  if (su == NULL)
+    {
+      vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
+               return CMD_WARNING;
+    }
+
+  peer = peer_lookup (NULL, su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_encap (vty, AFI_IP, NULL, bgp_show_type_neighbor, su, 0);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap_neighbor_routes,
+       show_bgp_ipv6_encap_neighbor_routes_cmd,
+       "show bgp ipv6 encap neighbors A.B.C.D routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  union sockunion *su;
+  struct peer *peer;
+  
+  su = sockunion_str2su (argv[0]);
+  if (su == NULL)
+    {
+      vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
+               return CMD_WARNING;
+    }
+
+  peer = peer_lookup (NULL, su);
+  if (! peer || ! peer->afc[AFI_IP6][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_encap (vty, AFI_IP6, NULL, bgp_show_type_neighbor, su, 0);
+}
+#endif
+
+DEFUN (show_bgp_ipv4_encap_rd_neighbor_routes,
+       show_bgp_ipv4_encap_rd_neighbor_routes_cmd,
+       "show bgp ipv4 encap rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  int ret;
+  union sockunion *su;
+  struct peer *peer;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  su = sockunion_str2su (argv[1]);
+  if (su == NULL)
+    {
+      vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE);
+               return CMD_WARNING;
+    }
+
+  peer = peer_lookup (NULL, su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_encap (vty, AFI_IP, &prd, bgp_show_type_neighbor, su, 0);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap_rd_neighbor_routes,
+       show_bgp_ipv6_encap_rd_neighbor_routes_cmd,
+       "show bgp ipv6 encap rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  int ret;
+  union sockunion *su;
+  struct peer *peer;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  su = sockunion_str2su (argv[1]);
+  if (su == NULL)
+    {
+      vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE);
+               return CMD_WARNING;
+    }
+
+  peer = peer_lookup (NULL, su);
+  if (! peer || ! peer->afc[AFI_IP6][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_encap (vty, AFI_IP6, &prd, bgp_show_type_neighbor, su, 0);
+}
+#endif
+
+DEFUN (show_bgp_ipv4_encap_neighbor_advertised_routes,
+       show_bgp_ipv4_encap_neighbor_advertised_routes_cmd,
+       "show bgp ipv4 encap neighbors A.B.C.D advertised-routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  int ret;
+  struct peer *peer;
+  union sockunion su;
+
+  ret = str2sockunion (argv[0], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  peer = peer_lookup (NULL, &su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return show_adj_route_encap (vty, peer, NULL);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap_neighbor_advertised_routes,
+       show_bgp_ipv6_encap_neighbor_advertised_routes_cmd,
+       "show bgp ipv6 encap neighbors A.B.C.D advertised-routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  int ret;
+  struct peer *peer;
+  union sockunion su;
+
+  ret = str2sockunion (argv[0], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  peer = peer_lookup (NULL, &su);
+  if (! peer || ! peer->afc[AFI_IP6][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return show_adj_route_encap (vty, peer, NULL);
+}
+#endif
+
+DEFUN (show_bgp_ipv4_encap_rd_neighbor_advertised_routes,
+       show_bgp_ipv4_encap_rd_neighbor_advertised_routes_cmd,
+       "show bgp ipv4 encap rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  int ret;
+  struct peer *peer;
+  struct prefix_rd prd;
+  union sockunion su;
+
+  ret = str2sockunion (argv[1], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", argv[1], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  peer = peer_lookup (NULL, &su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return show_adj_route_encap (vty, peer, &prd);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_ipv6_encap_rd_neighbor_advertised_routes,
+       show_bgp_ipv6_encap_rd_neighbor_advertised_routes_cmd,
+       "show bgp ipv6 encap rd ASN:nn_or_IP-address:nn neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       BGP_STR
+       "Address Family\n"
+       "Display ENCAP NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "ENCAP Route Distinguisher\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  int ret;
+  struct peer *peer;
+  struct prefix_rd prd;
+  union sockunion su;
+
+  ret = str2sockunion (argv[1], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", argv[1], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  peer = peer_lookup (NULL, &su);
+  if (! peer || ! peer->afc[AFI_IP6][SAFI_ENCAP])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return show_adj_route_encap (vty, peer, &prd);
+}
+#endif
+
+void
+bgp_encap_init (void)
+{
+  //install_element (BGP_ENCAP_NODE, &encap_network_cmd);
+  //install_element (BGP_ENCAP_NODE, &no_encap_network_cmd);
+
+
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_rd_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_tags_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_rd_tags_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_rd_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_neighbor_advertised_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv4_encap_rd_neighbor_advertised_routes_cmd);
+
+#ifdef HAVE_IPV6
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_rd_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_tags_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_rd_tags_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_rd_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_neighbor_advertised_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_encap_rd_neighbor_advertised_routes_cmd);
+#endif
+
+
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_rd_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_tags_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_rd_tags_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_rd_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_neighbor_advertised_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv4_encap_rd_neighbor_advertised_routes_cmd);
+
+#ifdef HAVE_IPV6
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_rd_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_tags_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_rd_tags_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_rd_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_neighbor_advertised_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_encap_rd_neighbor_advertised_routes_cmd);
+#endif
+
+
+}
diff --git a/bgpd/bgp_encap.h b/bgpd/bgp_encap.h
new file mode 100644 (file)
index 0000000..6f43b7b
--- /dev/null
@@ -0,0 +1,34 @@
+/* 
+ *
+ * Copyright 2009-2015, LabN Consulting, L.L.C.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef _QUAGGA_BGP_ENCAP_H
+#define _QUAGGA_BGP_ENCAP_H
+
+extern void bgp_encap_init (void);
+extern int bgp_nlri_parse_encap (
+    afi_t,
+    struct peer *,
+    struct attr *,
+    struct bgp_nlri *,
+    int withdraw);
+
+#include "bgp_encap_types.h"
+#endif /* _QUAGGA_BGP_ENCAP_H */
index 058b41eb562ecab94ea949691d3a168fac3dcc7b..347b4b3ce72c70ab29581e37b58c1b0b165e7bc6 100644 (file)
@@ -196,6 +196,34 @@ subtlv_encode_ipsec_ta(
     return new;
 }
 
+/* draft-rosen-idr-tunnel-encaps 2.1 */
+static struct bgp_attr_encap_subtlv *
+subtlv_encode_remote_endpoint(
+    struct bgp_tea_subtlv_remote_endpoint      *st)
+{
+    struct bgp_attr_encap_subtlv       *new;
+    uint8_t                            *p;
+    
+    int        total = (st->family==AF_INET?8:20);
+
+    assert(total <= 0xff);
+
+    new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total);
+    assert(new);
+    new->type = BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT;
+    new->length = total;
+    p = new->value;
+    if (st->family == AF_INET) {
+        memcpy (p, &(st->ip_address.v4.s_addr), 4);
+        p+=4;
+    } else {
+        assert (st->family == AF_INET6);
+        memcpy (p, &(st->ip_address.v6.s6_addr), 16);
+        p+=16;
+    }
+    memcpy (p, &(st->as4), 4);
+    return new;
+}
 
 /***********************************************************************
  *             TUNNEL TYPE-SPECIFIC TLV ENCODE
@@ -235,6 +263,7 @@ bgp_encap_type_l2tpv3overip_to_tlv(
     ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_l2tpv3_over_ip, st_encap);
     ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto);
     ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color);
+    ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, subtlv_encode_remote_endpoint, st_endpoint);
 }
 
 void
@@ -253,6 +282,7 @@ bgp_encap_type_gre_to_tlv(
     ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_gre, st_encap);
     ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto);
     ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color);
+    ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, subtlv_encode_remote_endpoint, st_endpoint);
 }
 
 void
@@ -270,6 +300,7 @@ bgp_encap_type_ip_in_ip_to_tlv(
 
     ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto);
     ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color);
+    ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, subtlv_encode_remote_endpoint, st_endpoint);
 }
 
 void
@@ -542,6 +573,36 @@ subtlv_decode_ipsec_ta(
     return 0;
 }
 
+/* draft-rosen-idr-tunnel-encaps 2.1 */
+static int
+subtlv_decode_remote_endpoint(
+    struct bgp_attr_encap_subtlv         *subtlv,
+    struct bgp_tea_subtlv_remote_endpoint *st)
+{
+   int i;
+   if (subtlv->length != 8 && subtlv->length != 20 ) {
+       zlog_debug("%s, subtlv length %d does not equal 8 or 20",
+           __func__, subtlv->length);
+       return -1;
+    }
+    if (subtlv->length == 8) {
+        st->family = AF_INET;
+        st->ip_address.v4.s_addr = ((subtlv->value[0] << 24) |
+                                    (subtlv->value[1] << 16) |
+                                    (subtlv->value[2] << 8)  |
+                                    subtlv->value[3]);
+    } else {
+        st->family = AF_INET6;
+        memcpy (&(st->ip_address.v6.s6_addr), subtlv->value, 16);
+    }
+    i = subtlv->length - 4;
+    st->as4 = ((subtlv->value[i] << 24) |
+               (subtlv->value[i+1] << 16) |
+               (subtlv->value[i+2] << 8)  |
+               subtlv->value[i+3]);
+    return 0;
+}
+
 /***********************************************************************
  *             TUNNEL TYPE-SPECIFIC TLV DECODE
  ***********************************************************************/
@@ -558,17 +619,22 @@ tlv_to_bgp_encap_type_l2tpv3overip(
        switch (st->type) {
            case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION:
                rc |= subtlv_decode_encap_l2tpv3_over_ip(st, &bet->st_encap);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_ENCAP;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP);
                break;
 
            case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE:
                rc |= subtlv_decode_proto_type(st, &bet->st_proto);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_PROTO_TYPE;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE);
                break;
 
            case BGP_ENCAP_SUBTLV_TYPE_COLOR:
                rc |= subtlv_decode_color(st, &bet->st_color);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_COLOR;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR);
+               break;
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
                break;
 
            default:
@@ -592,17 +658,22 @@ tlv_to_bgp_encap_type_gre(
        switch (st->type) {
            case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION:
                rc |= subtlv_decode_encap_gre(st, &bet->st_encap);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_ENCAP;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP);
                break;
 
            case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE:
                rc |= subtlv_decode_proto_type(st, &bet->st_proto);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_PROTO_TYPE;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE);
                break;
 
            case BGP_ENCAP_SUBTLV_TYPE_COLOR:
                rc |= subtlv_decode_color(st, &bet->st_color);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_COLOR;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR);
+               break;
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
                break;
 
            default:
@@ -626,12 +697,17 @@ tlv_to_bgp_encap_type_ip_in_ip(
        switch (st->type) {
            case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE:
                rc |= subtlv_decode_proto_type(st, &bet->st_proto);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_PROTO_TYPE;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE);
                break;
 
            case BGP_ENCAP_SUBTLV_TYPE_COLOR:
                rc |= subtlv_decode_color(st, &bet->st_color);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_COLOR;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR);
+               break;
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
                break;
 
            default:
@@ -653,6 +729,12 @@ tlv_to_bgp_encap_type_transmit_tunnel_endpoint(
 
     for (st = stlv; st; st = st->next) {
        switch (st->type) {
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
+               break;
+
            default:
                zlog_debug("%s: unexpected subtlv type %d", __func__, st->type);
                rc |= -1;
@@ -674,7 +756,12 @@ tlv_to_bgp_encap_type_ipsec_in_tunnel_mode(
        switch (st->type) {
            case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA:
                rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_IPSEC_TA;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA);
+               break;
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
                break;
 
            default:
@@ -698,7 +785,12 @@ tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode(
        switch (st->type) {
            case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA:
                rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_IPSEC_TA;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA);
+               break;
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
                break;
 
            default:
@@ -722,7 +814,12 @@ tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode(
        switch (st->type) {
            case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA:
                rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_IPSEC_TA;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA);
+               break;
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
                break;
 
            default:
@@ -744,6 +841,12 @@ tlv_to_bgp_encap_type_vxlan(
 
     for (st = stlv; st; st = st->next) {
        switch (st->type) {
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
+               break;
+
            default:
                zlog_debug("%s: unexpected subtlv type %d", __func__, st->type);
                rc |= -1;
@@ -763,6 +866,12 @@ tlv_to_bgp_encap_type_nvgre(
 
     for (st = stlv; st; st = st->next) {
        switch (st->type) {
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
+               break;
+
            default:
                zlog_debug("%s: unexpected subtlv type %d", __func__, st->type);
                rc |= -1;
@@ -782,6 +891,12 @@ tlv_to_bgp_encap_type_mpls(
 
     for (st = stlv; st; st = st->next) {
        switch (st->type) {
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
+               break;
+
            default:
                zlog_debug("%s: unexpected subtlv type %d", __func__, st->type);
                rc |= -1;
@@ -801,6 +916,12 @@ tlv_to_bgp_encap_type_mpls_in_gre(
 
     for (st = stlv; st; st = st->next) {
        switch (st->type) {
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
+               break;
+
            default:
                zlog_debug("%s: unexpected subtlv type %d", __func__, st->type);
                rc |= -1;
@@ -820,6 +941,12 @@ tlv_to_bgp_encap_type_vxlan_gpe(
 
     for (st = stlv; st; st = st->next) {
        switch (st->type) {
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
+               break;
+
            default:
                zlog_debug("%s: unexpected subtlv type %d", __func__, st->type);
                rc |= -1;
@@ -839,6 +966,12 @@ tlv_to_bgp_encap_type_mpls_in_udp(
 
     for (st = stlv; st; st = st->next) {
        switch (st->type) {
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
+               break;
+
            default:
                zlog_debug("%s: unexpected subtlv type %d", __func__, st->type);
                rc |= -1;
@@ -860,7 +993,12 @@ tlv_to_bgp_encap_type_pbb(
        switch (st->type) {
            case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION:
                rc |= subtlv_decode_encap_pbb(st, &bet->st_encap);
-               bet->valid_subtlvs |= BGP_TEA_SUBTLV_ENCAP;
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP);
+               break;
+
+           case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
+               rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint);
+               SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT);
                break;
 
            default:
index c81b7297987da47f9a1648e87e95b68823954981..603ff9d2d6249e5c657be2231fa4282d303384da 100644 (file)
@@ -44,6 +44,7 @@ typedef enum {
     BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE=2,
     BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA=3,
     BGP_ENCAP_SUBTLV_TYPE_COLOR=4,
+    BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT=6 /* speculative, IANA assignment TBD */
 } bgp_encap_subtlv_types;
 
 /*
@@ -75,6 +76,16 @@ struct bgp_tea_subtlv_color {
     uint32_t   color;
 };
 
+/* per draft-rosen-idr-tunnel-encaps */
+struct bgp_tea_subtlv_remote_endpoint {
+    u_char family;               /* IPv4 or IPv6 */
+    union {
+        struct in_addr  v4;
+        struct in6_addr v6;
+    } ip_address;
+    as_t               as4;     /* always 4 bytes */
+};
+
 /*
  * This is the length of the value part of the ipsec tunnel authenticator
  * subtlv. Currently we only support the length for authenticator type 1.
@@ -95,12 +106,18 @@ struct bgp_tea_subtlv_ipsec_ta {
 #define BGP_TEA_SUBTLV_PROTO_TYPE      0x00000002
 #define BGP_TEA_SUBTLV_COLOR           0x00000004
 #define BGP_TEA_SUBTLV_IPSEC_TA                0x00000008
+#define BGP_TEA_SUBTLV_REMOTE_ENDPOINT 0x00000010
 
+#define CHECK_SUBTLV_FLAG(ptr, flag)  CHECK_FLAG((ptr)->valid_subtlvs, (flag))
+#define SET_SUBTLV_FLAG(ptr, flag)      SET_FLAG((ptr)->valid_subtlvs, (flag))
+#define UNSET_SUBTLV_FLAG(ptr, flag)  UNSET_FLAG((ptr)->valid_subtlvs, (flag))
 
 /*
  * Tunnel Type-specific APIs
  */
 struct bgp_encap_type_reserved {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
 };
 
 struct bgp_encap_type_l2tpv3_over_ip {
@@ -108,6 +125,7 @@ struct bgp_encap_type_l2tpv3_over_ip {
     struct bgp_tea_subtlv_encap_l2tpv3_over_ip st_encap;
     struct bgp_tea_subtlv_proto_type           st_proto;       /* optional */
     struct bgp_tea_subtlv_color                        st_color;       /* optional */
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
 };
 
 struct bgp_encap_type_gre {
@@ -115,59 +133,79 @@ struct bgp_encap_type_gre {
     struct bgp_tea_subtlv_encap_gre_key                st_encap;       /* optional */
     struct bgp_tea_subtlv_proto_type           st_proto;       /* optional */
     struct bgp_tea_subtlv_color                        st_color;       /* optional */
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
 };
 
 struct bgp_encap_type_ip_in_ip {
     uint32_t                                   valid_subtlvs;
     struct bgp_tea_subtlv_proto_type           st_proto;       /* optional */
     struct bgp_tea_subtlv_color                        st_color;       /* optional */
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
 };
 
 struct bgp_encap_type_transmit_tunnel_endpoint {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     /* No subtlvs defined in spec? */
 };
 
 struct bgp_encap_type_ipsec_in_tunnel_mode {
     uint32_t                                   valid_subtlvs;
     struct bgp_tea_subtlv_ipsec_ta             st_ipsec_ta;    /* optional */
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
 };
 
 struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode {
     uint32_t                                   valid_subtlvs;
     struct bgp_tea_subtlv_ipsec_ta             st_ipsec_ta;    /* optional */
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
 };
 
 struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode {
     uint32_t                                   valid_subtlvs;
     struct bgp_tea_subtlv_ipsec_ta             st_ipsec_ta;    /* optional */
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
 };
 
 struct bgp_encap_type_vxlan {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     /* No subtlvs defined in spec? */
 };
 
 struct bgp_encap_type_nvgre {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     /* No subtlvs defined in spec? */
 };
 
 struct bgp_encap_type_mpls {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     /* No subtlvs defined in spec? */
 };
 
 struct bgp_encap_type_mpls_in_gre {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     /* No subtlvs defined in spec? */
 };
 
 struct bgp_encap_type_vxlan_gpe {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     /* No subtlvs defined in spec? */
 };
 
 struct bgp_encap_type_mpls_in_udp {
+    uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     /* No subtlvs defined in spec? */
 };
 
 struct bgp_encap_type_pbb {
     uint32_t                                   valid_subtlvs;
+    struct bgp_tea_subtlv_remote_endpoint       st_endpoint;    /* optional */
     struct bgp_tea_subtlv_encap_pbb            st_encap;
 };
 
index 54ca5efedefe2e63b28695ef83f3de9e1aba70b6..947f5c09d434572ae03115af5b46c5c82e53239b 100644 (file)
@@ -102,6 +102,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
                   case SAFI_MPLS_LABELED_VPN:
                     json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN");
                   break;
+                  case SAFI_ENCAP:
+                    json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "encap");
+                  break;
                   default:
                     json_object_int_add(json_cap, "capabilityErrorMultiProtocolSafiUnknown", mpc.safi);
                   break;
@@ -130,9 +133,12 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
                   case SAFI_MULTICAST:
                     vty_out (vty, "SAFI Multicast");
                   break;
-                 case SAFI_MPLS_LABELED_VPN:
+                  case SAFI_MPLS_LABELED_VPN:
                     vty_out (vty, "SAFI MPLS-labeled VPN");
                   break;
+                  case SAFI_ENCAP:
+                    vty_out (vty, "SAFI ENCAP");
+                  break;
                   default:
                     vty_out (vty, "SAFI Unknown %d ", mpc.safi);
                   break;
@@ -185,6 +191,7 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
        case SAFI_UNICAST:
        case SAFI_MULTICAST:
        case SAFI_MPLS_VPN:
+       case SAFI_ENCAP:
          return 1;
        }
       break;
@@ -1127,9 +1134,11 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
       if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] 
          && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
          && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
+         && ! peer->afc_nego[AFI_IP][SAFI_ENCAP]
          && ! 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_MPLS_VPN]
+         && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
        {
          zlog_err ("%s [Error] Configured AFI/SAFIs do not "
                    "overlap with received MP capabilities",
@@ -1276,6 +1285,18 @@ bgp_open_capability (struct stream *s, struct peer *peer)
       stream_putc (s, 0);
       stream_putc (s, SAFI_MPLS_LABELED_VPN);
     }
+  /* ENCAP */
+  if (peer->afc[AFI_IP][SAFI_ENCAP])
+    {
+      peer->afc_adv[AFI_IP][SAFI_ENCAP] = 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_IP);
+      stream_putc (s, 0);
+      stream_putc (s, SAFI_ENCAP);
+    }
 #ifdef HAVE_IPV6
   /* Currently supporting RFC-5549 for Link-Local peering only */
   if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
@@ -1333,6 +1354,18 @@ bgp_open_capability (struct stream *s, struct peer *peer)
       stream_putc (s, 0);
       stream_putc (s, SAFI_MPLS_LABELED_VPN);
     }
+  /* IPv6 ENCAP. */
+  if (peer->afc[AFI_IP6][SAFI_ENCAP])
+    {
+      peer->afc_adv[AFI_IP6][SAFI_ENCAP] = 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_IP6);
+      stream_putc (s, 0);
+      stream_putc (s, SAFI_ENCAP);
+    }
 #endif /* HAVE_IPV6 */
 
   /* Route refresh. */
index 3f69a98889d449bf5b85359c9d79655aa7e7ecd9..0236f6777a2ac4afe6f193948e00b19fa4987230 100644 (file)
@@ -47,6 +47,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "bgpd/bgp_ecommunity.h"
 #include "bgpd/bgp_network.h"
 #include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_encap.h"
 #include "bgpd/bgp_advertise.h"
 #include "bgpd/bgp_vty.h"
 #include "bgpd/bgp_updgrp.h"
@@ -1156,7 +1157,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
   /* Verify valid local address present based on negotiated address-families. */
   if (peer->afc_nego[AFI_IP][SAFI_UNICAST] ||
       peer->afc_nego[AFI_IP][SAFI_MULTICAST] ||
-      peer->afc_nego[AFI_IP][SAFI_MPLS_VPN])
+      peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] ||
+      peer->afc_nego[AFI_IP][SAFI_ENCAP])
     {
       if (!peer->nexthop.v4.s_addr)
         {
@@ -1168,7 +1170,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
     }
   if (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_MPLS_VPN] ||
+      peer->afc_nego[AFI_IP6][SAFI_ENCAP])
     {
       if (IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_global))
         {
@@ -1686,6 +1689,64 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
            zlog_debug ("rcvd End-of-RIB for VPNv6 Unicast from %s", peer->host);
        }
     }
+  if (peer->afc[AFI_IP][SAFI_ENCAP])
+    {
+      if (mp_update.length
+         && mp_update.afi == AFI_IP
+         && mp_update.safi == SAFI_ENCAP)
+       bgp_nlri_parse_encap (mp_update.afi, peer, &attr, &mp_update, 0);
+
+      if (mp_withdraw.length
+         && mp_withdraw.afi == AFI_IP
+         && mp_withdraw.safi == SAFI_ENCAP)
+       bgp_nlri_parse_encap (mp_withdraw.afi, peer, &attr, &mp_withdraw, 1);
+
+      if (! withdraw_len
+         && mp_withdraw.afi == AFI_IP
+         && mp_withdraw.safi == SAFI_ENCAP
+         && mp_withdraw.length == 0)
+       {
+         /* End-of-RIB received */
+          if (!CHECK_FLAG (peer->af_sflags[AFI_IP][SAFI_ENCAP],
+                           PEER_STATUS_EOR_RECEIVED))
+            {
+             SET_FLAG (peer->af_sflags[AFI_IP][SAFI_ENCAP], PEER_STATUS_EOR_RECEIVED);
+              bgp_update_explicit_eors(peer);
+            }
+
+          if (bgp_debug_neighbor_events(peer))
+           zlog_debug ("rcvd End-of-RIB for IPv4 Encap from %s", peer->host);
+       }
+    }
+  if (peer->afc[AFI_IP6][SAFI_ENCAP])
+    {
+      if (mp_update.length 
+         && mp_update.afi == AFI_IP6 
+         && mp_update.safi == SAFI_ENCAP)
+       bgp_nlri_parse_encap (mp_update.afi, peer, &attr, &mp_update, 0);
+
+      if (mp_withdraw.length 
+         && mp_withdraw.afi == AFI_IP6
+         && mp_withdraw.safi == SAFI_ENCAP)
+       bgp_nlri_parse_encap (mp_withdraw.afi, peer, &attr, &mp_withdraw, 1);
+
+      if (! withdraw_len
+         && mp_withdraw.afi == AFI_IP6
+         && mp_withdraw.safi == SAFI_ENCAP
+         && mp_withdraw.length == 0)
+       {
+         /* End-of-RIB received */
+          if (!CHECK_FLAG (peer->af_sflags[AFI_IP6][SAFI_ENCAP],
+                           PEER_STATUS_EOR_RECEIVED))
+            {
+             SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_ENCAP], PEER_STATUS_EOR_RECEIVED);
+              bgp_update_explicit_eors(peer);
+            }
+
+          if (bgp_debug_neighbor_events(peer))
+           zlog_debug ("rcvd End-of-RIB for IPv6 Encap from %s", peer->host);
+       }
+    }
 
   /* Everything is done.  We unintern temporary structures which
      interned in bgp_attr_parse(). */
index 3be971e13167ea758059d0aca44594e92c24d48f..d927c58625e3d64f7ea452ad9ac5d37797107480 100644 (file)
@@ -77,7 +77,7 @@ 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)
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
     {
       prn = bgp_node_get (table, (struct prefix *) prd);
 
@@ -90,7 +90,7 @@ 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)
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
     rn->prn = prn;
 
   return rn;
@@ -1367,13 +1367,18 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp,
     SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
 
 #ifdef HAVE_IPV6
+#define NEXTHOP_IS_V6 (\
+    (safi != SAFI_ENCAP && \
+     (p->family == AF_INET6 || peer_cap_enhe(peer))) || \
+    (safi == SAFI_ENCAP && attr->extra->mp_nexthop_len == 16))
+
   /* IPv6/MP starts with 1 nexthop. The link-local address is passed only if
    * the peer (group) is configured to receive link-local nexthop unchanged
    * and it is available in the prefix OR we're not reflecting the route and
    * the peer (group) to whom we're going to announce is on a shared network
    * and this is either a self-originated route or the peer is EBGP.
    */
-  if (p->family == AF_INET6 || peer_cap_enhe(peer))
+  if (NEXTHOP_IS_V6)
     {
       attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
       if ((CHECK_FLAG (peer->af_flags[afi][safi],
@@ -2645,7 +2650,6 @@ bgp_announce_route_timer_expired (struct thread *t)
   struct peer_af *paf;
   struct peer *peer;
 
-
   paf = THREAD_ARG (t);
   peer = paf->peer;
 
@@ -2759,7 +2763,7 @@ bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi)
   if (peer->status != Established)
     return;
 
-  if (safi != SAFI_MPLS_VPN)
+  if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP))
     bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL);
   else
     for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
@@ -2972,7 +2976,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)
+  if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP)
     bgp_clear_route_table (peer, afi, safi, NULL);
   else
     for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
@@ -3090,13 +3094,27 @@ bgp_cleanup_routes (void)
           */
          for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn;
                rn = bgp_route_next (rn))
-           if (rn->info)
+           {
+             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);
+                 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);
+               }
+           }
        }
     }
 }
@@ -3255,6 +3273,7 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, safi_t safi, u_char *pnt,
 
   while (pnt < end)
     {
+      int      badlength;
 
       /* If the NLRI is encoded using addpath then the first 4 bytes are
        * the addpath ID. */
@@ -3275,8 +3294,18 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, safi_t safi, u_char *pnt,
       prefixlen = *pnt++;
       
       /* Prefix length check. */
-      if ((afi == AFI_IP && prefixlen > 32)
-         || (afi == AFI_IP6 && prefixlen > 128))
+      badlength = 0;
+      if (safi == SAFI_ENCAP) {
+       if (prefixlen > 128)
+         badlength = 1;
+      } else {
+        if ((afi == AFI_IP && prefixlen > 32) ||
+           (afi == AFI_IP6 && prefixlen > 128)) {
+
+           badlength = 1;
+       }
+      }
+      if (badlength)
        {
          zlog_err ("%s [Error] Update packet error (wrong prefix length %d)",
                    peer->host, prefixlen);
@@ -3880,7 +3909,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)
+           if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
              {
                table = rn->info;
 
@@ -4776,7 +4805,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)
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
     return;
 
   table = bgp->aggregate[afi][safi];
@@ -4813,7 +4842,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)
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
     return;
 
   table = bgp->aggregate[afi][safi];
@@ -5812,10 +5841,40 @@ route_vty_out (struct vty *vty, struct prefix *p,
   attr = binfo->attr;
   if (attr) 
     {
+      /*
+       * For ENCAP routes, nexthop address family is not
+       * 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 (attr->extra)
+            {
+             char buf[BUFSIZ];
+              int af = NEXTHOP_FAMILY(attr->extra->mp_nexthop_len);
 
+              switch (af)
+                {
+                  case AF_INET:
+                    vty_out (vty, "%s", inet_ntop(af,
+                             &attr->extra->mp_nexthop_global_in, buf, BUFSIZ));
+                  break;
+#if HAVE_IPV6
+                  case AF_INET6:
+                    vty_out (vty, "%s", inet_ntop(af,
+                             &attr->extra->mp_nexthop_global, buf, BUFSIZ));
+                  break;
+#endif
+                  default:
+                    vty_out(vty, "?");
+                  break;
+                }
+            }
+          else
+            vty_out(vty, "?");
+        }
       /* IPv4 Next Hop */
-      if (p->family == AF_INET
-          && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
+      else if (p->family == AF_INET || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
        {
           if (json_paths)
             {
@@ -5838,7 +5897,6 @@ route_vty_out (struct vty *vty, struct prefix *p,
                vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
             }
        }
-
 #ifdef HAVE_IPV6
       /* IPv6 Next Hop */
       else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr))
@@ -6028,9 +6086,12 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t
     {
       if (use_json)
         {
-          if (p->family == AF_INET && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
+          if (p->family == AF_INET &&
+              (safi == SAFI_MPLS_VPN ||
+               safi == SAFI_ENCAP ||
+               !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
             {
-              if (safi == SAFI_MPLS_VPN)
+              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
                 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));
@@ -6065,9 +6126,12 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t
         }
       else
         {
-          if (p->family == AF_INET && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
+          if (p->family == AF_INET &&
+              (safi == SAFI_MPLS_VPN ||
+               safi == SAFI_ENCAP ||
+               !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
             {
-              if (safi == SAFI_MPLS_VPN)
+              if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
                 vty_out (vty, "%-16s",
                          inet_ntoa (attr->extra->mp_nexthop_global_in));
               else
@@ -6156,7 +6220,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)
+         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
             {
               if (json)
                 json_object_string_add(json_out, "mpNexthopGlobalIn", inet_ntoa (attr->extra->mp_nexthop_global_in));
@@ -6567,10 +6631,12 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
          
       /* Line2 display Next-hop, Neighbor, Router-id */
       /* Display the nexthop */
-      if (p->family == AF_INET
-          && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
+      if (p->family == AF_INET &&
+          (safi == SAFI_MPLS_VPN ||
+           safi == SAFI_ENCAP ||
+           !BGP_ATTR_NEXTHOP_AFI_IP6(attr)))
        {
-          if (safi == SAFI_MPLS_VPN)
+          if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
             {
               if (json_paths)
                 json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in));
@@ -7553,7 +7619,7 @@ 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_MPLS_VPN || safi == SAFI_ENCAP) ?
               prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""),
               safi == SAFI_MPLS_VPN ? ":" : "",
               inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN),
@@ -7673,7 +7739,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
       json_paths = json_object_new_array();
     }
 
-  if (safi == SAFI_MPLS_VPN)
+  if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
     {
       for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn))
         {
@@ -7697,8 +7763,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
                       if (header)
                         {
                           route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p,
-                                                       AFI_IP, SAFI_MPLS_VPN, json);
-
+                                                       AFI_IP, safi, json);
                           header = 0;
                         }
                       display++;
@@ -7707,7 +7772,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
                           (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) ||
                           (pathtype == BGP_PATH_MULTIPATH &&
                            (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))))
-                        route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN, json_paths);
+                        route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi, json_paths);
                     }
 
                   bgp_unlock_node (rm);
@@ -11449,18 +11514,20 @@ bgp_table_stats_vty (struct vty *vty, const char *name,
         safi = SAFI_MULTICAST;
       else if (strncmp (safi_str, "u", 1) == 0)
         safi = SAFI_UNICAST;
+      else if (strncmp (safi_str, "e", 1) == 0)
+        safi = SAFI_ENCAP;
       else if (strncmp (safi_str, "vpnv4", 5) == 0 || strncmp (safi_str, "vpnv6", 5) == 0)
         safi = SAFI_MPLS_VPN;
       else
         {
           vty_out (vty, "%% Invalid subsequent address family %s%s",
                    safi_str, VTY_NEWLINE);
-          return CMD_WARNING;
-        }
+            return CMD_WARNING;
+      }
     }
   else
     {
-      vty_out (vty, "%% Invalid address family %s%s",
+      vty_out (vty, "%% Invalid address family \"%s\"%s",
                afi_str, VTY_NEWLINE);
       return CMD_WARNING;
     }
@@ -11470,30 +11537,23 @@ bgp_table_stats_vty (struct vty *vty, const char *name,
 
 DEFUN (show_bgp_statistics,
        show_bgp_statistics_cmd,
-       "show bgp (ipv4|ipv6) (unicast|multicast) statistics",
+       "show bgp (ipv4|ipv6) (encap|multicast|unicast|vpn) statistics",
        SHOW_STR
        BGP_STR
        "Address family\n"
        "Address family\n"
        "Address Family modifier\n"
        "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
        "BGP RIB advertisement statistics\n")
 {
   return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
 }
 
-ALIAS (show_bgp_statistics,
-       show_bgp_statistics_vpnv4_cmd,
-       "show bgp (ipv4) (vpnv4) statistics",
-       SHOW_STR
-       BGP_STR
-       "Address family\n"
-       "Address Family modifier\n"
-       "BGP RIB advertisement statistics\n")
-
 DEFUN (show_bgp_statistics_view,
        show_bgp_statistics_view_cmd,
-       "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast) statistics",
+       "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast|vpn|encap) statistics",
        SHOW_STR
        BGP_STR
        BGP_INSTANCE_HELP_STR
@@ -11501,21 +11561,13 @@ DEFUN (show_bgp_statistics_view,
        "Address family\n"
        "Address Family modifier\n"
        "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
        "BGP RIB advertisement statistics\n")
 {
   return bgp_table_stats_vty (vty, NULL, argv[1], argv[2]);
 }
 
-ALIAS (show_bgp_statistics_view,
-       show_bgp_statistics_view_vpnv4_cmd,
-       "show bgp " BGP_INSTANCE_CMD " (ipv4) (vpnv4) statistics",
-       SHOW_STR
-       BGP_STR
-       BGP_INSTANCE_HELP_STR
-       "Address family\n"
-       "Address Family modifier\n"
-       "BGP RIB advertisement statistics\n")
-
 enum bgp_pcounts
 {
   PCOUNT_ADJ_IN = 0,
@@ -13906,9 +13958,9 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name,
 
   match.family = afi2family (afi);
 
-  if (safi == SAFI_MPLS_VPN)
+  if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
     {
-      for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
+      for (rn = bgp_table_top (bgp->rib[AFI_IP][safi]); rn; rn = bgp_route_next (rn))
         {
           if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
             continue;
@@ -14025,6 +14077,7 @@ DEFUN (clear_ip_bgp_dampening_address_mask,
                               SAFI_UNICAST, NULL, 0);
 }
 
+/* also used for encap safi */
 static int
 bgp_config_write_network_vpnv4 (struct vty *vty, struct bgp *bgp,
                                afi_t afi, safi_t safi, int *write)
@@ -14076,7 +14129,7 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp,
   struct bgp_aggregate *bgp_aggregate;
   char buf[SU_ADDRSTRLEN];
   
-  if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
+  if (afi == AFI_IP && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)))
     return bgp_config_write_network_vpnv4 (vty, bgp, afi, safi, write);
 
   /* Network configuration. */
@@ -14847,9 +14900,9 @@ bgp_route_init (void)
 
   /* Statistics */
   install_element (ENABLE_NODE, &show_bgp_statistics_cmd);
-  install_element (ENABLE_NODE, &show_bgp_statistics_vpnv4_cmd);
+  //install_element (ENABLE_NODE, &show_bgp_statistics_vpnv4_cmd);
   install_element (ENABLE_NODE, &show_bgp_statistics_view_cmd);
-  install_element (ENABLE_NODE, &show_bgp_statistics_view_vpnv4_cmd);
+  //install_element (ENABLE_NODE, &show_bgp_statistics_view_vpnv4_cmd);
   
   /* old command */
   install_element (VIEW_NODE, &show_ipv6_bgp_cmd);
index e3c4beb3009068b894ee3349ddb6688ae0a905ac..4b684be1bb178b4399bbb490569bcf288a5211d0 100644 (file)
@@ -602,6 +602,7 @@ subgroup_announce_table (struct update_subgroup *subgrp,
     table = peer->bgp->rib[afi][safi];
 
   if (safi != SAFI_MPLS_VPN
+      && safi != SAFI_ENCAP
       && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
     subgroup_default_originate (subgrp, 0);
 
@@ -664,7 +665,8 @@ subgroup_announce_route (struct update_subgroup *subgrp)
                  PEER_STATUS_ORF_WAIT_REFRESH))
     return;
 
-  if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN)
+  if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN &&
+      SUBGRP_SAFI (subgrp) != SAFI_ENCAP)
     subgroup_announce_table (subgrp, NULL);
   else
     for (rn = bgp_table_top (update_subgroup_rib (subgrp)); rn;
index 49f217068b6d527eab1db5d09b2616ec7cfb939f..ed7eca58c0a77cca0caaafd49e170274474e8ce3 100644 (file)
@@ -6457,6 +6457,33 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_out,
        "Address Family Modifier\n"
        BGP_SOFT_OUT_STR)
 
+DEFUN (clear_ip_bgp_all_encap_soft_out,
+       clear_ip_bgp_all_encap_soft_out_cmd,
+       "clear ip bgp * encap unicast soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_all,
+                       BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_encap_soft_out,
+       clear_ip_bgp_all_encap_out_cmd,
+       "clear ip bgp * encap unicast out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig outbound update\n")
+
 DEFUN (clear_bgp_all_soft_out,
        clear_bgp_all_soft_out_cmd,
        "clear bgp * soft out",
@@ -6728,6 +6755,33 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_out,
        "Address Family Modifier\n"
        BGP_SOFT_OUT_STR)
 
+DEFUN (clear_ip_bgp_peer_encap_soft_out,
+       clear_ip_bgp_peer_encap_soft_out_cmd,
+       "clear ip bgp A.B.C.D encap unicast soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_peer,
+                       BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_encap_soft_out,
+       clear_ip_bgp_peer_encap_out_cmd,
+       "clear ip bgp A.B.C.D encap unicast out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig outbound update\n")
+
 DEFUN (clear_bgp_peer_soft_out,
        clear_bgp_peer_soft_out_cmd,
        "clear bgp (A.B.C.D|X:X::X:X|WORD) soft out",
@@ -7387,6 +7441,33 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_out,
        "Address Family modifier\n"
        BGP_SOFT_OUT_STR)
 
+DEFUN (clear_ip_bgp_as_encap_soft_out,
+       clear_ip_bgp_as_encap_soft_out_cmd,
+       "clear ip bgp " CMD_AS_RANGE " encap unicast soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_as,
+                       BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_encap_soft_out,
+       clear_ip_bgp_as_encap_out_cmd,
+       "clear ip bgp " CMD_AS_RANGE " encap unicast out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+
 DEFUN (clear_bgp_as_soft_out,
        clear_bgp_as_soft_out_cmd,
        "clear bgp " CMD_AS_RANGE " soft out",
@@ -7654,6 +7735,33 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_in,
        "Address Family Modifier\n"
        BGP_SOFT_IN_STR)
 
+DEFUN (clear_ip_bgp_all_encap_soft_in,
+       clear_ip_bgp_all_encap_soft_in_cmd,
+       "clear ip bgp * encap unicast soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_all,
+                       BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_encap_soft_in,
+       clear_ip_bgp_all_encap_in_cmd,
+       "clear ip bgp * encap unicast in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig inbound update\n")
+
 DEFUN (clear_bgp_all_soft_in,
        clear_bgp_all_soft_in_cmd,
        "clear bgp * soft in",
@@ -7951,6 +8059,33 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_in,
        "Address Family Modifier\n"
        BGP_SOFT_IN_STR)
 
+DEFUN (clear_ip_bgp_peer_encap_soft_in,
+       clear_ip_bgp_peer_encap_soft_in_cmd,
+       "clear ip bgp A.B.C.D encap unicast soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_peer,
+                       BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_encap_soft_in,
+       clear_ip_bgp_peer_encap_in_cmd,
+       "clear ip bgp A.B.C.D encap unicast in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig inbound update\n")
+
 DEFUN (clear_bgp_peer_soft_in,
        clear_bgp_peer_soft_in_cmd,
        "clear bgp (A.B.C.D|X:X::X:X|WORD) soft in",
@@ -8792,6 +8927,33 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_in,
        "Address Family modifier\n"
        BGP_SOFT_IN_STR)
 
+DEFUN (clear_ip_bgp_as_encap_soft_in,
+       clear_ip_bgp_as_encap_soft_in_cmd,
+       "clear ip bgp " CMD_AS_RANGE " encap unicast soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_as,
+                       BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_encap_soft_in,
+       clear_ip_bgp_as_encap_in_cmd,
+       "clear ip bgp " CMD_AS_RANGE " encap unicast in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n")
+
 DEFUN (clear_bgp_as_soft_in,
        clear_bgp_as_soft_in_cmd,
        "clear bgp " CMD_AS_RANGE " soft in",
@@ -8984,6 +9146,21 @@ DEFUN (clear_ip_bgp_all_vpnv4_soft,
                        BGP_CLEAR_SOFT_BOTH, argv[0]);
 }
 
+DEFUN (clear_ip_bgp_all_encap_soft,
+       clear_ip_bgp_all_encap_soft_cmd,
+       "clear ip bgp * encap unicast soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_all,
+                       BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
 DEFUN (clear_bgp_all_soft,
        clear_bgp_all_soft_cmd,
        "clear bgp * soft",
@@ -9116,6 +9293,21 @@ DEFUN (clear_ip_bgp_peer_vpnv4_soft,
                        BGP_CLEAR_SOFT_BOTH, argv[0]);
 }
 
+DEFUN (clear_ip_bgp_peer_encap_soft,
+       clear_ip_bgp_peer_encap_soft_cmd,
+       "clear ip bgp A.B.C.D encap unicast soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_peer,
+                       BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
 DEFUN (clear_bgp_peer_soft,
        clear_bgp_peer_soft_cmd,
        "clear bgp (A.B.C.D|X:X::X:X|WORD) soft",
@@ -9483,6 +9675,21 @@ DEFUN (clear_ip_bgp_as_vpnv4_soft,
                        BGP_CLEAR_SOFT_BOTH, argv[0]);
 }
 
+DEFUN (clear_ip_bgp_as_encap_soft,
+       clear_ip_bgp_as_encap_soft_cmd,
+       "clear ip bgp " CMD_AS_RANGE " encap unicast soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_ENCAP, clear_as,
+                       BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
 DEFUN (clear_bgp_as_soft,
        clear_bgp_as_soft_cmd,
        "clear bgp " CMD_AS_RANGE " soft",
@@ -15033,7 +15240,12 @@ bgp_vty_init (void)
   install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_in_cmd);
   install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_soft_in_cmd);
   install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_in_cmd);
-
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_encap_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_encap_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_encap_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_encap_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_encap_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_encap_in_cmd);
   install_element (ENABLE_NODE, &clear_bgp_all_soft_in_cmd);
   install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_in_cmd);
   install_element (ENABLE_NODE, &clear_bgp_all_in_cmd);
@@ -15138,7 +15350,12 @@ bgp_vty_init (void)
   install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_out_cmd);
   install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_soft_out_cmd);
   install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_out_cmd);
-
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_encap_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_encap_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_encap_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_encap_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_encap_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_encap_out_cmd);
   install_element (ENABLE_NODE, &clear_bgp_all_soft_out_cmd);
   install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_out_cmd);
   install_element (ENABLE_NODE, &clear_bgp_all_out_cmd);
@@ -15204,7 +15421,9 @@ bgp_vty_init (void)
   install_element (ENABLE_NODE, &clear_ip_bgp_all_vpnv4_soft_cmd);
   install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_soft_cmd);
   install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_soft_cmd);
-
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_encap_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_encap_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_encap_soft_cmd);
   install_element (ENABLE_NODE, &clear_bgp_all_soft_cmd);
   install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_cmd);
   install_element (ENABLE_NODE, &clear_bgp_peer_soft_cmd);
index 10c580c777e5e9f2124d16b0a4f17d6a2d480ba7..f694f7156e0d3a06cc669dcd8b29ec42ccecc264 100644 (file)
@@ -42,6 +42,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "bfd.h"
 #include "hash.h"
 #include "jhash.h"
+#include "table.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"
@@ -61,6 +62,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "bgpd/bgp_nexthop.h"
 #include "bgpd/bgp_damp.h"
 #include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_encap.h"
 #include "bgpd/bgp_advertise.h"
 #include "bgpd/bgp_network.h"
 #include "bgpd/bgp_vty.h"
@@ -1541,12 +1543,16 @@ peer_as_change (struct peer *peer, as_t as, int as_specified)
                  PEER_FLAG_REFLECTOR_CLIENT);
       UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
                  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
+                 PEER_FLAG_REFLECTOR_CLIENT);
       UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
                  PEER_FLAG_REFLECTOR_CLIENT);
       UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
                  PEER_FLAG_REFLECTOR_CLIENT);
       UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
                  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
+                 PEER_FLAG_REFLECTOR_CLIENT);
     }
 
   /* local-as reset */
@@ -3459,9 +3465,11 @@ peer_active (struct peer *peer)
   if (peer->afc[AFI_IP][SAFI_UNICAST]
       || peer->afc[AFI_IP][SAFI_MULTICAST]
       || peer->afc[AFI_IP][SAFI_MPLS_VPN]
+      || peer->afc[AFI_IP][SAFI_ENCAP]
       || peer->afc[AFI_IP6][SAFI_UNICAST]
       || peer->afc[AFI_IP6][SAFI_MULTICAST]
-      || peer->afc[AFI_IP6][SAFI_MPLS_VPN])
+      || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
+      || peer->afc[AFI_IP6][SAFI_ENCAP])
     return 1;
   return 0;
 }
@@ -3473,9 +3481,11 @@ peer_active_nego (struct peer *peer)
   if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
       || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
       || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
+      || peer->afc_nego[AFI_IP][SAFI_ENCAP]
       || 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_MPLS_VPN]
+      || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
     return 1;
   return 0;
 }
@@ -7274,6 +7284,7 @@ bgp_init (void)
   bgp_route_map_init ();
   bgp_scan_vty_init();
   bgp_mplsvpn_init ();
+  bgp_encap_init ();
 
   /* Access list initialize. */
   access_list_init ();
index c834f11232b61cf803ab6e883f8a42f203e4c223..0c6aa6b21a21437382edfb4dcc2ec0355833af0c 100644 (file)
@@ -69,6 +69,8 @@ enum bgp_af_index
   BGP_AF_IPV6_UNICAST,
   BGP_AF_IPV6_MULTICAST,
   BGP_AF_IPV6_VPN,
+  BGP_AF_IPV4_ENCAP,
+  BGP_AF_IPV6_ENCAP,
   BGP_AF_MAX
 };
 
@@ -1348,6 +1350,9 @@ afindex (afi_t afi, safi_t safi)
        case SAFI_MPLS_VPN:
          return BGP_AF_IPV4_VPN;
          break;
+       case SAFI_ENCAP:
+         return BGP_AF_IPV4_ENCAP;
+         break;
        default:
          return BGP_AF_MAX;
          break;
@@ -1365,6 +1370,9 @@ afindex (afi_t afi, safi_t safi)
        case SAFI_MPLS_VPN:
          return BGP_AF_IPV6_VPN;
          break;
+       case SAFI_ENCAP:
+         return BGP_AF_IPV6_ENCAP;
+         break;
        default:
          return BGP_AF_MAX;
          break;
@@ -1391,7 +1399,8 @@ peer_afi_active_nego (const struct peer *peer, afi_t afi)
 {
   if (peer->afc_nego[afi][SAFI_UNICAST]
       || peer->afc_nego[afi][SAFI_MULTICAST]
-      || peer->afc_nego[afi][SAFI_MPLS_VPN])
+      || peer->afc_nego[afi][SAFI_MPLS_VPN]
+      || peer->afc_nego[afi][SAFI_ENCAP])
     return 1;
   return 0;
 }
@@ -1405,9 +1414,11 @@ peer_group_af_configured (struct peer_group *group)
   if (peer->afc[AFI_IP][SAFI_UNICAST]
       || peer->afc[AFI_IP][SAFI_MULTICAST]
       || peer->afc[AFI_IP][SAFI_MPLS_VPN]
+      || peer->afc[AFI_IP][SAFI_ENCAP]
       || peer->afc[AFI_IP6][SAFI_UNICAST]
       || peer->afc[AFI_IP6][SAFI_MULTICAST]
-      || peer->afc[AFI_IP6][SAFI_MPLS_VPN])
+      || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
+      || peer->afc[AFI_IP6][SAFI_ENCAP])
     return 1;
   return 0;
 }