]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: fix labels in adj-rib-in
authorPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 13 Jan 2023 14:59:52 +0000 (15:59 +0100)
committerLouis Scalbert <louis.scalbert@6wind.com>
Wed, 5 Jun 2024 11:11:29 +0000 (13:11 +0200)
In a BGP L3VPN context using ADJ-RIB-IN (ie. enabled with
'soft-reconfiguration inbound'), after applying a deny route-map and
removing it, the remote MPLS label information is lost. As a result, BGP
is unable to re-install the related routes in the RIB.

For example,

> router bgp 65500
> [..]
>  neighbor 192.0.2.2 remote-as 65501
>  address-family ipv4 vpn
>   neighbor 192.0.2.2 activate
>   neighbor 192.0.2.2 soft-reconfiguration inbound

The 192.168.0.0/24 prefix has a remote label value of 102 in the BGP
RIB.

> # show bgp ipv4 vpn 192.168.0.0/24
>  BGP routing table entry for 444:1:192.168.0.0/24, version 2
>  [..]
>      192.168.0.0 from 192.0.2.2
>        Origin incomplete, metric 0, valid, external, best (First path received)
>        Extended Community: RT:52:100
>        Remote label: 102

A route-map now filter all incoming BGP updates:

> route-map rmap deny 1
> router bgp 65500
>  address-family ipv4 vpn
>   neighbor 192.0.2.2 route-map rmap in

The prefix is now filtered:

> # show bgp ipv4 vpn 192.168.0.0/24
> #

The route-map is detached:

> router bgp 65500
>  address-family ipv4 vpn
>   no neighbor 192.168.0.1 route-map rmap in

The BGP RIB entry is present but the remote label is lost:

> # show bgp ipv4 vpn 192.168.0.0/24
>  BGP routing table entry for 444:1:192.168.0.0/24, version 2
>  [..]
>      192.168.0.0 from 192.0.2.2
>        Origin incomplete, metric 0, valid, external, best (First path received)
>        Extended Community: RT:52:100

The reason for the loose is that labels are stored within struct attr ->
struct extra -> struct bgp_labels but not in the struct bgp_adj_in.

Reference the bgp_labels pointer in struct bgp_adj_in and use its values
when doing a soft reconfiguration of the BGP table.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
bgpd/bgp_advertise.c
bgpd/bgp_advertise.h
bgpd/bgp_route.c

index d519749f6bcac3abb094d30245982799dc5b9ed1..d5c7e1887b6027a13a0214bc5702e99b01aed58c 100644 (file)
@@ -163,7 +163,7 @@ bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
 
 
 void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
-                   uint32_t addpath_id)
+                   uint32_t addpath_id, struct bgp_labels *labels)
 {
        struct bgp_adj_in *adj;
 
@@ -173,6 +173,10 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
                                bgp_attr_unintern(&adj->attr);
                                adj->attr = bgp_attr_intern(attr);
                        }
+                       if (!bgp_labels_cmp(adj->labels, labels)) {
+                               bgp_labels_unintern(&adj->labels);
+                               adj->labels = bgp_labels_intern(labels);
+                       }
                        return;
                }
        }
@@ -181,6 +185,7 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
        adj->attr = bgp_attr_intern(attr);
        adj->uptime = monotime(NULL);
        adj->addpath_rx_id = addpath_id;
+       adj->labels = bgp_labels_intern(labels);
        BGP_ADJ_IN_ADD(dest, adj);
        peer->stat_pfx_adj_rib_in++;
        bgp_dest_lock_node(dest);
@@ -189,6 +194,7 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
 void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai)
 {
        bgp_attr_unintern(&bai->attr);
+       bgp_labels_unintern(&bai->labels);
        if (bai->peer)
                bai->peer->stat_pfx_adj_rib_in--;
        BGP_ADJ_IN_DEL(*dest, bai);
index 49821061b1b8f53a6153dea4b29c889f9e3c5f34..e3cd743d43d2ecde9ee743dbc68dce5bb611d5e7 100644 (file)
@@ -95,6 +95,9 @@ struct bgp_adj_in {
        /* Received attribute.  */
        struct attr *attr;
 
+       /* VPN label information */
+       struct bgp_labels *labels;
+
        /* timestamp (monotime) */
        time_t uptime;
 
@@ -135,7 +138,8 @@ struct bgp_synchronize {
 extern bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
                               uint32_t addpath_tx_id);
 extern void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer,
-                          struct attr *attr, uint32_t addpath_id);
+                          struct attr *attr, uint32_t addpath_id,
+                          struct bgp_labels *labels);
 extern bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer,
                             uint32_t addpath_id);
 extern void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai);
index eada9264ac29193cb1e27ec1aa10e7efa06bce53..94c21e186150cf5e6e7d6a5173360bc64568dbf0 100644 (file)
@@ -4600,7 +4600,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
                        memcpy(&attr->evpn_overlay, evpn,
                               sizeof(struct bgp_route_evpn));
                }
-               bgp_adj_in_set(dest, peer, attr, addpath_id);
+               bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels);
        }
 
        /* Update permitted loop count */
@@ -5673,8 +5673,8 @@ static void bgp_soft_reconfig_table_update(struct peer *peer,
                if (pi->peer == peer)
                        break;
 
-       num_labels = bgp_path_info_num_labels(pi);
-       label_pnt = num_labels ? &pi->extra->labels->label[0] : NULL;
+       num_labels = ain->labels ? ain->labels->num_labels : 0;
+       label_pnt = num_labels ? &ain->labels->label[0] : NULL;
        if (pi)
                memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
                       sizeof(evpn));