From: Lou Berger Date: Tue, 12 Jan 2016 18:42:02 +0000 (-0500) Subject: bgpd: encap: add encap SAFI (RFC5512) X-Git-Tag: frr-2.0-rc1~540^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=587ff0fd881e3532226afa7a007a5a8ff7b89871;p=matthieu%2Ffrr.git bgpd: encap: add encap SAFI (RFC5512) Adds RFC5512 and Encapsulation Attribute. Signed-off-by: Lou Berger (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 --- diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 9183734a3c..5176a8e048 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -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@ diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 0d828dc7dc..ef1d02ecaf 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -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 index 0000000000..2186b21122 --- /dev/null +++ b/bgpd/bgp_encap.c @@ -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 + * + */ + +/* + +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 + +#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 /, 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 /, 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 index 0000000000..6f43b7b3b1 --- /dev/null +++ b/bgpd/bgp_encap.h @@ -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 */ diff --git a/bgpd/bgp_encap_tlv.c b/bgpd/bgp_encap_tlv.c index 058b41eb56..347b4b3ce7 100644 --- a/bgpd/bgp_encap_tlv.c +++ b/bgpd/bgp_encap_tlv.c @@ -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: diff --git a/bgpd/bgp_encap_types.h b/bgpd/bgp_encap_types.h index c81b729798..603ff9d2d6 100644 --- a/bgpd/bgp_encap_types.h +++ b/bgpd/bgp_encap_types.h @@ -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; }; diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 54ca5efede..947f5c09d4 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -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. */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 3f69a98889..0236f6777a 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -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(). */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3be971e131..d927c58625 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index e3c4beb300..4b684be1bb 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -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; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 49f217068b..ed7eca58c0 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -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); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 10c580c777..f694f7156e 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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 (); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index c834f11232..0c6aa6b21a 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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; }