CSIT-360: Parallel test sets run
[csit.git] / resources / libraries / python / Policer.py
1 # Copyright (c) 2016 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 """Policer utilities library."""
15
16 from enum import Enum
17
18 from ipaddress import ip_address
19
20 from resources.libraries.python.VatExecutor import VatExecutor
21 from resources.libraries.python.VatJsonUtil import VatJsonUtil
22 from resources.libraries.python.topology import Topology
23
24
25 # pylint: disable=too-few-public-methods
26 class PolicerRateType(Enum):
27     """Policer rate types."""
28     KBPS = 'kbps'
29     PPS = 'pps'
30
31     def __init__(self, string):
32         self.string = string
33
34
35 # pylint: disable=invalid-name
36 class PolicerRoundType(Enum):
37     """Policer round types."""
38     CLOSEST = 'closest'
39     UP = 'up'
40     DOWN = 'down'
41
42     def __init__(self, string):
43         self.string = string
44
45
46 class PolicerType(Enum):
47     """Policer type."""
48     P_1R2C = '1r2c'
49     P_1R3C = '1r3c'
50     P_2R3C_2698 = '2r3c-2698'
51     P_2R3C_4115 = '2r3c-4115'
52     P_2R3C_MEF5CF1 = '2r3c-mef5cf1'
53
54     def __init__(self, string):
55         self.string = string
56
57
58 class PolicerAction(Enum):
59     """Policer action."""
60     DROP = 'drop'
61     TRANSMIT = 'transmit'
62     MARK_AND_TRANSMIT = 'mark-and-transmit'
63
64     def __init__(self, string):
65         self.string = string
66
67
68 class DSCP(Enum):
69     """DSCP for mark-and-transmit action."""
70     CS0 = ('CS0', 0)
71     CS1 = ('CS1', 8)
72     CS2 = ('CS2', 16)
73     CS3 = ('CS3', 24)
74     CS4 = ('CS4', 32)
75     CS5 = ('CS5', 40)
76     CS6 = ('CS6', 48)
77     CS7 = ('CS7', 56)
78     AF11 = ('AF11', 10)
79     AF12 = ('AF12', 12)
80     AF13 = ('AF13', 14)
81     AF21 = ('AF21', 18)
82     AF22 = ('AF22', 20)
83     AF23 = ('AF23', 22)
84     AF31 = ('AF31', 26)
85     AF32 = ('AF32', 28)
86     AF33 = ('AF33', 30)
87     EF = ('EF', 46)
88
89     def __init__(self, string, num):
90         self.string = string
91         self.num = num
92
93
94 class PolicerClassifyPreColor(Enum):
95     """Policer classify precolor."""
96     CONFORM_COLOR = 'conform-color'
97     EXCEED_COLOR = 'exceed-color'
98
99     def __init__(self, string):
100         self.string = string
101
102
103 class PolicerClassifyTableType(Enum):
104     """Policer classify table type."""
105     IP4_TABLE = 'ip4-table'
106     IP6_TABLE = 'ip6-table'
107     L2_TABLE = 'l2-table'
108
109     def __init__(self, string):
110         self.string = string
111
112
113 # pylint: disable=too-many-instance-attributes
114 # pylint: disable=too-many-public-methods
115 class Policer(object):
116     """Policer utilities."""
117
118     def __init__(self):
119         self._cir = 0
120         self._eir = 0
121         self._cb = 0
122         self._eb = 0
123         self._rate_type = None
124         self._round_type = None
125         self._policer_type = None
126         self._conform_action = None
127         self._conform_dscp = None
128         self._exceed_action = None
129         self._exceed_dscp = None
130         self._violate_action = None
131         self._violate_dscp = None
132         self._color_aware = False
133         self._classify_match_ip = ''
134         self._classify_match_is_src = True
135         self._classify_precolor = None
136         self._sw_if_index = 0
137         self._node = None
138         self._policer_name = ''
139
140     def policer_set_configuration(self):
141         """Configure policer on VPP node.
142
143         ...note:: First set all required parameters.
144         """
145         node = self._node
146
147         # create policer
148         color_aware = 'color-aware' if self._color_aware else ''
149
150         # pylint: disable=no-member
151         conform_action = self._conform_action.value
152
153         if PolicerAction.MARK_AND_TRANSMIT == self._conform_action:
154             conform_action += ' {0}'.format(self._conform_dscp.string)
155
156         exceed_action = self._exceed_action.value
157         if PolicerAction.MARK_AND_TRANSMIT == self._exceed_action:
158             exceed_action += ' {0}'.format(self._exceed_dscp.string)
159
160         violate_action = self._violate_action.value
161         if PolicerAction.MARK_AND_TRANSMIT == self._violate_action:
162             violate_action += ' {0}'.format(self._violate_dscp.string)
163
164         out = VatExecutor.cmd_from_template(node,
165                                             "policer/policer_add_3c.vat",
166                                             name=self._policer_name,
167                                             cir=self._cir,
168                                             eir=self._eir,
169                                             cb=self._cb,
170                                             eb=self._eb,
171                                             rate_type=self._rate_type.value,
172                                             round_type=self._round_type.value,
173                                             p_type=self._policer_type.value,
174                                             conform_action=conform_action,
175                                             exceed_action=exceed_action,
176                                             violate_action=violate_action,
177                                             color_aware=color_aware)
178         # pylint: enable=no-member
179
180         VatJsonUtil.verify_vat_retval(
181             out[0],
182             err_msg='Add policer {0} failed on {1}'.format(self._policer_name,
183                                                            node['host']))
184
185         policer_index = out[0].get('policer_index')
186
187         # create classify table
188         direction = 'src' if self._classify_match_is_src else 'dst'
189
190         if 6 == ip_address(unicode(self._classify_match_ip)).version:
191             ip_version = 'ip6'
192             table_type = PolicerClassifyTableType.IP6_TABLE
193         else:
194             ip_version = 'ip4'
195             table_type = PolicerClassifyTableType.IP4_TABLE
196
197         out = VatExecutor.cmd_from_template(node,
198                                             "classify_add_table.vat",
199                                             ip_version=ip_version,
200                                             direction=direction)
201
202         VatJsonUtil.verify_vat_retval(
203             out[0],
204             err_msg='Add classify table failed on {0}'.format(node['host']))
205
206         new_table_index = out[0].get('new_table_index')
207         skip_n_vectors = out[0].get('skip_n_vectors')
208         match_n_vectors = out[0].get('match_n_vectors')
209
210         # create classify session
211         match = 'l3 {0} {1} {2}'.format(ip_version,
212                                         direction,
213                                         self._classify_match_ip)
214
215         out = VatExecutor.cmd_from_template(
216             node,
217             "policer/policer_classify_add_session.vat",
218             policer_index=policer_index,
219             pre_color=self._classify_precolor.value, # pylint: disable=no-member
220             table_index=new_table_index,
221             skip_n=skip_n_vectors,
222             match_n=match_n_vectors,
223             match=match)
224
225         VatJsonUtil.verify_vat_retval(
226             out[0],
227             err_msg='Add classify session failed on {0}'.format(node['host']))
228
229         # set classify interface
230         out = VatExecutor.cmd_from_template(
231             node,
232             "policer/policer_classify_set_interface.vat",
233             sw_if_index=self._sw_if_index,
234             table_type=table_type.value, # pylint: disable=no-member
235             table_index=new_table_index)
236
237         VatJsonUtil.verify_vat_retval(
238             out[0],
239             err_msg='Set classify interface failed on {0}'.format(node['host']))
240
241     def policer_clear_settings(self):
242         """Clear policer settings."""
243         self._cir = 0
244         self._eir = 0
245         self._cb = 0
246         self._eb = 0
247         self._rate_type = None
248         self._round_type = None
249         self._policer_type = None
250         self._conform_action = None
251         self._conform_dscp = None
252         self._exceed_action = None
253         self._exceed_dscp = None
254         self._violate_action = None
255         self._violate_dscp = None
256         self._color_aware = False
257         self._classify_match_ip = ''
258         self._classify_match_is_src = True
259         self._classify_precolor = None
260         self._sw_if_index = 0
261         self._node = None
262         self._policer_name = ''
263
264     def policer_set_name(self, name):
265         """Set policer name.
266
267         :param name: Policer name.
268         :type name: str
269         """
270         self._policer_name = name
271
272     def policer_set_node(self, node):
273         """Set node to setup policer on.
274
275         :param node: VPP node.
276         :type node: dict
277         """
278         self._node = node
279
280     def policer_set_cir(self, cir):
281         """Set policer CIR.
282
283         :param cir: Committed Information Rate.
284         :type cir: int
285         """
286         self._cir = cir
287
288     def policer_set_eir(self, eir):
289         """Set polcier EIR.
290
291         :param eir: Excess Information Rate.
292         :type eir: int
293         """
294         self._eir = eir
295
296     def policer_set_cb(self, cb):
297         """Set policer CB.
298
299         :param cb: Committed Burst size.
300         :type cb: int
301         """
302         self._cb = cb
303
304     def policer_set_eb(self, eb):
305         """Set policer EB.
306
307         :param eb: Excess Burst size.
308         :type eb: int
309         """
310         self._eb = eb
311
312     def policer_set_rate_type_kbps(self):
313         """Set policer rate type to kbps."""
314         self._rate_type = PolicerRateType.KBPS
315
316     def policer_set_rate_type_pps(self):
317         """Set policer rate type to pps."""
318         self._rate_type = PolicerRateType.PPS
319
320     def policer_set_round_type_closest(self):
321         """Set policer round type to closest."""
322         self._round_type = PolicerRoundType.CLOSEST
323
324     def policer_set_round_type_up(self):
325         """Set policer round type to up."""
326         self._round_type = PolicerRoundType.UP
327
328     def policer_set_round_type_down(self):
329         """Set policer round type to down."""
330         self._round_type = PolicerRoundType.DOWN
331
332     def policer_set_type_1r2c(self):
333         """Set policer type to 1r2c."""
334         self._policer_type = PolicerType.P_1R2C
335
336     def policer_set_type_1r3c(self):
337         """Set policer type to 1r3c RFC2697."""
338         self._policer_type = PolicerType.P_1R3C
339
340     def policer_set_type_2r3c_2698(self):
341         """Set policer type to 2r3c RFC2698."""
342         self._policer_type = PolicerType.P_2R3C_2698
343
344     def policer_set_type_2r3c_4115(self):
345         """Set policer type to 2r3c RFC4115."""
346         self._policer_type = PolicerType.P_2R3C_4115
347
348     def policer_set_type_2r3c_mef5cf1(self):
349         """Set policer type to 2r3c MEF5CF1."""
350         self._policer_type = PolicerType.P_2R3C_MEF5CF1
351
352     def policer_set_conform_action_drop(self):
353         """Set policer conform-action to drop."""
354         self._conform_action = PolicerAction.DROP
355
356     def policer_set_conform_action_transmit(self):
357         """Set policer conform-action to transmit."""
358         self._conform_action = PolicerAction.TRANSMIT
359
360     def policer_set_conform_action_mark_and_transmit(self, dscp):
361         """Set policer conform-action to mark-and-transmit.
362
363         :param dscp: DSCP value to mark.
364         :type dscp: DSCP
365         """
366         self._conform_action = PolicerAction.MARK_AND_TRANSMIT
367         self._conform_dscp = dscp
368
369     def policer_set_exceed_action_drop(self):
370         """Set policer exceed-action to drop."""
371         self._exceed_action = PolicerAction.DROP
372
373     def policer_set_exceed_action_transmit(self):
374         """Set policer exceed-action to transmit."""
375         self._exceed_action = PolicerAction.TRANSMIT
376
377     def policer_set_exceed_action_mark_and_transmit(self, dscp):
378         """Set policer exceed-action to mark-and-transmit.
379
380         :param dscp: DSCP value to mark.
381         :type dscp: DSCP
382         """
383         self._exceed_action = PolicerAction.MARK_AND_TRANSMIT
384         self._exceed_dscp = dscp
385
386     def policer_set_violate_action_drop(self):
387         """Set policer violate-action to drop."""
388         self._violate_action = PolicerAction.DROP
389
390     def policer_set_violate_action_transmit(self):
391         """Set policer violate-action to transmit."""
392         self._violate_action = PolicerAction.TRANSMIT
393
394     def policer_set_violate_action_mark_and_transmit(self, dscp):
395         """Set policer violate-action to mark-and-transmit.
396
397         :param dscp: DSCP value to mark.
398         :type dscp: DSCP
399         """
400         self._violate_action = PolicerAction.MARK_AND_TRANSMIT
401         self._violate_dscp = dscp
402
403     def policer_enable_color_aware(self):
404         """Enable color-aware mode for policer."""
405         self._color_aware = True
406
407     def policer_classify_set_precolor_conform(self):
408         """Set policer classify pre-color to conform-color."""
409         self._classify_precolor = PolicerClassifyPreColor.CONFORM_COLOR
410
411     def policer_classify_set_precolor_exceed(self):
412         """Set policer classify pre-color to exceeed-color."""
413         self._classify_precolor = PolicerClassifyPreColor.EXCEED_COLOR
414
415     def policer_classify_set_interface(self, interface):
416         """Set policer classify interface.
417
418         :param interface: Interface name or sw_if_index.
419         :type interface: str or int
420         .. note:: First set node with policer_set_node.
421         """
422         if isinstance(interface, basestring):
423             self._sw_if_index = Topology.get_interface_sw_index(self._node,
424                                                                 interface)
425         else:
426             self._sw_if_index = interface
427
428     def policer_classify_set_match_ip(self, ip, is_src=True):
429         """Set policer classify match source IP address.
430
431         :param ip: IPv4 or IPv6 address.
432         :param is_src: Match src IP if True otherwise match dst IP.
433         :type ip: str
434         :type is_src: bool
435         """
436         self._classify_match_ip = ip
437         self._classify_match_is_src = is_src
438
439     @staticmethod
440     def dscp_cs0():
441         """Return DSCP CS0.
442
443         :return: DSCP enum CS0 object.
444         :rtype: DSCP
445         """
446         return DSCP.CS0
447
448     @staticmethod
449     def dscp_cs1():
450         """Return DSCP CS1.
451
452         :return: DSCP enum CS1 object.
453         :rtype: DSCP
454         """
455         return DSCP.CS1
456
457     @staticmethod
458     def dscp_cs2():
459         """Return DSCP CS2.
460
461         :return: DSCP enum CS2 object.
462         :rtype: DSCP
463         """
464         return DSCP.CS2
465
466     @staticmethod
467     def dscp_cs3():
468         """Return DSCP CS3.
469
470         :return: DSCP enum CS3 object.
471         :rtype: DSCP
472         """
473         return DSCP.CS3
474
475     @staticmethod
476     def dscp_cs4():
477         """Return DSCP CS4.
478
479         :return: DSCP enum CS4 object.
480         :rtype: DSCP
481         """
482         return DSCP.CS4
483
484     @staticmethod
485     def dscp_cs5():
486         """Return DSCP CS5.
487
488         :return: DSCP enum CS5 object.
489         :rtype: DSCP
490         """
491         return DSCP.CS5
492
493     @staticmethod
494     def dscp_cs6():
495         """Return DSCP CS6.
496
497         :return: DSCP enum CS6 object.
498         :rtype: DSCP
499         """
500         return DSCP.CS6
501
502     @staticmethod
503     def dscp_cs7():
504         """Return DSCP CS7.
505
506         :return: DSCP enum CS7 object.
507         :rtype: DSCP
508         """
509         return DSCP.CS7
510
511     @staticmethod
512     def dscp_ef():
513         """Return DSCP EF.
514
515         :return: DSCP enum EF object.
516         :rtype: DSCP
517         """
518         return DSCP.EF
519
520     @staticmethod
521     def dscp_af11():
522         """Return DSCP AF11.
523
524         :return: DSCP enum AF11 object.
525         :rtype: DSCP
526         """
527         return DSCP.AF11
528
529     @staticmethod
530     def dscp_af12():
531         """Return DSCP AF12.
532
533         :return: DSCP enum AF12 object.
534         :rtype: DSCP
535         """
536         return DSCP.AF12
537
538     @staticmethod
539     def dscp_af13():
540         """Return DSCP AF13.
541
542         :return: DSCP enum AF13 object.
543         :rtype: DSCP
544         """
545         return DSCP.AF13
546
547     @staticmethod
548     def dscp_af21():
549         """Return DSCP AF21.
550
551         :return: DSCP enum AF21 object.
552         :rtype: DSCP
553         """
554         return DSCP.AF21
555
556     @staticmethod
557     def dscp_af22():
558         """Return DSCP AF22.
559
560         :return: DSCP enum AF22 object.
561         :rtype: DSCP
562         """
563         return DSCP.AF22
564
565     @staticmethod
566     def dscp_af23():
567         """Return DSCP AF23.
568
569         :return: DSCP enum AF23 object.
570         :rtype: DSCP
571         """
572         return DSCP.AF23
573
574     @staticmethod
575     def dscp_af31():
576         """Return DSCP AF31.
577
578         :return: DSCP enum AF31 object.
579         :rtype: DSCP
580         """
581         return DSCP.AF31
582
583     @staticmethod
584     def dscp_af32():
585         """Return DSCP AF32.
586
587         :return: DSCP enum AF32 object.
588         :rtype: DSCP
589         """
590         return DSCP.AF32
591
592     @staticmethod
593     def dscp_af33():
594         """Return DSCP AF33.
595
596         :return: DSCP enum AF33 object.
597         :rtype: DSCP
598         """
599         return DSCP.AF33
600
601     @staticmethod
602     def get_dscp_num_value(dscp):
603         """Return DSCP numeric value.
604
605         :param dscp: DSCP enum object.
606         :type dscp: DSCP
607         :return: DSCP numeric value.
608         :rtype: int
609         """
610         return dscp.num