TLDK udwfwd test case: 66/5966/26
authorQun Wan <qun.wan@intel.com>
Thu, 30 Mar 2017 18:36:56 +0000 (14:36 -0400)
committerPeter Mikus <pmikus@cisco.com>
Wed, 7 Jun 2017 05:24:57 +0000 (05:24 +0000)
    - ip fragement for ipv4
    - ip reassemble for ipv4
    - ip checksum for ipv4
    - ip checksum for ipv6
    - ip fragment for ipv6

    added the genpcap.py script to generate the pcap files and corresponding
    test scripts

Change-Id: I01329dbb0ecd3c3a5dd7a63ef1dea01b2e717da5
Signed-off-by: qun wan <qun.wan@intel.com>
25 files changed:
TLDK-tests/func/__init__.robot [new file with mode: 0644]
TLDK-tests/func/ipv4/ipv4_assemble.robot [new file with mode: 0644]
TLDK-tests/func/ipv4/ipv4_checksum.robot [new file with mode: 0644]
TLDK-tests/func/ipv4/ipv4_fragment.robot [new file with mode: 0644]
TLDK-tests/func/ipv6/ipv6_checksum.robot [new file with mode: 0644]
TLDK-tests/func/ipv6/ipv6_fragment.robot [new file with mode: 0644]
TLDK-tests/tldk_scripts/install_tldk.sh [new file with mode: 0755]
TLDK-tests/tldk_scripts/run_tldk.sh [new file with mode: 0755]
TLDK-tests/tldk_testconfig/test_ipv4_assemble_be.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv4_assemble_fe.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv4_checksum_be.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv4_checksum_fe.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv4_fragment_be.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv4_fragment_fe.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv6_checksum_be.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv6_checksum_fe.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv6_fragment_be.cfg [new file with mode: 0644]
TLDK-tests/tldk_testconfig/test_ipv6_fragment_fe.cfg [new file with mode: 0644]
docs/tag_documentation.rst
resources/libraries/python/TLDK/SetupTLDKTest.py [new file with mode: 0644]
resources/libraries/python/TLDK/TLDKConstants.py [new file with mode: 0644]
resources/libraries/python/TLDK/UdpTest.py [new file with mode: 0644]
resources/libraries/python/TLDK/__init__.py [new file with mode: 0644]
resources/libraries/python/TLDK/gen_pcap.py [new file with mode: 0644]
resources/libraries/robot/TLDK/TLDKUtils.robot [new file with mode: 0644]

diff --git a/TLDK-tests/func/__init__.robot b/TLDK-tests/func/__init__.robot
new file mode 100644 (file)
index 0000000..8f95c6c
--- /dev/null
@@ -0,0 +1,18 @@
+# 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/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
+| Library | resources.libraries.python.TLDK.SetupTLDKTest
+| Suite Setup | Setup TLDK Test | ${nodes}
diff --git a/TLDK-tests/func/ipv4/ipv4_assemble.robot b/TLDK-tests/func/ipv4/ipv4_assemble.robot
new file mode 100644 (file)
index 0000000..765e900
--- /dev/null
@@ -0,0 +1,46 @@
+# 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 ***
+| Library | resources.libraries.python.NodePath
+| Library | resources.libraries.python.Trace
+| Library | resources.libraries.python.TrafficScriptExecutor
+| Library | resources.libraries.python.TLDK.UdpTest
+| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
+| Resource | resources/libraries/robot/counters.robot
+| Resource | resources/libraries/robot/TLDK/TLDKUtils.robot
+| Force Tags | 3_NODE_SINGLE_LINK_TOPO | VM_ENV | FUNCTEST | TLDK
+| Documentation | *TLDK IPv4 assemble test suite.*
+| ...
+| ... | Test suite uses 3-node topology TG - DUT1 - DUT2 - TG with single link
+| ... | between nodes. From this topology only TG and DUT1 nodes are used.
+| ... | In VM environment, the DUT2 is not configured since the DUT1 is testing
+| ... | with the pcap file that generated with the pcap_gen.py. There is no 
+| ... | packet going out to DUT2, udpfwd app is verified on DUT1 only.
+| ... | This test case just use the pcap file for the UDP functional test.
+
+*** Variables ***
+| ${tc01_file_prefix}= | test_ipv4_assemble
+
+*** Test Cases ***
+| TC01: TLDK IPv4 assemble test case
+| | Given Path for 2-node testing is set | ${nodes['TG']} | ${nodes['DUT1']}
+| | And Pick out the port used to execute test
+| | And Get the pcap data | ${tc01_file_prefix}
+| | When Exec the udpfwd test | ${dut_node} | ${dut_port}
+| | ... | ${tc01_file_prefix} | ${dest_ip} | ${is_ipv4}
+| | ${pkt_count}= | Get the test result | ${dut_node}
+| | ... | ${tc01_file_prefix}
+| | ${result}= | Convert To Integer | ${pkt_count}
+| | Then Should Be Equal As Integers | ${result} | 1
diff --git a/TLDK-tests/func/ipv4/ipv4_checksum.robot b/TLDK-tests/func/ipv4/ipv4_checksum.robot
new file mode 100644 (file)
index 0000000..9e7dd97
--- /dev/null
@@ -0,0 +1,43 @@
+# 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 ***
+| Library | resources.libraries.python.NodePath
+| Library | resources.libraries.python.Trace
+| Library | resources.libraries.python.TrafficScriptExecutor
+| Library | resources.libraries.python.TLDK.UdpTest
+| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
+| Resource | resources/libraries/robot/counters.robot
+| Resource | resources/libraries/robot/TLDK/TLDKUtils.robot
+| Force Tags | 3_NODE_SINGLE_LINK_TOPO | VM_ENV | FUNCTEST | TLDK
+| Documentation | *TLDK IPv4 checksum test suite.*
+| ...
+| ... | Test suite uses 3-node topology TG - DUT1 - DUT2 - TG with single link
+| ... | between nodes. From this topology only TG and DUT1 nodes are used.
+| ... | This test case just use the pcap file for the UDP functional test.
+
+*** Variables ***
+| ${tc01_file_prefix}= | test_ipv4_checksum
+
+*** Test Cases ***
+| TC01: TLDK IPv4 checksum test case
+| | Given Path for 2-node testing is set | ${nodes['TG']} | ${nodes['DUT1']}
+| | And Pick out the port used to execute test
+| | And Get the pcap data | ${tc01_file_prefix}
+| | When Exec the udpfwd test | ${dut_node} | ${dut_port}
+| | ... | ${tc01_file_prefix} | ${dest_ip} | ${is_ipv4}
+| | ${checksum}= | Get the test result | ${dut_node}
+| | ... | ${tc01_file_prefix}
+| | ${result}= | Convert To Integer | ${checksum}
+| | Then Should Be Equal As Integers | ${result} | ${packet_num}
diff --git a/TLDK-tests/func/ipv4/ipv4_fragment.robot b/TLDK-tests/func/ipv4/ipv4_fragment.robot
new file mode 100644 (file)
index 0000000..b060eec
--- /dev/null
@@ -0,0 +1,43 @@
+# 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 ***
+| Library | resources.libraries.python.NodePath
+| Library | resources.libraries.python.Trace
+| Library | resources.libraries.python.TrafficScriptExecutor
+| Library | resources.libraries.python.TLDK.UdpTest
+| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
+| Resource | resources/libraries/robot/counters.robot
+| Resource | resources/libraries/robot/TLDK/TLDKUtils.robot
+| Force Tags | 3_NODE_SINGLE_LINK_TOPO | VM_ENV | FUNCTEST | TLDK
+| Documentation | *TLDK IPv4 fragment test suite.*
+| ...
+| ... | Test suite uses 3-node topology TG - DUT1 - DUT2 - TG with single link
+| ... | between nodes. From this topology only TG and DUT1 nodes are used.
+| ... | This test case just use the pcap file for the UDP functional test.
+
+*** Variables ***
+| ${tc01_file_prefix}= | test_ipv4_fragment
+
+*** Test Cases ***
+| TC01: TLDK IPv4 fragment test case
+| | Given Path for 2-node testing is set | ${nodes['TG']} | ${nodes['DUT1']}
+| | And Pick out the port used to execute test
+| | And Get the pcap data | ${tc01_file_prefix}
+| | When Exec the udpfwd test | ${dut_node} | ${dut_port}
+| | ... | ${tc01_file_prefix} | ${dest_ip} | ${is_ipv4}
+| | ${checksum}= | Get the test result | ${dut_node}
+| | ... | ${tc01_file_prefix}
+| | ${result}= | Convert To Integer | ${checksum}
+| | Then Should Be Equal As Integers | ${result} | 990
diff --git a/TLDK-tests/func/ipv6/ipv6_checksum.robot b/TLDK-tests/func/ipv6/ipv6_checksum.robot
new file mode 100644 (file)
index 0000000..ac05d3c
--- /dev/null
@@ -0,0 +1,43 @@
+# 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.NodePath
+| Library | resources.libraries.python.Trace
+| Library | resources.libraries.python.TrafficScriptExecutor
+| Library | resources.libraries.python.TLDK.UdpTest
+| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
+| Resource | resources/libraries/robot/counters.robot
+| Resource | resources/libraries/robot/TLDK/TLDKUtils.robot
+| Force Tags | 3_NODE_SINGLE_LINK_TOPO | VM_ENV | FUNCTEST | TLDK
+| Documentation | *TLDK IPv6 checksum test suit.*
+| ...
+| ... | Test suite uses 3-node topology TG - DUT1 - DUT2 - TG with single link
+| ... | between nodes. From this topology only TG and DUT1 nodes are used.
+| ... | This test case just use the pcap file for the UDP functional test.
+
+*** Variables ***
+| ${tc01_file_prefix}= | test_ipv6_checksum
+
+*** Test Cases ***
+| TC01: TLDK IPv6 checksum test case
+| | Given Path for 2-node testing is set | ${nodes['TG']} | ${nodes['DUT1']}
+| | And Pick out the port used to execute test
+| | And Get the pcap data | ${tc01_file_prefix}
+| | When Exec the udpfwd test | ${dut_node} | ${dut_port}
+| | ... | ${tc01_file_prefix} | ${dest_ip} | ${is_ipv4}
+| | ${pkt_count}= | Get the test result | ${dut_node}
+| | ... | ${tc01_file_prefix}
+| | ${result}= | Convert To Integer | ${pkt_count}
+| | Then Should Be Equal As Integers | ${result} | ${packet_num}
diff --git a/TLDK-tests/func/ipv6/ipv6_fragment.robot b/TLDK-tests/func/ipv6/ipv6_fragment.robot
new file mode 100644 (file)
index 0000000..ef9610b
--- /dev/null
@@ -0,0 +1,43 @@
+# 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 ***
+| Library | resources.libraries.python.NodePath
+| Library | resources.libraries.python.Trace
+| Library | resources.libraries.python.TrafficScriptExecutor
+| Library | resources.libraries.python.TLDK.UdpTest
+| Resource | resources/libraries/robot/default.robot
+| Resource | resources/libraries/robot/interfaces.robot
+| Resource | resources/libraries/robot/counters.robot
+| Resource | resources/libraries/robot/TLDK/TLDKUtils.robot
+| Force Tags | 3_NODE_SINGLE_LINK_TOPO | VM_ENV | FUNCTEST | TLDK
+| Documentation | *TLDK IPv6 fragment test suite.*
+| ...
+| ... | Test suite uses 3-node topology TG - DUT1 - DUT2 - TG with single link
+| ... | between nodes. From this topology only TG and DUT1 nodes are used.
+| ... | This test case just use the pcap file for the UDP functional test.
+
+*** Variables ***
+| ${tc01_file_prefix}= | test_ipv6_fragment
+
+*** Test Cases ***
+| TC01: TLDK IPv6 fragment test case
+| | Given Path for 2-node testing is set | ${nodes['TG']} | ${nodes['DUT1']}
+| | And Pick out the port used to execute test
+| | And Get the pcap data | ${tc01_file_prefix}
+| | When Exec the udpfwd test | ${dut_node} | ${dut_port}
+| | ... | ${tc01_file_prefix} | ${dest_ip} | ${is_ipv4}
+| | ${pkt_count}= | Get the test result | ${dut_node}
+| | ... | ${tc01_file_prefix}
+| | ${result}= | Convert To Integer | ${pkt_count}
+| | Then Should Be Equal As Integers | ${result} | ${970}
diff --git a/TLDK-tests/tldk_scripts/install_tldk.sh b/TLDK-tests/tldk_scripts/install_tldk.sh
new file mode 100755 (executable)
index 0000000..8941cfc
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+DPDK_VERSION=dpdk
+
+ROOTDIR=/tmp/TLDK-testing
+PWDDIR=$(pwd)
+DPDK_DIR=dpdk
+
+# compile and install the DPDK
+cd ${ROOTDIR}
+tar xvf dpdk-16.11.1.tar.xz
+mv dpdk-stable-16.11.1 dpdk
+echo $PWD
+echo ${DPDK_PACKAGE}
+cd ./${DPDK_DIR}
+sed -i 's/^CONFIG_RTE_LIBRTE_PMD_PCAP=n/CONFIG_RTE_LIBRTE_PMD_PCAP=y/g' ./config/common_base
+make install T=x86_64-native-linuxapp-gcc
+cd ${PWDDIR}
+
+# compile the TLDK
+export RTE_SDK=${ROOTDIR}/${DPDK_DIR}/
+export RTE_TARGET=x86_64-native-linuxapp-gcc
+cd ${ROOTDIR}/tldk
+make all
+cd ${PWDDIR}
+
+sudo killall -9 udpfwd 2>/dev/null
+
+pid=`pgrep udpfwd`
+if [ "$pid" != "" ]; then
+    echo "terminate the udpfwd failed!"
+    exit 1
+fi
+
+# check and setup the hugepages
+SYS_HUGEPAGE=$(cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages)
+if [ ${SYS_HUGEPAGE} -lt 1024 ]; then
+    MOUNT=$(mount | grep /mnt/huge)
+    while [ "${MOUNT}" != "" ]
+    do
+        sudo umount /mnt/huge
+        sleep 1
+        MOUNT=$(mount | grep /mnt/huge)
+    done
+
+    echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
+    echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
+
+    sudo mkdir -p /mnt/huge
+    sudo mount -t hugetlbfs nodev /mnt/huge/
+    test $? -eq 0 || exit 1
+fi
diff --git a/TLDK-tests/tldk_scripts/run_tldk.sh b/TLDK-tests/tldk_scripts/run_tldk.sh
new file mode 100755 (executable)
index 0000000..747f549
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+ROOTDIR=/tmp/TLDK-testing
+PWDDIR=$(pwd)
+
+rx_file=$1
+tx_file=$2
+nic_pci=$3
+fe_cfg=$4
+be_cfg=$5
+IPv4_addr=$6
+IPv6_addr=$7
+
+echo $IPv4_addr
+
+#kill the l4fwd
+sudo killall -9 l4fwd 2>/dev/null
+
+sleep 2
+
+pid=`pgrep l4fwd`
+if [ "$pid" != "" ]; then
+    echo "terminate the l4fwd failed!"
+    exit 1
+fi
+
+#mount the hugepages again
+sudo umount /mnt/huge
+sudo mount -t hugetlbfs nodev /mnt/huge/
+test $? -eq 0 || exit 1
+
+sleep 2
+
+#run the l4fwd with tag U
+# need to install libpcap, libpcap-dev to use --vdev
+cd ${ROOTDIR}
+if [ "$IPv6_addr" == "NONE" ]; then
+sudo sh -c "nohup ./tldk/x86_64-native-linuxapp-gcc/app/l4fwd --lcore='0' \
+    -n 2 --vdev 'eth_pcap1,rx_pcap=${rx_file},tx_pcap=${tx_file}' \
+    -b ${nic_pci} -- -P -U -R 0x1000 -S 0x1000 -s 0x20 -f ${fe_cfg} -b ${be_cfg} \
+    port=0,lcore=0,rx_offload=0,tx_offload=0,ipv4=${IPv4_addr} &"
+elif [ "$IPv4_addr" == "NONE" ]; then
+sudo sh -c "nohup ./tldk/x86_64-native-linuxapp-gcc/app/l4fwd --lcore='0' \
+    -n 2 --vdev 'eth_pcap1,rx_pcap=${rx_file},tx_pcap=${tx_file}' \
+    -b ${nic_pci} -- -P -U -R 0x1000 -S 0x1000 -s 0x20 -f ${fe_cfg} -b ${be_cfg} \
+    port=0,lcore=0,rx_offload=0,tx_offload=0,ipv6=${IPv6_addr} &"
+fi
+
+cd ${PWDDIR}
+
+sleep 10
diff --git a/TLDK-tests/tldk_testconfig/test_ipv4_assemble_be.cfg b/TLDK-tests/tldk_testconfig/test_ipv4_assemble_be.cfg
new file mode 100644 (file)
index 0000000..7f7cb8e
--- /dev/null
@@ -0,0 +1 @@
+port=0,masklen=24,addr=192.168.1.56,mac=68:05:ca:27:d1:6a
diff --git a/TLDK-tests/tldk_testconfig/test_ipv4_assemble_fe.cfg b/TLDK-tests/tldk_testconfig/test_ipv4_assemble_fe.cfg
new file mode 100644 (file)
index 0000000..f3531e0
--- /dev/null
@@ -0,0 +1,2 @@
+#udpfwd config file
+lcore=0,op=echo,laddr=0.0.0.0,lport=0x8000,raddr=0.0.0.0,rport=0
diff --git a/TLDK-tests/tldk_testconfig/test_ipv4_checksum_be.cfg b/TLDK-tests/tldk_testconfig/test_ipv4_checksum_be.cfg
new file mode 100644 (file)
index 0000000..c4e39e0
--- /dev/null
@@ -0,0 +1,2 @@
+port=0,masklen=24,addr=192.168.1.56,mac=68:05:ca:27:d1:6a
+port=0,addr=2001:4860:b002::56,masklen=64,mac=68:05:ca:27:d1:6a
diff --git a/TLDK-tests/tldk_testconfig/test_ipv4_checksum_fe.cfg b/TLDK-tests/tldk_testconfig/test_ipv4_checksum_fe.cfg
new file mode 100644 (file)
index 0000000..a8cd61b
--- /dev/null
@@ -0,0 +1,3 @@
+#udpfwd config file\r
+lcore=0,op=echo,laddr=0.0.0.0,lport=0x8000,raddr=0.0.0.0,rport=0\r
+lcore=0,op=echo,laddr=::,lport=0x8000,raddr=::,rport=0\r
diff --git a/TLDK-tests/tldk_testconfig/test_ipv4_fragment_be.cfg b/TLDK-tests/tldk_testconfig/test_ipv4_fragment_be.cfg
new file mode 100644 (file)
index 0000000..e769994
--- /dev/null
@@ -0,0 +1,2 @@
+port=0,masklen=24,addr=192.168.1.56,mac=68:05:ca:27:d1:6a,mtu=1024
+port=0,addr=2001:4860:b002::56,masklen=64,mac=68:05:ca:27:d1:6a,mtu=1024
diff --git a/TLDK-tests/tldk_testconfig/test_ipv4_fragment_fe.cfg b/TLDK-tests/tldk_testconfig/test_ipv4_fragment_fe.cfg
new file mode 100644 (file)
index 0000000..a8cd61b
--- /dev/null
@@ -0,0 +1,3 @@
+#udpfwd config file\r
+lcore=0,op=echo,laddr=0.0.0.0,lport=0x8000,raddr=0.0.0.0,rport=0\r
+lcore=0,op=echo,laddr=::,lport=0x8000,raddr=::,rport=0\r
diff --git a/TLDK-tests/tldk_testconfig/test_ipv6_checksum_be.cfg b/TLDK-tests/tldk_testconfig/test_ipv6_checksum_be.cfg
new file mode 100644 (file)
index 0000000..c4e39e0
--- /dev/null
@@ -0,0 +1,2 @@
+port=0,masklen=24,addr=192.168.1.56,mac=68:05:ca:27:d1:6a
+port=0,addr=2001:4860:b002::56,masklen=64,mac=68:05:ca:27:d1:6a
diff --git a/TLDK-tests/tldk_testconfig/test_ipv6_checksum_fe.cfg b/TLDK-tests/tldk_testconfig/test_ipv6_checksum_fe.cfg
new file mode 100644 (file)
index 0000000..9553b70
--- /dev/null
@@ -0,0 +1,3 @@
+#udpfwd config file
+lcore=0,op=echo,laddr=0.0.0.0,lport=0x8000,raddr=0.0.0.0,rport=0
+lcore=0,op=echo,laddr=::,lport=0x8000,raddr=::,rport=0
diff --git a/TLDK-tests/tldk_testconfig/test_ipv6_fragment_be.cfg b/TLDK-tests/tldk_testconfig/test_ipv6_fragment_be.cfg
new file mode 100644 (file)
index 0000000..e769994
--- /dev/null
@@ -0,0 +1,2 @@
+port=0,masklen=24,addr=192.168.1.56,mac=68:05:ca:27:d1:6a,mtu=1024
+port=0,addr=2001:4860:b002::56,masklen=64,mac=68:05:ca:27:d1:6a,mtu=1024
diff --git a/TLDK-tests/tldk_testconfig/test_ipv6_fragment_fe.cfg b/TLDK-tests/tldk_testconfig/test_ipv6_fragment_fe.cfg
new file mode 100644 (file)
index 0000000..9553b70
--- /dev/null
@@ -0,0 +1,3 @@
+#udpfwd config file
+lcore=0,op=echo,laddr=0.0.0.0,lport=0x8000,raddr=0.0.0.0,rport=0
+lcore=0,op=echo,laddr=::,lport=0x8000,raddr=::,rport=0
index 79b9f81..7c6cc47 100644 (file)
@@ -220,6 +220,10 @@ Test type tags
 
     At least one feature is configured in test cases. Use also feature tag(s).
 
+.. topic:: TLDK
+    
+    Functional test cases for TLDK.
+
 
 Forwarding mode tags
 --------------------
diff --git a/resources/libraries/python/TLDK/SetupTLDKTest.py b/resources/libraries/python/TLDK/SetupTLDKTest.py
new file mode 100644 (file)
index 0000000..3e3511c
--- /dev/null
@@ -0,0 +1,239 @@
+# 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.
+
+"""This module exists to provide setup utilities for the framework on topology
+nodes. All tasks required to be run before the actual tests are started is
+supposed to end up here.
+"""
+
+from shlex import split
+from subprocess import Popen, PIPE, call
+from multiprocessing import Pool
+from tempfile import NamedTemporaryFile
+from os.path import basename
+import os
+
+from robot.api import logger
+from robot.libraries.BuiltIn import BuiltIn
+
+from resources.libraries.python.ssh import SSH
+from resources.libraries.python.TLDK.TLDKConstants import TLDKConstants as con
+from resources.libraries.python.topology import NodeType
+from resources.libraries.python.TLDK.gen_pcap import gen_all_pcap
+
+__all__ = ["SetupTLDKTest"]
+
+
+def pack_framework_dir():
+    """Pack the testing WS into temp file, return its name.
+    :returns: file_name
+    :rtype: str
+    :raises RuntimeError: If pack the testing framework failed.
+    """
+    # Remove the TLDK and DPDK dir existted.
+    os.system("rm -rf tldk")
+    os.system("rm -rf dpdk")
+    os.system("rm -f dpdk-16.11.1.tar.xz")
+
+    # Get the latest TLDK and dpdk code.
+    os.system("git clone https://gerrit.fd.io/r/tldk")
+    os.system("wget http://fast.dpdk.org/rel/dpdk-16.11.1.tar.xz")
+
+    # Generate pcap file used to execute test case.
+    gen_all_pcap()
+
+    tmpfile = NamedTemporaryFile(suffix=".tgz", prefix="TLDK-testing-")
+    file_name = tmpfile.name
+    tmpfile.close()
+
+    proc = Popen(
+        split("tar --exclude-vcs -zcf {0} .".format(file_name)),
+        stdout=PIPE, stderr=PIPE)
+    (stdout, stderr) = proc.communicate()
+
+    logger.debug(stdout)
+    logger.debug(stderr)
+
+    return_code = proc.wait()
+    if return_code != 0:
+        raise RuntimeError("Could not pack testing framework.")
+
+    return file_name
+
+
+def copy_tarball_to_node(tarball, node):
+    """Copy tarball file from local host to remote node.
+
+    :param tarball: Path to tarball to upload.
+    :param node: Dictionary created from topology.
+    :type tarball: str
+    :type node: dict
+    :returns: nothing.
+    """
+    logger.console('Copying tarball to {0}'.format(node['host']))
+    ssh = SSH()
+    ssh.connect(node)
+
+    ssh.scp(tarball, "/tmp/")
+
+
+def extract_tarball_at_node(tarball, node):
+    """Extract tarball at given node.
+
+    Extracts tarball using tar on given node to specific CSIT location.
+    Raise runtime errors when failed.
+
+    :param tarball: Path to tarball to upload.
+    :param node: Dictionary created from topology.
+    :type tarball: str
+    :type node: dict
+    :return: nothing
+    :raises RuntimeError: If extract tarball failed.
+    """
+    logger.console('Extracting tarball to {0} on {1}'.format(
+        con.REMOTE_FW_DIR, node['host']))
+    ssh = SSH()
+    ssh.connect(node)
+
+    cmd = 'sudo rm -rf {1}; mkdir {1} ; tar -zxf {0} -C {1}; ' \
+        'rm -f {0}'.format(tarball, con.REMOTE_FW_DIR)
+    (ret_code, _, stderr) = ssh.exec_command(cmd, timeout=30)
+    if ret_code != 0:
+        logger.error('Unpack error: {0}'.format(stderr))
+        raise RuntimeError('Failed to unpack {0} at node {1}'.format(
+            tarball, node['host']))
+
+
+def create_env_directory_at_node(node):
+    """
+    Create fresh virtualenv to a directory, install pip requirements.
+
+    :param node: Dictionary created from topology, will only install in the TG.
+    :type node: dict
+    :returns: nothing
+    :raises RuntimeError: If the setup of virtualenv failed.
+    """
+    logger.console('Extracting virtualenv, installing requirements.txt '
+                   'on {0}'.format(node['host']))
+    ssh = SSH()
+    ssh.connect(node)
+    (ret_code, stdout, stderr) = ssh.exec_command(
+        'cd {0} && rm -rf env && '
+        '. virtualenv --system-site-packages --never-download env && '
+        '. env/bin/activate && pip install -r requirements.txt'
+        .format(con.REMOTE_FW_DIR), timeout=100)
+    if ret_code != 0:
+        logger.error('Virtualenv creation error: {0}'.format(stdout + stderr))
+        raise RuntimeError('Virtualenv setup failed')
+    else:
+        logger.console('Virtualenv created on {0}'.format(node['host']))
+
+def install_tldk_test(node):
+    """Prepare the TLDK test envrionment.
+    Raise errors when failed.
+
+    :param node: Dictionary created from topology.
+    :type node: dict
+    :returns: nothing.
+    :raises RuntimeError: If install tldk failed.
+    """
+    logger.console('Install the TLDK on {0}'.format(node['host']))
+
+    ssh = SSH()
+    ssh.connect(node)
+
+    (ret_code, _, stderr) = ssh.exec_command(
+        'cd {0}/{1} && ./install_tldk.sh'
+        .format(con.REMOTE_FW_DIR, con.TLDK_SCRIPTS), timeout=600)
+
+    if ret_code != 0:
+        logger.error('Install the TLDK error: {0}'.format(stderr))
+        raise RuntimeError('Install the TLDK failed')
+    else:
+        logger.console('Install the TLDK on {0} success!'.format(node['host']))
+
+def setup_node(args):
+    """Run all set-up methods for a node.
+
+    This method is used as map_async parameter. It receives tuple with all
+    parameters as passed to map_async function.
+
+    :param args: All parameters needed to setup one node.
+    :type args: tuple
+    :returns: True - success, False - error
+    :rtype: bool
+    :raises RuntimeError: If node setup failed.
+    """
+    tarball, remote_tarball, node = args
+    try:
+        copy_tarball_to_node(tarball, node)
+        extract_tarball_at_node(remote_tarball, node)
+        if node['type'] == NodeType.DUT:
+            install_tldk_test(node)
+        if node['type'] == NodeType.TG:
+            create_env_directory_at_node(node)
+    except RuntimeError as exc:
+        logger.error("Node setup failed, error:'{0}'".format(exc.message))
+        return False
+    else:
+        logger.console('Setup of node {0} done'.format(node['host']))
+        return True
+
+def delete_local_tarball(tarball):
+    """Delete local tarball to prevent disk pollution.
+
+    :param tarball: Path to tarball to upload.
+    :type tarball: str
+    :returns: nothing.
+    """
+    call(split('sh -c "rm {0} > /dev/null 2>&1"'.format(tarball)))
+
+
+class SetupTLDKTest(object):
+    """Setup suite run on topology nodes.
+
+    Many VAT/CLI based tests need the scripts at remote hosts before executing
+    them. This class packs the whole testing directory and copies it over
+    to all nodes in topology under /tmp/
+    """
+
+    @staticmethod
+    def setup_tldk_test(nodes):
+        """Pack the whole directory and extract in temp on each node."""
+
+        tarball = pack_framework_dir()
+        msg = 'Framework packed to {0}'.format(tarball)
+        logger.console(msg)
+        logger.trace(msg)
+        remote_tarball = "/tmp/{0}".format(basename(tarball))
+
+        # Turn off logging since we use multiprocessing.
+        log_level = BuiltIn().set_log_level('NONE')
+        params = ((tarball, remote_tarball, node) for node in nodes.values())
+        pool = Pool(processes=len(nodes))
+        result = pool.map_async(setup_node, params)
+        pool.close()
+        pool.join()
+
+        # Turn on logging.
+        BuiltIn().set_log_level(log_level)
+
+        logger.info(
+            'Executed node setups in parallel, waiting for processes to end')
+        result.wait()
+
+        logger.info('Results: {0}'.format(result.get()))
+
+        logger.trace('Test framework copied to all topology nodes')
+        delete_local_tarball(tarball)
+        logger.console('All nodes are ready')
diff --git a/resources/libraries/python/TLDK/TLDKConstants.py b/resources/libraries/python/TLDK/TLDKConstants.py
new file mode 100644 (file)
index 0000000..af9ebf2
--- /dev/null
@@ -0,0 +1,31 @@
+# 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.
+
+
+"""This file defines the constants variables for the TLDK test."""
+
+
+class TLDKConstants(object):
+    """Define the directory path for the TLDK test."""
+
+    # TLDK testing directory location at topology nodes
+    REMOTE_FW_DIR = '/tmp/TLDK-testing'
+
+    # Shell scripts location
+    TLDK_SCRIPTS = 'TLDK-tests/tldk_scripts'
+
+    # Libraries location
+    TLDK_DEPLIBS = 'TLDK-tests/tldk_deplibs'
+
+    # Config files location for the TLDK test
+    TLDK_TESTCONFIG = 'TLDK-tests/tldk_testconfig'
diff --git a/resources/libraries/python/TLDK/UdpTest.py b/resources/libraries/python/TLDK/UdpTest.py
new file mode 100644 (file)
index 0000000..adf0888
--- /dev/null
@@ -0,0 +1,126 @@
+# Copyright (c) 2017 Cisco and/or its affiliates.\r
+# Licensed under the Apache License, Version 2.0 (the "License");\r
+# you may not use this file except in compliance with the License.\r
+# You may obtain a copy of the License at:\r
+#\r
+#     http://www.apache.org/licenses/LICENSE-2.0\r
+#\r
+# Unless required by applicable law or agreed to in writing, software\r
+# distributed under the License is distributed on an "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+# See the License for the specific language governing permissions and\r
+# limitations under the License.\r
+\r
+\r
+"""\r
+This module exists to provide the UDP test for TLDK on topology nodes.\r
+"""\r
+\r
+from scapy.utils import rdpcap\r
+from scapy.layers.inet import IP\r
+from scapy.layers.inet6 import IPv6\r
+\r
+from robot.libraries.BuiltIn import BuiltIn\r
+\r
+from resources.libraries.python.ssh import SSH\r
+from resources.libraries.python.TLDK.TLDKConstants import TLDKConstants as con\r
+from resources.libraries.python.topology import Topology\r
+\r
+class UdpTest(object):\r
+    """Test the TLDK UDP function."""\r
+\r
+    @staticmethod\r
+    def get_pcap_info(file_prefix):\r
+        """Get the Dest IP from the RX pcap file\r
+\r
+        :param file_prefix: the test case pcap file prefix\r
+        :type file_prefix: str\r
+        :returns: packet counts, dest ip, is or not ipv4\r
+        :rtype: tuple(int, str, bool).\r
+        """\r
+        exec_dir = BuiltIn().get_variable_value("${EXECDIR}")\r
+\r
+        rx_pcapfile = '{0}/{1}/{2}_rx.pcap' \\r
+            .format(exec_dir, con.TLDK_TESTCONFIG, file_prefix)\r
+        packets = rdpcap(rx_pcapfile)\r
+        count = len(packets)\r
+\r
+        ### the first packet\r
+        pkt = packets[0]\r
+        if pkt.type == 0x0800:\r
+            ### this is a IPv4 packet\r
+            dest_ip = pkt[IP].dst\r
+            is_ipv4 = True\r
+        elif pkt.type == 0x86dd:\r
+            ### this is a IPv6 packet\r
+            dest_ip = pkt[IPv6].dst\r
+            is_ipv4 = False\r
+\r
+        return count, dest_ip, is_ipv4\r
+\r
+    @staticmethod\r
+    def exec_the_udpfwd_test(dut_node, dut_if, file_prefix, \\r
+            dest_ip, is_ipv4=True):\r
+        """Execute the udpfwd on the dut_node.\r
+\r
+        :param dut_node: Will execute the udpfwd on this node.\r
+        :param dut_if: DUT interface name.\r
+        :param file_prefix: The test case config file prefix.\r
+        :param dest_ip: The UDP packet dest IP.\r
+        :param is_ipv4: Execute the IPv4 or IPv6 test.\r
+        :type dut_node: dict\r
+        :type dut_if: str\r
+        :type file_prefix: str\r
+        :type dest_ip: str\r
+        :type is_ipv4: bool\r
+        :returns: none.\r
+        :raises RuntimeError: If failed to execute udpfwd test on the dut node.\r
+        """\r
+        pci_address = Topology.get_interface_pci_addr(dut_node, dut_if)\r
+        ssh = SSH()\r
+        ssh.connect(dut_node)\r
+        if is_ipv4:\r
+            cmd = 'cd {0}/{4} && ./run_tldk.sh {0}/{5}/{2}_rx.pcap ' \\r
+                '{0}/{5}/{2}_tx.pcap {1} {0}/{5}/{2}_fe.cfg ' \\r
+                '{0}/{5}/{2}_be.cfg {3} NONE' \\r
+                .format(con.REMOTE_FW_DIR, pci_address, file_prefix, \\r
+                dest_ip, con.TLDK_SCRIPTS, con.TLDK_TESTCONFIG)\r
+        else:\r
+            cmd = 'cd {0}/{4} && ./run_tldk.sh {0}/{5}/{2}_rx.pcap ' \\r
+                '{0}/{5}/{2}_tx.pcap {1} {0}/{5}/{2}_fe.cfg ' \\r
+                '{0}/{5}/{2}_be.cfg NONE {3}' \\r
+                .format(con.REMOTE_FW_DIR, pci_address, file_prefix, \\r
+                dest_ip, con.TLDK_SCRIPTS, con.TLDK_TESTCONFIG)\r
+\r
+        (ret_code, _, _) = ssh.exec_command(cmd, timeout=600)\r
+        if ret_code != 0:\r
+            raise RuntimeError('Failed to execute udpfwd test at node {0}'\r
+                               .format(dut_node['host']))\r
+\r
+    @staticmethod\r
+    def get_the_test_result(dut_node, file_prefix):\r
+        """\r
+        After execute the udpfwd cmd, use this to get the test result.\r
+\r
+        :param dut_node: will get the test result in this dut node\r
+        :param dut_if: the dut interface name\r
+        :param file_prefix: the test case output file prefix\r
+        :type dut_node: dice\r
+        :type dut_if: str\r
+        :type file_prefix: str\r
+        :returns: str.\r
+        :rtype: str\r
+        :raises RuntimeError: If failed to get the test result.\r
+        """\r
+        ssh = SSH()\r
+        ssh.connect(dut_node)\r
+        cmd = 'cd {0}; tcpdump -nnnn -vvv -r ./{2}/{1}_tx.pcap | ' \\r
+            'grep \'udp sum ok\' | wc -l' \\r
+            .format(con.REMOTE_FW_DIR, file_prefix, con.TLDK_TESTCONFIG)\r
+\r
+        (ret_code, stdout, _) = ssh.exec_command(cmd, timeout=100)\r
+        if ret_code != 0:\r
+            raise RuntimeError('Failed to get test result at node {0}'\r
+                               .format(dut_node['host']))\r
+\r
+        return stdout\r
diff --git a/resources/libraries/python/TLDK/__init__.py b/resources/libraries/python/TLDK/__init__.py
new file mode 100644 (file)
index 0000000..9cb1aee
--- /dev/null
@@ -0,0 +1,16 @@
+# 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.
+
+"""
+__init__ file for directory resources/libraries/python/TLDK
+"""
diff --git a/resources/libraries/python/TLDK/gen_pcap.py b/resources/libraries/python/TLDK/gen_pcap.py
new file mode 100644 (file)
index 0000000..bd9d2b1
--- /dev/null
@@ -0,0 +1,100 @@
+#! /usr/bin/python
+# 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.
+
+"""
+This module is used to generate pcap file used to execute UDP test cases.
+"""
+
+from scapy.layers.inet import Ether, IP, UDP, fragment
+from scapy.layers.inet6 import IPv6
+from scapy.utils import PcapWriter
+from resources.libraries.python.TLDK.TLDKConstants import TLDKConstants as con
+
+def create_packet(psz, is_ipv6, frag_size=None):
+    """Create a packet to use scapy send to DUT."""
+    if is_ipv6 != True:
+        packet = Ether()/IP()/UDP()/("X" * psz)
+        packet[IP].src = "192.168.1.56"
+        packet[IP].dst = "192.168.1.233"
+    else:
+        packet = Ether()/IPv6()/UDP()/("X" * psz)
+        packet[IPv6].src = "2001:4860:b002::56"
+        packet[IPv6].dst = "2001:4860:b002::28"
+    packet[Ether].src = "DE:AD:BE:EF:02:01"
+    packet[Ether].dst = "DE:AD:BE:EF:01:02"
+    packet[UDP].sport = 1111
+    packet[UDP].dport = 32768
+    if frag_size != None:
+        packet = fragment(packet, fragsize=frag_size)
+    return packet
+
+def gen_ipv4_checksum_pcap():
+    """Generate ipv4 checksum test case input pcap file."""
+    writer = PcapWriter(con.TLDK_TESTCONFIG + "/test_ipv4_checksum_rx.pcap",
+                        append=False)
+    for i in range(1, 1474):
+        packets = create_packet(i, False)
+        for packet in packets:
+            writer.write(packet)
+    writer.close()
+
+def gen_ipv6_checksum_pcap():
+    """Generate ipv6 checksum test case input pcap file."""
+    writer = PcapWriter(con.TLDK_TESTCONFIG + "/test_ipv6_checksum_rx.pcap",
+                        append=False)
+    for i in range(1, 1454):
+        packets = create_packet(i, True)
+        for packet in packets:
+            writer.write(packet)
+    writer.close()
+
+def gen_ipv4_fragment_pcap():
+    """Generate ipv4 fragment test case input pcap file."""
+    writer = PcapWriter(con.TLDK_TESTCONFIG + "/test_ipv4_fragment_rx.pcap",
+                        append=False)
+    for i in range(1, 1474):
+        packets = create_packet(i, False)
+        for packet in packets:
+            writer.write(packet)
+    writer.close()
+
+def gen_ipv6_fragment_pcap():
+    """Generate ipv6 fragment test case input pcap file."""
+    writer = PcapWriter(con.TLDK_TESTCONFIG + "/test_ipv6_fragment_rx.pcap",
+                        append=False)
+    for i in range(1, 1454):
+        packets = create_packet(i, True)
+        for packet in packets:
+            writer.write(packet)
+    writer.close()
+
+def gen_ipv4_assemble_pcap():
+    """Generate ipv4 assemble test case input pcap file."""
+    writer = PcapWriter(con.TLDK_TESTCONFIG + "/test_ipv4_assemble_rx.pcap",
+                        append=False)
+    packets = create_packet(1066, False, 1024)
+    for packet in packets:
+        writer.write(packet)
+    writer.close()
+
+def gen_all_pcap():
+    """Generate all test cases input pcap file."""
+    gen_ipv4_checksum_pcap()
+    gen_ipv6_checksum_pcap()
+    gen_ipv4_fragment_pcap()
+    gen_ipv6_fragment_pcap()
+    gen_ipv4_assemble_pcap()
+
+if __name__ == "__main__":
+    gen_all_pcap()
diff --git a/resources/libraries/robot/TLDK/TLDKUtils.robot b/resources/libraries/robot/TLDK/TLDKUtils.robot
new file mode 100644 (file)
index 0000000..75e9822
--- /dev/null
@@ -0,0 +1,80 @@
+# 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 ***
+| Library | resources.libraries.python.NodePath
+| Documentation | *Utilities for the path computing, pcap reading*
+| ...
+| ... | Utilities for the path computing, pcap file reading and also the port
+| ... | selection.
+
+*** Keywords ***
+| Path for 2-node testing is set
+| | [Documentation] | Compute the path for the 2 node testing. 
+| | ...
+| | ... | *Arguments:*
+| | ... | - tg_node - TG node. Type: dictionary
+| | ... | - dut_node - DUT node. Type: dictionary
+| | ...
+| | ... | *Return:*
+| | ... | - No value returned.
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Path for 2-node testing is set \| ${nodes['TG']} \
+| | ... | \| ${nodes['DUT1'] \|
+| | ...
+| | [Arguments] | ${tg_node} | ${dut_node}
+| | Append Nodes | ${tg_node} | ${dut_node}
+| | Compute Path
+
+| Pick out the port used to execute test
+| | [Documentation] | Pick out the port used to execute the test.
+| | ... 
+| | ... | *Arguments:*
+| | ... | - No arguments.
+| | ... 
+| | ... | *Return:*
+| | ... | - No value returned.
+| | ... 
+| | ... | *Example:*
+| | ... 
+| | ... | \| Pick out the port used to execute test \|
+| | ... 
+| | ${tg_port} | ${tg_node}= | First Interface
+| | ${dut_port} | ${dut_node}= | Last Interface
+| | set suite variable | ${tg_node}
+| | set suite variable | ${dut_node}
+| | set suite variable | ${tg_port}
+| | set suite variable | ${dut_port}
+
+| Get the pcap data
+| | [Documentation] | Get the pcap file detailed data.
+| | ...
+| | ... | *Arguments:*
+| | ... | - file_prefix - file prefix. Type: dictionary
+| | ...
+| | ... | *Return:*
+| | ... | - packet_num, dest_ip, is_ipv4 - a tuple of packet_num
+| | ... |   dest_ip, is_ipv4. Type: tuple(int, str, bool)
+| | ...
+| | ... | *Example:*
+| | ...
+| | ... | \| Get the pcap data \| ${tc01_file_prefix} \|
+| | ...
+| | [Arguments] | ${file_prefix}
+| | ${packet_num} | ${dest_ip} | ${is_ipv4}= | Get Pcap Info
+| | ... | ${file_prefix}
+| | set suite variable | ${packet_num}
+| | set suite variable | ${dest_ip}
+| | set suite variable | ${is_ipv4}