bgpd: update the mpls entry to handle return traffic

When advertising an mpls vpn entry with a new label,
the return traffic is redirected to the local machine,
but the MPLS traffic is dropped.

Add an MPLS entry to handle MPLS packets which have
the new label value. Traffic is swapped to the original
label value from the mpls vpn next-hop entry; then it is
sent to the resolved next-hop of the original next-hop
from the mpls vpn next-hop entry.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2023-05-11 15:42:08 +02:00
parent 98c615f05a
commit 27f4deed0a
5 changed files with 108 additions and 11 deletions

View File

@ -1730,7 +1730,7 @@ void bgp_label_per_nexthop_free(struct bgp_label_per_nexthop_cache *blnc)
bgp_zebra_send_nexthop_label(ZEBRA_MPLS_LABELS_DELETE,
blnc->label, blnc->nh->ifindex,
blnc->nh->vrf_id, ZEBRA_LSP_BGP,
&blnc->nexthop);
&blnc->nexthop, 0, NULL);
bgp_lp_release(LP_TYPE_NEXTHOP, blnc, blnc->label);
}
bgp_label_per_nexthop_cache_del(blnc->tree, blnc);

View File

@ -1390,9 +1390,10 @@ static int bgp_mplsvpn_get_label_per_nexthop_cb(mpls_label_t label,
/* update paths */
if (blnc->label != MPLS_INVALID_LABEL)
bgp_zebra_send_nexthop_label(
ZEBRA_MPLS_LABELS_ADD, blnc->label, blnc->nh->ifindex,
blnc->nh->vrf_id, ZEBRA_LSP_BGP, &blnc->nexthop);
bgp_zebra_send_nexthop_label(ZEBRA_MPLS_LABELS_ADD, blnc->label,
blnc->nh->ifindex,
blnc->nh->vrf_id, ZEBRA_LSP_BGP,
&blnc->nexthop, 0, NULL);
LIST_FOREACH (pi, &(blnc->paths), mplsvpn.blnc.label_nh_thread) {
if (!pi->net)
@ -1486,7 +1487,7 @@ _vpn_leak_from_vrf_get_per_nexthop_label(struct bgp_path_info *pi,
bgp_zebra_send_nexthop_label(
ZEBRA_MPLS_LABELS_REPLACE, blnc->label,
bnc->nexthop->ifindex, bnc->nexthop->vrf_id,
ZEBRA_LSP_BGP, &blnc->nexthop);
ZEBRA_LSP_BGP, &blnc->nexthop, 0, NULL);
}
}
@ -3885,6 +3886,68 @@ int bgp_mplsvpn_nh_label_bind_cmp(
return 0;
}
static void bgp_mplsvpn_nh_label_bind_send_nexthop_label(
struct bgp_mplsvpn_nh_label_bind_cache *bmnc, int cmd)
{
struct prefix pfx_nh, *p = NULL;
uint32_t num_labels = 0, lsp_num_labels;
mpls_label_t label[MPLS_MAX_LABELS];
struct nexthop *nh;
ifindex_t ifindex = IFINDEX_INTERNAL;
vrf_id_t vrf_id = VRF_DEFAULT;
uint32_t i;
if (bmnc->nh == NULL)
return;
nh = bmnc->nh;
switch (nh->type) {
case NEXTHOP_TYPE_IFINDEX:
p = &bmnc->nexthop;
label[num_labels] = bmnc->orig_label;
num_labels += 1;
ifindex = nh->ifindex;
vrf_id = nh->vrf_id;
break;
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
if (nh->type == NEXTHOP_TYPE_IPV4 ||
nh->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
pfx_nh.family = AF_INET;
pfx_nh.prefixlen = IPV4_MAX_BITLEN;
IPV4_ADDR_COPY(&pfx_nh.u.prefix4, &nh->gate.ipv4);
} else {
pfx_nh.family = AF_INET6;
pfx_nh.prefixlen = IPV6_MAX_BITLEN;
IPV6_ADDR_COPY(&pfx_nh.u.prefix6, &nh->gate.ipv6);
}
p = &pfx_nh;
if (nh->nh_label) {
if (nh->nh_label->num_labels >
MPLS_MAX_LABELS - num_labels)
lsp_num_labels = MPLS_MAX_LABELS - num_labels;
else
lsp_num_labels = nh->nh_label->num_labels;
for (i = 0; i < lsp_num_labels; i++)
label[num_labels + i] = nh->nh_label->label[i];
num_labels += lsp_num_labels;
}
label[num_labels] = bmnc->orig_label;
num_labels += 1;
if (nh->type == NEXTHOP_TYPE_IPV4_IFINDEX ||
nh->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
ifindex = nh->ifindex;
vrf_id = nh->vrf_id;
}
break;
case NEXTHOP_TYPE_BLACKHOLE:
return;
}
bgp_zebra_send_nexthop_label(cmd, bmnc->new_label, ifindex, vrf_id,
ZEBRA_LSP_BGP, p, num_labels, &label[0]);
}
void bgp_mplsvpn_nh_label_bind_free(
struct bgp_mplsvpn_nh_label_bind_cache *bmnc)
{
@ -3894,8 +3957,11 @@ void bgp_mplsvpn_nh_label_bind_free(
&bmnc->bgp_vpn->mplsvpn_nh_label_bind, bmnc);
return;
}
if (bmnc->new_label != MPLS_INVALID_LABEL)
if (bmnc->new_label != MPLS_INVALID_LABEL) {
bgp_mplsvpn_nh_label_bind_send_nexthop_label(
bmnc, ZEBRA_MPLS_LABELS_DELETE);
bgp_lp_release(LP_TYPE_BGP_L3VPN_BIND, bmnc, bmnc->new_label);
}
bgp_mplsvpn_nh_label_bind_cache_del(
&bmnc->bgp_vpn->mplsvpn_nh_label_bind, bmnc);
XFREE(MTYPE_MPLSVPN_NH_LABEL_BIND_CACHE, bmnc);
@ -4003,7 +4069,14 @@ static int bgp_mplsvpn_nh_label_bind_get_local_label_cb(mpls_label_t label,
}
bmnc->allocation_in_progress = false;
/* Create MPLS entry with new_label */
if (bmnc->new_label != MPLS_INVALID_LABEL)
/*
* Create the LSP : <local_label -> bmnc->orig_label,
* via bmnc->prefix, interface bnc->nexthop->ifindex
*/
bgp_mplsvpn_nh_label_bind_send_nexthop_label(
bmnc, ZEBRA_MPLS_LABELS_ADD);
LIST_FOREACH (pi, &(bmnc->paths), mplsvpn.bmnc.nh_label_bind_thread) {
/* we can advertise it */
if (!pi->net)
@ -4078,4 +4151,13 @@ void bgp_mplsvpn_nh_label_bind_register_local_label(struct bgp *bgp,
}
/* Add or update the selected nexthop */
if (!bmnc->nh)
bmnc->nh = nexthop_dup(pi->nexthop->nexthop, NULL);
else if (!nexthop_same(pi->nexthop->nexthop, bmnc->nh)) {
nexthop_free(bmnc->nh);
bmnc->nh = nexthop_dup(pi->nexthop->nexthop, NULL);
if (bmnc->new_label != MPLS_INVALID_LABEL)
bgp_mplsvpn_nh_label_bind_send_nexthop_label(
bmnc, ZEBRA_MPLS_LABELS_REPLACE);
}
}

View File

@ -349,6 +349,9 @@ struct bgp_mplsvpn_nh_label_bind_cache {
struct prefix nexthop;
mpls_label_t orig_label;
/* resolved interface for the paths */
struct nexthop *nh;
/* number of mplsvpn path */
unsigned int path_count;

View File

@ -3914,10 +3914,13 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)
void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t ifindex, vrf_id_t vrf_id,
enum lsp_types_t ltype, struct prefix *p)
enum lsp_types_t ltype, struct prefix *p,
uint32_t num_labels,
mpls_label_t out_labels[])
{
struct zapi_labels zl = {};
struct zapi_nexthop *znh;
int i = 0;
zl.type = ltype;
zl.local_label = label;
@ -3935,8 +3938,16 @@ void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
: NEXTHOP_TYPE_IPV6_IFINDEX;
znh->ifindex = ifindex;
znh->vrf_id = vrf_id;
znh->label_num = 0;
if (num_labels == 0)
znh->label_num = 0;
else {
if (num_labels > MPLS_MAX_LABELS)
znh->label_num = MPLS_MAX_LABELS;
else
znh->label_num = num_labels;
for (i = 0; i < znh->label_num; i++)
znh->labels[i] = out_labels[i];
}
/* vrf_id is DEFAULT_VRF */
zebra_send_mpls_labels(zclient, cmd, &zl);
}

View File

@ -121,5 +121,6 @@ extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name);
extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t index, vrf_id_t vrfid,
enum lsp_types_t ltype,
struct prefix *p);
struct prefix *p, uint32_t num_labels,
mpls_label_t out_labels[]);
#endif /* _QUAGGA_BGP_ZEBRA_H */