aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/robot/l2
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libraries/robot/l2')
-rw-r--r--resources/libraries/robot/l2/l2_bridge_domain.robot279
-rw-r--r--resources/libraries/robot/l2/l2_traffic.robot183
-rw-r--r--resources/libraries/robot/l2/l2_xconnect.robot24
-rw-r--r--resources/libraries/robot/l2/tagging.robot219
4 files changed, 705 insertions, 0 deletions
diff --git a/resources/libraries/robot/l2/l2_bridge_domain.robot b/resources/libraries/robot/l2/l2_bridge_domain.robot
new file mode 100644
index 0000000000..9c6c29dc7d
--- /dev/null
+++ b/resources/libraries/robot/l2/l2_bridge_domain.robot
@@ -0,0 +1,279 @@
+# Copyright (c) 2016 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 ***
+| Library | resources.libraries.python.L2Util
+| Library | resources.libraries.python.InterfaceUtil
+| Library | resources.libraries.python.NodePath
+| Library | resources.libraries.python.VhostUser
+| Resource | resources/libraries/robot/shared/interfaces.robot
+| Resource | resources/libraries/robot/l2/l2_traffic.robot
+
+*** Keywords ***
+| Configure L2BD forwarding
+| | [Documentation] | Setup BD between 2 interfaces on VPP node and if learning
+| | ... | is off set static L2FIB entry on second interface
+| | [Arguments] | ${node} | ${if1} | ${if2} | ${learn}=${TRUE} | ${mac}=${EMPTY}
+| | Set Interface State | ${node} | ${if1} | up
+| | Set Interface State | ${node} | ${if2} | up
+| | Vpp Add L2 Bridge Domain | ${node} | ${1} | ${if1} | ${if2} | ${learn}
+| | Run Keyword If | ${learn} == ${FALSE}
+| | ... | Vpp Add L2fib Entry | ${node} | ${mac} | ${if2} | ${1}
+| | All Vpp Interfaces Ready Wait | ${nodes}
+
+| Configure path for 3-node BD-SHG test
+| | [Documentation] | Compute path for bridge domain split-horizon group testing
+| | ... | on three given nodes with following interconnections
+| | ... | TG - (2 links) - DUT1 - (1 link) - DUT2 - (2 links) - TG
+| | ... | and set corresponding test case variables.
+| | ...
+| | ... | *Arguments:*
+| | ... | - ${tg_node} - TG node. Type: dictionary
+| | ... | - ${dut1_node} - DUT1 node. Type: dictionary
+| | ... | - ${dut2_node} - DUT2 node. Type: dictionary
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | _NOTE:_ This KW sets following test case variables:
+| | ... | - ${tg_node} - TG node.
+| | ... | - ${tg_to_dut1_if1} - TG interface 1 towards DUT1.
+| | ... | - ${tg_to_dut1_if2} - TG interface 2 towards DUT1.
+| | ... | - ${tg_to_dut2_if1} - TG interface 1 towards DUT2.
+| | ... | - ${tg_to_dut2_if2} - TG interface 2 towards DUT2.
+| | ... | - ${dut1_node} - DUT1 node.
+| | ... | - ${dut1_to_tg_if1} - DUT1 interface 1 towards TG.
+| | ... | - ${dut1_to_tg_if2} - DUT1 interface 2 towards TG.
+| | ... | - ${dut1_to_dut2} - DUT1 interface towards DUT2.
+| | ... | - ${dut2_node} - DUT2 node.
+| | ... | - ${dut2_to_tg_if1} - DUT2 interface 1 towards TG.
+| | ... | - ${dut2_to_tg_if2} - DUT2 interface 2 towards TG.
+| | ... | - ${dut2_to_dut1} - DUT2 interface towards DUT1.
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Given Configure path for 3-node BD-SHG test \| ${nodes['TG']} \
+| | ... | \| ${nodes['DUT1']} \| ${nodes['DUT2']} \|
+| | [Arguments] | ${tg_node} | ${dut1_node} | ${dut2_node}
+| | # Compute path TG - DUT1 with two links in between
+| | Append Nodes | ${tg_node} | ${dut1_node} | ${tg_node}
+| | Compute Path | always_same_link=${FALSE}
+| | ${tg_to_dut1_if1} | ${tmp}= | First Interface
+| | ${tg_to_dut1_if2} | ${tmp}= | Last Interface
+| | ${dut1_to_tg_if1} | ${tmp}= | First Ingress Interface
+| | ${dut1_to_tg_if2} | ${tmp}= | Last Egress Interface
+| | # Compute path TG - DUT2 with two links in between
+| | Clear Path
+| | Append Nodes | ${tg_node} | ${dut2_node} | ${tg_node}
+| | Compute Path | always_same_link=${FALSE}
+| | ${tg_to_dut2_if1} | ${tmp}= | First Interface
+| | ${tg_to_dut2_if2} | ${tmp}= | Last Interface
+| | ${dut2_to_tg_if1} | ${tmp}= | First Ingress Interface
+| | ${dut2_to_tg_if2} | ${tmp}= | Last Egress Interface
+| | # Compute path DUT1 - DUT2 with one link in between
+| | Clear Path
+| | Append Nodes | ${dut1_node} | ${dut2_node}
+| | Compute Path
+| | ${dut1_to_dut2} | ${tmp}= | Next Interface
+| | ${dut2_to_dut1} | ${tmp}= | Next Interface
+| | # Set test variables
+| | Set Test Variable | ${tg_to_dut1_if1}
+| | Set Test Variable | ${tg_to_dut1_if2}
+| | Set Test Variable | ${tg_to_dut2_if1}
+| | Set Test Variable | ${tg_to_dut2_if2}
+| | Set Test Variable | ${dut1_to_tg_if1}
+| | Set Test Variable | ${dut1_to_tg_if2}
+| | Set Test Variable | ${dut2_to_tg_if1}
+| | Set Test Variable | ${dut2_to_tg_if2}
+| | Set Test Variable | ${dut1_to_dut2}
+| | Set Test Variable | ${dut2_to_dut1}
+| | Set Test Variable | ${tg_node}
+| | Set Test Variable | ${dut1_node}
+| | Set Test Variable | ${dut2_node}
+
+| Set interfaces in 3-node BD-SHG test up
+| | [Documentation] | Set UP state on interfaces in 3-node path on nodes and
+| | ... | wait for all interfaces are ready.
+| | ...
+| | ... | *Arguments:*
+| | ... | - No arguments.
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned.
+| | ...
+| | ... | _NOTE:_ This KW uses test variables sets in
+| | ... | "Configure path for 3-node BD-SHG test" KW.
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Configure path for 3-node BD-SHG test \| ${nodes['TG']} \
+| | ... | \| ${nodes['DUT1']} \| ${nodes['DUT2']} \|
+| | ... | \| Set interfaces in 3-node BD-SHG test up \|
+| | ...
+| | Set Interface State | ${tg_node} | ${tg_to_dut1_if1} | up
+| | Set Interface State | ${tg_node} | ${tg_to_dut1_if2} | up
+| | Set Interface State | ${tg_node} | ${tg_to_dut2_if1} | up
+| | Set Interface State | ${tg_node} | ${tg_to_dut2_if2} | up
+| | Set Interface State | ${dut1_node} | ${dut1_to_tg_if1} | up
+| | Set Interface State | ${dut1_node} | ${dut1_to_tg_if2} | up
+| | Set Interface State | ${dut2_node} | ${dut2_to_tg_if1} | up
+| | Set Interface State | ${dut2_node} | ${dut2_to_tg_if2} | up
+| | Set Interface State | ${dut1_node} | ${dut1_to_dut2} | up
+| | Set Interface State | ${dut2_node} | ${dut2_to_dut1} | up
+| | Vpp Node Interfaces Ready Wait | ${dut1_node}
+| | Vpp Node Interfaces Ready Wait | ${dut2_node}
+
+| Create bridge domain
+| | [Documentation] | Create bridge domain on given VPP node with defined
+| | ... | learning status.
+| | ...
+| | ... | *Arguments:*
+| | ... | - ${dut_node} - DUT node. Type: dictionary
+| | ... | - ${bd_id} - Bridge domain ID. Type: integer
+| | ... | - ${learn} - Enable/disable MAC learn. Type: boolean, \
+| | ... | default value: ${TRUE}
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Create bridge domain \| ${nodes['DUT1']} \| 2 \|
+| | ... | \| Create bridge domain \| ${nodes['DUT1']} \| 5 \
+| | ... | \| learn=${FALSE} \|
+| | [Arguments] | ${dut_node} | ${bd_id} | ${learn}=${TRUE}
+| | ${learn} = | Set Variable If | ${learn} == ${TRUE} | ${1} | ${0}
+| | Create L2 BD | ${dut_node} | ${bd_id} | learn=${learn}
+
+| Add interface to bridge domain
+| | [Documentation] | Set given interface admin state to up and add this
+| | ... | interface to required L2 bridge domain on defined
+| | ... | VPP node.
+| | ...
+| | ... | *Arguments:*
+| | ... | - ${dut_node} - DUT node. Type: dictionary
+| | ... | - ${dut_if} - DUT node interface name. Type: string
+| | ... | - ${bd_id} - Bridge domain ID. Type: integer
+| | ... | - ${shg} - Split-horizon group ID. Type: integer, default value: 0
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Add interface to bridge domain \| ${nodes['DUT2']} \
+| | ... | \| GigabitEthernet0/8/0 \| 3 \|
+| | [Arguments] | ${dut_node} | ${dut_if} | ${bd_id} | ${shg}=0
+| | Set Interface State | ${dut_node} | ${dut_if} | up
+| | Add Interface To L2 BD | ${dut_node} | ${dut_if} | ${bd_id} | ${shg}
+
+| Add destination port to L2FIB
+| | [Documentation] | Create a static L2FIB entry for required destination port
+| | ... | on defined interface and bridge domain ID
+| | ... | of the given VPP node.
+| | ...
+| | ... | *Arguments:*
+| | ... | - ${dest_node} - Destination node. Type: dictionary
+| | ... | - ${dest_node_if} - Destination node interface name. Type: string
+| | ... | - ${vpp_node} - DUT node to add L2FIB entry on. Type: dictionary
+| | ... | - ${vpp_node_if} - DUT node interface name. Type: string
+| | ... | - ${bd_id} - Bridge domain ID. Type: integer
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Add destination port to L2FIB \| ${nodes['TG']} \
+| | ... | \| eth1 \| ${nodes['DUT2']} \| GigabitEthernet0/8/0 \| 3 \|
+| | [Arguments] | ${dest_node} | ${dest_node_if} | ${vpp_node}
+| | ... | ${vpp_node_if} | ${bd_id}
+| | ${mac}= | Get Interface Mac | ${dest_node} | ${dest_node_if}
+| | Vpp Add L2fib Entry | ${vpp_node} | ${mac} | ${vpp_node_if} | ${bd_id}
+
+| Configure VM for vhost L2BD forwarding
+| | [Documentation] | Setup QEMU and start VM with two vhost interfaces.
+| | ...
+| | ... | *Arguments:*
+| | ... | - ${dut_node} - DUT node to start VM on. Type: dictionary
+| | ... | - ${sock1} - Socket path for first Vhost-User interface. Type: string
+| | ... | - ${sock2} - Socket path for second Vhost-User interface. Type: string
+| | ... | - ${qemu_name} - Qemu instance name by which the object will be
+| | ... | accessed (Optional). Type: string
+| | ...
+| | ... | _NOTE:_ This KW sets following test case variable:
+| | ... | - ${${qemu_name}} - VM node info. Type: dictionary
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Configure VM for vhost L2BD forwarding \| ${nodes['DUT1']} \
+| | ... | \| /tmp/sock1 \| /tmp/sock2 \|
+| | ... | \| Configure VM for vhost L2BD forwarding \| ${nodes['DUT2']} \
+| | ... | \| /tmp/sock1 \| /tmp/sock2 \| qemu_instance_2 \|
+| | [Arguments] | ${dut_node} | ${sock1} | ${sock2} | ${qemu_name}=vm_node
+| | Run Keyword Unless | "${qemu_name}" == "vm_node" | Import Library
+| | ... | resources.libraries.python.QemuUtils | WITH NAME | ${qemu_name}
+| | Set Test Variable | ${${qemu_name}} | ${None}
+| | ${qemu_set_node}= | Run Keyword If | "${qemu_name}" == "vm_node"
+| | | ... | Set Variable | Qemu Set Node
+| | ... | ELSE | Replace Variables | ${qemu_name}.Qemu Set Node
+| | Run keyword | ${qemu_set_node} | ${dut_node}
+| | ${qemu_add_vhost}= | Run Keyword If | "${qemu_name}" == "vm_node"
+| | | ... | Set Variable | Qemu Add Vhost User If
+| | ... | ELSE | Replace Variables | ${qemu_name}.Qemu Add Vhost User If
+| | Run keyword | ${qemu_add_vhost} | ${sock1}
+| | Run keyword | ${qemu_add_vhost} | ${sock2}
+| | ${qemu_start}= | Run Keyword If | "${qemu_name}" == "vm_node"
+| | | ... | Set Variable | Qemu Start
+| | ... | ELSE | Replace Variables | ${qemu_name}.Qemu Start
+| | ${vm}= | Run keyword | ${qemu_start}
+| | ${br}= | Set Variable | br0
+| | ${vhost1}= | Get Vhost User If Name By Sock | ${vm} | ${sock1}
+| | ${vhost2}= | Get Vhost User If Name By Sock | ${vm} | ${sock2}
+| | Linux Add Bridge | ${vm} | ${br} | ${vhost1} | ${vhost2}
+| | Set Interface State | ${vm} | ${vhost1} | up | if_type=name
+| | Set Interface State | ${vm} | ${vhost2} | up | if_type=name
+| | Set Interface State | ${vm} | ${br} | up | if_type=name
+| | Set Test Variable | ${${qemu_name}} | ${vm}
+
+| Configure vhost interfaces for L2BD forwarding
+| | [Documentation] | Create two Vhost-User interfaces on defined VPP node.
+| | ...
+| | ... | *Arguments:*
+| | ... | - ${dut_node} - DUT node. Type: dictionary
+| | ... | - ${sock1} - Socket path for first Vhost-User interface. Type: string
+| | ... | - ${sock2} - Socket path for second Vhost-User interface. Type: string
+| | ... | - ${vhost_if1} - Name of the first Vhost-User interface (Optional).
+| | ... | Type: string
+| | ... | - ${vhost_if2} - Name of the second Vhost-User interface (Optional).
+| | ... | Type: string
+| | ...
+| | ... | _NOTE:_ This KW sets following test case variable:
+| | ... | - ${${vhost_if1}} - First Vhost-User interface.
+| | ... | - ${${vhost_if2}} - Second Vhost-User interface.
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Configure vhost interfaces for L2BD forwarding \
+| | ... | \| ${nodes['DUT1']} \| /tmp/sock1 \| /tmp/sock2 \|
+| | ... | \| Configure vhost interfaces for L2BD forwarding \
+| | ... | \| ${nodes['DUT2']} \| /tmp/sock1 \| /tmp/sock2 \| dut2_vhost_if1 \
+| | ... | \| dut2_vhost_if2 \|
+| | [Arguments] | ${dut_node} | ${sock1} | ${sock2} | ${vhost_if1}=vhost_if1
+| | ... | ${vhost_if2}=vhost_if2
+| | ${vhost_1}= | Vpp Create Vhost User Interface | ${dut_node} | ${sock1}
+| | ${vhost_2}= | Vpp Create Vhost User Interface | ${dut_node} | ${sock2}
+| | Set Interface State | ${dut_node} | ${vhost_1} | up
+| | Set Interface State | ${dut_node} | ${vhost_2} | up
+| | Set Test Variable | ${${vhost_if1}} | ${vhost_1}
+| | Set Test Variable | ${${vhost_if2}} | ${vhost_2}
diff --git a/resources/libraries/robot/l2/l2_traffic.robot b/resources/libraries/robot/l2/l2_traffic.robot
new file mode 100644
index 0000000000..bca801778e
--- /dev/null
+++ b/resources/libraries/robot/l2/l2_traffic.robot
@@ -0,0 +1,183 @@
+# Copyright (c) 2016 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 ***
+| Library | resources.libraries.python.topology.Topology
+| Library | resources.libraries.python.TrafficScriptExecutor
+| Documentation | Keywords to send and receive different types of traffic \
+| ... | through L2 network.
+
+*** Keywords ***
+| Send ICMP packet and verify received packet
+| | [Documentation] | Send ICMPv4/ICMPv6 echo request from source interface to \
+| | ... | destination interface. Packet can be set with Dot1q or
+| | ... | Dot1ad tag(s) when required.
+| | ...
+| | ... | *Arguments:*
+| | ...
+| | ... | - tg_node - TG node. Type: dictionary
+| | ... | - src_int - Source interface. Type: string
+| | ... | - dst_int - Destination interface. Type: string
+| | ... | - src_ip - Source IP address (Optional). Type: string
+| | ... | - dst_ip - Destination IP address (Optional). Type: string
+| | ... | - encaps - Encapsulation: Dot1q or Dot1ad (Optional). Type: string
+| | ... | - vlan1 - VLAN (outer) tag (Optional). Type: integer
+| | ... | - vlan2 - VLAN inner tag (Optional). Type: integer
+| | ... | - encaps_rx - Expected encapsulation on RX side: Dot1q or Dot1ad
+| | ... | (Optional). Type: string
+| | ... | - vlan1_rx - VLAN (outer) tag on RX side (Optional). Type: integer
+| | ... | - vlan2_rx - VLAN inner tag on RX side (Optional). Type: integer
+| | ...
+| | ... | *Return:*
+| | ...
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | _NOTE:_ Default IP is IPv4
+| | ...
+| | ... | \| Send ICMP packet and verify received packet \| ${nodes['TG']} \
+| | ... | \| ${tg_to_dut_if1} \| ${tg_to_dut_if2} \|
+| | ... | \| Send ICMP packet and verify received packet \| ${nodes['TG']} \
+| | ... | \| ${tg_to_dut1} \| ${tg_to_dut2} \| encaps=Dot1q \| vlan1=100 \|
+| | ... | \| Send ICMP packet and verify received packet \| ${nodes['TG']} \
+| | ... | \| ${tg_to_dut1} \| ${tg_to_dut2} \| encaps=Dot1ad \| vlan1=110 \
+| | ... | \| vlan2=220 \|
+| | ... | \| Send ICMP packet and verify received packet \| ${nodes['TG']} \
+| | ... | \| ${tg_to_dut1} \| ${tg_to_dut2} \| encaps=Dot1q \| vlan1=110 \
+| | ... | \| encaps_rx=Dot1q \|
+| | ... | \| Send ICMP packet and verify received packet \| ${nodes['TG']} \
+| | ... | \| ${tg_to_dut1} \| ${tg_to_dut2} \| encaps=Dot1q \| vlan1=110 \
+| | ... | \| encaps_rx=Dot1q \| vlan1_rx=120 \|
+| | ...
+| | [Arguments] | ${tg_node} | ${src_int} | ${dst_int}
+| | ... | ${src_ip}=192.168.100.1 | ${dst_ip}=192.168.100.2 | ${encaps}=${EMPTY}
+| | ... | ${vlan1}=${EMPTY} | ${vlan2}=${EMPTY} | ${encaps_rx}=${EMPTY}
+| | ... | ${vlan1_rx}=${EMPTY} | ${vlan2_rx}=${EMPTY}
+| | ...
+| | ${src_mac}= | Get Interface Mac | ${tg_node} | ${src_int}
+| | ${dst_mac}= | Get Interface Mac | ${tg_node} | ${dst_int}
+| | ${src_int_name}= | Get interface name | ${tg_node} | ${src_int}
+| | ${dst_int_name}= | Get interface name | ${tg_node} | ${dst_int}
+| | ${args}= | Traffic Script Gen Arg | ${dst_int_name} | ${src_int_name}
+| | ... | ${src_mac} | ${dst_mac} | ${src_ip} | ${dst_ip}
+| | ${args}= | Run Keyword If | '${encaps}' == '${EMPTY}'
+| | | ... | Set Variable | ${args}
+| | ... | ELSE | Catenate | ${args} | --encaps ${encaps} | --vlan1 ${vlan1}
+| | ${args}= | Run Keyword If | '${vlan2}' == '${EMPTY}'
+| | | ... | Set Variable | ${args}
+| | ... | ELSE | Catenate | ${args} | --vlan2 ${vlan2}
+| | ${args}= | Run Keyword If | '${encaps_rx}' == '${EMPTY}'
+| | | ... | Set Variable | ${args}
+| | ... | ELSE | Catenate | ${args} | --encaps_rx ${encaps_rx}
+| | ${args}= | Run Keyword If | '${vlan1_rx}' == '${EMPTY}'
+| | | ... | Set Variable | ${args}
+| | ... | ELSE | Catenate | ${args} | --vlan1_rx ${vlan1_rx}
+| | ${args}= | Run Keyword If | '${vlan2_rx}' == '${EMPTY}'
+| | | ... | Set Variable | ${args}
+| | ... | ELSE | Catenate | ${args} | --vlan2_rx ${vlan2_rx}
+| | Run Traffic Script On Node | send_ip_icmp.py | ${tg_node} | ${args}
+
+| ICMP packet transmission should fail
+| | [Documentation] | Send ICMPv4/ICMPv6 echo request from source interface to
+| | ... | destination interface and expect failure with
+| | ... | ICMP echo Rx timeout error message.
+| | ...
+| | ... | *Arguments:*
+| | ...
+| | ... | - tg_node - TG node. Type: dictionary
+| | ... | - src_int - Source interface. Type: string
+| | ... | - dst_int - Destination interface. Type: string
+| | ... | - src_ip - Source IP address (Optional). Type: string
+| | ... | - dst_ip - Destination IP address (Optional). Type: string
+| | ...
+| | ... | *Return:*
+| | ...
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | _NOTE:_ Default IP is IPv4
+| | ...
+| | ... | \| ICMP packet transmission should fail\| ${nodes['TG']} \
+| | ... | \| ${tg_to_dut_if1} \| ${tg_to_dut_if2} \|
+| | ...
+| | [Arguments] | ${tg_node} | ${src_int} | ${dst_int} |
+| | ... | ${src_ip}=192.168.100.1 | ${dst_ip}=192.168.100.2
+| | ...
+| | ${src_mac}= | Get Interface Mac | ${tg_node} | ${src_int}
+| | ${dst_mac}= | Get Interface Mac | ${tg_node} | ${dst_int}
+| | ${src_int_name}= | Get interface name | ${tg_node} | ${src_int}
+| | ${dst_int_name}= | Get interface name | ${tg_node} | ${dst_int}
+| | ${args}= | Traffic Script Gen Arg | ${dst_int_name} | ${src_int_name}
+| | ... | ${src_mac} | ${dst_mac} | ${src_ip} | ${dst_ip}
+| | Run Keyword And Expect Error | ICMP echo Rx timeout |
+| | ... | Run Traffic Script On Node | send_ip_icmp.py | ${tg_node} | ${args}
+
+| Send ICMPv4 bidirectionally and verify received packets
+| | [Documentation] | Send ICMPv4 echo request from both directions,
+| | ... | from interface1 to interface2 and from interface2 to interface1.
+| | ...
+| | ... | *Arguments:*
+| | ...
+| | ... | - tg_node - TG node. Type: dictionary
+| | ... | - src_int - Source interface. Type: string
+| | ... | - dst_int - Destination interface. Type: string
+| | ... | - src_ip - Source IP address (Optional). Type: string
+| | ... | - dst_ip - Destination IP address (Optional). Type: string
+| | ...
+| | ... | *Return:*
+| | ...
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Send ICMPv4 bidirectionally and verify received packets \
+| | ... | \| ${nodes['TG']} \| ${tg_to_dut_if1} \| ${tg_to_dut_if2} \|
+| | ...
+| | [Arguments] | ${tg_node} | ${int1} | ${int2} | ${src_ip}=192.168.100.1 |
+| | ... | ${dst_ip}=192.168.100.2
+| | ...
+| | Send ICMP packet and verify received packet
+| | ... | ${tg_node} | ${int1} | ${int2} | ${src_ip} | ${dst_ip}
+| | Send ICMP packet and verify received packet
+| | ... | ${tg_node} | ${int2} | ${int1} | ${dst_ip} | ${src_ip}
+
+| Send ICMPv6 bidirectionally and verify received packets
+| | [Documentation] | Send ICMPv6 echo request from both directions,
+| | ... | from interface1 to interface2 and from interface2 to interface1.
+| | ...
+| | ... | *Arguments:*
+| | ...
+| | ... | - tg_node - TG node. Type: dictionary
+| | ... | - src_int - Source interface. Type: string
+| | ... | - dst_int - Destination interface. Type: string
+| | ... | - src_ip - Source IP address (Optional). Type: string
+| | ... | - dst_ip - Destination IP address (Optional). Type: string
+| | ...
+| | ... | *Return:*
+| | ...
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Send ICMPv6 bidirectionally and verify received packets \
+| | ... | \| ${nodes['TG']} \| ${tg_to_dut_if1} \| ${tg_to_dut_if2} \|
+| | ...
+| | [Arguments] | ${tg_node} | ${int1} | ${int2} | ${src_ip}=3ffe:63::1 |
+| | ... | ${dst_ip}=3ffe:63::2
+| | ...
+| | Send ICMP packet and verify received packet
+| | ... | ${tg_node} | ${int1} | ${int2} | ${src_ip} | ${dst_ip}
+| | Send ICMP packet and verify received packet
+| | ... | ${tg_node} | ${int2} | ${int1} | ${dst_ip} | ${src_ip}
diff --git a/resources/libraries/robot/l2/l2_xconnect.robot b/resources/libraries/robot/l2/l2_xconnect.robot
new file mode 100644
index 0000000000..00d33e867a
--- /dev/null
+++ b/resources/libraries/robot/l2/l2_xconnect.robot
@@ -0,0 +1,24 @@
+# Copyright (c) 2016 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 ***
+| Library | resources.libraries.python.L2Util
+| Library | resources.libraries.python.InterfaceUtil
+
+*** Keywords ***
+| Configure L2XC
+| | [Documentation] | Setup Bidirectional Cross Connect on DUTs
+| | [Arguments] | ${node} | ${if1} | ${if2} |
+| | Set Interface State | ${node} | ${if1} | up
+| | Set Interface State | ${node} | ${if2} | up
+| | Vpp Setup Bidirectional Cross Connect | ${node} | ${if1} | ${if2}
diff --git a/resources/libraries/robot/l2/tagging.robot b/resources/libraries/robot/l2/tagging.robot
new file mode 100644
index 0000000000..7731ed193e
--- /dev/null
+++ b/resources/libraries/robot/l2/tagging.robot
@@ -0,0 +1,219 @@
+# Copyright (c) 2016 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 ***
+| Documentation | Keywords for VLAN tests
+| Resource | resources/libraries/robot/shared/default.robot
+| Resource | resources/libraries/robot/l2/l2_xconnect.robot
+| Library | resources.libraries.python.L2Util
+| Library | resources.libraries.python.InterfaceUtil
+| Library | resources.libraries.python.NodePath
+
+*** Keywords ***
+
+| Initialize VLAN sub-interfaces in 3-node circular topology
+| | [Arguments] | ${DUT1} | ${INT1} | ${DUT2} | ${INT2} | ${SUB_ID}
+| | ... | ${OUTER_VLAN_ID} | ${INNER_VLAN_ID} | ${TYPE_SUBIF}
+| | [Documentation] | *Create two subinterfaces on DUTs.*
+| | ...
+| | ... | *Arguments:*
+| | ... | - DUT1 - Node to add sub-interface.
+| | ... | - INT1 - Interface name on which create sub-interface.
+| | ... | - DUT2 - Node to add sub-interface.
+| | ... | - INT2 - Interface name on which create sub-interface.
+| | ... | - SUB_ID - ID of the sub-interface to be created.
+| | ... | - OUTER_VLAN_ID - Outer VLAN ID.
+| | ... | - INNER_VLAN_ID - Inner VLAN ID.
+| | ... | - TYPE_SUBIF - Type of sub-interface.
+| | ...
+| | ... | _Set testcase variables with name and index of created interfaces:_
+| | ... | - subif_name_1
+| | ... | - subif_index_1
+| | ... | - subif_name_2
+| | ... | - subif_index_2
+| | ...
+| | ${INT1_name}= | Get interface name | ${DUT1} | ${INT1}
+| | ${subif_name_1} | ${subif_index_1}= | Create subinterface | ${DUT1}
+| | ... | ${INT1_name} | ${SUB_ID}
+| | ... | ${OUTER_VLAN_ID} | ${INNER_VLAN_ID}
+| | ... | ${TYPE_SUBIF}
+| | ${INT2_name}= | Get interface name | ${DUT2} | ${INT2}
+| | ${subif_name_2} | ${subif_index_2}= | Create subinterface | ${DUT2}
+| | ... | ${INT2_name} | ${SUB_ID}
+| | ... | ${OUTER_VLAN_ID} | ${INNER_VLAN_ID}
+| | ... | ${TYPE_SUBIF}
+| | Set Interface State | ${DUT1} | ${subif_index_1} | up
+| | Set Interface State | ${DUT2} | ${subif_index_2} | up
+| | Set Test Variable | ${subif_name_1}
+| | Set Test Variable | ${subif_index_1}
+| | Set Test Variable | ${subif_name_2}
+| | Set Test Variable | ${subif_index_2}
+
+| Initialize VLAN dot1q sub-interfaces in 3-node circular topology
+| | [Arguments] | ${DUT1} | ${INT1} | ${DUT2} | ${INT2} | ${SUB_ID}
+| | [Documentation] | *Create two dot1q subinterfaces on DUTs.*
+| | ...
+| | ... | *Arguments:*
+| | ... | - DUT1 - Node to add sub-interface.
+| | ... | - INT1 - Interface name on which create VLAN sub-interface.
+| | ... | - DUT2 - Node to add sub-interface.
+| | ... | - INT2 - Interface name on which create VLAN sub-interface.
+| | ... | - SUB_ID - ID of the sub-interface to be created.
+| | ...
+| | ... | _Set testcase variables with name and index of created interfaces:_
+| | ... | - subif_name_1
+| | ... | - subif_index_1
+| | ... | - subif_name_2
+| | ... | - subif_index_2
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Initialize VLAN dot1q sub-interfaces in 3-node circular topology \
+| | ... | \| ${nodes['DUT1']} \| ${dut1_if2} \| ${nodes['DUT2']} \
+| | ... | \| ${dut1_if2} \| 10 \|
+| | ...
+| | ${INT1_NAME}= | Get interface name | ${DUT1} | ${INT1}
+| | ${INT2_NAME}= | Get interface name | ${DUT2} | ${INT2}
+| | ${subif_name_1} | ${subif_index_1}= | Create Vlan Subinterface
+| | | ... | ${DUT1} | ${INT1_NAME} | ${SUB_ID}
+| | ${subif_name_2} | ${subif_index_2}= | Create Vlan Subinterface
+| | | ... | ${DUT2} | ${INT2_NAME} | ${SUB_ID}
+| | Set Interface State | ${DUT1} | ${subif_index_1} | up
+| | Set Interface State | ${DUT2} | ${subif_index_2} | up
+| | Set Test Variable | ${subif_name_1}
+| | Set Test Variable | ${subif_index_1}
+| | Set Test Variable | ${subif_name_2}
+| | Set Test Variable | ${subif_index_2}
+
+| Configure L2 tag rewrite method on interfaces
+| | [Arguments] | ${DUT1} | ${SUB_INT1} | ${DUT2} | ${SUB_INT2}
+| | ... | ${TAG_REWRITE_METHOD}
+| | [Documentation] | *Setup tag rewrite on sub-interfaces on DUTs.*
+| | ...
+| | ... | *Arguments:*
+| | ... | - DUT1 - Node to rewrite tags.
+| | ... | - SUB_INT1 - Interface on which rewrite tags.
+| | ... | - DUT2 - Node to rewrite tags.
+| | ... | - SUB_INT2 - Interface on which rewrite tags.
+| | ... | - TAG_REWRITE_METHOD - Method of tag rewrite.
+| | ...
+| | L2 Vlan tag rewrite | ${DUT1} | ${SUB_INT1} | ${TAG_REWRITE_METHOD}
+| | L2 Vlan tag rewrite | ${DUT2} | ${SUB_INT2} | ${TAG_REWRITE_METHOD}
+
+| Connect interfaces and VLAN sub-interfaces using L2XC
+| | [Arguments] | ${DUT1} | ${INT1} | ${SUB_INT1}
+| | ... | ${DUT2} | ${INT2} | ${SUB_INT2}
+| | [Documentation] | *Add interface and subinterface to bidirectional
+| | ... | L2-xconnect on DUTs.*
+| | ...
+| | ... | *Arguments:*
+| | ... | - DUT1 - Node to add bidirectional cross-connect.
+| | ... | - INT1 - Interface to add to the cross-connect.
+| | ... | - SUB_INT1 - Sub-interface to add to the cross-connect.
+| | ... | - DUT2 - Node to add bidirectional cross-connect.
+| | ... | - INT2 - Interface to add to the cross-connect.
+| | ... | - SUB_INT2 - Sub-interface to add to the cross-connect.
+| | ...
+| | Configure L2XC | ${DUT1} | ${INT1} | ${SUB_INT1}
+| | Configure L2XC | ${DUT2} | ${INT2} | ${SUB_INT2}
+
+| Create vlan sub-interface
+| | [Documentation] | Create VLAN sub-interface on DUT and set admin status up.
+| | ...
+| | ... | *Arguments:*
+| | ... | - dut_node - Node to add VLAN sub-intreface. Type: dictionary
+| | ... | - interface - Interface to create VLAN sub-interface. Type: string
+| | ... | - vlan_id - VLAN ID. Type: integer
+| | ...
+| | ... | *Return:*
+| | ... | - vlan_name - VLAN sub-interface name. Type: string
+| | ... | - vlan_index - VLAN sub-interface SW index. Type: integer
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Create vlan sub-interface \| ${nodes['DUT1']} \| port3 \| 100 \|
+| | ...
+| | [Arguments] | ${dut_node} | ${interface} | ${vlan_id}
+| | [Return] | ${vlan_name} | ${vlan_index}
+| | ${interface_name}= | Get interface name | ${dut_node} | ${interface}
+| | ${vlan_name} | ${vlan_index}= | Create Vlan Subinterface
+| | ... | ${dut_node} | ${interface_name} | ${vlan_id}
+| | Set Interface State | ${dut_node} | ${vlan_index} | up
+
+| Create tagged sub-interface
+| | [Documentation] | Create tagged sub-interface on DUT. Type of tagged \
+| | ... | sub-intreface depends on type_subif value:
+| | ... | - one_tag -> VLAN
+| | ... | - two_tags -> QinQ VLAN
+| | ... | - two_tags dot1ad - DOT1AD
+| | ...
+| | ... | *Arguments:*
+| | ... | - dut_node - Node to add VLAN sub-intreface. Type: dictionary
+| | ... | - interface - Interface to create tagged sub-interface. Type: string
+| | ... | - subif_id - Sub-interface ID. Type: integer
+| | ... | - outer_vlan_id - VLAN (outer) ID (Optional). Type: integer
+| | ... | - inner_vlan_id - VLAN inner ID (Optional). Type: integer
+| | ... | - type_subif - Sub-interface type (Optional). Type: string
+| | ...
+| | ... | *Return:*
+| | ... | - subif_name - Sub-interface name. Type: string
+| | ... | - subif_index - Sub-interface SW index. Type: integer
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Create tagged sub-interface \| ${nodes['DUT1']} \| port1 \| 10 \
+| | ... | \| outer_vlan_id=100 \| inner_vlan_id=200 \
+| | ... | \| type_subif=two_tags dot1ad \|
+| | ...
+| | [Arguments] | ${dut_node} | ${interface} | ${subif_id}
+| | ... | ${outer_vlan_id}=${None} | ${inner_vlan_id}=${None}
+| | ... | ${type_subif}=${None}
+| | [Return] | ${subif_name} | ${subif_index}
+| | ${interface_name}= | Get interface name | ${dut_node} | ${interface}
+| | ${subif_name} | ${subif_index}= | Create Subinterface
+| | ... | ${dut_node} | ${interface_name} | ${subif_id}
+| | ... | outer_vlan_id=${outer_vlan_id} | inner_vlan_id=${inner_vlan_id}
+| | ... | type_subif=${type_subif}
+
+| Configure L2 tag rewrite method on interface
+| | [Documentation] | Set L2 tag rewrite on (sub-)interface on DUT
+| | ...
+| | ... | *Arguments:*
+| | ... | - dut_node - Node to set L2 tag rewrite method. Type: dictionary
+| | ... | - interface - (Sub-)interface name or SW index to set L2 tag rewrite
+| | ... | method. Type: string or integer
+| | ... | - tag_rewrite_method - Tag rewrite method. Type: string
+| | ... | - push_dot1q - True to push tags as Dot1q, False to push tags as
+| | ... | Dot1ad (Optional). Type: boolean
+| | ... | - tag1_id - VLAN tag1 ID (Optional). Type: integer
+| | ... | - tag2_id - VLAN tag2 ID (Optional). Type: integer
+| | ...
+| | ... | *Return:*
+| | ...
+| | ... | - No value returned
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Configure L2 tag rewrite method on interface \| ${nodes['DUT1']} \
+| | ... | \| 9 \| pop-1 \|
+| | ... | \| Configure L2 tag rewrite method on interface \| ${nodes['DUT2']} \
+| | ... | \| 10 \| translate-1-2 \| push_dot1q=${False} \| tag1_id=10 \
+| | ... | \| tag1_id=20 \|
+| | ...
+| | [Arguments] | ${dut_node} | ${interface} | ${tag_rewrite_method}
+| | ... | ${push_dot1q}=${True} | ${tag1_id}=${None} | ${tag2_id}=${None}
+| | ${result}= | Evaluate | isinstance($interface, int)
+| | ${interface_name}= | Run Keyword If | ${result} | Set Variable | ${interface}
+| | ... | ELSE | Get interface name | ${dut_node} | ${interface}
+| | L2 Vlan Tag Rewrite | ${dut_node} | ${interface_name} | ${tag_rewrite_method}
+| | ... | push_dot1q=${push_dot1q} | tag1_id=${tag1_id} | tag2_id=${tag2_id}