diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c index 3afb3db06b..137e88adea 100644 --- a/bgpd/bgp_labelpool.c +++ b/bgpd/bgp_labelpool.c @@ -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); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 1e932fe9c7..48d7cb0f71 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -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 : 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); + } } diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 6ff7a0a020..aeea4598e3 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -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; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1965cd2704..c5b2004d73 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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); } diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 7c85d86b31..7c60b542f8 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -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 */