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:
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 class PolicerRateType(Enum):
26 """Policer rate types."""
30 def __init__(self, string):
34 # pylint: disable=invalid-name
35 class PolicerRoundType(Enum):
36 """Policer round types."""
41 def __init__(self, string):
45 class PolicerType(Enum):
49 P_2R3C_2698 = '2r3c-2698'
50 P_2R3C_4115 = '2r3c-4115'
51 P_2R3C_MEF5CF1 = '2r3c-mef5cf1'
53 def __init__(self, string):
57 class PolicerAction(Enum):
61 MARK_AND_TRANSMIT = 'mark-and-transmit'
63 def __init__(self, string):
68 """DSCP for mark-and-transmit action."""
88 def __init__(self, string, num):
93 class PolicerClassifyPreColor(Enum):
94 """Policer classify precolor."""
95 CONFORM_COLOR = 'conform-color'
96 EXCEED_COLOR = 'exceed-color'
98 def __init__(self, string):
102 class PolicerClassifyTableType(Enum):
103 """Policer classify table type."""
104 IP4_TABLE = 'ip4-table'
105 IP6_TABLE = 'ip6-table'
106 L2_TABLE = 'l2-table'
108 def __init__(self, string):
112 # pylint: disable=too-many-instance-attributes
113 class Policer(object):
114 """Policer utilities."""
121 self._rate_type = None
122 self._round_type = None
123 self._policer_type = None
124 self._conform_action = None
125 self._conform_dscp = None
126 self._exceed_action = None
127 self._exceed_dscp = None
128 self._violate_action = None
129 self._violate_dscp = None
130 self._color_aware = False
131 self._classify_match_ip = ''
132 self._classify_match_is_src = True
133 self._classify_precolor = None
134 self._sw_if_index = 0
136 self._policer_name = ''
138 def policer_set_configuration(self):
139 """Configure policer on VPP node.
141 ...note:: First set all required parameters.
146 color_aware = 'color-aware' if self._color_aware else ''
148 # pylint: disable=no-member
149 conform_action = self._conform_action.value
151 if PolicerAction.MARK_AND_TRANSMIT == self._conform_action:
152 conform_action += ' {0}'.format(self._conform_dscp.string)
154 exceed_action = self._exceed_action.value
155 if PolicerAction.MARK_AND_TRANSMIT == self._exceed_action:
156 exceed_action += ' {0}'.format(self._exceed_dscp.string)
158 violate_action = self._violate_action.value
159 if PolicerAction.MARK_AND_TRANSMIT == self._violate_action:
160 violate_action += ' {0}'.format(self._violate_dscp.string)
162 out = VatExecutor.cmd_from_template(node,
163 "policer/policer_add_3c.vat",
164 name=self._policer_name,
169 rate_type=self._rate_type.value,
170 round_type=self._round_type.value,
171 p_type=self._policer_type.value,
172 conform_action=conform_action,
173 exceed_action=exceed_action,
174 violate_action=violate_action,
175 color_aware=color_aware)
177 VatJsonUtil.verify_vat_retval(
179 err_msg='Add policer {0} failed on {1}'.format(self._policer_name,
182 policer_index = out[0].get('policer_index')
184 # create classify table
185 direction = 'src' if self._classify_match_is_src else 'dst'
187 if ip_address(unicode(self._classify_match_ip)).version == 6:
189 table_type = PolicerClassifyTableType.IP6_TABLE
192 table_type = PolicerClassifyTableType.IP4_TABLE
194 out = VatExecutor.cmd_from_template(node,
195 "classify_add_table.vat",
196 ip_version=ip_version,
199 VatJsonUtil.verify_vat_retval(
201 err_msg='Add classify table failed on {0}'.format(node['host']))
203 new_table_index = out[0].get('new_table_index')
204 skip_n_vectors = out[0].get('skip_n_vectors')
205 match_n_vectors = out[0].get('match_n_vectors')
207 # create classify session
208 match = 'l3 {0} {1} {2}'.format(ip_version,
210 self._classify_match_ip)
212 out = VatExecutor.cmd_from_template(
214 "policer/policer_classify_add_session.vat",
215 policer_index=policer_index,
216 pre_color=self._classify_precolor.value, # pylint: disable=no-member
217 table_index=new_table_index,
218 skip_n=skip_n_vectors,
219 match_n=match_n_vectors,
222 VatJsonUtil.verify_vat_retval(
224 err_msg='Add classify session failed on {0}'.format(node['host']))
226 # set classify interface
227 out = VatExecutor.cmd_from_template(
229 "policer/policer_classify_set_interface.vat",
230 sw_if_index=self._sw_if_index,
231 table_type=table_type.value, # pylint: disable=no-member
232 table_index=new_table_index)
234 VatJsonUtil.verify_vat_retval(
236 err_msg='Set classify interface failed on {0}'.format(node['host']))
238 def policer_clear_settings(self):
239 """Clear policer settings."""
244 self._rate_type = None
245 self._round_type = None
246 self._policer_type = None
247 self._conform_action = None
248 self._conform_dscp = None
249 self._exceed_action = None
250 self._exceed_dscp = None
251 self._violate_action = None
252 self._violate_dscp = None
253 self._color_aware = False
254 self._classify_match_ip = ''
255 self._classify_match_is_src = True
256 self._classify_precolor = None
257 self._sw_if_index = 0
259 self._policer_name = ''
261 def policer_set_name(self, name):
264 :param name: Policer name.
267 self._policer_name = name
269 def policer_set_node(self, node):
270 """Set node to setup policer on.
272 :param node: VPP node.
277 def policer_set_cir(self, cir):
280 :param cir: Committed Information Rate.
285 def policer_set_eir(self, eir):
288 :param eir: Excess Information Rate.
293 def policer_set_cb(self, cb):
296 :param cb: Committed Burst size.
299 if cb == "IMIX_v4_1":
304 def policer_set_eb(self, eb):
307 :param eb: Excess Burst size.
310 if eb == "IMIX_v4_1":
315 def policer_set_rate_type_kbps(self):
316 """Set policer rate type to kbps."""
317 self._rate_type = PolicerRateType.KBPS
319 def policer_set_rate_type_pps(self):
320 """Set policer rate type to pps."""
321 self._rate_type = PolicerRateType.PPS
323 def policer_set_round_type_closest(self):
324 """Set policer round type to closest."""
325 self._round_type = PolicerRoundType.CLOSEST
327 def policer_set_round_type_up(self):
328 """Set policer round type to up."""
329 self._round_type = PolicerRoundType.UP
331 def policer_set_round_type_down(self):
332 """Set policer round type to down."""
333 self._round_type = PolicerRoundType.DOWN
335 def policer_set_type_1r2c(self):
336 """Set policer type to 1r2c."""
337 self._policer_type = PolicerType.P_1R2C
339 def policer_set_type_1r3c(self):
340 """Set policer type to 1r3c RFC2697."""
341 self._policer_type = PolicerType.P_1R3C
343 def policer_set_type_2r3c_2698(self):
344 """Set policer type to 2r3c RFC2698."""
345 self._policer_type = PolicerType.P_2R3C_2698
347 def policer_set_type_2r3c_4115(self):
348 """Set policer type to 2r3c RFC4115."""
349 self._policer_type = PolicerType.P_2R3C_4115
351 def policer_set_type_2r3c_mef5cf1(self):
352 """Set policer type to 2r3c MEF5CF1."""
353 self._policer_type = PolicerType.P_2R3C_MEF5CF1
355 def policer_set_conform_action_drop(self):
356 """Set policer conform-action to drop."""
357 self._conform_action = PolicerAction.DROP
359 def policer_set_conform_action_transmit(self):
360 """Set policer conform-action to transmit."""
361 self._conform_action = PolicerAction.TRANSMIT
363 def policer_set_conform_action_mark_and_transmit(self, dscp):
364 """Set policer conform-action to mark-and-transmit.
366 :param dscp: DSCP value to mark.
369 self._conform_action = PolicerAction.MARK_AND_TRANSMIT
370 self._conform_dscp = dscp
372 def policer_set_exceed_action_drop(self):
373 """Set policer exceed-action to drop."""
374 self._exceed_action = PolicerAction.DROP
376 def policer_set_exceed_action_transmit(self):
377 """Set policer exceed-action to transmit."""
378 self._exceed_action = PolicerAction.TRANSMIT
380 def policer_set_exceed_action_mark_and_transmit(self, dscp):
381 """Set policer exceed-action to mark-and-transmit.
383 :param dscp: DSCP value to mark.
386 self._exceed_action = PolicerAction.MARK_AND_TRANSMIT
387 self._exceed_dscp = dscp
389 def policer_set_violate_action_drop(self):
390 """Set policer violate-action to drop."""
391 self._violate_action = PolicerAction.DROP
393 def policer_set_violate_action_transmit(self):
394 """Set policer violate-action to transmit."""
395 self._violate_action = PolicerAction.TRANSMIT
397 def policer_set_violate_action_mark_and_transmit(self, dscp):
398 """Set policer violate-action to mark-and-transmit.
400 :param dscp: DSCP value to mark.
403 self._violate_action = PolicerAction.MARK_AND_TRANSMIT
404 self._violate_dscp = dscp
406 def policer_enable_color_aware(self):
407 """Enable color-aware mode for policer."""
408 self._color_aware = True
410 def policer_classify_set_precolor_conform(self):
411 """Set policer classify pre-color to conform-color."""
412 self._classify_precolor = PolicerClassifyPreColor.CONFORM_COLOR
414 def policer_classify_set_precolor_exceed(self):
415 """Set policer classify pre-color to exceeed-color."""
416 self._classify_precolor = PolicerClassifyPreColor.EXCEED_COLOR
418 def policer_classify_set_interface(self, interface):
419 """Set policer classify interface.
421 .. note:: First set node with policer_set_node.
423 :param interface: Interface name or sw_if_index.
424 :type interface: str or int
426 if isinstance(interface, basestring):
427 self._sw_if_index = Topology.get_interface_sw_index(self._node,
430 self._sw_if_index = interface
432 def policer_classify_set_match_ip(self, ip, is_src=True):
433 """Set policer classify match source IP address.
435 :param ip: IPv4 or IPv6 address.
436 :param is_src: Match src IP if True otherwise match dst IP.
440 self._classify_match_ip = ip
441 self._classify_match_is_src = is_src
447 :returns: DSCP enum CS0 object.
456 :returns: DSCP enum CS1 object.
465 :returns: DSCP enum CS2 object.
474 :returns: DSCP enum CS3 object.
483 :returns: DSCP enum CS4 object.
492 :returns: DSCP enum CS5 object.
501 :returns: DSCP enum CS6 object.
510 :returns: DSCP enum CS7 object.
519 :returns: DSCP enum EF object.
528 :returns: DSCP enum AF11 object.
537 :returns: DSCP enum AF12 object.
546 :returns: DSCP enum AF13 object.
555 :returns: DSCP enum AF21 object.
564 :returns: DSCP enum AF22 object.
573 :returns: DSCP enum AF23 object.
582 :returns: DSCP enum AF31 object.
591 :returns: DSCP enum AF32 object.
600 :returns: DSCP enum AF33 object.
606 def get_dscp_num_value(dscp):
607 """Return DSCP numeric value.
609 :param dscp: DSCP enum object.
611 :returns: DSCP numeric value.