diff options
author | Lou Berger <lberger@labn.net> | 2016-01-12 13:42:02 -0500 |
---|---|---|
committer | Paul Jakma <paul.jakma@hpe.com> | 2016-02-26 14:11:44 +0000 |
commit | 298cc2f688dbadf0a447fcd06ae8e20fa5006ce4 (patch) | |
tree | 50a27a17c45edc4e6a0b200617db0f066bb42fc2 | |
parent | c3741789530ee824693fd606356acac2ad695f83 (diff) | |
download | quagga-298cc2f688dbadf0a447fcd06ae8e20fa5006ce4.tar.bz2 quagga-298cc2f688dbadf0a447fcd06ae8e20fa5006ce4.tar.xz |
bgpd: encap: add encap SAFI (RFC5512)
Adds RFC5512 and Encapsulation Attribute.
Signed-off-by: Lou Berger <lberger@labn.net>
-rw-r--r-- | bgpd/Makefile.am | 4 | ||||
-rw-r--r-- | bgpd/bgp_attr.c | 44 | ||||
-rw-r--r-- | bgpd/bgp_encap.c | 992 | ||||
-rw-r--r-- | bgpd/bgp_encap.h | 34 | ||||
-rw-r--r-- | bgpd/bgp_encap_tlv.c | 162 | ||||
-rw-r--r-- | bgpd/bgp_encap_types.h | 38 | ||||
-rw-r--r-- | bgpd/bgp_open.c | 32 | ||||
-rw-r--r-- | bgpd/bgp_packet.c | 53 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 255 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 222 | ||||
-rw-r--r-- | bgpd/bgpd.c | 19 |
11 files changed, 1740 insertions, 115 deletions
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 82c69eac..7da4dd87 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -16,7 +16,7 @@ libbgp_a_SOURCES = \ bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \ 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_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 \ @@ -24,7 +24,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_encap_tlv.h bgp_encap_types.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 b019347b..5dc118be 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1891,9 +1891,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 (peer->log, LOG_ERR, @@ -2423,6 +2425,10 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, 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; case SAFI_UNICAST: /* invalid for IPv4 */ default: break; @@ -2465,6 +2471,11 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, } } break; + case SAFI_ENCAP: + assert (attr->extra); + stream_putc (s, 16); + stream_put (s, &attr->extra->mp_nexthop_global, 16); + break; default: break; } @@ -2517,6 +2528,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; @@ -2536,6 +2548,7 @@ bgp_packet_mpattr_tea( * V = concatenated subtlvs. */ attrlenfield = 2 + 2; /* T + L */ + attrhdrlen = 1 + 1; /* subTLV T + L */ break; default: @@ -2543,15 +2556,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 (peer->log, LOG_ERR, "%s attribute is too long (length=%d), can't send it", @@ -2581,8 +2594,10 @@ 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); } } @@ -2944,7 +2959,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 00000000..f9365084 --- /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 <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, attr, afi, SAFI_ENCAP, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0); + } else { + bgp_withdraw (peer, &p, 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); + } + } + } + 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); + else + route_vty_out (vty, &rm->p, ri, 0, SAFI_ENCAP); + 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 00000000..6f43b7b3 --- /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 058b41eb..347b4b3c 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 c81b7297..603ff9d2 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 302e4ce5..1c2ebd6d 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -97,6 +97,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) 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; @@ -137,6 +140,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; @@ -841,9 +845,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]) { plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not " "overlap with received MP capabilities", @@ -988,6 +994,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 /* IPv6 unicast. */ if (peer->afc[AFI_IP6][SAFI_UNICAST]) @@ -1025,6 +1043,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 841eaab8..1d18779b 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" @@ -212,7 +213,9 @@ bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi) /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */ total_attr_len = bgp_packet_attribute (NULL, peer, s, adv->baa->attr, - &rn->p, afi, safi, + ((afi == AFI_IP && safi == SAFI_UNICAST) ? + &rn->p : NULL), + afi, safi, from, prd, tag); } @@ -1939,6 +1942,54 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) 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_MPLS_LABELED_VPN + && mp_withdraw.length == 0) + { + /* End-of-RIB received */ + + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for Encap Unicast 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_MPLS_LABELED_VPN + && mp_withdraw.length == 0) + { + /* End-of-RIB received */ + + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for Encap Unicast 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 b024d80d..a780e9de 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -71,7 +71,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); @@ -84,7 +84,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; @@ -980,13 +980,24 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)); } + +#define NEXTHOP_IS_V4 (\ + (safi != SAFI_ENCAP && p->family == AF_INET) || \ + (safi == SAFI_ENCAP && attr->extra->mp_nexthop_len == 4)) + +#ifdef HAVE_IPV6 +#define NEXTHOP_IS_V6 (\ + (safi != SAFI_ENCAP && p->family == AF_INET6) || \ + (safi == SAFI_ENCAP && attr->extra->mp_nexthop_len == 16)) +#endif + /* next-hop-set */ if (transparent || (reflect && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF_ALL)) || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) - && ((p->family == AF_INET && attr->nexthop.s_addr) + && ((NEXTHOP_IS_V4 && attr->nexthop.s_addr) #ifdef HAVE_IPV6 - || (p->family == AF_INET6 && + || (NEXTHOP_IS_V6 && ! IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) #endif /* HAVE_IPV6 */ ))) @@ -994,18 +1005,18 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, /* NEXT-HOP Unchanged. */ } else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) - || (p->family == AF_INET && attr->nexthop.s_addr == 0) + || (NEXTHOP_IS_V4 && attr->nexthop.s_addr == 0) #ifdef HAVE_IPV6 - || (p->family == AF_INET6 && + || (NEXTHOP_IS_V6 && IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global)) #endif /* HAVE_IPV6 */ || (peer->sort == BGP_PEER_EBGP && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0)) { /* Set IPv4 nexthop. */ - if (p->family == AF_INET) + if (NEXTHOP_IS_V4) { - if (safi == SAFI_MPLS_VPN) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) memcpy (&attr->extra->mp_nexthop_global_in, &peer->nexthop.v4, IPV4_MAX_BYTELEN); else @@ -1013,7 +1024,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } #ifdef HAVE_IPV6 /* Set IPv6 nexthop. */ - if (p->family == AF_INET6) + if (NEXTHOP_IS_V6) { /* IPv6 global nexthop must be included. */ memcpy (&attr->extra->mp_nexthop_global, &peer->nexthop.v6_global, @@ -1024,7 +1035,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p, } #ifdef HAVE_IPV6 - if (p->family == AF_INET6) + if (p->family == AF_INET6 && safi != SAFI_ENCAP) { /* Left nexthop_local unchanged if so configured. */ if ( CHECK_FLAG (peer->af_flags[afi][safi], @@ -1214,7 +1225,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient, /* Set IPv4 nexthop. */ if (p->family == AF_INET) { - if (safi == SAFI_MPLS_VPN) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) memcpy (&attr->extra->mp_nexthop_global_in, &rsclient->nexthop.v4, IPV4_MAX_BYTELEN); else @@ -2657,10 +2668,12 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, struct attr attr; struct attr_extra extra; + memset(&extra, 0, sizeof(extra)); + if (! table) table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi]; - if (safi != SAFI_MPLS_VPN + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) bgp_default_originate (peer, afi, safi, 0); @@ -2678,6 +2691,8 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, else bgp_adj_out_unset (rn, peer, &rn->p, afi, safi); } + + bgp_attr_flush_encap(&attr); } void @@ -2696,7 +2711,7 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) return; - if (safi != SAFI_MPLS_VPN) + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)) bgp_announce_table (peer, afi, safi, NULL, 0); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; @@ -2746,7 +2761,7 @@ bgp_soft_reconfig_rsclient (struct peer *rsclient, afi_t afi, safi_t safi) struct bgp_table *table; struct bgp_node *rn; - if (safi != SAFI_MPLS_VPN) + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)) bgp_soft_reconfig_table_rsclient (rsclient, afi, safi, NULL, NULL); else @@ -2805,7 +2820,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; @@ -3022,7 +3037,7 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi, switch (purpose) { case BGP_CLEAR_ROUTE_NORMAL: - if (safi != SAFI_MPLS_VPN) + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)) bgp_clear_route_table (peer, afi, safi, NULL, NULL, purpose); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; @@ -3197,13 +3212,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); + } + } } } } @@ -3335,11 +3364,22 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, safi_t safi, while (pnt < end) { + int badlength; 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) { plog_err (peer->log, "%s [Error] Update packet error (wrong prefix length %d)", @@ -4082,7 +4122,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; @@ -4938,7 +4978,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]; @@ -4975,7 +5015,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]; @@ -5918,30 +5958,71 @@ route_vty_out (struct vty *vty, struct prefix *p, attr = binfo->attr; if (attr) { - if (p->family == AF_INET) - { - if (safi == SAFI_MPLS_VPN) - vty_out (vty, "%-16s", - inet_ntoa (attr->extra->mp_nexthop_global_in)); - else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + + /* + * NEXTHOP start + */ + + /* + * 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, "?"); + } + } else { + vty_out(vty, "?"); } + } else { + + if (p->family == AF_INET) + { + vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); + } #ifdef HAVE_IPV6 - else if (p->family == AF_INET6) - { - int len; - char buf[BUFSIZ]; + else if (p->family == AF_INET6) + { + int len; + char buf[BUFSIZ]; - len = vty_out (vty, "%s", - inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, - buf, BUFSIZ)); - len = 16 - len; - if (len < 1) - vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); - else - vty_out (vty, "%*s", len, " "); - } + len = vty_out (vty, "%s", + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, + buf, BUFSIZ)); + len = 16 - len; + if (len < 1) + vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " "); + else + vty_out (vty, "%*s", len, " "); + } #endif /* HAVE_IPV6 */ + else + { + vty_out(vty, "?"); + } + } + + /* + * NEXTHOP end + */ + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) vty_out (vty, "%10u", attr->med); @@ -5983,7 +6064,7 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, { if (p->family == AF_INET) { - 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 @@ -6056,7 +6137,7 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, { if (p->family == AF_INET) { - 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 @@ -6239,7 +6320,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, /* Line2 display Next-hop, Neighbor, Router-id */ if (p->family == AF_INET) { - vty_out (vty, " %s", safi == SAFI_MPLS_VPN ? + vty_out (vty, " %s", ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) ? inet_ntoa (attr->extra->mp_nexthop_global_in) : inet_ntoa (attr->nexthop)); } @@ -6675,12 +6756,12 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, int no_advertise = 0; int local_as = 0; int first = 0; + int printrd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)); p = &rn->p; vty_out (vty, "BGP routing table entry for %s%s%s/%d%s", - (safi == SAFI_MPLS_VPN ? - prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), - safi == SAFI_MPLS_VPN ? ":" : "", + (printrd ? prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), + printrd ? ":" : "", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN), p->prefixlen, VTY_NEWLINE); @@ -6766,7 +6847,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, match.family = afi2family (afi); - 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)) { @@ -6790,12 +6871,12 @@ 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); + AFI_IP, safi); header = 0; } display++; - route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN); + route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi); } bgp_unlock_node (rm); @@ -9835,22 +9916,28 @@ bgp_table_stats_vty (struct vty *vty, const char *name, afi_str, VTY_NEWLINE); return CMD_WARNING; } - if (strncmp (safi_str, "m", 1) == 0) - safi = SAFI_MULTICAST; - else if (strncmp (safi_str, "u", 1) == 0) - safi = SAFI_UNICAST; - else if (strncmp (safi_str, "vpnv4", 5) == 0 || strncmp (safi_str, "vpnv6", 5) == 0) - safi = SAFI_MPLS_LABELED_VPN; - else - { - vty_out (vty, "%% Invalid subsequent address family %s%s", + switch (safi_str[0]) { + case 'm': + safi = SAFI_MULTICAST; + break; + case 'u': + safi = SAFI_UNICAST; + break; + case 'v': + safi = SAFI_MPLS_LABELED_VPN; + break; + case 'e': + safi = SAFI_ENCAP; + break; + default: + 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; } @@ -9860,30 +9947,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 view WORD (ipv4|ipv6) (unicast|multicast) statistics", + "show bgp view WORD (ipv4|ipv6) (encap|multicast|unicast|vpn) statistics", SHOW_STR BGP_STR "BGP view\n" @@ -9891,20 +9971,24 @@ 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[0], argv[1]); } +#if 0 /* added as options to above command */ ALIAS (show_bgp_statistics_view, - show_bgp_statistics_view_vpnv4_cmd, - "show bgp view WORD (ipv4) (vpnv4) statistics", + show_bgp_statistics_view_encap_cmd, + "show bgp view WORD (ipv4) (encap) statistics", SHOW_STR BGP_STR "BGP view\n" "Address family\n" "Address Family modifier\n" "BGP RIB advertisement statistics\n") +#endif enum bgp_pcounts { @@ -12408,9 +12492,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; @@ -12527,6 +12611,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) @@ -12578,7 +12663,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. */ @@ -13302,9 +13387,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_vty.c b/bgpd/bgp_vty.c index 041a6a1f..e0f1c2b4 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -4802,6 +4802,33 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_out, "Address Family Modifier\n" "Soft reconfig outbound update\n") +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", @@ -4940,6 +4967,33 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_out, "Address Family Modifier\n" "Soft reconfig outbound update\n") +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) soft out", @@ -5267,6 +5321,33 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_out, "Address Family modifier\n" "Soft reconfig outbound update\n") +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", @@ -5503,6 +5584,33 @@ ALIAS (clear_ip_bgp_all_vpnv4_soft_in, "Address Family Modifier\n" "Soft reconfig inbound update\n") +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", @@ -5699,6 +5807,33 @@ ALIAS (clear_ip_bgp_peer_vpnv4_soft_in, "Address Family Modifier\n" "Soft reconfig inbound update\n") +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) soft in", @@ -6206,6 +6341,33 @@ ALIAS (clear_ip_bgp_as_vpnv4_soft_in, "Address Family modifier\n" "Soft reconfig inbound update\n") +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", @@ -6356,6 +6518,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", @@ -6439,6 +6616,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) soft", @@ -6622,6 +6814,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", @@ -10029,6 +10236,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); #ifdef HAVE_IPV6 install_element (ENABLE_NODE, &clear_bgp_all_soft_in_cmd); install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_in_cmd); @@ -10092,6 +10305,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); #ifdef HAVE_IPV6 install_element (ENABLE_NODE, &clear_bgp_all_soft_out_cmd); install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_out_cmd); @@ -10132,6 +10351,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); #ifdef HAVE_IPV6 install_element (ENABLE_NODE, &clear_bgp_all_soft_cmd); install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 636f5693..e70d3377 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -36,6 +36,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "plist.h" #include "linklist.h" #include "workqueue.h" +#include "table.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -55,6 +56,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" @@ -974,12 +976,16 @@ peer_as_change (struct peer *peer, as_t as) 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 */ @@ -1398,9 +1404,11 @@ peer_group_active (struct peer *peer) if (peer->af_group[AFI_IP][SAFI_UNICAST] || peer->af_group[AFI_IP][SAFI_MULTICAST] || peer->af_group[AFI_IP][SAFI_MPLS_VPN] + || peer->af_group[AFI_IP][SAFI_ENCAP] || peer->af_group[AFI_IP6][SAFI_UNICAST] || peer->af_group[AFI_IP6][SAFI_MULTICAST] - || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]) + || peer->af_group[AFI_IP6][SAFI_MPLS_VPN] + || peer->af_group[AFI_IP6][SAFI_ENCAP]) return 1; return 0; } @@ -2356,9 +2364,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; } @@ -2370,9 +2380,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; } @@ -5594,6 +5606,7 @@ bgp_init (void) bgp_address_init (); bgp_scan_init (); bgp_mplsvpn_init (); + bgp_encap_init (); /* Access list initialize. */ access_list_init (); |