e4fa2a308776430e00ece0476916f4a44bc6d88c
[csit.git] / resources / libraries / python / Classify.py
1 # Copyright (c) 2017 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 """Classify utilities library."""
15
16 from robot.api import logger
17
18 from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
19
20
21 class Classify(object):
22     """Classify utilities."""
23
24     @staticmethod
25     def vpp_creates_classify_table_l3(node, ip_version, direction):
26         """Create classify table for IP address filtering.
27
28         :param node: VPP node to create classify table.
29         :param ip_version: Version of IP protocol.
30         :param direction: Direction of traffic - src/dst.
31         :type node: dict
32         :type ip_version: str
33         :type direction: str
34         :returns (table_index, skip_n, match_n)
35         table_index: Classify table index.
36         skip_n: Number of skip vectors.
37         match_n: Number of match vectors.
38         :rtype: tuple(int, int, int)
39         :raises RuntimeError: If VPP can't create table.
40         """
41
42         output = VatExecutor.cmd_from_template(node, "classify_add_table.vat",
43                                                ip_version=ip_version,
44                                                direction=direction)
45
46         if output[0]["retval"] == 0:
47             table_index = output[0]["new_table_index"]
48             skip_n = output[0]["skip_n_vectors"]
49             match_n = output[0]["match_n_vectors"]
50             logger.trace('Classify table with table_index {} created on node {}'
51                          .format(table_index, node['host']))
52         else:
53             raise RuntimeError('Unable to create classify table on node {}'
54                                .format(node['host']))
55
56         return table_index, skip_n, match_n
57
58     @staticmethod
59     def vpp_creates_classify_table_l2(node, direction):
60         """Create classify table for MAC address filtering.
61
62         :param node: VPP node to create classify table.
63         :param direction: Direction of traffic - src/dst.
64         :type node: dict
65         :type direction: str
66         :returns (table_index, skip_n, match_n)
67         table_index: Classify table index.
68         skip_n: Number of skip vectors.
69         match_n: Number of match vectors.
70         :rtype: tuple(int, int, int)
71         :raises RuntimeError: If VPP can't create table.
72         """
73         output = VatExecutor.cmd_from_template(node,
74                                                "classify_add_table_l2.vat",
75                                                direction=direction)
76
77         if output[0]["retval"] == 0:
78             table_index = output[0]["new_table_index"]
79             skip_n = output[0]["skip_n_vectors"]
80             match_n = output[0]["match_n_vectors"]
81             logger.trace('Classify table with table_index {} created on node {}'
82                          .format(table_index, node['host']))
83         else:
84             raise RuntimeError('Unable to create classify table on node {}'
85                                .format(node['host']))
86
87         return table_index, skip_n, match_n
88
89     @staticmethod
90     def vpp_creates_classify_table_hex(node, hex_mask):
91         """Create classify table with hex mask.
92
93         :param node: VPP node to create classify table based on hex mask.
94         :param hex_mask: Classify hex mask.
95         :type node: dict
96         :type hex_mask: str
97         :returns (table_index, skip_n, match_n)
98         table_index: Classify table index.
99         skip_n: Number of skip vectors.
100         match_n: Number of match vectors.
101         :rtype: tuple(int, int, int)
102         :raises RuntimeError: If VPP can't create table.
103         """
104         output = VatExecutor.cmd_from_template(node,
105                                                "classify_add_table_hex.vat",
106                                                hex_mask=hex_mask)
107
108         if output[0]["retval"] == 0:
109             table_index = output[0]["new_table_index"]
110             skip_n = output[0]["skip_n_vectors"]
111             match_n = output[0]["match_n_vectors"]
112             logger.trace('Classify table with table_index {} created on node {}'
113                          .format(table_index, node['host']))
114         else:
115             raise RuntimeError('Unable to create classify table on node {}'
116                                .format(node['host']))
117
118         return table_index, skip_n, match_n
119
120     @staticmethod
121     def vpp_configures_classify_session_l3(node, acl_method, table_index,
122                                            skip_n, match_n, ip_version,
123                                            direction, address):
124         """Configuration of classify session for IP address filtering.
125
126         :param node: VPP node to setup classify session.
127         :param acl_method: ACL method - deny/permit.
128         :param table_index: Classify table index.
129         :param skip_n: Number of skip vectors based on mask.
130         :param match_n: Number of match vectors based on mask.
131         :param ip_version: Version of IP protocol.
132         :param direction: Direction of traffic - src/dst.
133         :param address: IPv4 or IPv6 address.
134         :type node: dict
135         :type acl_method: str
136         :type table_index: int
137         :type skip_n: int
138         :type match_n: int
139         :type ip_version: str
140         :type direction: str
141         :type address: str
142         """
143         with VatTerminal(node) as vat:
144             vat.vat_terminal_exec_cmd_from_template("classify_add_session.vat",
145                                                     acl_method=acl_method,
146                                                     table_index=table_index,
147                                                     skip_n=skip_n,
148                                                     match_n=match_n,
149                                                     ip_version=ip_version,
150                                                     direction=direction,
151                                                     address=address)
152
153     @staticmethod
154     def vpp_configures_classify_session_l2(node, acl_method, table_index,
155                                            skip_n, match_n, direction, address):
156         """Configuration of classify session for MAC address filtering.
157
158         :param node: VPP node to setup classify session.
159         :param acl_method: ACL method - deny/permit.
160         :param table_index: Classify table index.
161         :param skip_n: Number of skip vectors based on mask.
162         :param match_n: Number of match vectors based on mask.
163         :param direction: Direction of traffic - src/dst.
164         :param address: IPv4 or IPv6 address.
165         :type node: dict
166         :type acl_method: str
167         :type table_index: int
168         :type skip_n: int
169         :type match_n: int
170         :type direction: str
171         :type address: str
172         """
173         with VatTerminal(node) as vat:
174             vat.vat_terminal_exec_cmd_from_template(
175                 "classify_add_session_l2.vat",
176                 acl_method=acl_method,
177                 table_index=table_index,
178                 skip_n=skip_n,
179                 match_n=match_n,
180                 direction=direction,
181                 address=address)
182
183     @staticmethod
184     def vpp_configures_classify_session_hex(node, acl_method, table_index,
185                                             skip_n, match_n, hex_value):
186         """Configuration of classify session with hex value.
187
188         :param node: VPP node to setup classify session.
189         :param acl_method: ACL method - deny/permit.
190         :param table_index: Classify table index.
191         :param skip_n: Number of skip vectors based on mask.
192         :param match_n: Number of match vectors based on mask.
193         :param hex_value: Classify hex value.
194         :type node: dict
195         :type acl_method: str
196         :type table_index: int
197         :type skip_n: int
198         :type match_n: int
199         :type hex_value: str
200         """
201         with VatTerminal(node) as vat:
202             vat.vat_terminal_exec_cmd_from_template(
203                 "classify_add_session_hex.vat",
204                 acl_method=acl_method,
205                 table_index=table_index,
206                 skip_n=skip_n,
207                 match_n=match_n,
208                 hex_value=hex_value)
209
210     @staticmethod
211     def vpp_configures_classify_session_generic(node, session_type, table_index,
212                                                 skip_n, match_n, match,
213                                                 match2=''):
214         """Configuration of classify session.
215
216         :param node: VPP node to setup classify session.
217         :param session_type: Session type - hit-next, l2-hit-next, acl-hit-next
218         or policer-hit-next, and their respective parameters.
219         :param table_index: Classify table index.
220         :param skip_n: Number of skip vectors based on mask.
221         :param match_n: Number of match vectors based on mask.
222         :param match: Match value - l2, l3, l4 or hex, and their
223         respective parameters.
224         :param match2: Additional match values, to avoid using overly long
225         variables in RobotFramework.
226         :type node: dict
227         :type session_type: str
228         :type table_index: int
229         :type skip_n: int
230         :type match_n: int
231         :type match: str
232         :type match2: str
233         """
234
235         match = ' '.join((match, match2))
236
237         with VatTerminal(node) as vat:
238             vat.vat_terminal_exec_cmd_from_template(
239                 "classify_add_session_generic.vat",
240                 type=session_type,
241                 table_index=table_index,
242                 skip_n=skip_n,
243                 match_n=match_n,
244                 match=match,
245             )
246
247     @staticmethod
248     def compute_classify_hex_mask(ip_version, protocol, direction):
249         """Compute classify hex mask for TCP or UDP packet matching.
250
251         :param ip_version: Version of IP protocol.
252         :param protocol: Type of protocol.
253         :param direction: Traffic direction.
254         :type ip_version: str
255         :type protocol: str
256         :type direction: str
257         :returns: Classify hex mask.
258         :rtype : str
259         :raises ValueError: If protocol is not TCP or UDP.
260         :raises ValueError: If direction is not source or destination or
261                             source + destination.
262         """
263         if protocol == 'TCP' or protocol == 'UDP':
264             base_mask = Classify._compute_base_mask(ip_version)
265
266             if direction == 'source':
267                 return base_mask + 'FFFF0000'
268             elif direction == 'destination':
269                 return base_mask + '0000FFFF'
270             elif direction == 'source + destination':
271                 return base_mask + 'FFFFFFFF'
272             else:
273                 raise ValueError("Invalid direction!")
274         else:
275             raise ValueError("Invalid protocol!")
276
277     @staticmethod
278     def compute_classify_hex_value(hex_mask, source_port, destination_port):
279         """Compute classify hex value for TCP or UDP packet matching.
280
281         :param hex_mask: Classify hex mask.
282         :param source_port: Source TCP/UDP port.
283         :param destination_port: Destination TCP/UDP port.
284         :type hex_mask: str
285         :type source_port: str
286         :type destination_port: str
287         :returns: Classify hex value.
288         :rtype: str
289         """
290         source_port_hex = Classify._port_convert(source_port)
291         destination_port_hex = Classify._port_convert(destination_port)
292
293         return hex_mask[:-8] + source_port_hex + destination_port_hex
294
295     @staticmethod
296     def _port_convert(port):
297         """Convert port number for classify hex table format.
298
299         :param port: TCP/UDP port number.
300         :type port: str
301         :returns: TCP/UDP port number in 4-digit hexadecimal format.
302         :rtype: str
303         """
304         return '{0:04x}'.format(int(port))
305
306     @staticmethod
307     def _compute_base_mask(ip_version):
308         """Compute base classify hex mask based on IP version.
309
310         :param ip_version: Version of IP protocol.
311         :type ip_version: str
312         :return: Base hex mask.
313         :rtype: str
314         """
315         if ip_version == 'ip4':
316             return 68 * '0'
317             # base value of classify hex table for IPv4 TCP/UDP ports
318         elif ip_version == 'ip6':
319             return 108 * '0'
320             # base value of classify hex table for IPv6 TCP/UDP ports
321         else:
322             raise ValueError("Invalid IP version!")
323
324     @staticmethod
325     def get_classify_table_data(node, table_index):
326         """Retrieve settings for classify table by ID.
327
328         :param node: VPP node to retrieve classify data from.
329         :param table_index: Index of a specific classify table.
330         :type node: dict
331         :type table_index: int
332         :returns: Classify table settings.
333         :rtype: dict
334         """
335         with VatTerminal(node) as vat:
336             data = vat.vat_terminal_exec_cmd_from_template(
337                 "classify_table_info.vat",
338                 table_id=table_index
339             )
340         return data[0]
341
342     @staticmethod
343     def get_classify_session_data(node, table_index, session_index=None):
344         """Retrieve settings for all classify sessions in a table,
345         or for a specific classify session.
346
347         :param node: VPP node to retrieve classify data from.
348         :param table_index: Index of a classify table.
349         :param session_index: Index of a specific classify session. (Optional)
350         :type node: dict
351         :type table_index: int
352         :type session_index: int
353         :returns: List of classify session settings, or a dictionary of settings
354          for a specific classify session.
355         :rtype: list or dict
356         """
357         with VatTerminal(node) as vat:
358             data = vat.vat_terminal_exec_cmd_from_template(
359                 "classify_session_dump.vat",
360                 table_id=table_index
361             )
362         if session_index is not None:
363             return data[0][session_index]
364         else:
365             return data[0]
366
367     @staticmethod
368     def vpp_log_plugin_acl_settings(node):
369         """Retrieve configured settings from the ACL plugin
370          and write to robot log.
371
372         :param node: VPP node.
373         :type node: dict
374         """
375         try:
376             VatExecutor.cmd_from_template(
377                 node, "acl_plugin/acl_dump.vat")
378         except (ValueError, RuntimeError):
379             # Fails to parse JSON data in response, but it is still logged
380             pass
381
382     @staticmethod
383     def vpp_log_plugin_acl_interface_assignment(node):
384         """Retrieve interface assignment from the ACL plugin
385         and write to robot log.
386
387         :param node: VPP node.
388         :type node: dict
389         """
390
391         try:
392             VatExecutor.cmd_from_template(
393                 node, "acl_plugin/acl_interface_dump.vat", json_out=False)
394         except RuntimeError:
395             # Fails to parse response, but it is still logged
396             pass

©2016 FD.io a Linux Foundation Collaborative Project. All Rights Reserved.
Linux Foundation is a registered trademark of The Linux Foundation. Linux is a registered trademark of Linus Torvalds.
Please see our privacy policy and terms of use.