@@ -85,26 +85,37 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
85
85
self .config_db_map ['' ].connect ()
86
86
self .iptables_cmd_ns_prefix ['' ] = ""
87
87
self .namespace_mgmt_ip = self .get_namespace_mgmt_ip (self .iptables_cmd_ns_prefix ['' ], '' )
88
+ self .namespace_mgmt_ipv6 = self .get_namespace_mgmt_ipv6 (self .iptables_cmd_ns_prefix ['' ], '' )
88
89
self .namespace_docker_mgmt_ip = {}
90
+ self .namespace_docker_mgmt_ipv6 = {}
89
91
namespaces = device_info .get_all_namespaces ()
90
92
for front_asic_namespace in namespaces ['front_ns' ]:
91
93
self .config_db_map [front_asic_namespace ] = ConfigDBConnector (use_unix_socket_path = True , namespace = front_asic_namespace )
92
94
self .config_db_map [front_asic_namespace ].connect ()
93
95
self .iptables_cmd_ns_prefix [front_asic_namespace ] = "ip netns exec " + front_asic_namespace + " "
94
96
self .namespace_docker_mgmt_ip [front_asic_namespace ] = self .get_namespace_mgmt_ip (self .iptables_cmd_ns_prefix [front_asic_namespace ],
95
97
front_asic_namespace )
98
+ self .namespace_docker_mgmt_ipv6 [front_asic_namespace ] = self .get_namespace_mgmt_ipv6 (self .iptables_cmd_ns_prefix [front_asic_namespace ],
99
+ front_asic_namespace )
96
100
97
101
for back_asic_namespace in namespaces ['back_ns' ]:
98
102
self .iptables_cmd_ns_prefix [back_asic_namespace ] = "ip netns exec " + back_asic_namespace + " "
99
103
self .namespace_docker_mgmt_ip [back_asic_namespace ] = self .get_namespace_mgmt_ip (self .iptables_cmd_ns_prefix [back_asic_namespace ],
100
104
back_asic_namespace )
105
+ self .namespace_docker_mgmt_ipv6 [back_asic_namespace ] = self .get_namespace_mgmt_ipv6 (self .iptables_cmd_ns_prefix [back_asic_namespace ],
106
+ back_asic_namespace )
101
107
102
108
def get_namespace_mgmt_ip (self , iptable_ns_cmd_prefix , namespace ):
103
109
ip_address_get_command = iptable_ns_cmd_prefix + "ip -4 -o addr show " + ("eth0" if namespace else "docker0" ) + \
104
110
" | awk '{print $4}' | cut -d'/' -f1 | head -1"
105
111
106
112
return self .run_commands ([ip_address_get_command ])
107
113
114
+ def get_namespace_mgmt_ipv6 (self , iptable_ns_cmd_prefix , namespace ):
115
+ ipv6_address_get_command = iptable_ns_cmd_prefix + "ip -6 -o addr show scope global " + ("eth0" if namespace else "docker0" ) + \
116
+ " | awk '{print $4}' | cut -d'/' -f1 | head -1"
117
+ return self .run_commands ([ipv6_address_get_command ])
118
+
108
119
def run_commands (self , commands ):
109
120
"""
110
121
Given a list of shell commands, run them in order
@@ -206,6 +217,39 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
206
217
(docker_mgmt_ip , self .namespace_mgmt_ip ))
207
218
return allow_internal_docker_ip_cmds
208
219
220
+ def generate_fwd_snmp_traffic_from_namespace_to_host_commands (self , namespace ):
221
+ """
222
+ The below SNAT and DNAT rules are added in asic namespace in multi-ASIC platforms. It helps to forward the SNMP request coming
223
+ in through the front panel interfaces created/present in the asic namespace to the SNMP Agent running in SNMP container in
224
+ linux host network namespace. The external IP addresses are NATed to the internal docker IP addresses for the SNMP Agent to respond.
225
+ """
226
+ fwd_snmp_traffic_from_namespace_to_host_cmds = []
227
+
228
+ if namespace :
229
+ # IPv4 rules
230
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] + "iptables -t nat -X" )
231
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] + "iptables -t nat -F" )
232
+
233
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] +
234
+ "iptables -t nat -A PREROUTING -p udp --dport {} -j DNAT --to-destination {}" .format
235
+ (self .ACL_SERVICES ['SNMP' ]['dst_ports' ][0 ], self .namespace_mgmt_ip ))
236
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] +
237
+ "iptables -t nat -A POSTROUTING -p udp --dport {} -j SNAT --to-source {}" .format
238
+ (self .ACL_SERVICES ['SNMP' ]['dst_ports' ][0 ], self .namespace_docker_mgmt_ip [namespace ]))
239
+
240
+ # IPv6 rules
241
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] + "ip6tables -t nat -X" )
242
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] + "ip6tables -t nat -F" )
243
+
244
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] +
245
+ "ip6tables -t nat -A PREROUTING -p udp --dport {} -j DNAT --to-destination {}" .format
246
+ (self .ACL_SERVICES ['SNMP' ]['dst_ports' ][0 ], self .namespace_mgmt_ipv6 ))
247
+ fwd_snmp_traffic_from_namespace_to_host_cmds .append (self .iptables_cmd_ns_prefix [namespace ] +
248
+ "ip6tables -t nat -A POSTROUTING -p udp --dport {} -j SNAT --to-source {}" .format
249
+ (self .ACL_SERVICES ['SNMP' ]['dst_ports' ][0 ], self .namespace_docker_mgmt_ipv6 [namespace ]))
250
+
251
+ return fwd_snmp_traffic_from_namespace_to_host_cmds
252
+
209
253
def is_rule_ipv4 (self , rule_props ):
210
254
if (("SRC_IP" in rule_props and rule_props ["SRC_IP" ]) or
211
255
("DST_IP" in rule_props and rule_props ["DST_IP" ])):
@@ -438,6 +482,19 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
438
482
439
483
self .run_commands (iptables_cmds )
440
484
485
+ def update_control_plane_nat_acls (self , namespace ):
486
+ """
487
+ Convenience wrapper which programs the NAT rules for allowing the
488
+ snmp traffic coming on the front panel interface
489
+ """
490
+ # Add iptables commands to allow front panel snmp traffic
491
+ iptables_cmds = self .generate_fwd_snmp_traffic_from_namespace_to_host_commands (namespace )
492
+ self .log_info ("Issuing the following iptables commands:" )
493
+ for cmd in iptables_cmds :
494
+ self .log_info (" " + cmd )
495
+
496
+ self .run_commands (iptables_cmds )
497
+
441
498
def run (self ):
442
499
# Select Time-out for 10 Seconds
443
500
SELECT_TIMEOUT_MS = 1000 * 10
@@ -462,6 +519,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
462
519
for namespace in self .config_db_map .keys ():
463
520
# Unconditionally update control plane ACLs once at start on given namespace
464
521
self .update_control_plane_acls (namespace )
522
+ self .update_control_plane_nat_acls (namespace )
465
523
# Connect to Config DB of given namespace
466
524
acl_db_connector = swsscommon .DBConnector ("CONFIG_DB" , 0 , False , namespace )
467
525
# Subscribe to notifications when ACL tables changes
0 commit comments