-
Notifications
You must be signed in to change notification settings - Fork 1.4k
bgp: Support multiple labels in BGP-LU #19961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
|
@@ -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", | ||
|
|
@@ -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; | ||
|
|
@@ -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, | ||
|
|
@@ -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); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -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; | ||
|
|
||
|
|
@@ -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, | ||
|
|
@@ -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, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
Theoretically they could have been merged, but pairs of functions |
||
| 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; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.