]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: update the mpls entry to handle return traffic
authorPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 11 May 2023 13:42:08 +0000 (15:42 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 16 Jun 2023 08:54:58 +0000 (10:54 +0200)
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>
bgpd/bgp_labelpool.c
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h

index 3afb3db06b33572b193ecc600024fd1867ef4770..137e88adeadb57462a4f9f386974fd6e25e4503d 100644 (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);
index 1e932fe9c719de99d8bd0132e0bb2c53032e8e3e..48d7cb0f71ef1a018d64b7189494b7b8e91e68dd 100644 (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);
+       }
 }
index 6ff7a0a0206ed7b152872164cb33352992a2d819..aeea4598e3cd3217f73ec126b98d5cf8a16f276e 100644 (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;
 
index 1965cd270471553eeac051adf2def5aae65f00c5..c5b2004d73ca802bee1b62cb20ef32bfe2880f6e 100644 (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);
 }
index 7c85d86b317a5cf606ad2918900f473d045421cc..7c60b542f8f0c62dad7ccbb2d4f8efaa2b7bdae1 100644 (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 */