forked from Mirror/frr
bgpd: Handle multiple PREFIX_SID's at a time.
Handle multiple PREFIX_SID's at the same time. The draft clearly states that multiple should be handled and we have a actual pcap file that clearly has multiple PREFIX_SID's at the same time. Fixes: #2153 Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
d71b0564c2
commit
30adbd4e4f
|
@ -2021,36 +2021,32 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Prefix SID attribute
|
||||
* draft-ietf-idr-bgp-prefix-sid-05
|
||||
/*
|
||||
* Read an individual SID value returning how much data we have read
|
||||
* Returns 0 if there was an error that needs to be passed up the stack
|
||||
*/
|
||||
static bgp_attr_parse_ret_t
|
||||
bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *mp_update)
|
||||
static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
|
||||
int32_t length,
|
||||
struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *mp_update)
|
||||
{
|
||||
struct peer *const peer = args->peer;
|
||||
struct attr *const attr = args->attr;
|
||||
int type;
|
||||
int length;
|
||||
uint32_t label_index;
|
||||
struct in6_addr ipv6_sid;
|
||||
uint32_t srgb_base;
|
||||
uint32_t srgb_range;
|
||||
int srgb_count;
|
||||
|
||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
|
||||
|
||||
type = stream_getc(peer->curr);
|
||||
length = stream_getw(peer->curr);
|
||||
|
||||
if (type == BGP_PREFIX_SID_LABEL_INDEX) {
|
||||
if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
|
||||
zlog_err(
|
||||
"Prefix SID label index length is %d instead of %d",
|
||||
length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
|
||||
return bgp_attr_malformed(
|
||||
args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||
args->total);
|
||||
"Prefix SID label index length is %d instead of %d",
|
||||
length,
|
||||
BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
|
||||
return bgp_attr_malformed(args,
|
||||
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||
args->total);
|
||||
}
|
||||
|
||||
/* Ignore flags and reserved */
|
||||
|
@ -2060,9 +2056,8 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
|
|||
/* Fetch the label index and see if it is valid. */
|
||||
label_index = stream_getl(peer->curr);
|
||||
if (label_index == BGP_INVALID_LABEL_INDEX)
|
||||
return bgp_attr_malformed(
|
||||
args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
||||
args->total);
|
||||
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
||||
args->total);
|
||||
|
||||
/* Store label index; subsequently, we'll check on
|
||||
* address-family */
|
||||
|
@ -2083,9 +2078,9 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
|
|||
if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
|
||||
zlog_err("Prefix SID IPv6 length is %d instead of %d",
|
||||
length, BGP_PREFIX_SID_IPV6_LENGTH);
|
||||
return bgp_attr_malformed(
|
||||
args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||
args->total);
|
||||
return bgp_attr_malformed(args,
|
||||
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||
args->total);
|
||||
}
|
||||
|
||||
/* Ignore reserved */
|
||||
|
@ -2122,6 +2117,47 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
|
|||
return BGP_ATTR_PARSE_PROCEED;
|
||||
}
|
||||
|
||||
/* Prefix SID attribute
|
||||
* draft-ietf-idr-bgp-prefix-sid-05
|
||||
*/
|
||||
bgp_attr_parse_ret_t
|
||||
bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *mp_update)
|
||||
{
|
||||
struct peer *const peer = args->peer;
|
||||
struct attr *const attr = args->attr;
|
||||
bgp_attr_parse_ret_t ret;
|
||||
|
||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
|
||||
|
||||
while (tlength) {
|
||||
int32_t type, length;
|
||||
|
||||
type = stream_getc(peer->curr);
|
||||
length = stream_getw(peer->curr);
|
||||
|
||||
ret = bgp_attr_psid_sub(type, length, args, mp_update);
|
||||
|
||||
if (ret != BGP_ATTR_PARSE_PROCEED)
|
||||
return ret;
|
||||
/*
|
||||
* Subtract length + the T and the L
|
||||
* since length is the Vector portion
|
||||
*/
|
||||
tlength -= length + 3;
|
||||
|
||||
if (tlength < 0) {
|
||||
zlog_err("Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
|
||||
length);
|
||||
return bgp_attr_malformed(args,
|
||||
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||
args->total);
|
||||
}
|
||||
}
|
||||
|
||||
return BGP_ATTR_PARSE_PROCEED;
|
||||
}
|
||||
|
||||
/* PMSI tunnel attribute (RFC 6514)
|
||||
* Basic validation checks done here.
|
||||
*/
|
||||
|
@ -2498,7 +2534,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
|
|||
startp);
|
||||
break;
|
||||
case BGP_ATTR_PREFIX_SID:
|
||||
ret = bgp_attr_prefix_sid(&attr_args, mp_update);
|
||||
ret = bgp_attr_prefix_sid(length,
|
||||
&attr_args, mp_update);
|
||||
break;
|
||||
case BGP_ATTR_PMSI_TUNNEL:
|
||||
ret = bgp_attr_pmsi_tunnel(&attr_args);
|
||||
|
|
|
@ -308,6 +308,9 @@ extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
|
|||
struct bgp_nlri *);
|
||||
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *);
|
||||
extern bgp_attr_parse_ret_t
|
||||
bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *mp_update);
|
||||
|
||||
extern struct bgp_attr_encap_subtlv *
|
||||
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
|
||||
|
|
Loading…
Reference in a new issue