From 1c6aa043efb5f3c2632e59c4594536b318c51fdc Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 16 Feb 2023 10:39:40 +0100 Subject: [PATCH] bgpd: use nexthop interface when adding LSP in BGP MPLSVPN BGP MPLSVPN next hop label allocation was using only the next-hop IP address. As MPLSVPN contexts rely on bnc contexts, the real nexthop interface is known, and the LSP entry to enter can apply to the specific interface. To illustrate, the BGP service is able to handle the following two iproute2 commands: > ip -f mpls route add 105 via inet 192.0.2.45 dev r1-eth1 > ip -f mpls route add 105 via inet 192.0.2.46 dev r1-eth2 Signed-off-by: Philippe Guibert --- bgpd/bgp_labelpool.c | 6 +++++- bgpd/bgp_labelpool.h | 5 +++++ bgpd/bgp_mplsvpn.c | 20 ++++++++++++++++++-- bgpd/bgp_zebra.c | 12 +++++++++--- bgpd/bgp_zebra.h | 1 + 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c index 41d4eabe1f..c08589cb91 100644 --- a/bgpd/bgp_labelpool.c +++ b/bgpd/bgp_labelpool.c @@ -1606,10 +1606,14 @@ void bgp_label_per_nexthop_free(struct bgp_label_per_nexthop_cache *blnc) { if (blnc->label != MPLS_INVALID_LABEL) { bgp_zebra_send_nexthop_label(ZEBRA_MPLS_LABELS_DELETE, - blnc->label, ZEBRA_LSP_BGP, + blnc->label, blnc->nh->ifindex, + blnc->nh->vrf_id, ZEBRA_LSP_BGP, &blnc->nexthop); bgp_lp_release(LP_TYPE_NEXTHOP, blnc, blnc->label); } bgp_label_per_nexthop_cache_del(blnc->tree, blnc); + if (blnc->nh) + nexthop_free(blnc->nh); + blnc->nh = NULL; XFREE(MTYPE_LABEL_PER_NEXTHOP_CACHE, blnc); } diff --git a/bgpd/bgp_labelpool.h b/bgpd/bgp_labelpool.h index 0e965f3b9a..d1a2d5f003 100644 --- a/bgpd/bgp_labelpool.h +++ b/bgpd/bgp_labelpool.h @@ -66,6 +66,11 @@ struct bgp_label_per_nexthop_cache { /* back pointer to bgp instance */ struct bgp *to_bgp; + /* copy a nexthop resolution from bgp nexthop tracking + * used to extract the interface nexthop + */ + struct nexthop *nh; + /* list of path_vrfs using it */ LIST_HEAD(path_lists, bgp_path_info) paths; diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index e9391acaf1..951dbd1efc 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1388,8 +1388,9 @@ 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, - 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); LIST_FOREACH (pi, &(blnc->paths), label_nh_thread) { if (!pi->net) @@ -1470,6 +1471,21 @@ static mpls_label_t _vpn_leak_from_vrf_get_per_nexthop_label( pi->label_nexthop_cache = blnc; pi->label_nexthop_cache->path_count++; } + + /* then add or update the selected nexthop */ + if (!blnc->nh) + blnc->nh = nexthop_dup(bnc->nexthop, NULL); + else if (!nexthop_same(bnc->nexthop, blnc->nh)) { + nexthop_free(blnc->nh); + blnc->nh = nexthop_dup(bnc->nexthop, NULL); + if (blnc->label != MPLS_INVALID_LABEL) { + bgp_zebra_send_nexthop_label( + ZEBRA_MPLS_LABELS_REPLACE, blnc->label, + bnc->nexthop->ifindex, bnc->nexthop->vrf_id, + ZEBRA_LSP_BGP, &blnc->nexthop); + } + } + return blnc->label; } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index f0724f4eb1..1965cd2704 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -3913,6 +3913,7 @@ 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) { struct zapi_labels zl = {}; @@ -3926,9 +3927,14 @@ void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label, IPV4_ADDR_COPY(&znh->gate.ipv4, &p->u.prefix4); else IPV6_ADDR_COPY(&znh->gate.ipv6, &p->u.prefix6); - znh->type = - (p->family == AF_INET) ? NEXTHOP_TYPE_IPV4 : NEXTHOP_TYPE_IPV6; - znh->ifindex = 0; + if (ifindex == IFINDEX_INTERNAL) + znh->type = (p->family == AF_INET) ? NEXTHOP_TYPE_IPV4 + : NEXTHOP_TYPE_IPV6; + else + znh->type = (p->family == AF_INET) ? NEXTHOP_TYPE_IPV4_IFINDEX + : NEXTHOP_TYPE_IPV6_IFINDEX; + znh->ifindex = ifindex; + znh->vrf_id = vrf_id; znh->label_num = 0; /* vrf_id is DEFAULT_VRF */ diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 6a266e1a67..7c85d86b31 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -119,6 +119,7 @@ extern int bgp_zebra_stale_timer_update(struct bgp *bgp); extern int bgp_zebra_srv6_manager_get_locator_chunk(const char *name); 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); #endif /* _QUAGGA_BGP_ZEBRA_H */