]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Fix to avoid two Vrfs with same table ids
authorRajasekar Raja <rajasekarr@nvidia.com>
Fri, 5 Jul 2024 23:02:12 +0000 (16:02 -0700)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Sun, 14 Jul 2024 00:14:29 +0000 (00:14 +0000)
During internal testing, when the following sequence is followed, two
non default vrfs end up pointing to the same table-id

 - Initially vrf201 has table id 1002
 - ip link add dev vrf202 type vrf table 1002
 - ip link set dev vrf202 up
 - ip link set dev <intrerface> master vrf202

This will ideally lead to zebra exit since this is a misconfiguration as
expected.

However if we perform a restart frr.service at this point, we end up
having two vrfs pointing to same table-id and bad things can happen.
This is because in the interface_vrf_change, we incorrectly check for
vrf_lookup_by_id() to evaluate if there is a misconfig. This works well
for a non restart case but not for the startup case.

root@mlx-3700-20:mgmt:/var/log/frr# sudo vtysh -c "sh vrf"
vrf mgmt id 37 table 1001
vrf vrf201 id 46 table 1002
vrf vrf202 id 59 table 1002 >>>>

Fix: in all cases of misconfiguration, exit zebra as expected.

Ticket :#3970414

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Signed-off-by: Rajasekar Raja <rajasekarr@nvidia.com>
(cherry picked from commit c77e15710d6a3a9be71f41a9ce608f06b2795dfb)

zebra/interface.c

index e824f1bf63cf31ffac612a2c7cd5cb617516ab5f..5b468d0dfd707e6162ce3c7dbfa5c07d3debe029 100644 (file)
@@ -1538,23 +1538,27 @@ static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex,
                                "DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u",
                                name, ifindex, tableid);
 
-               if (!vrf_lookup_by_id((vrf_id_t)ifindex)) {
-                       vrf_id_t exist_id;
-
-                       exist_id = zebra_vrf_lookup_by_table(tableid, ns_id);
-                       if (exist_id != VRF_DEFAULT) {
-                               vrf = vrf_lookup_by_id(exist_id);
-
-                               if (vrf)
-                                       flog_err(EC_ZEBRA_VRF_MISCONFIGURED,
-                                                "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting",
-                                                name, ifindex, vrf->name,
-                                                vrf->vrf_id);
-                               else
-                                       flog_err(EC_ZEBRA_VRF_NOT_FOUND,
-                                                "VRF %s id %u does not exist",
-                                                name, ifindex);
+               /*
+                * For a given tableid, if there already exists a vrf and it
+                * is different from the current vrf to be operated, then there
+                * is a misconfiguration and zebra will exit.
+                */
+               vrf_id_t exist_id = zebra_vrf_lookup_by_table(tableid, ns_id);
+
+               if (exist_id != VRF_DEFAULT) {
+                       vrf = vrf_lookup_by_id(exist_id);
+
+                       if (!vrf_lookup_by_id((vrf_id_t)ifindex) && !vrf) {
+                               flog_err(EC_ZEBRA_VRF_NOT_FOUND,
+                                        "VRF %s id %u does not exist", name,
+                                        ifindex);
+                               exit(-1);
+                       }
 
+                       if (vrf && strcmp(name, vrf->name)) {
+                               flog_err(EC_ZEBRA_VRF_MISCONFIGURED,
+                                        "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting",
+                                        name, ifindex, vrf->name, vrf->vrf_id);
                                exit(-1);
                        }
                }