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