Revert "CSIT-986: Use MLRsearch from pip"
[csit.git] / resources / libraries / python / SRv6.py
1 # Copyright (c) 2018 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 """Segment Routing over IPv6 dataplane utilities library."""
15
16 from resources.libraries.python.VatExecutor import VatTerminal
17 from resources.libraries.python.topology import Topology
18
19
20 # SRv6 LocalSID supported functions.
21 # Endpoint function
22 SRV6BEHAVIOUR_END = 'end'
23 # Endpoint function with Layer-3 cross-connect
24 SRV6BEHAVIOUR_END_X = 'end.x'
25 # Endpoint with decapsulation and Layer-2 cross-connect
26 SRV6BEHAVIOUR_END_DX2 = 'end.dx2'
27 # Endpoint with decapsulation and IPv4 cross-connect
28 SRV6BEHAVIOUR_END_DX4 = 'end.dx4'
29 # Endpoint with decapsulation and IPv4 table lookup
30 SRV6BEHAVIOUR_END_DT4 = 'end.dt4'
31 # Endpoint with decapsulation and IPv6 cross-connect
32 SRV6BEHAVIOUR_END_DX6 = 'end.dx6'
33 # Endpoint with decapsulation and IPv6 table lookup
34 SRV6BEHAVIOUR_END_DT6 = 'end.dt6'
35 # Endpoint to SR-unaware appliance via static proxy
36 SRV6BEHAVIOUR_END_AS = 'end.as'
37 # Endpoint to SR-unaware appliance via dynamic proxy
38 SRV6BEHAVIOUR_END_AD = 'end.ad'
39 # Endpoint to SR-unaware appliance via masquerading
40 SRV6BEHAVIOUR_END_AM = 'end.am'
41
42
43 class SRv6(object):
44     """SRv6 class."""
45
46     def __init__(self):
47         pass
48
49     @staticmethod
50     def configure_sr_localsid(node, local_sid, behavior, interface=None,
51                               next_hop=None, fib_table=None, out_if=None,
52                               in_if=None, src_addr=None, sid_list=None):
53         """Create SRv6 LocalSID and binds it to a particular behaviour on
54         the given node.
55
56         :param node: Given node to create localSID on.
57         :param local_sid: LocalSID IPv6 address.
58         :param behavior: SRv6 LocalSID function.
59         :param interface: Interface name (Optional, required for
60             L2/L3 xconnects).
61         :param next_hop: Next hop IPv4/IPv6 address (Optional, required for L3
62             xconnects).
63         :param fib_table: FIB table for IPv4/IPv6 lookup (Optional, required for
64             L3 routing).
65         :param out_if: Interface name of local interface for sending traffic
66             towards the Service Function (Optional, required for SRv6 endpoint
67             to SR-unaware appliance).
68         :param in_if: Interface name of local interface receiving the traffic
69             coming back from the Service Function (Optional, required for SRv6
70             endpoint to SR-unaware appliance).
71         :param src_addr: Source address on the packets coming back on in_if
72             interface (Optional, required for SRv6 endpoint to SR-unaware
73             appliance via static proxy).
74         :param sid_list: SID list (Optional, required for SRv6 endpoint to
75             SR-unaware appliance via static proxy).
76         :type node: dict
77         :type local_sid: str
78         :type behavior: str
79         :type interface: str
80         :type next_hop: int
81         :type fib_table: str
82         :type out_if: str
83         :type in_if: str
84         :type src_addr: str
85         :type sid_list: list
86         :raises ValueError: If unsupported SRv6 LocalSID function used or
87             required parameter is missing.
88         """
89         if behavior == SRV6BEHAVIOUR_END:
90             params = ''
91         elif behavior in [SRV6BEHAVIOUR_END_X, SRV6BEHAVIOUR_END_DX4,
92                           SRV6BEHAVIOUR_END_DX6]:
93             if interface is None or next_hop is None:
94                 raise ValueError('Required parameter(s) missing.\ninterface:{0}'
95                                  '\nnext_hop:{1}'.format(interface, next_hop))
96             interface_name = Topology.get_interface_name(node, interface)
97             params = '{0} {1}'.format(interface_name, next_hop)
98         elif behavior == SRV6BEHAVIOUR_END_DX2:
99             if interface is None:
100                 raise ValueError('Required parameter missing.\ninterface:{0}'.
101                                  format(interface))
102             params = '{0}'.format(interface)
103         elif behavior in [SRV6BEHAVIOUR_END_DT4, SRV6BEHAVIOUR_END_DT6]:
104             if fib_table is None:
105                 raise ValueError('Required parameter missing.\nfib_table: {0}'.
106                                  format(fib_table))
107             params = '{0}'.format(fib_table)
108         elif behavior == SRV6BEHAVIOUR_END_AS:
109             if next_hop is None or out_if is None or in_if is None or \
110                             src_addr is None or sid_list is None:
111                 raise ValueError('Required parameter(s) missing.\nnext_hop:{0}'
112                                  '\nout_if:{1}\nin_if:{2}\nsrc_addr:{3}\n'
113                                  'sid_list:{4}'.format(next_hop, out_if, in_if,
114                                                        src_addr, sid_list))
115             sid_conf = 'next ' + ' next '.join(sid_list)
116             params = 'nh {0} oif {1} iif {2} src {3} {4}'.\
117                 format(next_hop, out_if, in_if, src_addr, sid_conf)
118         elif behavior in [SRV6BEHAVIOUR_END_AD, SRV6BEHAVIOUR_END_AM]:
119             if next_hop is None or out_if is None or in_if is None:
120                 raise ValueError('Required parameter(s) missing.\nnext_hop:{0}'
121                                  '\nout_if:{1}\nin_if:{2}'.
122                                  format(next_hop, out_if, in_if))
123             params = 'nh {0} oif {1} iif {2}'.format(next_hop, out_if, in_if)
124         else:
125             raise ValueError('Unsupported SRv6 LocalSID function: {0}'.
126                              format(behavior))
127
128         with VatTerminal(node, json_param=False) as vat:
129             vat.vat_terminal_exec_cmd_from_template(
130                 'srv6/sr_localsid_add.vat', local_sid=local_sid,
131                 behavior=behavior, params=params)
132
133         if "exec error: Misc" in vat.vat_stdout:
134             raise RuntimeError('Create SRv6 LocalSID {0} failed on node {1}'.
135                                format(local_sid, node['host']))
136
137     @staticmethod
138     def delete_sr_localsid(node, local_sid):
139         """Delete SRv6 LocalSID on the given node.
140
141         :param node: Given node to delete localSID on.
142         :param local_sid: LocalSID IPv6 address.
143         :type node: dict
144         :type local_sid: str
145         """
146         with VatTerminal(node, json_param=False) as vat:
147             vat.vat_terminal_exec_cmd_from_template(
148                 'srv6/sr_localsid_del.vat', local_sid=local_sid)
149
150         if "exec error: Misc" in vat.vat_stdout:
151             raise RuntimeError('Delete SRv6 LocalSID {0} failed on node {1}'.
152                                format(local_sid, node['host']))
153
154     @staticmethod
155     def show_sr_localsids(node):
156         """Show SRv6 LocalSIDs on the given node.
157
158         :param node: Given node to show localSIDs on.
159         :type node: dict
160         """
161         with VatTerminal(node, json_param=False) as vat:
162             vat.vat_terminal_exec_cmd_from_template(
163                 'srv6/sr_localsids_show.vat')
164
165     @staticmethod
166     def configure_sr_policy(node, bsid, sid_list, mode='encap'):
167         """Create SRv6 policy on the given node.
168
169         :param node: Given node to create SRv6 policy on.
170         :param bsid: BindingSID - local SID IPv6 address.
171         :param sid_list: SID list.
172         :param mode: Encapsulation / insertion mode.
173         :type node: dict
174         :type bsid: str
175         :type sid_list: list
176         :type mode: str
177         """
178         sid_conf = 'next ' + ' next '.join(sid_list)
179
180         with VatTerminal(node, json_param=False) as vat:
181             vat.vat_terminal_exec_cmd_from_template(
182                 'srv6/sr_policy_add.vat', bsid=bsid,
183                 sid_conf=sid_conf, mode=mode)
184
185         if "exec error: Misc" in vat.vat_stdout:
186             raise RuntimeError('Create SRv6 policy for BindingSID {0} failed on'
187                                ' node {1}'.format(bsid, node['host']))
188
189     @staticmethod
190     def delete_sr_policy(node, bsid):
191         """Delete SRv6 policy on the given node.
192
193         :param node: Given node to delete SRv6 policy on.
194         :param bsid: BindingSID IPv6 address.
195         :type node: dict
196         :type bsid: str
197         """
198         with VatTerminal(node, json_param=False) as vat:
199             vat.vat_terminal_exec_cmd_from_template(
200                 'srv6/sr_policy_del.vat', bsid=bsid)
201
202         if "exec error: Misc" in vat.vat_stdout:
203             raise RuntimeError('Delete SRv6 policy for BindingSID {0} failed on'
204                                ' node {1}'.format(bsid, node['host']))
205
206     @staticmethod
207     def show_sr_policies(node):
208         """Show SRv6 policies on the given node.
209
210         :param node: Given node to show SRv6 policies on.
211         :type node: dict
212         """
213         with VatTerminal(node, json_param=False) as vat:
214             vat.vat_terminal_exec_cmd_from_template(
215                 'srv6/sr_policies_show.vat')
216
217     @staticmethod
218     def configure_sr_steer(node, mode, bsid, interface=None, ip_addr=None,
219                            prefix=None):
220         """Create SRv6 steering policy on the given node.
221
222         :param node: Given node to create steering policy on.
223         :param mode: Mode of operation - L2 or L3.
224         :param bsid: BindingSID - local SID IPv6 address.
225         :param interface: Interface name (Optional, required in case of
226             L2 mode).
227         :param ip_addr: IPv4/IPv6 address (Optional, required in case of L3
228             mode).
229         :param prefix: IP address prefix (Optional, required in case of L3
230             mode).
231         :type node: dict
232         :type mode: str
233         :type bsid: str
234         :type interface: str
235         :type ip_addr: str
236         :type prefix: int
237         :raises ValueError: If unsupported mode used or required parameter
238             is missing.
239         """
240         if mode.lower() == 'l2':
241             if interface is None:
242                 raise ValueError('Required data missing.\ninterface:{0}\n'.
243                                  format(interface))
244             interface_name = Topology.get_interface_name(node, interface)
245             params = 'l2 {0}'.format(interface_name)
246         elif mode.lower() == 'l3':
247             if ip_addr is None or prefix is None:
248                 raise ValueError('Required data missing.\nIP address:{0}\n'
249                                  'mask:{1}'.format(ip_addr, prefix))
250             params = 'l3 {0}/{1}'.format(ip_addr, prefix)
251         else:
252             raise ValueError('Unsupported mode: {0}'.format(mode))
253
254         with VatTerminal(node, json_param=False) as vat:
255             vat.vat_terminal_exec_cmd_from_template(
256                 'srv6/sr_steer_add_del.vat', params=params, bsid=bsid)
257
258         sr_steer_errors = ("exec error: Misc",
259                            "sr steer: No SR policy specified")
260         for err in sr_steer_errors:
261             if err in vat.vat_stdout:
262                 raise RuntimeError('Create SRv6 steering policy for BindingSID'
263                                    ' {0} failed on node {1}'.
264                                    format(bsid, node['host']))
265
266     @staticmethod
267     def delete_sr_steer(node, mode, bsid, interface=None, ip_addr=None,
268                         mask=None):
269         """Delete SRv6 steering policy on the given node.
270
271         :param node: Given node to delete steering policy on.
272         :param mode: Mode of operation - L2 or L3.
273         :param bsid: BindingSID - local SID IPv6 address.
274         :param interface: Interface name (Optional, required in case of
275             L2 mode).
276         :param ip_addr: IPv4/IPv6 address (Optional, required in case of L3
277             mode).
278         :param mask: IP address mask (Optional, required in case of L3 mode).
279         :type node: dict
280         :type mode: str
281         :type bsid: str
282         :type interface: str
283         :type ip_addr: int
284         :type mask: int
285         :raises ValueError: If unsupported mode used or required parameter
286             is missing.
287         """
288         params = 'del'
289         if mode == 'l2':
290             if interface is None:
291                 raise ValueError('Required data missing.\ninterface:{0}\n'.
292                                  format(interface))
293             interface_name = Topology.get_interface_name(node, interface)
294             params += 'l2 {0}'.format(interface_name)
295         elif mode == 'l3':
296             if ip_addr is None or mask is None:
297                 raise ValueError('Required data missing.\nIP address:{0}\n'
298                                  'mask:{1}'.format(ip_addr, mask))
299             params += '{0}/{1}'.format(ip_addr, mask)
300         else:
301             raise ValueError('Unsupported mode: {0}'.format(mode))
302
303         with VatTerminal(node, json_param=False) as vat:
304             vat.vat_terminal_exec_cmd_from_template(
305                 'srv6/sr_steer_add_del.vat', params=params, bsid=bsid)
306
307         if "exec error: Misc" in vat.vat_stdout:
308             raise RuntimeError('Delete SRv6 policy for bsid {0} failed on node'
309                                ' {1}'.format(bsid, node['host']))
310
311     @staticmethod
312     def show_sr_steering_policies(node):
313         """Show SRv6 steering policies on the given node.
314
315         :param node: Given node to show SRv6 steering policies on.
316         :type node: dict
317         """
318         with VatTerminal(node, json_param=False) as vat:
319             vat.vat_terminal_exec_cmd_from_template(
320                 'srv6/sr_steer_policies_show.vat')
321
322     @staticmethod
323     def set_sr_encaps_source_address(node, ip6_addr):
324         """Set SRv6 encapsulation source address on the given node.
325
326         :param node: Given node to set SRv6 encapsulation source address on.
327         :param ip6_addr: Local SID IPv6 address.
328         :type node: dict
329         :type ip6_addr: str
330         """
331         with VatTerminal(node, json_param=False) as vat:
332             vat.vat_terminal_exec_cmd_from_template(
333                 'srv6/sr_set_encaps_source.vat', ip6_addr=ip6_addr)