Add vpp loadbalancer l3dsr/nat4 mode test suites
[csit.git] / resources / libraries / python / LoadBalancerUtil.py
1 # Copyright (c) 2019 Intel 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 """Loadbalancer util library."""
15
16 from socket import htonl
17 from ipaddress import ip_address
18 from resources.libraries.python.topology import NodeType, Topology
19 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
20
21 class LoadBalancerUtil(object):
22     """Basic Loadbalancer parameter configuration."""
23
24     @staticmethod
25     def vpp_lb_conf(node, **kwargs):
26         """Config global parameters for loadbalancer.
27
28         :param node: Node where the interface is.
29         :param kwargs: Optional key-value arguments:
30
31             ip4_src_addr: IPv4 address to be used as source for IPv4 traffic.
32                           (str)
33             ip6_src_addr: IPv6 address to be used as source for IPv6 traffic.
34                           (str)
35             flow_timeout: Time in seconds after which, if no packet is received
36                           for a given flow, the flow is removed from the
37                           established flow table. (int)
38             buckets_per_core: Number of buckets *per worker thread* in the
39                               established flow table (int)
40
41         :type node: dict
42         :type kwargs: dict
43         :returns: Nothing.
44         :raises ValueError: If the node has an unknown node type.
45         """
46         if node['type'] == NodeType.DUT:
47             ip4_src_addr = ip_address(unicode(kwargs.pop('ip4_src_addr',
48                                                          '255.255.255.255')))
49             ip6_src_addr = ip_address(unicode(kwargs.pop('ip6_src_addr',\
50                     'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')))
51             flow_timeout = kwargs.pop('flow_timeout', 40)
52             sticky_buckets_per_core = kwargs.pop('buckets_per_core', 1024)
53
54             cmd = 'lb_conf'
55             err_msg = 'Failed to set lb conf on host {host}'.format(
56                 host=node['host'])
57
58             args = dict(ip4_src_address=str(ip4_src_addr),
59                         ip6_src_address=str(ip6_src_addr),
60                         sticky_buckets_per_core=sticky_buckets_per_core,
61                         flow_timeout=flow_timeout)
62
63             with PapiSocketExecutor(node) as papi_exec:
64                 papi_exec.add(cmd, **args).get_reply(err_msg)
65         else:
66             raise ValueError('Node {host} has unknown NodeType: "{type}"'
67                              .format(host=node['host'], type=node['type']))
68
69     @staticmethod
70     def vpp_lb_add_del_vip(node, **kwargs):
71         """Config vip for loadbalancer.
72
73         :param node: Node where the interface is.
74         :param kwargs: Optional key-value arguments:
75
76             vip_addr: IPv4 address to be used as source for IPv4 traffic. (str)
77             protocol: tcp or udp. (int)
78             port: destination port. (int)
79             encap: encap is ip4 GRE(0) or ip6 (1GRE) or L3DSR(2) or NAT4(3) or
80                    NAT6(4). (int)
81             dscp: dscp bit corresponding to VIP
82             type: service type
83             target_port: Pod's port corresponding to specific service
84             node_port: Node's port
85             new_len: Size of the new connections flow table used
86                      for this VIP
87             is_del: 1 if the VIP should be removed otherwise 0.
88
89         :type node: dict
90         :type kwargs: dict
91         :returns: Nothing.
92         :raises ValueError: If the node has an unknown node type.
93         """
94         if node['type'] == NodeType.DUT:
95             vip_addr = kwargs.pop('vip_addr', '0.0.0.0')
96             protocol = kwargs.pop('protocol', 255)
97             port = kwargs.pop('port', 0)
98             encap = kwargs.pop('encap', 0)
99             dscp = kwargs.pop('dscp', 0)
100             srv_type = kwargs.pop('srv_type', 0)
101             target_port = kwargs.pop('target_port', 0)
102             node_port = kwargs.pop('node_port', 0)
103             new_len = kwargs.pop('new_len', 1024)
104             is_del = kwargs.pop('is_del', 0)
105
106             cmd = 'lb_add_del_vip'
107             err_msg = 'Failed to add vip on host {host}'.format(
108                 host=node['host'])
109
110             vip_addr = ip_address(unicode(vip_addr)).packed
111             args = dict(pfx={'len': 128,
112                              'address': {'un': {'ip4': vip_addr}, 'af': 0}},
113                         protocol=protocol,
114                         port=port,
115                         encap=htonl(encap),
116                         dscp=dscp,
117                         type=srv_type,
118                         target_port=target_port,
119                         node_port=node_port,
120                         new_flows_table_length=int(new_len),
121                         is_del=is_del)
122
123             with PapiSocketExecutor(node) as papi_exec:
124                 papi_exec.add(cmd, **args).get_reply(err_msg)
125         else:
126             raise ValueError('Node {host} has unknown NodeType: "{type}"'
127                              .format(host=node['host'], type=node['type']))
128
129     @staticmethod
130     def vpp_lb_add_del_as(node, **kwargs):
131         """Config AS for Loadbalancer.
132
133         :param node: Node where the interface is.
134         :param kwargs: Optional key-value arguments:
135
136             vip_addr: IPv4 address to be used as source for IPv4 traffic. (str)
137             protocol: tcp or udp. (int)
138             port: destination port. (int)
139             as_addr: The application server address. (str)
140             is_del: 1 if the VIP should be removed otherwise 0. (int)
141             is_flush: 1 if the sessions related to this AS should be flushed
142                       otherwise 0. (int)
143
144         :type node: dict
145         :type kwargs: dict
146         :returns: Nothing.
147         :raises ValueError: If the node has an unknown node type.
148         """
149         if node['type'] == NodeType.DUT:
150             cmd = 'lb_add_del_as'
151             err_msg = 'Failed to add lb as on host {host}'.format(
152                 host=node['host'])
153
154             vip_addr = kwargs.pop('vip_addr', '0.0.0.0')
155             protocol = kwargs.pop('protocol', 255)
156             port = kwargs.pop('port', 0)
157             as_addr = kwargs.pop('as_addr', '0.0.0.0')
158             is_del = kwargs.pop('is_del', 0)
159             is_flush = kwargs.pop('is_flush', 0)
160
161             vip_addr = ip_address(unicode(vip_addr)).packed
162             as_addr = ip_address(unicode(as_addr)).packed
163
164             args = dict(pfx={'len': 128,
165                              'address': {'un': {'ip4': vip_addr}, 'af': 0}},
166                         protocol=protocol,
167                         port=port,
168                         as_address={'un': {'ip4': as_addr}, 'af': 0},
169                         is_del=is_del,
170                         is_flush=is_flush)
171
172             with PapiSocketExecutor(node) as papi_exec:
173                 papi_exec.add(cmd, **args).get_reply(err_msg)
174         else:
175             raise ValueError('Node {host} has unknown NodeType: "{type}"'
176                              .format(host=node['host'], type=node['type']))
177
178     @staticmethod
179     def vpp_lb_add_del_intf_nat4(node, **kwargs):
180         """Enable/disable NAT4 feature on the interface.
181
182         :param node: Node where the interface is.
183         :param kwargs: Optional key-value arguments:
184
185             is_add: true if add, false if delete. (bool)
186             interface: software index of the interface. (int)
187
188         :type node: dict
189         :type kwargs: dict
190         :returns: Nothing.
191         :raises ValueError: If the node has an unknown node type.
192         """
193         if node['type'] == NodeType.DUT:
194             cmd = 'lb_add_del_intf_nat4'
195             err_msg = 'Failed to add interface nat4 on host {host}'.format(
196                 host=node['host'])
197
198             is_add = kwargs.pop('is_add', True)
199             interface = kwargs.pop('interface', 0)
200             sw_if_index = Topology.get_interface_sw_index(node, interface)
201             args = dict(is_add=is_add, sw_if_index=sw_if_index)
202
203             with PapiSocketExecutor(node) as papi_exec:
204                 papi_exec.add(cmd, **args).get_reply(err_msg)
205         else:
206             raise ValueError('Node {host} has unknown NodeType: "{type}"'
207                              .format(host=node['host'], type=node['type']))