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;
|
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
|
static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
|
||||||
bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
|
int32_t length,
|
||||||
struct bgp_nlri *mp_update)
|
struct bgp_attr_parser_args *args,
|
||||||
|
struct bgp_nlri *mp_update)
|
||||||
{
|
{
|
||||||
struct peer *const peer = args->peer;
|
struct peer *const peer = args->peer;
|
||||||
struct attr *const attr = args->attr;
|
struct attr *const attr = args->attr;
|
||||||
int type;
|
|
||||||
int length;
|
|
||||||
uint32_t label_index;
|
uint32_t label_index;
|
||||||
struct in6_addr ipv6_sid;
|
struct in6_addr ipv6_sid;
|
||||||
uint32_t srgb_base;
|
uint32_t srgb_base;
|
||||||
uint32_t srgb_range;
|
uint32_t srgb_range;
|
||||||
int srgb_count;
|
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 (type == BGP_PREFIX_SID_LABEL_INDEX) {
|
||||||
if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
|
if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
|
||||||
zlog_err(
|
zlog_err(
|
||||||
"Prefix SID label index length is %d instead of %d",
|
"Prefix SID label index length is %d instead of %d",
|
||||||
length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
|
length,
|
||||||
return bgp_attr_malformed(
|
BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
|
||||||
args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
return bgp_attr_malformed(args,
|
||||||
args->total);
|
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||||
|
args->total);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore flags and reserved */
|
/* 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. */
|
/* Fetch the label index and see if it is valid. */
|
||||||
label_index = stream_getl(peer->curr);
|
label_index = stream_getl(peer->curr);
|
||||||
if (label_index == BGP_INVALID_LABEL_INDEX)
|
if (label_index == BGP_INVALID_LABEL_INDEX)
|
||||||
return bgp_attr_malformed(
|
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
||||||
args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
|
args->total);
|
||||||
args->total);
|
|
||||||
|
|
||||||
/* Store label index; subsequently, we'll check on
|
/* Store label index; subsequently, we'll check on
|
||||||
* address-family */
|
* address-family */
|
||||||
|
@ -2083,9 +2078,9 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
|
||||||
if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
|
if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
|
||||||
zlog_err("Prefix SID IPv6 length is %d instead of %d",
|
zlog_err("Prefix SID IPv6 length is %d instead of %d",
|
||||||
length, BGP_PREFIX_SID_IPV6_LENGTH);
|
length, BGP_PREFIX_SID_IPV6_LENGTH);
|
||||||
return bgp_attr_malformed(
|
return bgp_attr_malformed(args,
|
||||||
args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
|
||||||
args->total);
|
args->total);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore reserved */
|
/* Ignore reserved */
|
||||||
|
@ -2122,6 +2117,47 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
|
||||||
return BGP_ATTR_PARSE_PROCEED;
|
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)
|
/* PMSI tunnel attribute (RFC 6514)
|
||||||
* Basic validation checks done here.
|
* Basic validation checks done here.
|
||||||
*/
|
*/
|
||||||
|
@ -2498,7 +2534,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
|
||||||
startp);
|
startp);
|
||||||
break;
|
break;
|
||||||
case BGP_ATTR_PREFIX_SID:
|
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;
|
break;
|
||||||
case BGP_ATTR_PMSI_TUNNEL:
|
case BGP_ATTR_PMSI_TUNNEL:
|
||||||
ret = bgp_attr_pmsi_tunnel(&attr_args);
|
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 *);
|
struct bgp_nlri *);
|
||||||
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
|
extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
|
||||||
struct bgp_nlri *);
|
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 *
|
extern struct bgp_attr_encap_subtlv *
|
||||||
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
|
encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
|
||||||
|
|
Loading…
Reference in a new issue