aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--resources/libraries/python/honeycomb/HcAPIKwInterfaces.py63
-rw-r--r--resources/libraries/python/honeycomb/Routing.py57
-rw-r--r--resources/libraries/robot/honeycomb/policer.robot163
-rw-r--r--resources/templates/honeycomb/config_policer.url1
-rw-r--r--resources/templates/honeycomb/oper_policer.url1
-rw-r--r--resources/test_data/honeycomb/policer_variables.py146
-rw-r--r--tests/func/honeycomb/mgmt-cfg-acl-apihc-apivat-func.robot2
-rw-r--r--tests/func/honeycomb/mgmt-cfg-policer-apihc-func.robot128
8 files changed, 560 insertions, 1 deletions
diff --git a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py
index 19ce8f26c8..d57f93913f 100644
--- a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py
+++ b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py
@@ -1512,6 +1512,69 @@ class InterfaceKeywords(object):
return resp
@staticmethod
+ def enable_policer_on_interface(node, interface, table_name):
+ """Enable Policer on the given interface.
+
+ :param node: Honeycomb node.
+ :param interface: The interface where policer will be enabled.
+ :param table_name: Name of the classify table.
+ :type node: dict
+ :type interface: str
+ :type table_name: str
+ :returns: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the configuration of interface is not
+ successful.
+ """
+ interface = Topology.convert_interface_reference(
+ node, interface, "name")
+ interface = interface.replace("/", "%2F")
+
+ data = {
+ "interface-policer:policer": {
+ "ip4-table": table_name
+ }
+ }
+
+ path = "/interface/" + interface + "/interface-policer:policer"
+ status_code, resp = HcUtil.\
+ put_honeycomb_data(node, "config_vpp_interfaces", data, path,
+ data_representation=DataRepresentation.JSON)
+ if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
+ raise HoneycombError(
+ "The configuration of interface '{0}' was not successful. "
+ "Status code: {1}.".format(interface, status_code))
+ return resp
+
+ @staticmethod
+ def disable_policer_on_interface(node, interface):
+ """Disable Policer on the given interface.
+
+ :param node: Honeycomb node.
+ :param interface: The interface where policer will be disabled.
+ :param table_name: Name of the classify table.
+ :type node: dict
+ :type interface: str
+ :type table_name: str
+ :returns: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If the configuration of interface is not
+ successful.
+ """
+ interface = Topology.convert_interface_reference(
+ node, interface, "name")
+ interface = interface.replace("/", "%2F")
+
+ path = "/interface/" + interface + "/interface-policer:policer"
+ status_code, resp = HcUtil.\
+ delete_honeycomb_data(node, "config_vpp_interfaces", path)
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "The configuration of interface '{0}' was not successful. "
+ "Status code: {1}.".format(interface, status_code))
+ return resp
+
+ @staticmethod
def disable_acl_on_interface(node, interface):
"""Disable ACL on the given interface.
diff --git a/resources/libraries/python/honeycomb/Routing.py b/resources/libraries/python/honeycomb/Routing.py
index c39031d920..a4d606bd5d 100644
--- a/resources/libraries/python/honeycomb/Routing.py
+++ b/resources/libraries/python/honeycomb/Routing.py
@@ -273,3 +273,60 @@ class RoutingKeywords(object):
return {k: str(v) for k, v in dict_of_str.items()}
except (KeyError, TypeError):
return {}
+
+ @staticmethod
+ def configure_policer(node, policy_name, policer_data=None):
+ """Configure Policer on the specified node.
+
+ :param node: Honeycomb node.
+ :param policer_data: Dictionary of configurations to apply. \
+ If it is None then the existing configuration is removed.
+ :type node: dict
+ :type policer_data: dict
+ :returns: Content of response.
+ :rtype: bytearray
+ :raises HoneycombError: If policer could not be configured.
+ """
+
+ path = '/' + policy_name
+
+ if not policer_data:
+ status_code, _ = HcUtil.delete_honeycomb_data(
+ node, 'config_policer', path)
+ else:
+ data = {
+ 'policer': policer_data
+ }
+
+ status_code, _ = HcUtil.put_honeycomb_data(
+ node, 'config_policer', data, path)
+
+ if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED):
+ raise HoneycombError(
+ 'Configuring policer failed. Status code:{0}'\
+ .format(status_code))
+
+ @staticmethod
+ def get_policer_oper_data(node, policy_name):
+ """Get operational data about Policer on the node.
+
+ :param node: Honeycomb node.
+ :type node: dict
+ :returns: dict of Policer operational data.
+ :rtype: dict
+ :raises HoneycombError: If status code differs from successful.
+ """
+
+ path = '/' + policy_name
+
+ status_code, resp = HcUtil.\
+ get_honeycomb_data(node, "oper_policer", path)
+
+ if status_code != HTTPCodes.OK:
+ raise HoneycombError(
+ "Not possible to get operational information about Policer. "
+ "Status code: {0}.".format(status_code))
+ try:
+ return resp['policer']
+ except (KeyError, TypeError):
+ return {}
diff --git a/resources/libraries/robot/honeycomb/policer.robot b/resources/libraries/robot/honeycomb/policer.robot
new file mode 100644
index 0000000000..65ef319d43
--- /dev/null
+++ b/resources/libraries/robot/honeycomb/policer.robot
@@ -0,0 +1,163 @@
+# Copyright (c) 2017 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+*** Settings ***
+| Resource | resources/libraries/robot/traffic.robot
+| Library | resources.libraries.python.honeycomb.Routing.RoutingKeywords
+| ... | WITH NAME | RoutingKeywordsAPI
+| Variables | resources/test_data/honeycomb/policer_variables.py
+| Documentation | Keywords used to test Policer using Honeycomb.
+
+*** Keywords ***
+| Honeycomb Configures Policer
+| | [Documentation] | Uses Honeycomb API to configure Policer on the specified\
+| | ... | interface.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - information about a DUT node. Type: dictionary
+| | ... | - policer_data - data needed to configure Policer. Type: dictionary
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Honeycomb Configures Policer \| ${node} \
+| | ... | \| ${policer_data} \|
+| | ...
+| | [Arguments] | ${node} | ${policer_data}
+| | Configure Policer
+| | ... | ${node} | ${policer_data['name']} | ${policer_data}
+
+| Policer configuration from Honeycomb should be
+| | [Documentation] | Retrieves Policer operational data and verifies if\
+| | ... | Policer is configured correctly.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - information about a DUT node. Type: dictionary
+| | ... | - policer_data - data to compare configuration Policer with.\
+| | ... | Type: dictionary
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Policer configuration from Honeycomb should be \
+| | ... | \| ${node} \| ${policer_data} \|
+| | ...
+| | [Arguments] | ${node} | ${policer_data}
+| | ${data}= | Get Policer oper data | ${node} | ${policer_data['name']}
+| | Compare data structures | ${data[0]} | ${policer_data}
+
+| Policer configuration from Honeycomb should be empty
+| | [Documentation] | Checks whether Policer configuration from Honeycomb \
+| | ... | is empty.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - Information about a DUT node. Type: dictionary
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Policer configuration from Honeycomb should be empty \
+| | ... | \| ${node} \|
+| | ...
+| | [Arguments] | ${node}
+| | Run keyword and expect error | HoneycombError*404*
+| | ... | Get Policer oper data | ${node} | ${policer_data['name']}
+
+| Honeycomb removes Policer configuration
+| | [Documentation] | Uses Honeycomb API to remove Policer configuration\
+| | ... | from the specified interface.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - information about a DUT node. Type: dictionary
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Honeycomb removes Policer configuration \
+| | ... | \| ${nodes['DUT1']} \| GigabitEthernet0/8/0 \|
+| | ...
+| | [Arguments] | ${node}
+| | Configure Policer | ${node} | ${policer_data['name']}
+
+| Policer test teardown
+| | [Documentation] | Uses Honeycomb API to remove Policer configuration\
+| | ... | and reset interface state.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - information about a DUT node. Type: dictionary
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Honeycomb removes Policer configuration \
+| | ... | \| ${nodes['DUT1']} \| GigabitEthernet0/8/0 \|
+| | ...
+| | [Arguments] | ${node}
+| | Honeycomb removes Policer configuration | ${node}
+
+| Honeycomb enables Policer on interface
+| | [Documentation] | Uses Honeycomb API to enable Policer on an interface.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - information about a DUT node. Type: dictionary
+| | ... | - interface - name of an interface on the specified node. Type: string
+| | ... | - table_name - name of an ACL table. Type: string
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Honeycomb enables ACL on interface \| ${nodes['DUT1']} \
+| | ... | \| GigabithEthernet0/8/0 \| table0 \|
+| | ...
+| | [Arguments] | ${node} | ${interface} | ${table_name}
+| | Enable Policer on interface
+| | ... | ${node} | ${interface} | ${table_name}
+
+| Honeycomb disables Policer on interface
+| | [Documentation] | Uses Honeycomb API to disable Policer on an interface.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - information about a DUT node. Type: dictionary
+| | ... | - interface - name of an interface on the specified node. Type: string
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Honeycomb disables Policer on interface \| ${nodes['DUT1']} \
+| | ... | \| GigabithEthernet0/8/0 \|
+| | ...
+| | [Arguments] | ${node} | ${interface}
+| | Disable Policer on interface
+| | ... | ${node} | ${interface}
+
+| Honeycomb Send Packet and Verify Marking
+| | [Documentation] | Send packet and verify DSCP of the received packet.
+| | ...
+| | ... | *Arguments:*
+| | ... | - node - TG node. Type: dictionary
+| | ... | - tx_if - TG transmit interface. Type: string
+| | ... | - rx_if - TG receive interface. Type: string
+| | ... | - src_mac - Packet source MAC. Type: string
+| | ... | - dst_mac - Packet destination MAC. Type: string
+| | ... | - src_ip - Packet source IP address. Type: string
+| | ... | - dst_ip - Packet destination IP address. Type: string
+| | ... | - dscp_num - DSCP value to verify. Type: integer
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| ${dscp}= \| DSCP AF22 \|
+| | ... | \| Send Packet and Verify Marking \| ${nodes['TG']} \| eth1 \| eth2 \
+| | ... | \| 08:00:27:87:4d:f7 \| 52:54:00:d4:d8:22 \| 192.168.122.2 \
+| | ... | \| 192.168.122.1 \| ${dscp} \|
+| | ...
+| | [Arguments] | ${node} | ${tx_if} | ${rx_if} | ${src_mac} | ${dst_mac}
+| | ... | ${src_ip} | ${dst_ip} | ${dscp_num}
+| | ${tx_if_name}= | Get Interface Name | ${node} | ${tx_if}
+| | ${rx_if_name}= | Get Interface Name | ${node} | ${rx_if}
+| | ${args}= | Traffic Script Gen Arg | ${rx_if_name} | ${tx_if_name}
+| | ... | ${src_mac} | ${dst_mac} | ${src_ip} | ${dst_ip}
+| | ${args}= | Set Variable | ${args} --dscp ${dscp_num}
+| | Run Traffic Script On Node | policer.py | ${node} | ${args}
diff --git a/resources/templates/honeycomb/config_policer.url b/resources/templates/honeycomb/config_policer.url
new file mode 100644
index 0000000000..ed840e1d0b
--- /dev/null
+++ b/resources/templates/honeycomb/config_policer.url
@@ -0,0 +1 @@
+/restconf/config{odl_url_part}/policer:policers/policer \ No newline at end of file
diff --git a/resources/templates/honeycomb/oper_policer.url b/resources/templates/honeycomb/oper_policer.url
new file mode 100644
index 0000000000..fe42bc1966
--- /dev/null
+++ b/resources/templates/honeycomb/oper_policer.url
@@ -0,0 +1 @@
+/restconf/operational{odl_url_part}/policer:policers-state/policer \ No newline at end of file
diff --git a/resources/test_data/honeycomb/policer_variables.py b/resources/test_data/honeycomb/policer_variables.py
new file mode 100644
index 0000000000..6c6c9a575a
--- /dev/null
+++ b/resources/test_data/honeycomb/policer_variables.py
@@ -0,0 +1,146 @@
+# Copyright (c) 2017 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Test variables for Policer test suite."""
+
+
+def get_variables():
+ """Create and return a dictionary of test variables for the specified
+ test case.
+
+ :returns: Dictionary of test variables - settings for Honeycomb's Policer.
+ :rtype: dict
+ """
+ policer_data = {
+ "policer_data": {
+ "name": "policy1",
+ "cir": 450,
+ "cb": 50000,
+ "rate-type": "kbps",
+ "round-type": "closest",
+ "type": "1r2c",
+ "conform-action": {
+ "meter-action-type": "meter-action-transmit"
+ },
+ "exceed-action": {
+ "meter-action-type": "meter-action-drop"
+ }
+ },
+ "policer_data_oper": {
+ "name": "policy1",
+ "cir": 450,
+ "cb": 50000,
+ "rate-type": "kbps",
+ "round-type": "closest",
+ "type": "1r2c",
+ "conform-action": {
+ "meter-action-type": "policer:meter-action-transmit"
+ },
+ "exceed-action": {
+ "meter-action-type": "policer:meter-action-drop"
+ }
+ },
+ "policer_data_2": {
+ "name": "policy1",
+ "cir": 900,
+ "cb": 50000,
+ "rate-type": "kbps",
+ "round-type": "closest",
+ "type": "1r2c",
+ "conform-action": {
+ "meter-action-type": "meter-action-transmit"
+ },
+ "exceed-action": {
+ "meter-action-type": "meter-action-drop"
+ }
+ },
+ "policer_data_oper_2": {
+ "name": "policy1",
+ "cir": 900,
+ "cb": 50000,
+ "rate-type": "kbps",
+ "round-type": "closest",
+ "type": "1r2c",
+ "conform-action": {
+ "meter-action-type": "policer:meter-action-transmit"
+ },
+ "exceed-action": {
+ "meter-action-type": "policer:meter-action-drop"
+ }
+ },
+ "policer_data_3": {
+ "name": "policy1",
+ "cir": 100,
+ "eir": 150,
+ "cb": 200,
+ "eb": 300,
+ "rate-type": "pps",
+ "round-type": "closest",
+ "type": "2r3c-2698",
+ "conform-action": {
+ "meter-action-type": "meter-action-transmit"
+ },
+ "exceed-action": {
+ "meter-action-type": "meter-action-mark-dscp",
+ "dscp": "AF22"
+ },
+ "violate-action": {
+ "meter-action-type": "meter-action-drop"
+ },
+ "color-aware": True
+ },
+ "policer_data_oper_3": {
+ "name": "policy1",
+ "cir": 100,
+ "eir": 150,
+ "cb": 200,
+ "eb": 300,
+ "rate-type": "pps",
+ "round-type": "closest",
+ "type": "2r3c-2698",
+ "conform-action": {
+ "meter-action-type": "policer:meter-action-transmit"
+ },
+ "exceed-action": {
+ "meter-action-type": "policer:meter-action-mark-dscp",
+ },
+ "violate-action": {
+ "meter-action-type": "policer:meter-action-drop"
+ },
+ "color-aware": True
+ },
+
+ "acl_tables": {
+ # settings for policer tables
+ "hc_acl_table": {
+ "name": "table0",
+ "nbuckets": 2,
+ "memory_size": 1048576,
+ "skip_n_vectors": 12,
+ "miss_next": "permit",
+ "mask": "00:00:00:00:00:00:00:00:00:00:00:00:ff:ff:ff:ff"
+ },
+ # setting for acl sessions
+ "hc_acl_session": {
+ "match": "00:00:00:00:00:00:00:00:00:00:00:00:C0:A8:7A:01",
+ "policer_hit_next": "policy1",
+ "color_classfier": "exceed-color",
+ },
+ "hc_acl_session2": {
+ "match": "00:00:00:00:00:00:00:00:00:00:00:00:C0:A8:7A:02",
+ "policer_hit_next": "policy1",
+ "color_classfier": "exceed-color",
+ },
+ },
+ }
+ return policer_data
diff --git a/tests/func/honeycomb/mgmt-cfg-acl-apihc-apivat-func.robot b/tests/func/honeycomb/mgmt-cfg-acl-apihc-apivat-func.robot
index 4dad038fde..1dac59839b 100644
--- a/tests/func/honeycomb/mgmt-cfg-acl-apihc-apivat-func.robot
+++ b/tests/func/honeycomb/mgmt-cfg-acl-apihc-apivat-func.robot
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 Cisco and/or its affiliates.
+# Copyright (c) 2017 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
diff --git a/tests/func/honeycomb/mgmt-cfg-policer-apihc-func.robot b/tests/func/honeycomb/mgmt-cfg-policer-apihc-func.robot
new file mode 100644
index 0000000000..f7d8e9912b
--- /dev/null
+++ b/tests/func/honeycomb/mgmt-cfg-policer-apihc-func.robot
@@ -0,0 +1,128 @@
+# Copyright (c) 2017 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+*** Variables ***
+| ${interface}= | ${node['interfaces']['port1']['name']}
+| ${tg_to_dut_if1_ip}= | 192.168.122.1
+| ${dut_to_tg_if1_ip}= | 192.168.122.2
+| ${dut_to_tg_if2_ip}= | 192.168.123.1
+| ${tg_to_dut_if2_ip}= | 192.168.123.2
+| ${prefix_length}= | ${24}
+| ${dscp_number}= | ${20}
+
+*** Settings ***
+| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/honeycomb/honeycomb.robot
+| Resource | resources/libraries/robot/honeycomb/interfaces.robot
+| Resource | resources/libraries/robot/honeycomb/policer.robot
+| Resource | resources/libraries/robot/honeycomb/access_control_lists.robot
+| Resource | resources/libraries/robot/testing_path.robot
+| Library | resources.libraries.python.Trace
+| Variables | resources/test_data/honeycomb/policer_variables.py
+| Suite Teardown
+| ... | Run Keyword If Any Tests Failed
+| ... | Restart Honeycomb and VPP | ${node}
+| Force Tags | honeycomb_sanity | honeycomb_odl
+| Documentation | *Honeycomb Policer management test suite.*
+
+*** Test Cases ***
+| TC01: Honeycomb can configure Policer
+| | [Documentation] | Checks if Honeycomb can configure Policer.
+| | Given Policer configuration from Honeycomb should be empty | ${node}
+| | When Honeycomb configures Policer | ${node} | ${policer_data}
+| | Then Policer configuration from Honeycomb should be | ${node}
+| | ... | ${policer_data_oper}
+
+| TC02: Honeycomb can disable Policer
+| | [Documentation] | Checks if Honeycomb can disable Policer.
+| | Given Policer configuration from Honeycomb should be | ${node}
+| | ... | ${policer_data_oper}
+| | When Honeycomb removes Policer configuration | ${node}
+| | Then Policer configuration from Honeycomb should be empty | ${node}
+
+| TC03: Honeycomb can configure Policer with increased values of CIR (900kbps)
+| | [Documentation] | Checks if Honeycomb can configure Policer\
+| | ... | with increased values of CIR.
+| | [Teardown] | Policer test teardown | ${node}
+| | Given Policer configuration from Honeycomb should be empty | ${node}
+| | When Honeycomb configures Policer | ${node} | ${policer_data_2}
+| | Then Policer configuration from Honeycomb should be | ${node}
+| | ... | ${policer_data_oper_2}
+
+| TC04: Honeycomb can configure Packets-Per-Second Based Policer
+| | [Documentation] | Checks if Honeycomb can configure Policer\
+| | ... | based on rate-type measured in pps.
+| | [Teardown] | Policer test teardown | ${node}
+| | Given Policer configuration from Honeycomb should be empty | ${node}
+| | When Honeycomb configures Policer | ${node} | ${policer_data_3}
+| | Then Policer configuration from Honeycomb should be | ${node}
+| | ... | ${policer_data_oper_3}
+
+| TC05: Configure Policer on Interface
+| | [Documentation] | Honeycomb can configure Policer\
+| | ... | on a given interface.
+| | [Teardown] | Run Keywords
+| | ... | Honeycomb disables Policer on interface | ${node} | ${interface} | AND
+| | ... | Honeycomb removes ACL session
+| | ... | ${node} | ${acl_tables['hc_acl_table']['name']}
+| | ... | ${acl_tables['hc_acl_session']['match']} | AND
+| | ... | Honeycomb removes ACL table | ${node}
+| | ... | ${acl_tables['hc_acl_table']['name']} | AND
+| | ... | Policer test teardown | ${node}
+| | Given Honeycomb configures Policer | ${node} | ${policer_data}
+| | And ACL table from Honeycomb should not exist
+| | ... | ${node} | ${acl_tables['hc_acl_table']['name']}
+| | When Honeycomb creates ACL table
+| | ... | ${node} | ${acl_tables['hc_acl_table']}
+| | And Honeycomb adds ACL session
+| | ... | ${node} | ${acl_tables['hc_acl_table']['name']}
+| | ... | ${acl_tables['hc_acl_session']}
+| | Then Honeycomb enables policer on interface
+| | ... | ${node} | ${interface} | ${acl_tables['hc_acl_table']['name']}
+
+| TC06: VPP policer 2R3C Color-aware marks packet
+| | [Documentation]
+| | ... | [Top] TG=DUT1.
+| | ... | [Ref] RFC2474, RFC2698.
+| | ... | [Cfg] Configure 2R3C color-aware policer on DUT1 on the first\
+| | ... | interface.
+| | ... | [Ver] TG sends IPv4 TCP packet on the first link to DUT1.\
+| | ... | Packet on DUT1 is marked with DSCP tag. Verifies if DUT1 sends\
+| | ... | correct IPv4 TCP packet with correct DSCP on the second link to TG.
+| | [Teardown] | Show Packet Trace on All DUTs | ${nodes}
+| | Given Path for 2-node testing is set
+| | ... | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['TG']}
+| | And Honeycomb configures Policer | ${dut_node} | ${policer_data_3}
+| | And ACL table from Honeycomb should not exist
+| | ... | ${dut_node} | ${acl_tables['hc_acl_table']['name']}
+| | When Honeycomb creates ACL table
+| | ... | ${dut_node} | ${acl_tables['hc_acl_table']}
+| | And Honeycomb adds ACL session
+| | ... | ${dut_node} | ${acl_tables['hc_acl_table']['name']}
+| | ... | ${acl_tables['hc_acl_session']}
+| | And Honeycomb enables policer on interface
+| | ... | ${dut_node} | ${dut_to_tg_if1} | ${acl_tables['hc_acl_table']['name']}
+| | And Honeycomb sets interface state | ${dut_node} | ${dut_to_tg_if1} | up
+| | And Honeycomb sets interface state | ${dut_node} | ${dut_to_tg_if2} | up
+| | And Honeycomb sets interface ipv4 address with prefix | ${dut_node}
+| | ... | ${dut_to_tg_if1} | ${dut_to_tg_if1_ip} | ${prefix_length}
+| | And Honeycomb sets interface ipv4 address with prefix | ${dut_node}
+| | ... | ${dut_to_tg_if2} | ${dut_to_tg_if2_ip} | ${prefix_length}
+| | And Honeycomb adds interface ipv4 neighbor
+| | ... | ${dut_node} | ${dut_to_tg_if2} | ${tg_to_dut_if2_ip}
+| | ... | ${tg_to_dut_if2_mac}
+| | And interfaceCLI.VPP Node Interfaces Ready Wait | ${dut_node}
+| | Then Honeycomb Send Packet and Verify Marking | ${tg_node}
+| | ... | ${tg_to_dut_if1}
+| | ... | ${tg_to_dut_if2} | ${tg_to_dut_if1_mac} | ${dut_to_tg_if1_mac}
+| | ... | ${tg_to_dut_if1_ip} | ${tg_to_dut_if2_ip} | ${dscp_number}