1 # Copyright (c) 2020 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """NAT utilities library."""
16 from pprint import pformat
17 from enum import IntEnum
19 from ipaddress import IPv4Address
20 from robot.api import logger
22 from resources.libraries.python.Constants import Constants
23 from resources.libraries.python.InterfaceUtil import InterfaceUtil
24 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
27 class NatConfigFlags(IntEnum):
28 """Common NAT plugin APIs"""
30 NAT_IS_TWICE_NAT = 0x01
31 NAT_IS_SELF_TWICE_NAT = 0x02
32 NAT_IS_OUT2IN_ONLY = 0x04
33 NAT_IS_ADDR_ONLY = 0x08
37 NAT_IS_EXT_HOST_VALID = 0x80
40 class NatAddrPortAllocAlg(IntEnum):
41 """NAT Address and port assignment algorithms."""
42 NAT_ALLOC_ALG_DEFAULT = 0
43 NAT_ALLOC_ALG_MAP_E = 1
44 NAT_ALLOC_ALG_PORT_RANGE = 2
48 """This class defines the methods to set NAT."""
54 def set_nat44_interface(node, interface, flag):
55 """Set inside and outside interfaces for NAT44.
57 :param node: DUT node.
58 :param interface: Inside interface.
59 :param flag: Interface NAT configuration flag name.
64 cmd = u"nat44_interface_add_del_feature"
66 err_msg = f"Failed to set {flag} interface {interface} for NAT44 " \
67 f"on host {node[u'host']}"
69 sw_if_index=InterfaceUtil.get_sw_if_index(node, interface),
71 flags=getattr(NatConfigFlags, flag).value
74 with PapiSocketExecutor(node) as papi_exec:
75 papi_exec.add(cmd, **args_in).get_reply(err_msg)
78 def set_nat44_interfaces(node, int_in, int_out):
79 """Set inside and outside interfaces for NAT44.
81 :param node: DUT node.
82 :param int_in: Inside interface.
83 :param int_out: Outside interface.
88 NATUtil.set_nat44_interface(node, int_in, u"NAT_IS_INSIDE")
89 NATUtil.set_nat44_interface(node, int_out, u"NAT_IS_OUTSIDE")
92 def set_nat44_deterministic(node, ip_in, subnet_in, ip_out, subnet_out):
93 """Set deterministic behaviour of NAT44.
95 :param node: DUT node.
96 :param ip_in: Inside IP.
97 :param subnet_in: Inside IP subnet.
98 :param ip_out: Outside IP.
99 :param subnet_out: Outside IP subnet.
102 :type subnet_in: str or int
104 :type subnet_out: str or int
106 cmd = u"nat_det_add_del_map"
107 err_msg = f"Failed to set deterministic behaviour of NAT " \
108 f"on host {node[u'host']}"
111 in_addr=IPv4Address(str(ip_in)).packed,
112 in_plen=int(subnet_in),
113 out_addr=IPv4Address(str(ip_out)).packed,
114 out_plen=int(subnet_out)
117 with PapiSocketExecutor(node) as papi_exec:
118 papi_exec.add(cmd, **args_in).get_reply(err_msg)
121 def set_nat44_address_range(
122 node, start_ip, end_ip, vrf_id=Constants.BITWISE_NON_ZERO,
123 flag=u"NAT_IS_NONE"):
124 """Set NAT44 address range.
126 :param node: DUT node.
127 :param start_ip: IP range start.
128 :param end_ip: IP range end.
129 :param vrf_id: VRF index (Optional).
130 :param flag: NAT flag name.
137 cmd = u"nat44_add_del_address_range"
138 err_msg = f"Failed to set NAT44 address range on host {node[u'host']}"
141 first_ip_address=IPv4Address(str(start_ip)).packed,
142 last_ip_address=IPv4Address(str(end_ip)).packed,
144 flags=getattr(NatConfigFlags, flag).value
147 with PapiSocketExecutor(node) as papi_exec:
148 papi_exec.add(cmd, **args_in).get_reply(err_msg)
151 def show_nat_config(node):
152 """Show the NAT configuration.
154 :param node: DUT node.
157 cmd = u"nat_show_config"
158 err_msg = f"Failed to get NAT configuration on host {node[u'host']}"
160 with PapiSocketExecutor(node) as papi_exec:
161 reply = papi_exec.add(cmd).get_reply(err_msg)
163 logger.debug(f"NAT Configuration:\n{pformat(reply)}")
166 def show_nat44_summary(node):
167 """Show NAT44 summary on the specified topology node.
169 :param node: Topology node.
172 PapiSocketExecutor.run_cli_cmd(node, u"show nat44 summary")
175 def show_nat_base_data(node):
176 """Show the NAT base data.
181 nat44_interface_addr_dump
183 nat44_static_mapping_dump
186 :param node: DUT node.
189 cmd = u"nat_show_config"
190 err_msg = f"Failed to get NAT base data on host {node[u'host']}"
192 with PapiSocketExecutor(node) as papi_exec:
193 reply = papi_exec.add(cmd).get_reply(err_msg)
195 logger.debug(f"NAT Configuration:\n{pformat(reply)}")
199 u"nat44_interface_addr_dump",
200 u"nat44_address_dump",
201 u"nat44_static_mapping_dump",
202 u"nat44_interface_dump",
204 PapiSocketExecutor.dump_and_log(node, cmds)
207 def show_nat_user_data(node):
208 """Show the NAT user data.
213 nat44_user_session_dump
215 :param node: DUT node.
218 cmd = u"nat_show_config"
219 err_msg = f"Failed to get NAT user data on host {node[u'host']}"
221 with PapiSocketExecutor(node) as papi_exec:
222 reply = papi_exec.add(cmd).get_reply(err_msg)
224 logger.debug(f"NAT Configuration:\n{pformat(reply)}")
228 u"nat44_user_session_dump",
230 PapiSocketExecutor.dump_and_log(node, cmds)