Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions bgpd/bgp_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3582,7 +3582,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
uint8_t tnl_type;
int attr_parse_len = 2 + BGP_LABEL_BYTES;
int attr_parse_len = 2 + MPLS_LABEL_LEN_BYTES;

if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
goto pmsi_tunnel_ignore;
Expand Down Expand Up @@ -3617,7 +3617,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)

bgp_attr_set(attr, BGP_ATTR_PMSI_TUNNEL);
bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
stream_get(&attr->label, connection->curr, BGP_LABEL_BYTES);
stream_get(&attr->label, connection->curr, MPLS_LABEL_LEN_BYTES);

/* Forward read pointer of input stream. */
stream_forward_getp(connection->curr, length - attr_parse_len);
Expand Down Expand Up @@ -4752,7 +4752,7 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
stream_putl(s, addpath_tx_id);
/* Label, RD, Prefix write. */
stream_putc(s, p->prefixlen + 88);
stream_put(s, label, BGP_LABEL_BYTES);
stream_put(s, label, MPLS_LABEL_LEN_BYTES);
stream_put(s, prd->val, 8);
stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
break;
Expand All @@ -4767,8 +4767,7 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
break;
case SAFI_LABELED_UNICAST:
/* Prefix write with label. */
stream_put_labeled_prefix(s, p, label, addpath_capable,
addpath_tx_id);
stream_put_labeled_prefix(s, p, label, num_labels, addpath_capable, addpath_tx_id);
break;
case SAFI_FLOWSPEC:
stream_putc(s, p->u.prefix_flowspec.prefixlen);
Expand Down Expand Up @@ -4807,7 +4806,11 @@ size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
assert(!"Do we try to use this?");
break;
case SAFI_LABELED_UNICAST:
size += BGP_LABEL_BYTES;
/*
* Length of all labels + prefix is given in bits in one octet,
* so maximum 256 bits, 32 bytes
*/
size += 32 - PSIZE(p->prefixlen);
break;
case SAFI_EVPN:
/*
Expand Down Expand Up @@ -5431,7 +5434,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct strea
stream_putc(s, 0); // Flags
stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr));
stream_put(s, &(attr->label),
BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
MPLS_LABEL_LEN_BYTES); // MPLS Label / VXLAN VNI
stream_put_ipv4(s, attr->nexthop.s_addr);
// Unicast tunnel endpoint IP address
}
Expand Down
6 changes: 1 addition & 5 deletions bgpd/bgp_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -2965,11 +2965,7 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
snprintf(tag_buf, sizeof(tag_buf), " label %s",
tag_buf2);
} else {
uint32_t label_value;

label_value = decode_label(label);
snprintf(tag_buf, sizeof(tag_buf), " label %u",
label_value);
mpls_labels2str(label, num_labels, " label ", tag_buf, sizeof(tag_buf));
}
}

Expand Down
16 changes: 8 additions & 8 deletions bgpd/bgp_evpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -4988,13 +4988,13 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
}

/* Get the VNI(s). Stored as bytes here. */
STREAM_GET(&label[0], pkt, BGP_LABEL_BYTES);
STREAM_GET(&label[0], pkt, MPLS_LABEL_LEN_BYTES);
num_labels++;

/* Do we have a second VNI? */
if (STREAM_READABLE(pkt)) {
num_labels++;
STREAM_GET(&label[1], pkt, BGP_LABEL_BYTES);
STREAM_GET(&label[1], pkt, MPLS_LABEL_LEN_BYTES);
}

/* Process the route. */
Expand Down Expand Up @@ -5187,11 +5187,11 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,

/* Get the VNI (in MPLS label field). Stored as bytes here. */
memset(&label, 0, sizeof(label));
memcpy(&label, pfx, BGP_LABEL_BYTES);
memcpy(&label, pfx, MPLS_LABEL_LEN_BYTES);

/*
* If in future, we are required to access additional fields,
* we MUST increment pfx by BGP_LABEL_BYTES in before reading the next
* we MUST increment pfx by MPLS_LABEL_LEN_BYTES in before reading the next
* field
*/

Expand Down Expand Up @@ -6157,10 +6157,10 @@ void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
stream_put(s, &evp->prefix.macip_addr.ip.ip.addr,
ipa_len);
/* 1st label is the L2 VNI */
stream_put(s, label, BGP_LABEL_BYTES);
stream_put(s, label, MPLS_LABEL_LEN_BYTES);
/* Include 2nd label (L3 VNI) if advertising MAC+IP */
if (ipa_len && num_labels > 1)
stream_put(s, label + 1, BGP_LABEL_BYTES);
stream_put(s, label + 1, MPLS_LABEL_LEN_BYTES);
break;

case BGP_EVPN_IMET_ROUTE:
Expand Down Expand Up @@ -6198,12 +6198,12 @@ void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,

case BGP_EVPN_AD_ROUTE:
/* RD, ESI, EthTag, 1 VNI */
len = RD_BYTES + ESI_BYTES + EVPN_ETH_TAG_BYTES + BGP_LABEL_BYTES;
len = RD_BYTES + ESI_BYTES + EVPN_ETH_TAG_BYTES + MPLS_LABEL_LEN_BYTES;
stream_putc(s, len);
stream_put(s, prd->val, RD_BYTES); /* RD */
stream_put(s, evp->prefix.ead_addr.esi.val, ESI_BYTES); /* ESI */
stream_putl(s, evp->prefix.ead_addr.eth_tag); /* Ethernet Tag */
stream_put(s, label, BGP_LABEL_BYTES);
stream_put(s, label, MPLS_LABEL_LEN_BYTES);
break;

case BGP_EVPN_IP_PREFIX_ROUTE:
Expand Down
2 changes: 1 addition & 1 deletion bgpd/bgp_evpn_mh.c
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
eth_tag = ntohl(eth_tag);
pfx += EVPN_ETH_TAG_BYTES;

memcpy(&label[0], pfx, BGP_LABEL_BYTES);
memcpy(&label[0], pfx, MPLS_LABEL_LEN_BYTES);

/* EAD route prefix doesn't include the nexthop in the global
* table
Expand Down
124 changes: 89 additions & 35 deletions bgpd/bgp_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,32 +198,40 @@ int bgp_parse_fec_update(void)
return 1;
}

mpls_label_t bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi,
struct peer *to, afi_t afi, safi_t safi)
void bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi, struct peer *to, afi_t afi,
safi_t safi, mpls_label_t *labels, uint8_t *num_labels)
{
struct peer *from;
mpls_label_t remote_label;
int reflect;
uint8_t i;
bool use_local_label = true;

if (!dest || !pi || !to)
return MPLS_INVALID_LABEL;
labels[0] = MPLS_INVALID_LABEL;
if (!dest || !pi || !to) {
*num_labels = 0;
return;
}

remote_label = BGP_PATH_INFO_NUM_LABELS(pi)
? pi->extra->labels->label[0]
: MPLS_INVALID_LABEL;
from = pi->peer;
reflect =
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));

if (reflect
&& !CHECK_FLAG(to->af_flags[afi][safi],
PEER_FLAG_FORCE_NEXTHOP_SELF))
return remote_label;
use_local_label = false;

if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
return remote_label;
use_local_label = false;

return dest->local_label;
if (use_local_label) {
*num_labels = 1;
labels[0] = dest->local_label;
} else {
*num_labels = BGP_PATH_INFO_NUM_LABELS(pi);
for (i = 0; i < *num_labels; i++)
labels[i] = pi->extra->labels->label[i];
}
}

static void bgp_send_fec_register_label_msg(struct bgp_dest *dest, bool reg,
Expand Down Expand Up @@ -413,35 +421,50 @@ void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi,
dest, reg, with_label_index ? pi->attr->label_index : 0);
}

static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen,
mpls_label_t *label)
/* Labels must have BGP_MAX_LABELS elements */
static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen, mpls_label_t *labels,
uint8_t *num_labels)
{
uint8_t *data = pnt;
uint8_t *lim = pnt + plen;
uint8_t llen = 0;
uint8_t label_depth = 0;
mpls_label_t *label_pnt;
mpls_label_t label;

if (plen < BGP_LABEL_BYTES)
if (plen < MPLS_LABEL_LEN_BYTES)
return 0;

for (; data < lim; data += BGP_LABEL_BYTES) {
memcpy(label, data, BGP_LABEL_BYTES);
llen += BGP_LABEL_BYTES;
label_pnt = &labels[0];
for (; data < lim; data += MPLS_LABEL_LEN_BYTES, label_pnt++) {
/*
* Support only BGP_MAX_LABELS, read rest to local variable and
* discard, shouldn't be possible - see comment to BGP_MAX_LABELS
*/
if (label_depth >= BGP_MAX_LABELS)
label_pnt = &label;

memcpy(label_pnt, data, MPLS_LABEL_LEN_BYTES);
llen += MPLS_LABEL_LEN_BYTES;

bgp_set_valid_label(label_pnt);

bgp_set_valid_label(label);
label_depth += 1;

if (bgp_is_withdraw_label(label) || label_bos(label))
if (bgp_is_withdraw_label(label_pnt) || label_bos(label_pnt))
break;
}

/* If we RX multiple labels we will end up keeping only the last
* one. We do not yet support a label stack greater than 1. */
if (label_depth > 1)
zlog_info("%pBP rcvd UPDATE with label stack %d deep", peer,
label_depth);
*num_labels = label_depth;

if (label_depth > BGP_MAX_LABELS) {
*num_labels = BGP_MAX_LABELS;
label_set_bos(&labels[*num_labels - 1]);
zlog_info("%pBP rcvd UPDATE with label stack %d deep, using only first %d labels",
peer, label_depth, BGP_MAX_LABELS);
}

if (!(bgp_is_withdraw_label(label) || label_bos(label)))
if (!(bgp_is_withdraw_label(label_pnt) || label_bos(label_pnt)))
flog_warn(
EC_BGP_INVALID_LABEL_STACK,
"%pBP rcvd UPDATE with invalid label stack - no bottom of stack",
Expand All @@ -462,7 +485,8 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
safi_t safi;
bool addpath_capable;
uint32_t addpath_id;
mpls_label_t label = MPLS_INVALID_LABEL;
mpls_label_t labels[MPLS_MAX_LABELS] = { MPLS_INVALID_LABEL };
uint8_t num_labels = 0;
uint8_t llen;

pnt = packet->nlri;
Expand Down Expand Up @@ -506,7 +530,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
}

/* Fill in the labels */
llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
llen = bgp_nlri_get_labels(peer, pnt, psize, labels, &num_labels);
if (llen == 0) {
flog_err(
EC_BGP_UPDATE_RCV,
Expand Down Expand Up @@ -573,13 +597,11 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
}

if (attr) {
bgp_update(peer, &p, addpath_id, attr, packet->afi,
safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
NULL, &label, 1, 0, NULL);
bgp_update(peer, &p, addpath_id, attr, packet->afi, safi, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, NULL, labels, num_labels, 0, NULL);
} else {
bgp_withdraw(peer, &p, addpath_id, packet->afi,
SAFI_UNICAST, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, NULL, &label, 1);
bgp_withdraw(peer, &p, addpath_id, packet->afi, SAFI_UNICAST,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, labels, num_labels);
}
}

Expand All @@ -606,7 +628,7 @@ uint32_t decode_label(mpls_label_t *label_pnt)
return l;
}

void encode_label(mpls_label_t label, mpls_label_t *label_pnt)
void encode_label_bos(mpls_label_t label, mpls_label_t *label_pnt, bool bos)
{
uint8_t *pnt = (uint8_t *)label_pnt;

Expand All @@ -618,7 +640,12 @@ void encode_label(mpls_label_t label, mpls_label_t *label_pnt)
}
*pnt++ = (label >> 12) & 0xff;
*pnt++ = (label >> 4) & 0xff;
*pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */
*pnt++ = ((label << 4) + (bos ? 1 : 0)) & 0xff;
}

void encode_label(mpls_label_t label, mpls_label_t *label_pnt)
{
encode_label_bos(label, label_pnt, true);
}

bool bgp_labels_same(const mpls_label_t *tbl_a, const uint8_t num_labels_a,
Expand Down Expand Up @@ -646,3 +673,30 @@ bool bgp_labels_is_implicit_null(struct bgp_path_info *pi)
return true;
return false;
}

char *mpls_labels2str(mpls_label_t *labels, uint8_t num_labels, const char *prefix, char *buf,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if we can reuse the existing function - mpls_label2str() from lib/mpls.c

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately can't just reuse it - it doesn't decode labels, just outputs as integers:

		if (pretty)
			label2str(labels[i], type, label_buf,
				  sizeof(label_buf));
		else
			snprintf(label_buf, sizeof(label_buf), "%u",
				 ((type == ZEBRA_LSP_EVPN)
					  ? label2vni(&labels[i])
					  : labels[i]));

label2str does the same - just outputs label as integer or label2vni in EVPN case.

Theoretically they could have been merged, but pairs of functions decode_label/mpls_lse_decode etc hint that somewhy they are not merged. Probably it would be a good refactoring but I don't think it is a good idea to include that in this task.

int size)
{
uint32_t label_value;
uint32_t len = 0;
uint8_t i;

buf[0] = '\0';
if (!num_labels)
return buf;

if (prefix) {
strlcat(buf + len, prefix, size - len);
len = strlen(buf);
}

label_value = decode_label(&labels[0]);
len += snprintf(buf + len, size - len, "%u", label_value);

for (i = 1; i < num_labels; i++) {
label_value = decode_label(&labels[i]);
len += snprintf(buf + len, size - len, "/%u", label_value);
}

return buf;
}
Loading
Loading