[caclmgrd][dualtor] add src IP to the SNAT rule for allowing gRPC (#13087)

This PR is a required for changing the L3 IP forwarding Behavior to SoC in active-active toplogy.
Basically a src IP is added to the SNAT rule so that only packets originating from ToR with src IP as vlan IP get natted by the rule and change the src IP to LoopBack IP

Master Branch PR with combined change is here

sonic-net/sonic-host-services#3

How I did it
check the config DB if the ToR is a DualToR and has an SoC IP assigned.
put an iptable rule
iptables -t nat -A POSTROUTING --destination -j SNAT --to-source "
Signed-off-by: vaibhav-dahiya vdahiya@microsoft.com

Signed-off-by: vaibhav-dahiya <vdahiya@microsoft.com>
This commit is contained in:
vdahiya12 2022-12-16 18:37:44 -08:00 committed by GitHub
parent 1f677f5a71
commit 6e1ca643fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 6 deletions

View File

@ -48,11 +48,12 @@ def get_ip_from_interface_table(table, intf_name):
if not _ip_prefix_in_key(key):
continue
iface_name, iface_cidr = key
if iface_name.startswith(intf_name):
ip_ntwrk = ipaddress.ip_network(iface_cidr, strict=False)
if isinstance(ip_ntwrk, ipaddress.IPv4Network):
ip_addr = ip_ntwrk.network_address
ip_str = iface_cidr.split("/")[0]
ip_addr = ipaddress.ip_address(ip_str)
if isinstance(ip_addr, ipaddress.IPv4Address):
return ip_addr
return None
@ -75,6 +76,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
MUX_CABLE_TABLE = "MUX_CABLE_TABLE"
CONFIG_MUX_CABLE = "MUX_CABLE"
LOOPBACK_TABLE = "LOOPBACK_INTERFACE"
VLAN_INTF_TABLE = "VLAN_INTERFACE"
ACL_TABLE_TYPE_CTRLPLANE = "CTRLPLANE"
@ -318,6 +320,9 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
loopback_table = self.config_db_map[DEFAULT_NAMESPACE].get_table(self.LOOPBACK_TABLE)
loopback_name = 'Loopback3'
loopback_address = get_ip_from_interface_table(loopback_table, loopback_name)
vlan_name = 'Vlan'
vlan_table = self.config_db_map[DEFAULT_NAMESPACE].get_table(self.VLAN_INTF_TABLE)
vlan_address = get_ip_from_interface_table(vlan_table, vlan_name)
fwd_dualtor_grpc_traffic_from_host_to_soc_cmds.append(self.iptables_cmd_ns_prefix[namespace] +
"iptables -t nat --flush POSTROUTING")
@ -328,7 +333,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
kvp = mux_table.get(key)
if 'cable_type' in kvp and kvp['cable_type'] == 'active-active':
fwd_dualtor_grpc_traffic_from_host_to_soc_cmds.append(self.iptables_cmd_ns_prefix[namespace] +
"iptables -t nat -A POSTROUTING --destination {} -j SNAT --to-source {}".format(kvp['soc_ipv4'], loopback_address))
"iptables -t nat -A POSTROUTING --destination {} --source {} -j SNAT --to-source {}".format(kvp['soc_ipv4'], vlan_address, loopback_address))
return fwd_dualtor_grpc_traffic_from_host_to_soc_cmds
@ -356,7 +361,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
for ip_protocol in self.ACL_SERVICES[acl_service]["ip_protocols"]:
if "dst_ports" in self.ACL_SERVICES[acl_service]:
for dst_port in self.ACL_SERVICES[acl_service]["dst_ports"]:
for dst_port in self.ACL_SERVICES[acl_service]["dst_ports"]:
for ipv4_src_ip in nat_source_ipv4_set:
# IPv4 rules
fwd_traffic_from_namespace_to_host_cmds.append(self.iptables_cmd_ns_prefix[namespace] +

View File

@ -4,6 +4,7 @@ import swsscommon
from parameterized import parameterized
from sonic_py_common.general import load_module_from_source
from ipaddress import IPv4Address
from unittest import TestCase, mock
from pyfakefs.fake_filesystem_unittest import patchfs
@ -49,3 +50,11 @@ class TestCaclmgrdSoc(TestCase):
caclmgrd_daemon.update_control_plane_nat_acls('', {})
mocked_subprocess.Popen.assert_has_calls(test_data["expected_subprocess_calls"], any_order=True)
def test_get_ip_from_interface_table(self):
if not os.path.exists(DBCONFIG_PATH):
fs.create_file(DBCONFIG_PATH) # fake database_config.json
table = {("Vlan1000","10.10.10.1/32"): "val"}
ip_addr = self.caclmgrd.get_ip_from_interface_table(table, "Vlan")
assert (ip_addr == IPv4Address('10.10.10.1'))

View File

@ -21,6 +21,11 @@ CACLMGRD_SOC_TEST_VECTOR = [
"soc_ipv4": "192.168.1.0/32",
}
},
"VLAN_INTERFACE": {
"Vlan1000|10.10.2.2/23": {
"NULL": "NULL",
}
},
"LOOPBACK_INTERFACE": {
"Loopback3|10.10.10.10/32": {
"NULL": "NULL",
@ -30,7 +35,7 @@ CACLMGRD_SOC_TEST_VECTOR = [
},
},
"expected_subprocess_calls": [
call("iptables -t nat -A POSTROUTING --destination 192.168.1.0/32 -j SNAT --to-source 10.10.10.10",shell=True, universal_newlines=True, stdout=-1)
call("iptables -t nat -A POSTROUTING --destination 192.168.1.0/32 --source 10.10.10.10 -j SNAT --to-source 10.10.10.10",shell=True, universal_newlines=True, stdout=-1)
],
"popen_attributes": {
'communicate.return_value': ('output', 'error'),