BGP: add addpath RX support

This commit is contained in:
Donald Sharp 2015-05-19 18:03:45 -07:00
parent 0e5c866a48
commit a82478b985
9 changed files with 218 additions and 40 deletions

View File

@ -1607,8 +1607,8 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
if (safi != SAFI_MPLS_LABELED_VPN) if (safi != SAFI_MPLS_LABELED_VPN)
{ {
ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len, ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
&num_mp_pfx); nlri_len, &num_mp_pfx);
if (ret < 0) if (ret < 0)
{ {
zlog_info ("%s: (%s) NLRI doesn't pass sanity check", 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) if (safi != SAFI_MPLS_LABELED_VPN)
{ {
ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len, ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
&num_mp_pfx); withdraw_len, &num_mp_pfx);
if (ret < 0) if (ret < 0)
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
} }

View File

@ -90,6 +90,10 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
struct rd_ip rd_ip; struct rd_ip rd_ip;
struct prefix_rd prd; struct prefix_rd prd;
u_char *tagpnt; u_char *tagpnt;
afi_t afi;
safi_t safi;
u_char addpath_encoded;
u_int32_t addpath_id;
/* Check peer status. */ /* Check peer status. */
if (peer->status != Established) if (peer->status != Established)
@ -101,12 +105,24 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
pnt = packet->nlri; pnt = packet->nlri;
lim = pnt + packet->length; 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) for (; pnt < lim; pnt += psize)
{ {
/* Clear prefix structure. */ /* Clear prefix structure. */
memset (&p, 0, sizeof (struct prefix)); memset (&p, 0, sizeof (struct prefix));
if (addpath_encoded)
{
addpath_id = ntohl(*((uint32_t*) pnt));
pnt += BGP_ADDPATH_ID_LEN;
}
/* Fetch prefix length. */ /* Fetch prefix length. */
prefixlen = *pnt++; prefixlen = *pnt++;
p.family = AF_INET; p.family = AF_INET;
@ -156,10 +172,10 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
return -1; return -1;
if (attr) 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); ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
else 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); ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
} }

View File

@ -417,6 +417,39 @@ bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
return as4; 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[] = static const struct message capcode_str[] =
{ {
{ CAPABILITY_CODE_MP, "MultiProtocol Extensions" }, { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
@ -424,6 +457,7 @@ static const struct message capcode_str[] =
{ CAPABILITY_CODE_ORF, "Cooperative Route Filtering" }, { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
{ CAPABILITY_CODE_RESTART, "Graceful Restart" }, { CAPABILITY_CODE_RESTART, "Graceful Restart" },
{ CAPABILITY_CODE_AS4, "4-octet AS number" }, { CAPABILITY_CODE_AS4, "4-octet AS number" },
{ CAPABILITY_CODE_ADDPATH, "AddPath" },
{ CAPABILITY_CODE_DYNAMIC, "Dynamic" }, { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
{ CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" }, { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
{ CAPABILITY_CODE_ORF_OLD, "ORF (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_ORF] = sizeof (struct capability_orf_entry),
[CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr), [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
[CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
[CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
[CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
[CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
[CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry), [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_ORF_OLD:
case CAPABILITY_CODE_RESTART: case CAPABILITY_CODE_RESTART:
case CAPABILITY_CODE_AS4: case CAPABILITY_CODE_AS4:
case CAPABILITY_CODE_ADDPATH:
case CAPABILITY_CODE_DYNAMIC: case CAPABILITY_CODE_DYNAMIC:
/* Check length. */ /* Check length. */
if (caphdr.length < cap_minsizes[caphdr.code]) 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)) if (!bgp_capability_as4 (peer, &caphdr))
return -1; return -1;
break; break;
case CAPABILITY_CODE_ADDPATH:
if (bgp_capability_addpath (peer, &caphdr))
return -1;
break;
default: default:
if (caphdr.code > 128) if (caphdr.code > 128)
{ {
@ -905,6 +945,7 @@ bgp_open_capability (struct stream *s, struct peer *peer)
safi_t safi; safi_t safi;
as_t local_as; as_t local_as;
u_int32_t restart_time; u_int32_t restart_time;
u_char afi_safi_count = 0;
/* Remember current pointer for Opt Parm Len. */ /* Remember current pointer for Opt Parm Len. */
cp = stream_get_endp (s); cp = stream_get_endp (s);
@ -1003,6 +1044,30 @@ bgp_open_capability (struct stream *s, struct peer *peer)
local_as = peer->local_as; local_as = peer->local_as;
stream_putl (s, 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. */ /* ORF capability. */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++) for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)

View File

@ -73,6 +73,7 @@ struct capability_gr
#define CAPABILITY_CODE_RESTART 64 /* Graceful Restart Capability */ #define CAPABILITY_CODE_RESTART 64 /* Graceful Restart Capability */
#define CAPABILITY_CODE_AS4 65 /* 4-octet AS number Capability */ #define CAPABILITY_CODE_AS4 65 /* 4-octet AS number Capability */
#define CAPABILITY_CODE_DYNAMIC 66 /* Dynamic 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_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering 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_DYNAMIC_LEN 0
#define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */ #define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */
#define CAPABILITY_CODE_AS4_LEN 4 #define CAPABILITY_CODE_AS4_LEN 4
#define CAPABILITY_CODE_ADDPATH_LEN 4
/* Cooperative Route Filtering Capability. */ /* Cooperative Route Filtering Capability. */

View File

@ -1796,8 +1796,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
/* Unfeasible Route packet format check. */ /* Unfeasible Route packet format check. */
if (withdraw_len > 0) if (withdraw_len > 0)
{ {
ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len, ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s),
&num_pfx_wd); withdraw_len, &num_pfx_wd);
if (ret < 0) if (ret < 0)
return -1; return -1;
@ -1884,8 +1884,8 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (update_len) if (update_len)
{ {
/* Check NLRI packet format and prefix length. */ /* Check NLRI packet format and prefix length. */
ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len, ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s),
&num_pfx_adv); update_len, &num_pfx_adv);
if (ret < 0) if (ret < 0)
{ {
bgp_attr_unintern_sub (&attr); bgp_attr_unintern_sub (&attr);

View File

@ -2286,9 +2286,10 @@ bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
} }
static int static int
bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, bgp_update_main (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
afi_t afi, safi_t safi, int type, int sub_type, struct attr *attr, afi_t afi, safi_t safi, int type,
struct prefix_rd *prd, u_char *tag, int soft_reconfig) int sub_type, struct prefix_rd *prd, u_char *tag,
int soft_reconfig)
{ {
int ret; int ret;
int aspath_loop_count = 0; 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. */ /* Check previously received route. */
for (ri = rn->info; ri; ri = ri->next) 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; break;
/* AS path local-as loop check. */ /* 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); bgp_unlock_node (rn);
return 0; return 0;
} } // End of implicit withdraw
/* Received Logging. */ /* Received Logging. */
if (bgp_debug_update(peer, p, 1)) if (bgp_debug_update(peer, p, 1))
@ -2590,6 +2592,10 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
else else
bgp_info_set_flag (rn, new, BGP_INFO_VALID); bgp_info_set_flag (rn, new, BGP_INFO_VALID);
/* Addpath ID */
new->addpath_rx_id = addpath_id;
new->addpath_tx_id = 0;
/* Increment prefix */ /* Increment prefix */
bgp_aggregate_increment (bgp, p, new, afi, safi); 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 int
bgp_update (struct peer *peer, struct prefix *p, struct attr *attr, bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
afi_t afi, safi_t safi, int type, int sub_type, 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 prefix_rd *prd, u_char *tag, int soft_reconfig)
{ {
struct peer *rsclient; struct peer *rsclient;
@ -2644,8 +2650,8 @@ bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
struct bgp *bgp; struct bgp *bgp;
int ret; int ret;
ret = bgp_update_main (peer, p, attr, afi, safi, type, sub_type, prd, tag, ret = bgp_update_main (peer, p, addpath_id, attr, afi, safi, type, sub_type,
soft_reconfig); prd, tag, soft_reconfig);
bgp = peer->bgp; 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)) for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
{ {
if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
bgp_update_rsclient (rsclient, afi, safi, attr, peer, p, type, bgp_update_rsclient (rsclient, afi, safi, attr, peer, p,
sub_type, prd, tag); type, sub_type, prd, tag);
} }
return ret; return ret;
} }
int int
bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
afi_t afi, safi_t safi, int type, int sub_type, struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type,
struct prefix_rd *prd, u_char *tag) struct prefix_rd *prd, u_char *tag)
{ {
struct bgp *bgp; struct bgp *bgp;
char buf[SU_ADDRSTRLEN]; 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)) for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
{ {
if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) 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. */ /* Logging. */
@ -2699,7 +2706,8 @@ bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
/* Lookup withdrawn route. */ /* Lookup withdrawn route. */
for (ri = rn->info; ri; ri = ri->next) 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; break;
/* Withdraw specified route from routing table. */ /* 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; struct bgp_info *ri = rn->info;
u_char *tag = (ri && ri->extra) ? ri->extra->tag : NULL; u_char *tag = (ri && ri->extra) ? ri->extra->tag : NULL;
ret = bgp_update (peer, &rn->p, ain->attr, afi, safi, ret = bgp_update (peer, &rn->p, ri->addpath_rx_id, ain->attr,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
prd, tag, 1); prd, tag, 1);
if (ret < 0) if (ret < 0)
@ -3343,6 +3351,10 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
struct prefix p; struct prefix p;
int psize; int psize;
int ret; int ret;
afi_t afi;
safi_t safi;
u_char addpath_encoded;
u_int32_t addpath_id;
/* Check peer status. */ /* Check peer status. */
if (peer->status != Established) if (peer->status != Established)
@ -3350,20 +3362,32 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
pnt = packet->nlri; pnt = packet->nlri;
lim = pnt + packet->length; 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) for (; pnt < lim; pnt += psize)
{ {
/* Clear prefix structure. */ /* Clear prefix structure. */
memset (&p, 0, sizeof (struct prefix)); memset (&p, 0, sizeof (struct prefix));
if (addpath_encoded)
{
addpath_id = ntohl(*((uint32_t*) pnt));
pnt += BGP_ADDPATH_ID_LEN;
}
/* Fetch prefix length. */ /* Fetch prefix length. */
p.prefixlen = *pnt++; p.prefixlen = *pnt++;
p.family = afi2family (packet->afi); p.family = afi2family (afi);
/* Already checked in nlri_sanity_check(). We do double check /* Already checked in nlri_sanity_check(). We do double check
here. */ here. */
if ((packet->afi == AFI_IP && p.prefixlen > 32) if ((afi == AFI_IP && p.prefixlen > 32)
|| (packet->afi == AFI_IP6 && p.prefixlen > 128)) || (afi == AFI_IP6 && p.prefixlen > 128))
return -1; return -1;
/* Packet size overflow check. */ /* 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); memcpy (&p.u.prefix, pnt, psize);
/* Check address. */ /* 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))) 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 #ifdef HAVE_IPV6
/* Check address. */ /* 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)) 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. */ /* Normal process. */
if (attr) 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); ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0);
else 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); ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL);
/* Address family configuration mismatch or maximum-prefix count /* 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. */ /* NLRI encode syntax check routine. */
int 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) bgp_size_t length, int *numpfx)
{ {
u_char *end; u_char *end;
u_char prefixlen; u_char prefixlen;
int psize; int psize;
u_char addpath_encoded;
*numpfx = 0; *numpfx = 0;
end = pnt + length; 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 /* RFC1771 6.3 The NLRI field in the UPDATE message is checked for
syntactic validity. If the field is syntactically incorrect, syntactic validity. If the field is syntactically incorrect,
then the Error Subcode is set to Invalid Network Field. */ then the Error Subcode is set to Invalid Network Field. */
while (pnt < end) 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++; prefixlen = *pnt++;
/* Prefix length check. */ /* 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) if (binfo->extra && binfo->extra->damp_info)
bgp_damp_info_vty (vty, binfo); 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 #ifdef HAVE_CLOCK_MONOTONIC
tbuf = time(NULL) - (bgp_clock() - binfo->uptime); tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
vty_out (vty, " Last update: %s", ctime(&tbuf)); vty_out (vty, " Last update: %s", ctime(&tbuf));

View File

@ -108,6 +108,10 @@ struct bgp_info
u_short instance; u_short instance;
/* Addpath identifiers */
u_int32_t addpath_rx_id;
u_int32_t addpath_tx_id;
}; };
/* BGP static route configuration. */ /* 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_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 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_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int); 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 *); const char *, const char *);
/* this is primarily for MPLS-VPN */ /* 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 *, afi_t, safi_t, int, int, struct prefix_rd *,
u_char *, int); 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 *); afi_t, safi_t, int, int, struct prefix_rd *, u_char *);
/* for bgp_nexthop and bgp_damp */ /* for bgp_nexthop and bgp_damp */

View File

@ -8645,6 +8645,47 @@ bgp_show_peer (struct vty *vty, struct peer *p)
CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV) ? "and " : ""); CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV) ? "and " : "");
vty_out (vty, "%s", VTY_NEWLINE); 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 */ /* Dynamic */
if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV) if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
|| CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV)) || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))

View File

@ -272,6 +272,11 @@ struct bgp_nexthop
#endif /* HAVE_IPV6 */ #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. */ /* BGP router distinguisher value. */
#define BGP_RD_SIZE 8 #define BGP_RD_SIZE 8
@ -442,6 +447,8 @@ struct peer
#define PEER_CAP_AS4_RCV (1 << 8) /* as4 received */ #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_ADV (1 << 9) /* sent restart state */
#define PEER_CAP_RESTART_BIT_RCV (1 << 10) /* peer 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) */ /* Capability flags (reset in bgp_stop) */
u_int16_t af_cap[AFI_MAX][SAFI_MAX]; 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_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_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_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. */ /* Global configuration flags. */
u_int32_t flags; u_int32_t flags;