Skip to content

Commit 17b0213

Browse files
committed
bgpd: Support sending multiple labels in BGP-LU
* Move label manipulation logic out of stream_put_labeled_prefix (lib/stream.c) to new function stream_bgp_put_labeled_prefix in bgpd/bgp_attr.c * Merge stream_put_labeled_prefix with with stream_put_prefix_addpath * Add multiple label support in stream_bgp_put_labeled_prefix Signed-off-by: Kyrylo Yatsenko <hedrok@gmail.com>
1 parent 3bac562 commit 17b0213

File tree

3 files changed

+78
-67
lines changed

3 files changed

+78
-67
lines changed

bgpd/bgp_attr.c

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,42 @@ static void stream_put_bgp_aigp_tlv_metric(struct stream *s, uint64_t aigp)
492492
stream_putq(s, aigp);
493493
}
494494

495+
/* Encode labels to buffer and pass to stream_put_labeled_prefix, truncate
496+
* labels if needed, set/restore BOS of label in this case
497+
*/
498+
static void stream_bgp_put_labeled_prefix(struct stream *s, const struct prefix *p,
499+
mpls_label_t *labels, uint8_t num_labels,
500+
bool addpath_capable, uint32_t addpath_tx_id)
501+
{
502+
/* 32 is absolute maximum BGP-LU allows in case of prefixlen=0 */
503+
uint8_t labels_buffer[32];
504+
size_t labels_size = 0;
505+
uint8_t i;
506+
bool added_bos = false;
507+
mpls_label_t restore_label;
508+
509+
if (p->prefixlen + BGP_LABEL_BYTES * 8 * num_labels >= 256) {
510+
num_labels = (256 - p->prefixlen) / 8 / BGP_LABEL_BYTES;
511+
zlog_warn("%s: Ignoring extra labels, can fit only %d in BGP-LU message with prefixlen %d",
512+
__func__, num_labels, p->prefixlen);
513+
added_bos = true;
514+
restore_label = labels[num_labels - 1];
515+
label_set_bos(&labels[num_labels - 1]);
516+
}
517+
518+
for (i = 0; i < num_labels; i++) {
519+
uint8_t *label_pnt = (uint8_t *)(&labels[i]);
520+
521+
labels_buffer[labels_size++] = label_pnt[0];
522+
labels_buffer[labels_size++] = label_pnt[1];
523+
labels_buffer[labels_size++] = label_pnt[2];
524+
}
525+
if (added_bos)
526+
labels[num_labels - 1] = restore_label;
527+
528+
stream_put_labeled_prefix(s, p, labels_size, labels_buffer, addpath_capable, addpath_tx_id);
529+
}
530+
495531
static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
496532
{
497533
uint8_t *data = pnt;
@@ -4745,8 +4781,6 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
47454781
uint8_t num_labels, bool addpath_capable,
47464782
uint32_t addpath_tx_id, struct attr *attr)
47474783
{
4748-
mpls_label_t restore_label;
4749-
47504784
switch (safi) {
47514785
case SAFI_UNSPEC:
47524786
case SAFI_MAX:
@@ -4771,16 +4805,9 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
47714805
assert(!"Add encoding bits here for other AFI's");
47724806
break;
47734807
case SAFI_LABELED_UNICAST:
4774-
if (num_labels > 1) {
4775-
zlog_warn("%s: stream_put_labeled_prefix currently supports only one label, ignoring rest (num_labels=%d)",
4776-
__func__, num_labels);
4777-
restore_label = label[0];
4778-
label_set_bos(&label[0]);
4779-
}
47804808
/* Prefix write with label. */
4781-
stream_put_labeled_prefix(s, p, label, addpath_capable, addpath_tx_id);
4782-
if (num_labels > 1)
4783-
label[0] = restore_label;
4809+
stream_bgp_put_labeled_prefix(s, p, label, num_labels, addpath_capable,
4810+
addpath_tx_id);
47844811
break;
47854812
case SAFI_FLOWSPEC:
47864813
stream_putc(s, p->u.prefix_flowspec.prefixlen);
@@ -4819,7 +4846,11 @@ size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
48194846
assert(!"Do we try to use this?");
48204847
break;
48214848
case SAFI_LABELED_UNICAST:
4822-
size += BGP_LABEL_BYTES;
4849+
/*
4850+
* Length of all labels + prefix is given in bits in one octet,
4851+
* so maximum 256 bits, 32 bytes
4852+
*/
4853+
size = 32;
48234854
break;
48244855
case SAFI_EVPN:
48254856
/*

lib/stream.c

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,26 +1051,35 @@ int stream_put_in6_addr_at(struct stream *s, size_t putp,
10511051
return 16;
10521052
}
10531053

1054-
/* Put prefix by nlri type format. */
1055-
int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
1056-
bool addpath_capable, uint32_t addpath_tx_id)
1054+
/* Put NLRI with optional labels */
1055+
int stream_put_labeled_prefix(struct stream *s, const struct prefix *p, size_t labels_size,
1056+
uint8_t *labels_buffer, bool addpath_capable, uint32_t addpath_tx_id)
10571057
{
10581058
size_t psize;
1059-
size_t psize_with_addpath;
1059+
size_t psize_with_addpath_and_labels;
10601060

10611061
STREAM_VERIFY_SANE(s);
10621062

1063-
psize = PSIZE(p->prefixlen);
1063+
if (!labels_buffer)
1064+
labels_size = 0;
1065+
1066+
if (labels_size * 8 + p->prefixlen >= 256) {
1067+
/* This should be taken care of in BGP code, but checking just in case
1068+
* because if wrong whole stream will become invalid.
1069+
* In this case ignoring all labels not to take care of BOS changes in case of
1070+
* using less labels than needed.
1071+
*/
1072+
flog_warn(EC_LIB_STREAM, "%s: too big labels_size, ignoring labels", __func__);
1073+
labels_size = 0;
1074+
}
10641075

1065-
if (addpath_capable)
1066-
psize_with_addpath = psize + 4;
1067-
else
1068-
psize_with_addpath = psize;
1076+
psize = PSIZE(p->prefixlen);
1077+
psize_with_addpath_and_labels = psize + (addpath_capable ? 4 : 0) + labels_size +
1078+
sizeof(uint8_t);
10691079

1070-
if (STREAM_WRITEABLE(s) < (psize_with_addpath + sizeof(uint8_t))) {
1080+
if (STREAM_WRITEABLE(s) < psize_with_addpath_and_labels) {
10711081
if (s->allow_expansion) {
1072-
stream_expand(s,
1073-
STREAM_EXPAND_SIZE(s, psize_with_addpath + sizeof(uint8_t)));
1082+
stream_expand(s, STREAM_EXPAND_SIZE(s, psize_with_addpath_and_labels));
10741083
} else {
10751084
STREAM_BOUND_WARN(s, "put");
10761085
return 0;
@@ -1084,56 +1093,27 @@ int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
10841093
s->data[s->endp++] = (uint8_t)addpath_tx_id;
10851094
}
10861095

1087-
s->data[s->endp++] = p->prefixlen;
1096+
s->data[s->endp++] = p->prefixlen + 8 * labels_size;
1097+
if (labels_size) {
1098+
memcpy(s->data + s->endp, labels_buffer, labels_size);
1099+
s->endp += labels_size;
1100+
}
10881101
memcpy(s->data + s->endp, &p->u.prefix, psize);
10891102
s->endp += psize;
10901103

1091-
return psize;
1104+
return psize + labels_size;
10921105
}
10931106

1094-
int stream_put_prefix(struct stream *s, const struct prefix *p)
1107+
/* Put prefix by nlri type format. */
1108+
int stream_put_prefix_addpath(struct stream *s, const struct prefix *p, bool addpath_capable,
1109+
uint32_t addpath_tx_id)
10951110
{
1096-
return stream_put_prefix_addpath(s, p, 0, 0);
1111+
return stream_put_labeled_prefix(s, p, 0, NULL, addpath_capable, addpath_tx_id);
10971112
}
10981113

1099-
/* Put NLRI with label */
1100-
int stream_put_labeled_prefix(struct stream *s, const struct prefix *p,
1101-
mpls_label_t *label, bool addpath_capable,
1102-
uint32_t addpath_tx_id)
1114+
int stream_put_prefix(struct stream *s, const struct prefix *p)
11031115
{
1104-
size_t psize;
1105-
size_t psize_with_addpath;
1106-
uint8_t *label_pnt = (uint8_t *)label;
1107-
1108-
STREAM_VERIFY_SANE(s);
1109-
1110-
psize = PSIZE(p->prefixlen);
1111-
psize_with_addpath = psize + (addpath_capable ? 4 : 0);
1112-
1113-
if (STREAM_WRITEABLE(s) < (psize_with_addpath + 3)) {
1114-
if (s->allow_expansion) {
1115-
stream_expand(s, STREAM_EXPAND_SIZE(s, psize_with_addpath + 3));
1116-
} else {
1117-
STREAM_BOUND_WARN(s, "put");
1118-
return 0;
1119-
}
1120-
}
1121-
1122-
if (addpath_capable) {
1123-
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 24);
1124-
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 16);
1125-
s->data[s->endp++] = (uint8_t)(addpath_tx_id >> 8);
1126-
s->data[s->endp++] = (uint8_t)addpath_tx_id;
1127-
}
1128-
1129-
stream_putc(s, (p->prefixlen + 24));
1130-
stream_putc(s, label_pnt[0]);
1131-
stream_putc(s, label_pnt[1]);
1132-
stream_putc(s, label_pnt[2]);
1133-
memcpy(s->data + s->endp, &p->u.prefix, psize);
1134-
s->endp += psize;
1135-
1136-
return (psize + 3);
1116+
return stream_put_prefix_addpath(s, p, 0, 0);
11371117
}
11381118

11391119
/* Read size from fd. */

lib/stream.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ extern int stream_put_prefix_addpath(struct stream *s, const struct prefix *p,
186186
bool addpath_capable,
187187
uint32_t addpath_tx_id);
188188
extern int stream_put_prefix(struct stream *s, const struct prefix *p);
189-
extern int stream_put_labeled_prefix(struct stream *s, const struct prefix *p,
190-
mpls_label_t *label, bool addpath_capable,
189+
extern int stream_put_labeled_prefix(struct stream *s, const struct prefix *p, size_t labels_size,
190+
uint8_t *labels_buffer, bool addpath_capable,
191191
uint32_t addpath_tx_id);
192192
extern void stream_get(void *dst, struct stream *s, size_t size);
193193
extern bool stream_get2(void *data, struct stream *s, size_t size);

0 commit comments

Comments
 (0)