summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 03:03:45 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 03:03:45 +0200
commita82478b985085105741eed222d8fab7ecc49f25d (patch)
tree9ef546ed14694cbfef607dfb27716207fd2010fd
parentA valid BGP nexthop is flagged as invalid (diff)
downloadfrr-a82478b985085105741eed222d8fab7ecc49f25d.tar.xz
frr-a82478b985085105741eed222d8fab7ecc49f25d.zip
BGP: add addpath RX support
-rw-r--r--bgpd/bgp_attr.c8
-rw-r--r--bgpd/bgp_mplsvpn.c20
-rw-r--r--bgpd/bgp_open.c65
-rw-r--r--bgpd/bgp_open.h2
-rw-r--r--bgpd/bgp_packet.c8
-rw-r--r--bgpd/bgp_route.c93
-rw-r--r--bgpd/bgp_route.h10
-rw-r--r--bgpd/bgp_vty.c41
-rw-r--r--bgpd/bgpd.h11
9 files changed, 218 insertions, 40 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 8ff8a5cff..506583b3e 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1607,8 +1607,8 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
if (safi != SAFI_MPLS_LABELED_VPN)
{
- ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len,
- &num_mp_pfx);
+ ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
+ nlri_len, &num_mp_pfx);
if (ret < 0)
{
zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
@@ -1655,8 +1655,8 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
if (safi != SAFI_MPLS_LABELED_VPN)
{
- ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len,
- &num_mp_pfx);
+ ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
+ withdraw_len, &num_mp_pfx);
if (ret < 0)
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 087f544b6..22ae54e0e 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -90,6 +90,10 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
struct rd_ip rd_ip;
struct prefix_rd prd;
u_char *tagpnt;
+ afi_t afi;
+ safi_t safi;
+ u_char addpath_encoded;
+ u_int32_t addpath_id;
/* Check peer status. */
if (peer->status != Established)
@@ -101,12 +105,24 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
pnt = packet->nlri;
lim = pnt + packet->length;
+ afi = packet->afi;
+ safi = packet->safi;
+ addpath_id = 0;
+
+ addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) &&
+ CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV));
for (; pnt < lim; pnt += psize)
{
/* Clear prefix structure. */
memset (&p, 0, sizeof (struct prefix));
+ if (addpath_encoded)
+ {
+ addpath_id = ntohl(*((uint32_t*) pnt));
+ pnt += BGP_ADDPATH_ID_LEN;
+ }
+
/* Fetch prefix length. */
prefixlen = *pnt++;
p.family = AF_INET;
@@ -156,10 +172,10 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
return -1;
if (attr)
- bgp_update (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
+ bgp_update (peer, &p, addpath_id, attr, AFI_IP, SAFI_MPLS_VPN,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
else
- bgp_withdraw (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
+ bgp_withdraw (peer, &p, addpath_id, attr, AFI_IP, SAFI_MPLS_VPN,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
}
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 0bcccb8aa..7aef76d53 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -417,6 +417,39 @@ bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
return as4;
}
+static int
+bgp_capability_addpath (struct peer *peer, struct capability_header *hdr)
+{
+ struct stream *s = BGP_INPUT (peer);
+ size_t end = stream_get_getp (s) + hdr->length;
+
+ SET_FLAG (peer->cap, PEER_CAP_ADDPATH_RCV);
+
+ while (stream_get_getp (s) + 4 <= end)
+ {
+ afi_t afi = stream_getw (s);
+ safi_t safi = stream_getc (s);
+ u_char send_receive = stream_getc (s);
+
+ if (bgp_debug_neighbor_events(peer->host))
+ zlog_debug ("%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s",
+ peer->host, afi, safi,
+ (send_receive & BGP_ADDPATH_RX) ? ", receive" : "",
+ (send_receive & BGP_ADDPATH_TX) ? ", transmit" : "");
+
+ if (!bgp_afi_safi_valid_indices (afi, &safi))
+ return -1;
+
+ if (send_receive & BGP_ADDPATH_RX)
+ SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV);
+
+ if (send_receive & BGP_ADDPATH_TX)
+ SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV);
+ }
+
+ return 0;
+}
+
static const struct message capcode_str[] =
{
{ CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
@@ -424,6 +457,7 @@ static const struct message capcode_str[] =
{ CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
{ CAPABILITY_CODE_RESTART, "Graceful Restart" },
{ CAPABILITY_CODE_AS4, "4-octet AS number" },
+ { CAPABILITY_CODE_ADDPATH, "AddPath" },
{ CAPABILITY_CODE_DYNAMIC, "Dynamic" },
{ CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
{ CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
@@ -438,6 +472,7 @@ static const size_t cap_minsizes[] =
[CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
[CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
[CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
+ [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
[CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
[CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
[CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
@@ -502,6 +537,7 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
case CAPABILITY_CODE_ORF_OLD:
case CAPABILITY_CODE_RESTART:
case CAPABILITY_CODE_AS4:
+ case CAPABILITY_CODE_ADDPATH:
case CAPABILITY_CODE_DYNAMIC:
/* Check length. */
if (caphdr.length < cap_minsizes[caphdr.code])
@@ -572,6 +608,10 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
if (!bgp_capability_as4 (peer, &caphdr))
return -1;
break;
+ case CAPABILITY_CODE_ADDPATH:
+ if (bgp_capability_addpath (peer, &caphdr))
+ return -1;
+ break;
default:
if (caphdr.code > 128)
{
@@ -905,6 +945,7 @@ bgp_open_capability (struct stream *s, struct peer *peer)
safi_t safi;
as_t local_as;
u_int32_t restart_time;
+ u_char afi_safi_count = 0;
/* Remember current pointer for Opt Parm Len. */
cp = stream_get_endp (s);
@@ -1003,6 +1044,30 @@ bgp_open_capability (struct stream *s, struct peer *peer)
local_as = peer->local_as;
stream_putl (s, local_as );
+ /* AddPath
+ * For now we will only advertise RX support. TX support will be added later.
+ */
+ for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ if (peer->afc[afi][safi])
+ afi_safi_count++;
+
+ SET_FLAG (peer->cap, PEER_CAP_ADDPATH_ADV);
+ stream_putc (s, BGP_OPEN_OPT_CAP);
+ stream_putc (s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2);
+ stream_putc (s, CAPABILITY_CODE_ADDPATH);
+ stream_putc (s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count);
+
+ for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ if (peer->afc[afi][safi])
+ {
+ stream_putw (s, afi);
+ stream_putc (s, safi);
+ stream_putc (s, BGP_ADDPATH_RX);
+ SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV);
+ }
+
/* ORF capability. */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index 2b1382d8b..fa9c78ec9 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -73,6 +73,7 @@ struct capability_gr
#define CAPABILITY_CODE_RESTART 64 /* Graceful Restart Capability */
#define CAPABILITY_CODE_AS4 65 /* 4-octet AS number Capability */
#define CAPABILITY_CODE_DYNAMIC 66 /* Dynamic Capability */
+#define CAPABILITY_CODE_ADDPATH 69 /* Addpath Capability */
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
@@ -82,6 +83,7 @@ struct capability_gr
#define CAPABILITY_CODE_DYNAMIC_LEN 0
#define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */
#define CAPABILITY_CODE_AS4_LEN 4
+#define CAPABILITY_CODE_ADDPATH_LEN 4
/* Cooperative Route Filtering Capability. */
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 1d7d2d5f9..7213d1a00 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1796,8 +1796,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* Unfeasible Route packet format check. */
if (withdraw_len > 0)
{
- ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len,
- &num_pfx_wd);
+ ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s),
+ withdraw_len, &num_pfx_wd);
if (ret < 0)
return -1;
@@ -1884,8 +1884,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (update_len)
{
/* Check NLRI packet format and prefix length. */
- ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len,
- &num_pfx_adv);
+ ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s),
+ update_len, &num_pfx_adv);
if (ret < 0)
{
bgp_attr_unintern_sub (&attr);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 76b429dc0..f0b1e5ddf 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2286,9 +2286,10 @@ bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
}
static int
-bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, u_char *tag, int soft_reconfig)
+bgp_update_main (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
+ struct attr *attr, afi_t afi, safi_t safi, int type,
+ int sub_type, struct prefix_rd *prd, u_char *tag,
+ int soft_reconfig)
{
int ret;
int aspath_loop_count = 0;
@@ -2314,7 +2315,8 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
/* Check previously received route. */
for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
+ if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type &&
+ ri->addpath_rx_id == addpath_id)
break;
/* AS path local-as loop check. */
@@ -2541,7 +2543,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
bgp_unlock_node (rn);
return 0;
- }
+ } // End of implicit withdraw
/* Received Logging. */
if (bgp_debug_update(peer, p, 1))
@@ -2590,6 +2592,10 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
else
bgp_info_set_flag (rn, new, BGP_INFO_VALID);
+ /* Addpath ID */
+ new->addpath_rx_id = addpath_id;
+ new->addpath_tx_id = 0;
+
/* Increment prefix */
bgp_aggregate_increment (bgp, p, new, afi, safi);
@@ -2635,8 +2641,8 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
}
int
-bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi, int type, int sub_type,
+bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
+ struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type,
struct prefix_rd *prd, u_char *tag, int soft_reconfig)
{
struct peer *rsclient;
@@ -2644,8 +2650,8 @@ bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
struct bgp *bgp;
int ret;
- ret = bgp_update_main (peer, p, attr, afi, safi, type, sub_type, prd, tag,
- soft_reconfig);
+ ret = bgp_update_main (peer, p, addpath_id, attr, afi, safi, type, sub_type,
+ prd, tag, soft_reconfig);
bgp = peer->bgp;
@@ -2653,17 +2659,17 @@ bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
{
if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- bgp_update_rsclient (rsclient, afi, safi, attr, peer, p, type,
- sub_type, prd, tag);
+ bgp_update_rsclient (rsclient, afi, safi, attr, peer, p,
+ type, sub_type, prd, tag);
}
return ret;
}
int
-bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, u_char *tag)
+bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
+ struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type,
+ struct prefix_rd *prd, u_char *tag)
{
struct bgp *bgp;
char buf[SU_ADDRSTRLEN];
@@ -2678,7 +2684,8 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
{
if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- bgp_withdraw_rsclient (rsclient, afi, safi, peer, p, type, sub_type, prd, tag);
+ bgp_withdraw_rsclient (rsclient, afi, safi, peer, p, type,
+ sub_type, prd, tag);
}
/* Logging. */
@@ -2699,7 +2706,8 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
/* Lookup withdrawn route. */
for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
+ if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type &&
+ ri->addpath_rx_id == addpath_id)
break;
/* Withdraw specified route from routing table. */
@@ -2959,8 +2967,8 @@ bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi,
struct bgp_info *ri = rn->info;
u_char *tag = (ri && ri->extra) ? ri->extra->tag : NULL;
- ret = bgp_update (peer, &rn->p, ain->attr, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
+ ret = bgp_update (peer, &rn->p, ri->addpath_rx_id, ain->attr,
+ afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
prd, tag, 1);
if (ret < 0)
@@ -3343,6 +3351,10 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
struct prefix p;
int psize;
int ret;
+ afi_t afi;
+ safi_t safi;
+ u_char addpath_encoded;
+ u_int32_t addpath_id;
/* Check peer status. */
if (peer->status != Established)
@@ -3350,20 +3362,32 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
pnt = packet->nlri;
lim = pnt + packet->length;
+ afi = packet->afi;
+ safi = packet->safi;
+ addpath_id = 0;
+
+ addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) &&
+ CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV));
for (; pnt < lim; pnt += psize)
{
/* Clear prefix structure. */
memset (&p, 0, sizeof (struct prefix));
+ if (addpath_encoded)
+ {
+ addpath_id = ntohl(*((uint32_t*) pnt));
+ pnt += BGP_ADDPATH_ID_LEN;
+ }
+
/* Fetch prefix length. */
p.prefixlen = *pnt++;
- p.family = afi2family (packet->afi);
+ p.family = afi2family (afi);
/* Already checked in nlri_sanity_check(). We do double check
here. */
- if ((packet->afi == AFI_IP && p.prefixlen > 32)
- || (packet->afi == AFI_IP6 && p.prefixlen > 128))
+ if ((afi == AFI_IP && p.prefixlen > 32)
+ || (afi == AFI_IP6 && p.prefixlen > 128))
return -1;
/* Packet size overflow check. */
@@ -3377,7 +3401,7 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
memcpy (&p.u.prefix, pnt, psize);
/* Check address. */
- if (packet->afi == AFI_IP && packet->safi == SAFI_UNICAST)
+ if (afi == AFI_IP && safi == SAFI_UNICAST)
{
if (IN_CLASSD (ntohl (p.u.prefix4.s_addr)))
{
@@ -3397,7 +3421,7 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
#ifdef HAVE_IPV6
/* Check address. */
- if (packet->afi == AFI_IP6 && packet->safi == SAFI_UNICAST)
+ if (afi == AFI_IP6 && safi == SAFI_UNICAST)
{
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
{
@@ -3413,10 +3437,10 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
/* Normal process. */
if (attr)
- ret = bgp_update (peer, &p, attr, packet->afi, packet->safi,
+ ret = bgp_update (peer, &p, addpath_id, attr, afi, safi,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0);
else
- ret = bgp_withdraw (peer, &p, attr, packet->afi, packet->safi,
+ ret = bgp_withdraw (peer, &p, addpath_id, attr, afi, safi,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL);
/* Address family configuration mismatch or maximum-prefix count
@@ -3434,22 +3458,31 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
/* NLRI encode syntax check routine. */
int
-bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt,
+bgp_nlri_sanity_check (struct peer *peer, int afi, safi_t safi, u_char *pnt,
bgp_size_t length, int *numpfx)
{
u_char *end;
u_char prefixlen;
int psize;
+ u_char addpath_encoded;
*numpfx = 0;
end = pnt + length;
+ addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) &&
+ CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV));
+
/* RFC1771 6.3 The NLRI field in the UPDATE message is checked for
syntactic validity. If the field is syntactically incorrect,
then the Error Subcode is set to Invalid Network Field. */
while (pnt < end)
{
+ /* If the NLRI is encoded using addpath then the first 4 bytes are
+ * the addpath ID. */
+ if (addpath_encoded)
+ pnt += BGP_ADDPATH_ID_LEN;
+
prefixlen = *pnt++;
/* Prefix length check. */
@@ -6563,7 +6596,13 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (binfo->extra && binfo->extra->damp_info)
bgp_damp_info_vty (vty, binfo);
- /* Line 7 display Uptime */
+ /* Line 7 display Addpath IDs */
+ if (binfo->addpath_rx_id || binfo->addpath_tx_id)
+ vty_out (vty, " AddPath ID: RX %u, TX %u%s",
+ binfo->addpath_rx_id, binfo->addpath_tx_id,
+ VTY_NEWLINE);
+
+ /* Line 8 display Uptime */
#ifdef HAVE_CLOCK_MONOTONIC
tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
vty_out (vty, " Last update: %s", ctime(&tbuf));
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index f452ea254..c35b5f111 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -108,6 +108,10 @@ struct bgp_info
u_short instance;
+ /* Addpath identifiers */
+ u_int32_t addpath_rx_id;
+ u_int32_t addpath_tx_id;
+
};
/* BGP static route configuration. */
@@ -220,7 +224,7 @@ extern struct bgp_info_extra *bgp_info_extra_get (struct bgp_info *);
extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
-extern int bgp_nlri_sanity_check (struct peer *, int, u_char *, bgp_size_t, int *);
+extern int bgp_nlri_sanity_check (struct peer *, int, safi_t, u_char *, bgp_size_t, int *);
extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
@@ -243,10 +247,10 @@ extern int bgp_static_unset_vpnv4 (struct vty *, const char *,
const char *, const char *);
/* this is primarily for MPLS-VPN */
-extern int bgp_update (struct peer *, struct prefix *, struct attr *,
+extern int bgp_update (struct peer *, struct prefix *, u_int32_t, struct attr *,
afi_t, safi_t, int, int, struct prefix_rd *,
u_char *, int);
-extern int bgp_withdraw (struct peer *, struct prefix *, struct attr *,
+extern int bgp_withdraw (struct peer *, struct prefix *, u_int32_t, struct attr *,
afi_t, safi_t, int, int, struct prefix_rd *, u_char *);
/* for bgp_nexthop and bgp_damp */
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index a7b5a90ba..348687d38 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -8645,6 +8645,47 @@ bgp_show_peer (struct vty *vty, struct peer *p)
CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV) ? "and " : "");
vty_out (vty, "%s", VTY_NEWLINE);
}
+
+ /* AddPath */
+ if (CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_RCV)
+ || CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_ADV))
+ {
+ vty_out (vty, " AddPath:%s", VTY_NEWLINE);
+
+ for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) ||
+ CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV))
+ {
+ vty_out (vty, " %s: TX ", afi_safi_print (afi, safi));
+
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV))
+ vty_out (vty, "advertised", afi_safi_print (afi, safi));
+
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV))
+ vty_out (vty, "%sreceived", CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) ? " and " : "" );
+
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) ||
+ CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV))
+ {
+ vty_out (vty, " %s: RX ", afi_safi_print (afi, safi));
+
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV))
+ vty_out (vty, "advertised", afi_safi_print (afi, safi));
+
+ if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV))
+ vty_out (vty, "%sreceived", CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) ? " and " : "" );
+
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+ }
+ }
+
/* Dynamic */
if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
|| CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 94540749b..6eafb59b2 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -272,6 +272,11 @@ struct bgp_nexthop
#endif /* HAVE_IPV6 */
};
+/* BGP addpath values */
+#define BGP_ADDPATH_RX 1
+#define BGP_ADDPATH_TX 2
+#define BGP_ADDPATH_ID_LEN 4
+
/* BGP router distinguisher value. */
#define BGP_RD_SIZE 8
@@ -442,6 +447,8 @@ struct peer
#define PEER_CAP_AS4_RCV (1 << 8) /* as4 received */
#define PEER_CAP_RESTART_BIT_ADV (1 << 9) /* sent restart state */
#define PEER_CAP_RESTART_BIT_RCV (1 << 10) /* peer restart state */
+#define PEER_CAP_ADDPATH_ADV (1 << 11) /* addpath advertised */
+#define PEER_CAP_ADDPATH_RCV (1 << 12) /* addpath received */
/* Capability flags (reset in bgp_stop) */
u_int16_t af_cap[AFI_MAX][SAFI_MAX];
@@ -453,6 +460,10 @@ struct peer
#define PEER_CAP_ORF_PREFIX_RM_OLD_RCV (1 << 5) /* receive-mode received */
#define PEER_CAP_RESTART_AF_RCV (1 << 6) /* graceful restart afi/safi received */
#define PEER_CAP_RESTART_AF_PRESERVE_RCV (1 << 7) /* graceful restart afi/safi F-bit received */
+#define PEER_CAP_ADDPATH_AF_TX_ADV (1 << 8) /* addpath tx advertised */
+#define PEER_CAP_ADDPATH_AF_TX_RCV (1 << 9) /* addpath tx received */
+#define PEER_CAP_ADDPATH_AF_RX_ADV (1 << 10) /* addpath rx advertised */
+#define PEER_CAP_ADDPATH_AF_RX_RCV (1 << 11) /* addpath rx received */
/* Global configuration flags. */
u_int32_t flags;