diff options
| author | Rajasekar Raja <rajasekarr@nvidia.com> | 2024-07-05 16:02:12 -0700 | 
|---|---|---|
| committer | Mergify <37929162+mergify[bot]@users.noreply.github.com> | 2024-07-14 00:14:24 +0000 | 
| commit | d32c3aea86a1790152693cb51af61b8189f71e56 (patch) | |
| tree | 3053c8b12647edf05b673f35aa78cc3d816f63af /zebra/interface.c | |
| parent | b3d3e3384153783fecf8afef1636070ae81badb9 (diff) | |
zebra: Fix to avoid two Vrfs with same table ids
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)
Diffstat (limited to 'zebra/interface.c')
| -rw-r--r-- | zebra/interface.c | 36 | 
1 files changed, 20 insertions, 16 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index 41624d4dba..9eb1503551 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1523,23 +1523,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);  			}  		}  | 
