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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """Policer utilities library."""
18 from ipaddress import ip_address
20 from resources.libraries.python.VatExecutor import VatExecutor
21 from resources.libraries.python.VatJsonUtil import VatJsonUtil
22 from resources.libraries.python.topology import Topology
25 # pylint: disable=too-few-public-methods
26 class PolicerRateType(Enum):
27 """Policer rate types."""
31 def __init__(self, string):
35 # pylint: disable=invalid-name
36 class PolicerRoundType(Enum):
37 """Policer round types."""
42 def __init__(self, string):
46 class PolicerType(Enum):
50 P_2R3C_2698 = '2r3c-2698'
51 P_2R3C_4115 = '2r3c-4115'
52 P_2R3C_MEF5CF1 = '2r3c-mef5cf1'
54 def __init__(self, string):
58 class PolicerAction(Enum):
62 MARK_AND_TRANSMIT = 'mark-and-transmit'
64 def __init__(self, string):
69 """DSCP for mark-and-transmit action."""
89 def __init__(self, string, num):
94 class PolicerClassifyPreColor(Enum):
95 """Policer classify precolor."""
96 CONFORM_COLOR = 'conform-color'
97 EXCEED_COLOR = 'exceed-color'
99 def __init__(self, string):
103 class PolicerClassifyTableType(Enum):
104 """Policer classify table type."""
105 IP4_TABLE = 'ip4-table'
106 IP6_TABLE = 'ip6-table'
107 L2_TABLE = 'l2-table'
109 def __init__(self, string):
113 # pylint: disable=too-many-instance-attributes
114 # pylint: disable=too-many-public-methods
115 class Policer(object):
116 """Policer utilities."""
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
138 self._policer_name = ''
140 def policer_set_configuration(self):
141 """Configure policer on VPP node.
143 ...note:: First set all required parameters.
148 color_aware = 'color-aware' if self._color_aware else ''
150 # pylint: disable=no-member
151 conform_action = self._conform_action.value
153 if PolicerAction.MARK_AND_TRANSMIT == self._conform_action:
154 conform_action += ' {0}'.format(self._conform_dscp.string)
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)
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)
164 out = VatExecutor.cmd_from_template(node,
165 "policer/policer_add_3c.vat",
166 name=self._policer_name,
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
180 VatJsonUtil.verify_vat_retval(
182 err_msg='Add policer {0} failed on {1}'.format(self._policer_name,
185 policer_index = out[0].get('policer_index')
187 # create classify table
188 direction = 'src' if self._classify_match_is_src else 'dst'
190 if 6 == ip_address(unicode(self._classify_match_ip)).version:
192 table_type = PolicerClassifyTableType.IP6_TABLE
195 table_type = PolicerClassifyTableType.IP4_TABLE
197 out = VatExecutor.cmd_from_template(node,
198 "classify_add_table.vat",
199 ip_version=ip_version,
202 VatJsonUtil.verify_vat_retval(
204 err_msg='Add classify table failed on {0}'.format(node['host']))
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')
210 # create classify session
211 match = 'l3 {0} {1} {2}'.format(ip_version,
213 self._classify_match_ip)
215 out = VatExecutor.cmd_from_template(
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,
225 VatJsonUtil.verify_vat_retval(
227 err_msg='Add classify session failed on {0}'.format(node['host']))
229 # set classify interface
230 out = VatExecutor.cmd_from_template(
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)
237 VatJsonUtil.verify_vat_retval(
239 err_msg='Set classify interface failed on {0}'.format(node['host']))
241 def policer_clear_settings(self):
242 """Clear policer settings."""
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
262 self._policer_name = ''
264 def policer_set_name(self, name):
267 :param name: Policer name.
270 self._policer_name = name
272 def policer_set_node(self, node):
273 """Set node to setup policer on.
275 :param node: VPP node.
280 def policer_set_cir(self, cir):
283 :param cir: Committed Information Rate.
288 def policer_set_eir(self, eir):
291 :param eir: Excess Information Rate.
296 def policer_set_cb(self, cb):
299 :param cb: Committed Burst size.
304 def policer_set_eb(self, eb):
307 :param eb: Excess Burst size.
312 def policer_set_rate_type_kbps(self):
313 """Set policer rate type to kbps."""
314 self._rate_type = PolicerRateType.KBPS
316 def policer_set_rate_type_pps(self):
317 """Set policer rate type to pps."""
318 self._rate_type = PolicerRateType.PPS
320 def policer_set_round_type_closest(self):
321 """Set policer round type to closest."""
322 self._round_type = PolicerRoundType.CLOSEST
324 def policer_set_round_type_up(self):
325 """Set policer round type to up."""
326 self._round_type = PolicerRoundType.UP
328 def policer_set_round_type_down(self):
329 """Set policer round type to down."""
330 self._round_type = PolicerRoundType.DOWN
332 def policer_set_type_1r2c(self):
333 """Set policer type to 1r2c."""
334 self._policer_type = PolicerType.P_1R2C
336 def policer_set_type_1r3c(self):
337 """Set policer type to 1r3c RFC2697."""
338 self._policer_type = PolicerType.P_1R3C
340 def policer_set_type_2r3c_2698(self):
341 """Set policer type to 2r3c RFC2698."""
342 self._policer_type = PolicerType.P_2R3C_2698
344 def policer_set_type_2r3c_4115(self):
345 """Set policer type to 2r3c RFC4115."""
346 self._policer_type = PolicerType.P_2R3C_4115
348 def policer_set_type_2r3c_mef5cf1(self):
349 """Set policer type to 2r3c MEF5CF1."""
350 self._policer_type = PolicerType.P_2R3C_MEF5CF1
352 def policer_set_conform_action_drop(self):
353 """Set policer conform-action to drop."""
354 self._conform_action = PolicerAction.DROP
356 def policer_set_conform_action_transmit(self):
357 """Set policer conform-action to transmit."""
358 self._conform_action = PolicerAction.TRANSMIT
360 def policer_set_conform_action_mark_and_transmit(self, dscp):
361 """Set policer conform-action to mark-and-transmit.
363 :param dscp: DSCP value to mark.
366 self._conform_action = PolicerAction.MARK_AND_TRANSMIT
367 self._conform_dscp = dscp
369 def policer_set_exceed_action_drop(self):
370 """Set policer exceed-action to drop."""
371 self._exceed_action = PolicerAction.DROP
373 def policer_set_exceed_action_transmit(self):
374 """Set policer exceed-action to transmit."""
375 self._exceed_action = PolicerAction.TRANSMIT
377 def policer_set_exceed_action_mark_and_transmit(self, dscp):
378 """Set policer exceed-action to mark-and-transmit.
380 :param dscp: DSCP value to mark.
383 self._exceed_action = PolicerAction.MARK_AND_TRANSMIT
384 self._exceed_dscp = dscp
386 def policer_set_violate_action_drop(self):
387 """Set policer violate-action to drop."""
388 self._violate_action = PolicerAction.DROP
390 def policer_set_violate_action_transmit(self):
391 """Set policer violate-action to transmit."""
392 self._violate_action = PolicerAction.TRANSMIT
394 def policer_set_violate_action_mark_and_transmit(self, dscp):
395 """Set policer violate-action to mark-and-transmit.
397 :param dscp: DSCP value to mark.
400 self._violate_action = PolicerAction.MARK_AND_TRANSMIT
401 self._violate_dscp = dscp
403 def policer_enable_color_aware(self):
404 """Enable color-aware mode for policer."""
405 self._color_aware = True
407 def policer_classify_set_precolor_conform(self):
408 """Set policer classify pre-color to conform-color."""
409 self._classify_precolor = PolicerClassifyPreColor.CONFORM_COLOR
411 def policer_classify_set_precolor_exceed(self):
412 """Set policer classify pre-color to exceeed-color."""
413 self._classify_precolor = PolicerClassifyPreColor.EXCEED_COLOR
415 def policer_classify_set_interface(self, interface):
416 """Set policer classify interface.
418 :param interface: Interface name or sw_if_index.
419 :type interface: str or int
420 .. note:: First set node with policer_set_node.
422 if isinstance(interface, basestring):
423 self._sw_if_index = Topology.get_interface_sw_index(self._node,
426 self._sw_if_index = interface
428 def policer_classify_set_match_ip(self, ip, is_src=True):
429 """Set policer classify match source IP address.
431 :param ip: IPv4 or IPv6 address.
432 :param is_src: Match src IP if True otherwise match dst IP.
436 self._classify_match_ip = ip
437 self._classify_match_is_src = is_src
443 :return: DSCP enum CS0 object.
452 :return: DSCP enum CS1 object.
461 :return: DSCP enum CS2 object.
470 :return: DSCP enum CS3 object.
479 :return: DSCP enum CS4 object.
488 :return: DSCP enum CS5 object.
497 :return: DSCP enum CS6 object.
506 :return: DSCP enum CS7 object.
515 :return: DSCP enum EF object.
524 :return: DSCP enum AF11 object.
533 :return: DSCP enum AF12 object.
542 :return: DSCP enum AF13 object.
551 :return: DSCP enum AF21 object.
560 :return: DSCP enum AF22 object.
569 :return: DSCP enum AF23 object.
578 :return: DSCP enum AF31 object.
587 :return: DSCP enum AF32 object.
596 :return: DSCP enum AF33 object.
602 def get_dscp_num_value(dscp):
603 """Return DSCP numeric value.
605 :param dscp: DSCP enum object.
607 :return: DSCP numeric value.