Tolerate failures when setting MTU
[csit.git] / resources / libraries / python / NATUtil.py
1 # Copyright (c) 2019 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:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
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.
13
14 """NAT utilities library."""
15
16 from pprint import pformat
17 from socket import AF_INET, inet_pton
18
19 from enum import IntEnum
20
21 from robot.api import logger
22
23 from resources.libraries.python.InterfaceUtil import InterfaceUtil
24 from resources.libraries.python.PapiExecutor import PapiExecutor
25
26
27 class NATConfigFlags(IntEnum):
28     """Common NAT plugin APIs"""
29     NAT_IS_NONE = 0x00
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
34     NAT_IS_OUTSIDE = 0x10
35     NAT_IS_INSIDE = 0x20
36     NAT_IS_STATIC = 0x40
37     NAT_IS_EXT_HOST_VALID = 0x80
38
39
40 class NATUtil(object):
41     """This class defines the methods to set NAT."""
42
43     def __init__(self):
44         pass
45
46     @staticmethod
47     def set_nat44_interfaces(node, int_in, int_out):
48         """Set inside and outside interfaces for NAT44.
49
50         :param node: DUT node.
51         :param int_in: Inside interface.
52         :param int_out: Outside interface.
53         :type node: dict
54         :type int_in: str
55         :type int_out: str
56         """
57
58         cmd = 'nat44_interface_add_del_feature'
59
60         int_in_idx = InterfaceUtil.get_sw_if_index(node, int_in)
61         err_msg = 'Failed to set inside interface {int} for NAT44 on host ' \
62                   '{host}'.format(int=int_in, host=node['host'])
63         args_in = dict(
64             sw_if_index=int_in_idx,
65             is_add=1,
66             flags=getattr(NATConfigFlags, "NAT_IS_INSIDE").value
67         )
68         with PapiExecutor(node) as papi_exec:
69             papi_exec.add(cmd, **args_in).get_replies(err_msg).\
70                 verify_reply(err_msg=err_msg)
71
72         int_out_idx = InterfaceUtil.get_sw_if_index(node, int_out)
73         err_msg = 'Failed to set outside interface {int} for NAT44 on host ' \
74                   '{host}'.format(int=int_out, host=node['host'])
75         args_in = dict(
76             sw_if_index=int_out_idx,
77             is_add=1,
78             flags=getattr(NATConfigFlags, "NAT_IS_OUTSIDE").value
79         )
80         with PapiExecutor(node) as papi_exec:
81             papi_exec.add(cmd, **args_in).get_replies(err_msg). \
82                 verify_reply(err_msg=err_msg)
83
84     @staticmethod
85     def set_nat44_deterministic(node, ip_in, subnet_in, ip_out, subnet_out):
86         """Set deterministic behaviour of NAT44.
87
88         :param node: DUT node.
89         :param ip_in: Inside IP.
90         :param subnet_in: Inside IP subnet.
91         :param ip_out: Outside IP.
92         :param subnet_out: Outside IP subnet.
93         :type node: dict
94         :type ip_in: str
95         :type subnet_in: str or int
96         :type ip_out: str
97         :type subnet_out: str or int
98         """
99
100         cmd = 'nat_det_add_del_map'
101         err_msg = 'Failed to set deterministic behaviour of NAT on host ' \
102                   '{host}'.format(host=node['host'])
103         args_in = dict(
104             is_add=True,
105             in_addr=inet_pton(AF_INET, str(ip_in)),
106             in_plen=int(subnet_in),
107             out_addr=inet_pton(AF_INET, str(ip_out)),
108             out_plen=int(subnet_out)
109         )
110         with PapiExecutor(node) as papi_exec:
111             papi_exec.add(cmd, **args_in).get_replies(err_msg). \
112                 verify_reply(err_msg=err_msg)
113
114     @staticmethod
115     def show_nat(node):
116         """Show the NAT configuration and data.
117
118         Used data sources:
119
120             nat_show_config
121             nat_worker_dump
122             nat44_interface_addr_dump
123             nat44_address_dump
124             nat44_static_mapping_dump
125             nat44_user_dump
126             nat44_interface_dump
127             nat44_user_session_dump
128             nat_det_map_dump
129
130         :param node: DUT node.
131         :type node: dict
132         """
133
134         cmd = 'nat_show_config'
135         err_msg = 'Failed to get NAT configuration on host {host}'.\
136             format(host=node['host'])
137         with PapiExecutor(node) as papi_exec:
138             data = papi_exec.add(cmd).get_replies(err_msg).\
139                 verify_reply(err_msg=err_msg)
140         logger.debug("NAT Configuration:\n{data}".format(data=pformat(data)))
141
142         cmds = [
143             "nat_worker_dump",
144             "nat44_interface_addr_dump",
145             "nat44_address_dump",
146             "nat44_static_mapping_dump",
147             "nat44_user_dump",
148             "nat44_interface_dump",
149             "nat44_user_session_dump",
150             "nat_det_map_dump"
151         ]
152         PapiExecutor.dump_and_log(node, cmds)