Last bulk update of CSIT. 04/304/1
authorStefan Kobza <skobza@cisco.com>
Fri, 12 Feb 2016 14:28:57 +0000 (15:28 +0100)
committerStefan Kobza <skobza@cisco.com>
Fri, 12 Feb 2016 14:28:57 +0000 (15:28 +0100)
Change-Id: I815e4d54e74a49fd19a9927554ce5c37a2719f7e
Signed-off-by: Stefan Kobza <skobza@cisco.com>
15 files changed:
resources/libraries/python/IPv6Setup.py
resources/libraries/python/Routing.py [new file with mode: 0644]
resources/libraries/python/TrafficGenerator.py
resources/libraries/python/topology.py
resources/libraries/robot/ipv4.robot
resources/libraries/robot/ipv6.robot
resources/libraries/robot/l2_xconnect.robot
resources/templates/vat/l2_bridge_domain_gen.vat [new file with mode: 0644]
resources/templates/vat/l2_xconnect.vat
resources/tools/t-rex-installer.sh [new file with mode: 0755]
resources/tools/t-rex-stateless.py [new file with mode: 0755]
resources/topology_schemas/topology.sch.yaml
tests/suites/ipv6/ipv6_untagged.robot
tests/suites/l2_xconnect/l2_xconnect_untagged.robot
tests/suites/performance/short.robot

index 45a8eba..db49775 100644 (file)
@@ -248,42 +248,33 @@ class IPv6Setup(object):
                 self.vpp_ra_supress_link_layer(node, if_name)
 
     @staticmethod
                 self.vpp_ra_supress_link_layer(node, if_name)
 
     @staticmethod
-    def vpp_ipv6_route_add(node, link, interface, nodes_addr):
-        """Setup IPv6 route on the VPP node.
-
-           :param node: Node to add route on.
-           :param link: Route to following link.
-           :param interface: Route output interface.
-           :param nodes_addr: Available nodes IPv6 adresses.
-           :type node: dict
-           :type link: str
-           :type interface: str
-           :type nodes_addr: dict
+    def get_link_address(link, nodes_addr):
+        """Get link IPv6 address.
+
+        :param link: Link name.
+        :param nodes_addr: Available nodes IPv6 adresses.
+        :type link: str
+        :type nodes_addr: dict
+        :return: Link IPv6 address.
+        :rtype: str
         """
         """
-        ssh = SSH()
-        ssh.connect(node)
-
-        # Get route destination address from link name
         net = nodes_addr.get(link)
         if net is None:
         net = nodes_addr.get(link)
         if net is None:
-            raise ValueError('No network for link "{0}"'.format(link))
-        dst_net = '{0}/{1}'.format(net['net_addr'], net['prefix'])
+            raise ValueError('Link "{0}" address not found'.format(link))
+        return net.get('net_addr')
 
 
-        # Get next-hop address
-        nh_addr = None
-        for net in nodes_addr.values():
-            for port in net['ports'].values():
-                if port['if'] == interface and port['node'] == node['host']:
-                    for nh in net['ports'].values():
-                        if nh['if'] != interface and nh['node'] != node['host']:
-                            nh_addr = nh['addr']
-        if nh_addr is None:
-            raise Exception('next-hop not found')
-
-        cmd_input = 'ip_add_del_route {0} via {1} {2} resolve-attempts 10'. \
-            format(dst_net, nh_addr, interface)
-        (ret_code, _, _) = ssh.exec_command_sudo(Constants.VAT_BIN_NAME,
-                                                 cmd_input)
-        if int(ret_code) != 0:
-            raise Exception("'{0}' failed on {1}".format(cmd_input,
-                                                         node['host']))
+    @staticmethod
+    def get_link_prefix(link, nodes_addr):
+        """Get link IPv6 address prefix.
+
+        :param link: Link name.
+        :param nodes_addr: Available nodes IPv6 adresses.
+        :type link: str
+        :type nodes_addr: dict
+        :return: Link IPv6 address prefix.
+        :rtype: int
+        """
+        net = nodes_addr.get(link)
+        if net is None:
+            raise ValueError('Link "{0}" address not found'.format(link))
+        return net.get('prefix')
diff --git a/resources/libraries/python/Routing.py b/resources/libraries/python/Routing.py
new file mode 100644 (file)
index 0000000..b22516a
--- /dev/null
@@ -0,0 +1,45 @@
+# 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.
+
+"""Routing utilities library."""
+
+from VatExecutor import VatTerminal
+from topology import Topology
+
+
+class Routing(object):
+    """Routing utilities."""
+
+    @staticmethod
+    def vpp_route_add(node, network, prefix_len, gateway, interface):
+        """Add route to the VPP node.
+
+        :param node: Node to add route on.
+        :param network: Route destination network address.
+        :param prefix_len: Route destination network prefix length.
+        :param gateway: Route gateway address.
+        :param interface: Route interface.
+        :type node: str
+        :type network: str
+        :type prefix_len: int
+        :type gateway: str
+        :type interface: str
+        """
+        sw_if_index = Topology.get_interface_sw_index(node, interface)
+        vat = VatTerminal(node)
+        vat.vat_terminal_exec_cmd_from_template('add_route.vat',
+                                                network=network,
+                                                prefix_length=prefix_len,
+                                                gateway=gateway,
+                                                sw_if_index=sw_if_index)
+        vat.vat_terminal_close()
index d86917a..24bec0a 100644 (file)
 # 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.
 # 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.
-from ssh import SSH
+
+"""Traffic generator library."""
+
 from robot.api import logger
 
 from robot.api import logger
 
+from resources.libraries.python.ssh import SSH
+from resources.libraries.python.topology import NodeType
+from resources.libraries.python.topology import NodeSubTypeTG
+from resources.libraries.python.topology import Topology
+
 __all__ = ['TrafficGenerator']
 
 class TrafficGenerator(object):
 __all__ = ['TrafficGenerator']
 
 class TrafficGenerator(object):
+    """Traffic Generator"""
 
     def __init__(self):
         self._result = None
 
     def __init__(self):
         self._result = None
@@ -23,18 +31,130 @@ class TrafficGenerator(object):
         self._sent = None
         self._received = None
 
         self._sent = None
         self._received = None
 
+    @staticmethod
+    def initialize_traffic_generator(node, interface1, interface2):
+        """TG initialization
+        :param node: Traffic generator node
+        :param interface1: PCI address of first interface
+        :param interface2: PCI address of second interface
+        :type node: dict
+        :type interface1: str
+        :type interface2: str
+        :return: nothing
+        """
+
+        if node['type'] != NodeType.TG:
+            raise Exception('Node type is not a TG')
+        if node['subtype'] == NodeSubTypeTG.TREX:
+            ssh = SSH()
+            ssh.connect(node)
+
+            (ret, stdout, stderr) = ssh.exec_command(
+                "sh -c 'cd /opt/trex-core-1.88/scripts/ && "
+                "--bind=igb_uio {0} {1}".format(interface1, interface2))
+            (ret, stdout, stderr) = ssh.exec_command(
+                "sh -c 'cd /opt/trex-core-1.88/scripts/ && "
+                "sudo nohup ./t-rex-64 -i -c 4 --iom 0 > /dev/null 2>&1 &'")
+
+    @staticmethod
+    def teardown_traffic_generator(node):
+        """TG teardown
+        :param node: Traffic generator node
+        :type node: dict
+        :return: nothing
+        """
+
+        if node['type'] != NodeType.TG:
+            raise Exception('Node type is not a TG')
+        if node['subtype'] == NodeSubTypeTG.TREX:
+            ssh = SSH()
+            ssh.connect(node)
+            (ret, stdout, stderr) = ssh.exec_command(
+                "sh -c 'sudo pkill t-rex'")
+
+    def send_traffic_on(self, nodes_info, duration, rate,
+                        framesize, traffic_type):
+        """Send traffic from all configured interfaces on TG
+        :param nodes_info: Dictionary containing information on all nodes
+        in topology.
+        :param duration: Duration of test traffic generation in seconds
+        :param rate: Percentage of linerate
+        :param framesize: Frame size (L2) in Bytes
+        :param traffic_type: Traffic profile
+        :type nodes_info: dict
+        :type duration: str
+        :type rate: str
+        :type framesize: str
+        :type traffic_type: str
+        :return: TG output
+        :rtype: str
+        """
+
+        node = nodes_info["TG"]
+
+        if node['type'] != NodeType.TG:
+            raise Exception('Node type is not a TG')
+
+        if node['subtype'] is None:
+            raise Exception('TG subtype not defined')
 
 
-    def send_traffic_on(self, node, tx_port, rx_port, duration, rate,
-            framesize):
         ssh = SSH()
         ssh.connect(node)
 
         ssh = SSH()
         ssh.connect(node)
 
-        (ret, stdout, stderr) = ssh.exec_command(
-                "sh -c 'cd MoonGen && sudo -S build/MoonGen "
-                "rfc2544/benchmarks/vpp-frameloss.lua --txport 0 --rxport 1 "
-                "--duration {0} --rate {1} --framesize {2}'".format(
-                    duration, rate, framesize),
-                timeout=int(duration)+60)
+        tg_port3_src_mac = Topology.get_interface_mac_by_port_key(node, "port3")
+        _, adj_int = Topology.\
+            get_adjacent_node_and_interface_by_key(nodes_info, node, "port3")
+        tg_port3_dst_mac = adj_int['mac_address']
+
+        tg_port5_src_mac = Topology.get_interface_mac_by_port_key(node, "port5")
+        _, adj_int = Topology.\
+            get_adjacent_node_and_interface_by_key(nodes_info, node, "port5")
+        tg_port5_dst_mac = adj_int['mac_address']
+
+
+        if node['subtype'] == NodeSubTypeTG.TREX:
+            if traffic_type in ["3-node-xconnect", "3-node-bridge"]:
+                (ret, stdout, stderr) = ssh.exec_command(
+                    "sh -c '/tmp/openvpp-testing/resources/tools/t-rex-stateless.py "
+                    "-d {0} -r {1}% -s {2} "
+                    "--p1_src_mac 52:00:00:00:00:01 "
+                    "--p1_dst_mac 52:00:00:00:00:02 "
+                    "--p1_src_start_ip 10.10.10.1 "
+                    "--p1_src_end_ip 10.10.10.254 "
+                    "--p1_dst_start_ip 20.20.20.1 "
+                    "--p1_dst_end_ip 20.20.20.254 "
+                    "--p2_src_mac 52:00:00:00:00:02 "
+                    "--p2_dst_mac 52:00:00:00:00:01 "
+                    "--p2_src_start_ip 20.20.20.1 "
+                    "--p2_src_end_ip 20.20.20.254 "
+                    "--p2_dst_start_ip 10.10.10.1 "
+                    "--p2_dst_end_ip 10.10.10.254'".\
+                    format(duration, rate, framesize), timeout=int(duration)+60)
+            elif traffic_type in ["3-node-IPv4"]:
+                (ret, stdout, stderr) = ssh.exec_command(
+                    "sh -c '/tmp/openvpp-testing/resources/tools/t-rex-stateless.py "
+                    "-d {0} -r {1}% -s {2} "
+                    "--p1_src_mac {3} "
+                    "--p1_dst_mac {4} "
+                    "--p1_src_start_ip 10.10.10.2 "
+                    "--p1_src_end_ip 10.10.10.254 "
+                    "--p1_dst_start_ip 20.20.20.2 "
+                    "--p1_dst_end_ip 20.20.20.2 "
+                    "--p2_src_mac {5} "
+                    "--p2_dst_mac {6} "
+                    "--p2_src_start_ip 20.20.20.2 "
+                    "--p2_src_end_ip 20.20.20.254 "
+                    "--p2_dst_start_ip 10.10.10.2 "
+                    "--p2_dst_end_ip 10.10.10.2'".\
+                    format(duration, rate, framesize,\
+                           tg_port3_src_mac, tg_port3_dst_mac,\
+                           tg_port5_src_mac, tg_port5_dst_mac),\
+                           timeout=int(duration)+60)
+            else:
+                raise NotImplementedError('Unsupported traffic type')
+
+        else:
+            raise NotImplementedError("TG subtype not supported")
 
         logger.trace(ret)
         logger.trace(stdout)
 
         logger.trace(ret)
         logger.trace(stdout)
@@ -51,6 +171,10 @@ class TrafficGenerator(object):
         return self._result
 
     def no_traffic_loss_occured(self):
         return self._result
 
     def no_traffic_loss_occured(self):
+        """Fail is loss occured in traffic run
+        :return: nothing
+        """
+
         if self._loss is None:
             raise Exception('The traffic generation has not been issued')
         if self._loss != '0':
         if self._loss is None:
             raise Exception('The traffic generation has not been issued')
         if self._loss != '0':
index 2b202e5..3ced69d 100644 (file)
@@ -43,6 +43,14 @@ class NodeType(object):
     # Traffic Generator (this node has traffic generator on it)
     TG = 'TG'
 
     # Traffic Generator (this node has traffic generator on it)
     TG = 'TG'
 
+class NodeSubTypeTG(object):
+    #T-Rex traffic generator
+    TREX = 'TREX'
+    # Moongen
+    MOONGEN = 'MOONGEN'
+    #IxNetwork
+    IXNET = 'IXNET'
+
 DICT__nodes = load_topo_from_yaml()
 
 
 DICT__nodes = load_topo_from_yaml()
 
 
@@ -345,6 +353,22 @@ class Topology(object):
 
         return None
 
 
         return None
 
+    @staticmethod
+    def get_interface_mac_by_port_key(node, port_key):
+        """Get MAC address for the interface based on port key.
+
+        :param node: Node to get interface mac on.
+        :param port_key: Dictionary key name of interface.
+        :type node: dict
+        :type port_key: str
+        :return: Return MAC or None if not found.
+        """
+        for port_name, port_data in node['interfaces'].iteritems():
+            if port_name == port_key:
+                return port_data['mac_address']
+
+        return None
+
     @staticmethod
     def get_interface_mac(node, interface):
         """Get MAC address for the interface.
     @staticmethod
     def get_interface_mac(node, interface):
         """Get MAC address for the interface.
@@ -364,6 +388,45 @@ class Topology(object):
 
         return None
 
 
         return None
 
+    @staticmethod
+    def get_adjacent_node_and_interface_by_key(nodes_info, node, port_key):
+        """Get node and interface adjacent to specified interface
+        on local network.
+
+        :param nodes_info: Dictionary containing information on all nodes
+        in topology.
+        :param node: Node that contains specified interface.
+        :param port_key: Interface port key.
+        :type nodes_info: dict
+        :type node: dict
+        :type port_key: str
+        :return: Return (node, interface info) tuple or None if not found.
+        :rtype: (dict, dict)
+        """
+        link_name = None
+       # get link name where the interface belongs to
+        for port_name, port_data in node['interfaces'].iteritems():
+            if port_name == 'mgmt':
+                continue
+            if port_name == port_key:
+                link_name = port_data['link']
+                break
+
+        if link_name is None: 
+            return None
+
+        # find link
+        for node_data in nodes_info.values():
+            # skip self
+            if node_data['host'] == node['host']:
+                continue
+            for interface, interface_data \
+                    in node_data['interfaces'].iteritems():
+                if 'link' not in interface_data:
+                    continue
+                if interface_data['link'] == link_name:
+                    return node_data, node_data['interfaces'][interface]
+
     @staticmethod
     def get_adjacent_node_and_interface(nodes_info, node, interface_name):
         """Get node and interface adjacent to specified interface
     @staticmethod
     def get_adjacent_node_and_interface(nodes_info, node, interface_name):
         """Get node and interface adjacent to specified interface
index 60d729f..b5f313d 100644 (file)
@@ -20,9 +20,9 @@
 *** Keywords ***
 
 | Setup IPv4 adresses on all DUT nodes in topology
 *** Keywords ***
 
 | Setup IPv4 adresses on all DUT nodes in topology
-| | [Documentation] | Setup IPv4 address on all DUTs and TG in topology
+| | [Documentation] | Setup IPv4 address on all DUTs in topology
 | | [Arguments] | ${nodes} | ${nodes_addr}
 | | [Arguments] | ${nodes} | ${nodes_addr}
-| | DUT nodes setup IPv4 addresses | ${nodes} | ${nodes_addr}
+| | DUT Nodes setup IPv4 addresses | ${nodes} | ${nodes_addr}
 
 | Interfaces needed for IPv4 testing are in "${state}" state
 | | Node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port1']['name']}" is in "${state}" state
 
 | Interfaces needed for IPv4 testing are in "${state}" state
 | | Node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port1']['name']}" is in "${state}" state
 | | ${prefix_length} = | Get IPv4 address prefix of node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port1']['name']}"
 | | Node "${nodes['DUT2']}" routes to IPv4 network "${subnet}" with prefix length "${prefix_length}" using interface "${nodes['DUT2']['interfaces']['port3']['name']}" via "${gateway}"
 
 | | ${prefix_length} = | Get IPv4 address prefix of node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port1']['name']}"
 | | Node "${nodes['DUT2']}" routes to IPv4 network "${subnet}" with prefix length "${prefix_length}" using interface "${nodes['DUT2']['interfaces']['port3']['name']}" via "${gateway}"
 
+| Setup DUT nodes for IPv4 testing
+| | Interfaces needed for IPv4 testing are in "up" state
+| | Setup IPv4 adresses on all DUT nodes in topology | ${nodes} | ${nodes_ipv4_addr}
+| | Setup ARP on all DUTs | ${nodes}
+| | Routes are set up for IPv4 testing
+
 | Setup nodes for IPv4 testing
 | | Interfaces needed for IPv4 testing are in "up" state
 | | Setup IPv4 adresses on all DUT nodes in topology | ${nodes} | ${nodes_ipv4_addr}
 | Setup nodes for IPv4 testing
 | | Interfaces needed for IPv4 testing are in "up" state
 | | Setup IPv4 adresses on all DUT nodes in topology | ${nodes} | ${nodes_ipv4_addr}
index f45ba7c..3d8a2ea 100644 (file)
@@ -17,6 +17,8 @@
 | Library | resources/libraries/python/IPv6Util.py
 | Library | resources/libraries/python/IPv6Setup.py
 | Library | resources/libraries/python/TrafficScriptExecutor.py
 | Library | resources/libraries/python/IPv6Util.py
 | Library | resources/libraries/python/IPv6Setup.py
 | Library | resources/libraries/python/TrafficScriptExecutor.py
+| Library | resources/libraries/python/NodePath.py
+| Library | resources/libraries/python/Routing.py
 | Library | resources.libraries.python.topology.Topology
 | Resource | resources/libraries/robot/default.robot
 | Resource | resources/libraries/robot/counters.robot
 | Library | resources.libraries.python.topology.Topology
 | Resource | resources/libraries/robot/default.robot
 | Resource | resources/libraries/robot/counters.robot
 *** Keywords ***
 | Ipv6 icmp echo
 | | [Documentation] | Type of the src_node must be TG and dst_node must be DUT
 *** Keywords ***
 | Ipv6 icmp echo
 | | [Documentation] | Type of the src_node must be TG and dst_node must be DUT
-| | [Arguments] | ${src_node} | ${dst_node} | ${nodes_addr}
-| | ${link}= | Get first active connecting link between node "${src_node}" and "${dst_node}"
-| | ${src_port}= | Get Interface By Link Name | ${src_node} | ${link}
-| | ${dst_port}= | Get Interface By Link Name | ${dst_node} | ${link}
+| | [Arguments] | ${tg_node} | ${dut_node} | ${nodes_addr}
+| | Append Nodes | ${tg_node} | ${dut_node}
+| | Compute Path
+| | ${src_port} | ${src_node}= | First Interface
+| | ${dst_port} | ${dst_node}= | Last Interface
 | | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
 | | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
 | | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
 | | ${dst_mac}= | Get Interface Mac | ${dst_node} | ${dst_port}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
 | | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
 | | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
 | | ${dst_mac}= | Get Interface Mac | ${dst_node} | ${dst_port}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
-| | Run Traffic Script On Node | icmpv6_echo.py | ${src_node} | ${args}
+| | Run Traffic Script On Node | icmpv6_echo.py | ${tg_node} | ${args}
 | | Vpp dump stats | ${dst_node}
 | | ${ipv6_counter}= | Vpp get interface ipv6 counter | ${dst_node} | ${dst_port}
 | | Should Be Equal | ${ipv6_counter} | ${2} | #ICMPv6 neighbor advertisment + ICMPv6 echo request
 
 | Ipv6 icmp echo sweep
 | | [Documentation] | Type of the src_node must be TG and dst_node must be DUT
 | | Vpp dump stats | ${dst_node}
 | | ${ipv6_counter}= | Vpp get interface ipv6 counter | ${dst_node} | ${dst_port}
 | | Should Be Equal | ${ipv6_counter} | ${2} | #ICMPv6 neighbor advertisment + ICMPv6 echo request
 
 | Ipv6 icmp echo sweep
 | | [Documentation] | Type of the src_node must be TG and dst_node must be DUT
-| | [Arguments] | ${src_node} | ${dst_node} | ${nodes_addr}
-| | ${link}= | Get first active connecting link between node "${src_node}" and "${dst_node}"
-| | ${src_port}= | Get Interface By Link Name | ${src_node} | ${link}
-| | ${dst_port}= | Get Interface By Link Name | ${dst_node} | ${link}
+| | [Arguments] | ${tg_node} | ${dut_node} | ${nodes_addr}
+| | Append Nodes | ${tg_node} | ${dut_node}
+| | Compute Path
+| | ${src_port} | ${src_node}= | First Interface
+| | ${dst_port} | ${dst_node}= | Last Interface
 | | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
 | | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
 | | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
 | | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
 | | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
 | | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
 | # TODO: end_size is currently minimum MTU size for IPv6 minus IPv6 and ICMPv6
 | # echo header size, MTU info is not in VAT sw_interface_dump output
 | | ${args}= | Set Variable | ${args} --start_size 0 --end_size 1232 --step 1
 | # TODO: end_size is currently minimum MTU size for IPv6 minus IPv6 and ICMPv6
 | # echo header size, MTU info is not in VAT sw_interface_dump output
 | | ${args}= | Set Variable | ${args} --start_size 0 --end_size 1232 --step 1
-| | Run Traffic Script On Node | ipv6_sweep_ping.py | ${src_node} | ${args} | ${20}
+| | Run Traffic Script On Node | ipv6_sweep_ping.py | ${tg_node} | ${args} | ${20}
 
 | Ipv6 tg to dut1 egress
 | | [Documentation] | Send traffic from TG to first DUT egress interface
 
 | Ipv6 tg to dut1 egress
 | | [Documentation] | Send traffic from TG to first DUT egress interface
-| | [Arguments] | ${tg_node} | ${first_dut} | ${nodes_addr}
-| | ${link}= | Get first active connecting link between node "${tg_node}" and "${first_dut}"
-| | ${src_port}= | Get Interface By Link Name | ${tg_node} | ${link}
-| | ${first_hop_port}= | Get Interface By Link Name | ${first_dut} | ${link}
-| | ${dst_port}= | Get first egress interface on "${first_dut}" for link with "${tg_node}"
-| | ${src_ip}= | Get Node Port Ipv6 Address | ${tg_node} | ${src_port} | ${nodes_addr}
-| | ${dst_ip}= | Get Node Port Ipv6 Address | ${first_dut} | ${dst_port} | ${nodes_addr}
-| | ${src_mac}= | Get Interface Mac | ${tg_node} | ${src_port}
-| | ${dst_mac}= | Get Interface Mac | ${first_dut} | ${first_hop_port}
+| | [Arguments] | ${tg_node} | ${first_dut} | ${second_dut} | ${nodes_addr}
+| | Append Nodes | ${tg_node} | ${first_dut} | ${second_dut}
+| | Compute Path
+| | ${src_port} | ${src_node}= | First Interface
+| | ${dst_port} | ${dst_node}= | Last Egress Interface
+| | ${hop_port} | ${hop_node}= | First Ingress Interface
+| | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
+| | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
+| | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
+| | ${dst_mac}= | Get Interface Mac | ${hop_node} | ${hop_port}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | Run Traffic Script On Node | icmpv6_echo.py | ${tg_node} | ${args}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | Run Traffic Script On Node | icmpv6_echo.py | ${tg_node} | ${args}
 | Ipv6 tg to dut2 via dut1
 | | [Documentation] | Send traffic from TG to second DUT through first DUT
 | | [Arguments] | ${tg_node} | ${first_dut} | ${second_dut} | ${nodes_addr}
 | Ipv6 tg to dut2 via dut1
 | | [Documentation] | Send traffic from TG to second DUT through first DUT
 | | [Arguments] | ${tg_node} | ${first_dut} | ${second_dut} | ${nodes_addr}
-| | ${link1}= | Get first active connecting link between node "${tg_node}" and "${first_dut}"
-| | ${src_port}= | Get Interface By Link Name | ${tg_node} | ${link1}
-| | ${first_hop_port}= | Get Interface By Link Name | ${first_dut} | ${link1}
-| | ${link2}= | Get first active connecting link between node "${first_dut}" and "${second_dut}"
-| | ${dst_port}= | Get Interface By Link Name | ${second_dut} | ${link2}
-| | ${src_ip}= | Get Node Port Ipv6 Address | ${tg_node} | ${src_port} | ${nodes_addr}
-| | ${dst_ip}= | Get Node Port Ipv6 Address | ${second_dut} | ${dst_port} | ${nodes_addr}
-| | ${src_mac}= | Get Interface Mac | ${tg_node} | ${src_port}
-| | ${dst_mac}= | Get Interface Mac | ${first_dut} | ${first_hop_port}
+| | Append Nodes | ${tg_node} | ${first_dut} | ${second_dut}
+| | Compute Path
+| | ${src_port} | ${src_node}= | First Interface
+| | ${dst_port} | ${dst_node}= | Last Interface
+| | ${hop_port} | ${hop_node}= | First Ingress Interface
+| | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
+| | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
+| | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
+| | ${dst_mac}= | Get Interface Mac | ${hop_node} | ${hop_port}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | Run Traffic Script On Node | icmpv6_echo.py | ${tg_node} | ${args}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | Run Traffic Script On Node | icmpv6_echo.py | ${tg_node} | ${args}
 | Ipv6 tg to dut2 egress via dut1
 | | [Documentation] | Send traffic from TG to second DUT egress interface through first DUT
 | | [Arguments] | ${tg_node} | ${first_dut} | ${second_dut} | ${nodes_addr}
 | Ipv6 tg to dut2 egress via dut1
 | | [Documentation] | Send traffic from TG to second DUT egress interface through first DUT
 | | [Arguments] | ${tg_node} | ${first_dut} | ${second_dut} | ${nodes_addr}
-| | ${link}= | Get first active connecting link between node "${tg_node}" and "${first_dut}"
-| | ${src_port}= | Get Interface By Link Name | ${tg_node} | ${link}
-| | ${first_hop_port}= | Get Interface By Link Name | ${first_dut} | ${link}
-| | ${dst_port}= | Get first egress interface on "${first_dut}" for link with "${second_dut}"
-| | ${src_ip}= | Get Node Port Ipv6 Address | ${tg_node} | ${src_port} | ${nodes_addr}
-| | ${dst_ip}= | Get Node Port Ipv6 Address | ${second_dut} | ${dst_port} | ${nodes_addr}
-| | ${src_mac}= | Get Interface Mac | ${tg_node} | ${src_port}
-| | ${dst_mac}= | Get Interface Mac | ${first_dut} | ${first_hop_port}
+| | Append Nodes | ${tg_node} | ${first_dut} | ${second_dut} | ${tg_node}
+| | Compute Path
+| | ${src_port} | ${src_node}= | First Interface
+| | ${dst_port} | ${dst_node}= | Last Egress Interface
+| | ${hop_port} | ${hop_node}= | First Ingress Interface
+| | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
+| | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
+| | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
+| | ${dst_mac}= | Get Interface Mac | ${hop_node} | ${hop_port}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | Run Traffic Script On Node | icmpv6_echo.py | ${tg_node} | ${args}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | Run Traffic Script On Node | icmpv6_echo.py | ${tg_node} | ${args}
 | | [Documentation] | Send traffic from one TG port to another through DUT nodes
 | | ...             | and send reply back, also verify hop limit processing
 | | [Arguments] | ${tg_node} | ${first_dut} | ${second_dut} | ${nodes_addr}
 | | [Documentation] | Send traffic from one TG port to another through DUT nodes
 | | ...             | and send reply back, also verify hop limit processing
 | | [Arguments] | ${tg_node} | ${first_dut} | ${second_dut} | ${nodes_addr}
-| | ${link1}= | Get first active connecting link between node "${tg_node}" and "${first_dut}"
-| | ${src_port}= | Get Interface By Link Name | ${tg_node} | ${link1}
-| | ${src_nh_port}= | Get Interface By Link Name | ${first_dut} | ${link1}
-| | ${link2}= | Get first active connecting link between node "${tg_node}" and "${second_dut}"
-| | ${dst_port}= | Get Interface By Link Name | ${tg_node} | ${link2}
-| | ${dst_nh_port}= | Get Interface By Link Name | ${second_dut} | ${link2}
-| | ${src_ip}= | Get Node Port Ipv6 Address | ${tg_node} | ${src_port} | ${nodes_addr}
-| | ${dst_ip}= | Get Node Port Ipv6 Address | ${tg_node} | ${dst_port} | ${nodes_addr}
-| | ${src_mac}= | Get Interface Mac | ${tg_node} | ${src_port}
-| | ${dst_mac}= | Get Interface Mac | ${tg_node} | ${dst_port}
-| | ${src_nh_mac}= | Get Interface Mac | ${first_dut} | ${src_nh_port}
-| | ${dst_nh_mac}= | Get Interface Mac | ${second_dut} | ${dst_nh_port}
+| | Append Nodes | ${tg_node} | ${first_dut} | ${second_dut} | ${tg_node}
+| | Compute Path
+| | ${src_port} | ${src_node}= | First Interface
+| | ${dst_port} | ${dst_node}= | Last Interface
+| | ${src_nh_port} | ${src_nh_node}= | First Ingress Interface
+| | ${dst_nh_port} | ${dst_nh_node}= | Last Egress Interface
+| | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
+| | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
+| | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
+| | ${dst_mac}= | Get Interface Mac | ${src_node} | ${dst_port}
+| | ${src_nh_mac}= | Get Interface Mac | ${src_nh_node} | ${src_nh_port}
+| | ${dst_nh_mac}= | Get Interface Mac | ${dst_nh_node} | ${dst_nh_port}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${dst_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | ${args}= | Traffic Script Gen Arg | ${src_port} | ${dst_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
-| | ${args}= | Set Variable | ${args} --src_nh_mac ${src_nh_mac} --dst_nh_mac ${dst_nh_mac} --h_num 2
+| | ${args}= | Catenate | ${args} | --src_nh_mac ${src_nh_mac}
+| |          | ...      | --dst_nh_mac ${dst_nh_mac} | --h_num 2
 | | Run Traffic Script On Node | icmpv6_echo_req_resp.py | ${tg_node} | ${args}
 
 | Ipv6 neighbor solicitation
 | | [Documentation] | Send IPv6 neighbor solicitation from TG to DUT
 | | [Arguments] | ${tg_node} | ${dut_node} | ${nodes_addr}
 | | Run Traffic Script On Node | icmpv6_echo_req_resp.py | ${tg_node} | ${args}
 
 | Ipv6 neighbor solicitation
 | | [Documentation] | Send IPv6 neighbor solicitation from TG to DUT
 | | [Arguments] | ${tg_node} | ${dut_node} | ${nodes_addr}
-| | ${link}= | Get first active connecting link between node "${tg_node}" and "${dut_node}"
-| | ${tg_port}= | Get Interface By Link Name | ${tg_node} | ${link}
-| | ${dut_port}= | Get Interface By Link Name | ${dut_node} | ${link}
-| | ${src_ip}= | Get Node Port Ipv6 Address | ${tg_node} | ${tg_port} | ${nodes_addr}
-| | ${dst_ip}= | Get Node Port Ipv6 Address | ${dut_node} | ${dut_port} | ${nodes_addr}
-| | ${src_mac}= | Get Interface Mac | ${tg_node} | ${tg_port}
-| | ${dst_mac}= | Get Interface Mac | ${dut_node} | ${dut_port}
-| | ${args}= | Traffic Script Gen Arg | ${tg_port} | ${tg_port} | ${src_mac}
+| | Append Nodes | ${tg_node} | ${dut_node}
+| | Compute Path
+| | ${src_port} | ${src_node}= | First Interface
+| | ${dst_port} | ${dst_node}= | Last Interface
+| | ${src_ip}= | Get Node Port Ipv6 Address | ${src_node} | ${src_port} | ${nodes_addr}
+| | ${dst_ip}= | Get Node Port Ipv6 Address | ${dst_node} | ${dst_port} | ${nodes_addr}
+| | ${src_mac}= | Get Interface Mac | ${src_node} | ${src_port}
+| | ${dst_mac}= | Get Interface Mac | ${dst_node} | ${dst_port}
+| | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
 | |          | ...                    | ${dst_mac} | ${src_ip} | ${dst_ip}
-| | Run Traffic Script On Node | ipv6_ns.py | ${tg_node} | ${args}
+| | Run Traffic Script On Node | ipv6_ns.py | ${src_node} | ${args}
 
 | Setup ipv6 to all dut in topology
 | | [Documentation] | Setup IPv6 address on all DUTs
 
 | Setup ipv6 to all dut in topology
 | | [Documentation] | Setup IPv6 address on all DUTs
 | Vpp nodes setup ipv6 routing
 | | [Documentation] | Setup routing on all VPP nodes required for IPv6 tests
 | | [Arguments] | ${nodes} | ${nodes_addr}
 | Vpp nodes setup ipv6 routing
 | | [Documentation] | Setup routing on all VPP nodes required for IPv6 tests
 | | [Arguments] | ${nodes} | ${nodes_addr}
-| | ${link_tg_dut1}= | Get first active connecting link between node "${nodes['TG']}" and "${nodes['DUT1']}"
-| | ${link_tg_dut2}= | Get first active connecting link between node "${nodes['TG']}" and "${nodes['DUT2']}"
-| | ${link_dut1_dut2}= | Get first active connecting link between node "${nodes['DUT1']}" and "${nodes['DUT2']}"
-| | ${dut1_if}= | Get Interface By Link Name | ${nodes['DUT1']} | ${link_dut1_dut2}
-| | ${dut2_if}= | Get Interface By Link Name | ${nodes['DUT2']} | ${link_dut1_dut2}
-| | Vpp Ipv6 Route Add | ${nodes['DUT1']} | ${link_tg_dut2} | ${dut1_if} | ${nodes_addr}
-| | Vpp Ipv6 Route Add | ${nodes['DUT2']} | ${link_tg_dut1} | ${dut2_if} | ${nodes_addr}
+| | Append Nodes | ${nodes['DUT1']} | ${nodes['DUT2']}
+| | Compute Path
+| | ${tg}= | Set Variable | ${nodes['TG']}
+| | ${dut1_if} | ${dut1}= | First Interface
+| | ${dut2_if} | ${dut2}= | Last Interface
+| | ${dut1_if_addr}= | Get Node Port Ipv6 Address | ${dut1} | ${dut1_if} | ${nodes_addr}
+| | ${dut2_if_addr}= | Get Node Port Ipv6 Address | ${dut2} | ${dut2_if} | ${nodes_addr}
+| | @{tg_dut1_links}= | Get active links connecting "${tg}" and "${dut1}"
+| | @{tg_dut2_links}= | Get active links connecting "${tg}" and "${dut2}"
+| | :FOR | ${link} | IN | @{tg_dut1_links}
+| | | ${net}= | Get Link Address | ${link} | ${nodes_addr}
+| | | ${prefix}= | Get Link Prefix | ${link} | ${nodes_addr}
+| | | Vpp Route Add | ${dut2} | ${net} | ${prefix} | ${dut1_if_addr} | ${dut2_if}
+| | :FOR | ${link} | IN | @{tg_dut2_links}
+| | | ${net}= | Get Link Address | ${link} | ${nodes_addr}
+| | | ${prefix}= | Get Link Prefix | ${link} | ${nodes_addr}
+| | | Vpp Route Add | ${dut1} | ${net} | ${prefix} | ${dut2_if_addr} | ${dut1_if}
index 001062c..2603863 100644 (file)
@@ -17,6 +17,7 @@
 | Library | resources.libraries.python.CrossConnectSetup
 | Library | resources.libraries.python.topology.Topology
 | Library | resources.libraries.python.TrafficScriptExecutor
 | Library | resources.libraries.python.CrossConnectSetup
 | Library | resources.libraries.python.topology.Topology
 | Library | resources.libraries.python.TrafficScriptExecutor
+| Library | resources.libraries.python.IPv4Util
 | Variables | resources/libraries/python/constants.py
 
 *** Keywords ***
 | Variables | resources/libraries/python/constants.py
 
 *** Keywords ***
 | | ${dst_ip}= | Set Variable | 192.168.100.2
 | | ${src_mac}= | Get Node Link Mac | ${node} | ${link1}
 | | ${dst_mac}= | Get Node Link Mac | ${node} | ${link2}
 | | ${dst_ip}= | Set Variable | 192.168.100.2
 | | ${src_mac}= | Get Node Link Mac | ${node} | ${link1}
 | | ${dst_mac}= | Get Node Link Mac | ${node} | ${link2}
-| | ${args}= | Traffic Script Gen Arg | ${src_port} | ${src_port} | ${src_mac} | ${dst_mac} | ${src_ip} | ${dst_ip}
+| | ${args}= | Traffic Script Gen Arg | ${dst_port} | ${src_port} | ${src_mac} | ${dst_mac} | ${src_ip} | ${dst_ip}
 | | Run Traffic Script On Node | send_ip_icmp.py | ${node} | ${args}
 | | Run Traffic Script On Node | send_ip_icmp.py | ${node} | ${args}
+
+
+| Interfaces on all DUTs are in "${state}" state
+| | Node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port1']['name']}" is in "${state}" state
+| | Node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port3']['name']}" is in "${state}" state
+| | Node "${nodes['DUT2']}" interface "${nodes['DUT2']['interfaces']['port1']['name']}" is in "${state}" state
+| | Node "${nodes['DUT2']}" interface "${nodes['DUT2']['interfaces']['port3']['name']}" is in "${state}" state
+
diff --git a/resources/templates/vat/l2_bridge_domain_gen.vat b/resources/templates/vat/l2_bridge_domain_gen.vat
new file mode 100644 (file)
index 0000000..9513b07
--- /dev/null
@@ -0,0 +1,6 @@
+sw_interface_set_flags TenGigabitEthernet84/0/1 admin-up link-up
+sw_interface_set_flags TenGigabitEthernet84/0/0 admin-up link-up
+bridge_domain_add_del bd_id 1 flood 1 uu-flood 1 forward 1 learn 1 arp-term 0
+sw_interface_set_l2_bridge TenGigabitEthernet84/0/1 bd_id 1 shg 0  enable
+sw_interface_set_l2_bridge TenGigabitEthernet84/0/0 bd_id 1 shg 0  enable
+exec trace add dpdk-input 100
index 3812e9a..77cb9d6 100644 (file)
@@ -1 +1 @@
-sw_interface_set_l2_xconnect rx_sw_if_index {interface1} tx_sw_if_index {interface2}
\ No newline at end of file
+sw_interface_set_l2_xconnect rx_sw_if_index {interface1} tx_sw_if_index {interface2}
diff --git a/resources/tools/t-rex-installer.sh b/resources/tools/t-rex-installer.sh
new file mode 100755 (executable)
index 0000000..28d4ecb
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+TREX_DOWNLOAD_REPO="https://github.com/cisco-system-traffic-generator/trex-core/archive/"
+TREX_DOWNLOAD_PACKAGE="v1.88.zip"
+TREX_PACKAGE_URL="${TREX_DOWNLOAD_REPO}${TREX_DOWNLOAD_PACKAGE}"
+TARGET_DIR="/opt/"
+TREX_DIR="trex-core-1.88/"
+TREX_INSTALL_DIR="${TARGET_DIR}${TREX_DIR}"
+
+if test "$(id -u)" -ne 0
+then
+    echo "Please use root or sudo to be able to access target installation directory: ${TARGET_DIR}"
+    exit 1
+fi
+
+WORKING_DIR=$(mktemp -d)
+test $? -eq 0 || exit 1
+
+cleanup () {
+    rm -r ${WORKING_DIR}
+}
+
+trap cleanup EXIT
+
+test -d ${TREX_INSTALL_DIR} && echo "T-REX aleready installed: ${TREX_INSTALL_DIR}" && exit 1
+
+wget -P ${WORKING_DIR} ${TREX_PACKAGE_URL}
+test $? -eq 0 || exit 1
+
+unzip ${WORKING_DIR}/${TREX_DOWNLOAD_PACKAGE} -d ${TARGET_DIR}
+test $? -eq 0 || exit 1
+
+cd ${TREX_INSTALL_DIR}/linux_dpdk/ && ./b configure && ./b build || exit 1
+cd ${TREX_INSTALL_DIR}/scripts/ko/src && make || exit 1
+
diff --git a/resources/tools/t-rex-stateless.py b/resources/tools/t-rex-stateless.py
new file mode 100755 (executable)
index 0000000..dfc4ad4
--- /dev/null
@@ -0,0 +1,264 @@
+#!/usr/bin/python
+
+# 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.
+
+
+import sys, getopt
+sys.path.insert(0, "/opt/trex-core-1.88/scripts/api/stl/")
+
+from trex_stl_api import *
+
+import dpkt
+import json
+import string
+
+def generate_payload(length):
+    word = ''
+    alphabet_size = len(string.letters)
+    for i in range(length):
+        word += string.letters[(i % alphabet_size)]
+    return word
+
+def create_packets(traffic_options, frame_size=64):
+
+    if frame_size < 64:
+        print "Packet min. size is 64B"
+        sys.exit(2)
+
+    # build A side packet
+    pkt_a = STLPktBuilder()
+
+    pkt_a.add_pkt_layer("l2", dpkt.ethernet.Ethernet())
+    pkt_a.add_pkt_layer("l3_ip", dpkt.ip.IP())
+    pkt_a.add_pkt_layer("l4_udp", dpkt.udp.UDP())
+    pkt_a.set_pkt_payload(generate_payload(frame_size -
+                                           pkt_a.get_packet_length()))
+    pkt_a.set_layer_attr("l3_ip", "len", len(pkt_a.get_layer('l3_ip')))
+
+    # build B side packet
+    pkt_b = pkt_a.clone()
+
+    p1_src_mac = traffic_options['p1_src_mac']
+    p1_dst_mac = traffic_options['p1_dst_mac']
+    p1_src_start_ip = traffic_options['p1_src_start_ip']
+    p1_src_end_ip = traffic_options['p1_src_end_ip']
+    p1_dst_start_ip = traffic_options['p1_dst_start_ip']
+    p1_dst_end_ip = traffic_options['p1_dst_end_ip']
+    p2_src_mac = traffic_options['p2_src_mac']
+    p2_dst_mac = traffic_options['p2_dst_mac']
+    p2_src_start_ip = traffic_options['p2_src_start_ip']
+    p2_src_end_ip = traffic_options['p2_src_end_ip']
+    p2_dst_start_ip = traffic_options['p2_dst_start_ip']
+    p2_dst_end_ip = traffic_options['p2_dst_end_ip']
+
+    pkt_a.set_eth_layer_addr(layer_name="l2",
+                             attr="src",
+                             mac_addr=p1_src_mac)
+    pkt_a.set_eth_layer_addr(layer_name="l2",
+                             attr="dst",
+                             mac_addr=p1_dst_mac)
+    pkt_b.set_eth_layer_addr(layer_name="l2",
+                             attr="src",
+                             mac_addr=p2_src_mac)
+    pkt_b.set_eth_layer_addr(layer_name="l2",
+                             attr="dst",
+                             mac_addr=p2_dst_mac)
+
+    # set IP range for pkt and split it by multiple cores
+    pkt_a.set_vm_ip_range(ip_layer_name="l3_ip",
+                          ip_field="src",
+                          ip_start=p1_src_start_ip, ip_end=p1_src_end_ip,
+                          operation="inc",
+                          split=True)
+
+    pkt_a.set_vm_ip_range(ip_layer_name="l3_ip",
+                          ip_field="dst",
+                          ip_start=p1_dst_start_ip, ip_end=p1_dst_end_ip,
+                          operation="inc")
+
+
+    # build B side packet
+    pkt_b.set_vm_ip_range(ip_layer_name="l3_ip",
+                          ip_field="src",
+                          ip_start=p2_src_start_ip, ip_end=p2_src_end_ip,
+                          operation="inc",
+                          split=True)
+
+    pkt_b.set_vm_ip_range(ip_layer_name="l3_ip",
+                          ip_field="dst",
+                          ip_start=p2_dst_start_ip, ip_end=p2_dst_end_ip,
+                          operation="inc")
+
+    return(pkt_a, pkt_b)
+
+def simple_burst(pkt_a, pkt_b, duration=10, rate="1mpps",
+                 warmup=True, warmup_time=5):
+
+    # create client
+    c = STLClient()
+    passed = True
+
+    try:
+        # turn this on for some information
+        #c.set_verbose("high")
+
+        # create two streams
+        s1 = STLStream(packet=pkt_a,
+                       mode=STLTXCont(pps=100))
+
+        # second stream with a phase of 1ms (inter stream gap)
+        s2 = STLStream(packet=pkt_b,
+                       isg=1000,
+                       mode=STLTXCont(pps=100))
+
+
+        # connect to server
+        c.connect()
+
+        # prepare our ports (my machine has 0 <--> 1 with static route)
+        c.reset(ports=[0, 1])
+
+        # add both streams to ports
+        c.add_streams(s1, ports=[0])
+        c.add_streams(s2, ports=[1])
+
+        #warmup phase
+        if warmup == True:
+            c.clear_stats()
+            c.start(ports=[0, 1], mult=rate, duration=warmup_time)
+            c.wait_on_traffic(ports=[0, 1])
+            stats = c.get_stats()
+            print "#####warmup statistics#####"
+            print json.dumps(stats["port 0"], indent=4,
+                             separators=(',', ': '), sort_keys=True)
+            print json.dumps(stats["port 1"], indent=4,
+                             separators=(',', ': '), sort_keys=True)
+            lost_a = stats["port 0"]["opackets"] - stats["port 1"]["ipackets"]
+            lost_b = stats["port 1"]["opackets"] - stats["port 0"]["ipackets"]
+
+            print "\npackets lost from 0 --> 1:   {0} pkts".format(lost_a)
+            print "packets lost from 1 --> 0:   {0} pkts".format(lost_b)
+
+
+        # clear the stats before injecting
+        c.clear_stats()
+
+        # choose rate and start traffic
+        c.start(ports=[0, 1], mult=rate, duration=duration)
+
+        # block until done
+        c.wait_on_traffic(ports=[0, 1])
+
+        # read the stats after the test
+        stats = c.get_stats()
+
+        print "#####statistics#####"
+        print json.dumps(stats["port 0"], indent=4,
+                         separators=(',', ': '), sort_keys=True)
+        print json.dumps(stats["port 1"], indent=4,
+                         separators=(',', ': '), sort_keys=True)
+
+        lost_a = stats["port 0"]["opackets"] - stats["port 1"]["ipackets"]
+        lost_b = stats["port 1"]["opackets"] - stats["port 0"]["ipackets"]
+
+        total_sent = stats["port 0"]["opackets"] + stats["port 1"]["opackets"]
+        total_rcvd = stats["port 0"]["ipackets"] + stats["port 1"]["ipackets"]
+
+        print "\npackets lost from 0 --> 1:   {0} pkts".format(lost_a)
+        print "packets lost from 1 --> 0:   {0} pkts".format(lost_b)
+        print "rate={0}, totalReceived={1}, totalSent={2}, frameLoss={3}"\
+              .format(rate, total_rcvd, total_sent, lost_a+lost_b)
+
+        if (lost_a == 0) and (lost_b == 0):
+            passed = True
+        else:
+            passed = False
+
+    except STLError as e:
+        passed = False
+        print e
+
+    finally:
+        c.disconnect()
+
+def print_help():
+
+    print "args: [-h] -d <duration> -s <size of frame in bytes>"+\
+    " [-r] <traffic rate with unit: %, mpps> "+\
+    "--p1_src_mac <port1_src_mac> "+\
+    "--p1_dst_mac <port1_dst_mac> "+\
+    "--p1_src_start_ip <port1_src_start_ip> "+\
+    "--p1_src_end_ip <port1_src_end_ip> "+\
+    "--p1_dst_start_ip <port1_dst_start_ip> "+\
+    "--p1_dst_end_ip <port1_dst_end_ip> "+\
+    "--p2_src_mac <port2_src_mac> "+\
+    "--p2_dst_mac <port2_dst_mac> "+\
+    "--p2_src_start_ip <port2_src_start_ip> "+\
+    "--p2_src_end_ip <port2_src_end_ip> "+\
+    "--p2_dst_start_ip <port2_dst_start_ip> "+\
+    "--p2_dst_end_ip <port2_dst_end_ip>"
+
+
+def main(argv):
+
+    _duration = 10
+    _frame_size = 64
+    _rate = '1mpps'
+    _traffic_options = {}
+
+    try:
+        opts, args = getopt.getopt(argv, "hd:s:r:o:",
+                                   ["help",
+                                    "p1_src_mac=",
+                                    "p1_dst_mac=",
+                                    "p1_src_start_ip=",
+                                    "p1_src_end_ip=",
+                                    "p1_dst_start_ip=",
+                                    "p1_dst_end_ip=",
+                                    "p2_src_mac=",
+                                    "p2_dst_mac=",
+                                    "p2_src_start_ip=",
+                                    "p2_src_end_ip=",
+                                    "p2_dst_start_ip=",
+                                    "p2_dst_end_ip="])
+    except getopt.GetoptError:
+        print_help()
+        sys.exit(2)
+    for opt, arg in opts:
+        if opt in ('-h', "--help"):
+            print_help()
+            sys.exit()
+        elif opt == '-d':
+            _duration = int(arg)
+        elif opt == '-s':
+            _frame_size = int(arg)
+        elif opt == '-r':
+            _rate = arg
+        elif opt.startswith( "--p" ):
+            _traffic_options[opt[2:]] = arg
+
+    print _traffic_options
+    if len(_traffic_options) != 12:
+        print "Expected all 12 traffic options"
+        print_help()
+        sys.exit(2)
+
+    pkt_a, pkt_b = create_packets(_traffic_options,
+                                  frame_size=_frame_size)
+
+    simple_burst(pkt_a, pkt_b, duration=_duration, rate=_rate)
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
+
index b69cd2d..33b4e7b 100644 (file)
@@ -99,6 +99,8 @@ schema;type_tg:
     type:
       <<: *type_node_mapping_type
       enum: [TG]
     type:
       <<: *type_node_mapping_type
       enum: [TG]
+    subtype:
+      type: str
     interfaces:
       <<: *type_interface_tg
 
     interfaces:
       <<: *type_interface_tg
 
index e437ae6..6f8b9c0 100644 (file)
 | | Ipv6 icmp echo sweep | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes_ipv6_addr}
 
 | TG can route to first DUT egress interface
 | | Ipv6 icmp echo sweep | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes_ipv6_addr}
 
 | TG can route to first DUT egress interface
-| | Ipv6 tg to dut1 egress | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes_ipv6_addr}
+| | Ipv6 tg to dut1 egress | ${nodes['TG']} | ${nodes['DUT1']} |
+| | ...                    | ${nodes['DUT2']} | ${nodes_ipv6_addr}
 
 | TG can route to second DUT through first DUT
 
 | TG can route to second DUT through first DUT
-| | Ipv6 tg to dut2 via dut1 | ${nodes['TG']} | ${nodes['DUT1']} | ${nodes['DUT2']}
-| | ...                      | ${nodes_ipv6_addr}
+| | Ipv6 tg to dut2 via dut1 | ${nodes['TG']} | ${nodes['DUT1']}
+| | ...                      | ${nodes['DUT2']} | ${nodes_ipv6_addr}
 
 | TG can route to second DUT egress interface through first DUT
 | | Ipv6 tg to dut2 egress via dut1 | ${nodes['TG']} | ${nodes['DUT1']}
 
 | TG can route to second DUT egress interface through first DUT
 | | Ipv6 tg to dut2 egress via dut1 | ${nodes['TG']} | ${nodes['DUT1']}
index 4aaf150..36f49b3 100644 (file)
@@ -16,9 +16,9 @@
 | Resource | resources/libraries/robot/default.robot
 | Resource | resources/libraries/robot/l2_xconnect.robot
 | Force Tags | 3_NODE_SINGLE_LINK_TOPO
 | Resource | resources/libraries/robot/default.robot
 | Resource | resources/libraries/robot/l2_xconnect.robot
 | Force Tags | 3_NODE_SINGLE_LINK_TOPO
-| Test Setup | Setup all DUTs before test
-| Suite Setup | Setup all TGs before traffic script
-
+| Suite Setup | Run Keywords | Setup all DUTs before test
+| ...         | AND          | Setup all TGs before traffic script
+| ...         | AND          | Interfaces on all DUTs are in "up" state
 
 *** Test Cases ***
 
 
 *** Test Cases ***
 
index 5c04d5e..3d29485 100644 (file)
 *** Settings ***
 | Resource | resources/libraries/robot/default.robot
 | Resource | resources/libraries/robot/interfaces.robot
 *** Settings ***
 | Resource | resources/libraries/robot/default.robot
 | Resource | resources/libraries/robot/interfaces.robot
-| Library | resources/libraries/python/VatExecutor.py
+| Resource | resources/libraries/robot/bridge_domain.robot
+| Resource | resources/libraries/robot/ipv4.robot
 | Library | resources/libraries/python/TrafficGenerator.py
 | Library | resources/libraries/python/TrafficGenerator.py
+| Library | resources/libraries/python/CrossConnectSetup.py
 | Force Tags | topo-3node
 | Test Setup | Setup all DUTs before test
 | Force Tags | topo-3node
 | Test Setup | Setup all DUTs before test
+| Suite Setup | Initialize traffic generator | ${nodes['TG']}
+| ... | ${nodes['TG']['interfaces']['port3']['pci_address']}
+| ... | ${nodes['TG']['interfaces']['port5']['pci_address']}
+| Suite Teardown | Teardown traffic generator | ${nodes['TG']}
 
 *** Test Cases ***
 
 *** Test Cases ***
-| VPP passes traffic through L2 cross connect
-| | Given L2 xconnect initialized in topology
-| | Then Traffic should pass with no loss | 10 | 10 | 512
+| VPP passes 64B frames through L2 cross connect at 30% of linerate in 3-node-topology
+| | Given L2 xconnect initialized in a 3-node topology
+| | Then Traffic should pass with no loss | 10 | 30 | 64 | 3-node-xconnect
+
+| VPP passes 1518B frames through L2 cross connect at 100% of linerate in 3-node-topology
+| | Given L2 xconnect initialized in a 3-node topology
+| | Then Traffic should pass with no loss | 10 | 100 | 1518 | 3-node-xconnect
+
+| VPP passes 9000B frames through L2 cross connect at 100% of linerate in 3-node-topology
+| | Given L2 xconnect initialized in a 3-node topology
+| | Then Traffic should pass with no loss | 10 | 100 | 9000 | 3-node-xconnect
+
+| VPP passes 64B frames through bridge domain at 30% in 3-node topology
+| | Given L2 bridge domain initialized in a 3-node topology
+| | Then Traffic should pass with no loss | 10 | 30 | 64 | 3-node-bridge
+
+| VPP passes 1518B frames through bridge domain at 100% in 3-node topology
+| | Given L2 bridge domain initialized in a 3-node topology
+| | Then Traffic should pass with no loss | 10 | 100 | 1518 | 3-node-bridge
+
+| VPP passes 9000B frames through bridge domain at 100% in 3-node topology
+| | Given L2 bridge domain initialized in a 3-node topology
+| | Then Traffic should pass with no loss | 10 | 100 | 9000 | 3-node-bridge
+
+#| VPP passes 64B frames through IPv4 forwarding at 30% in 3-node topology
+#| | Given IPv4 forwarding initialized in a 3-node topology
+#| | Then Traffic should pass with no loss | 10 | 30 | 64 | 3-node-IPv4
+
+#| VPP passes 1518B frames through IPv4 forwarding at 100% in 3-node topology
+#| | Given IPv4 forwarding initialized in a 3-node topology
+#| | Then Traffic should pass with no loss | 10 | 100 | 1518 | 3-node-IPv4
+
+#| VPP passes 9000B frames through IPv4 forwarding at 100% in 3-node topology
+#| | Given IPv4 forwarding initialized in a 3-node topology
+#| | Then Traffic should pass with no loss | 10 | 100 | 9000 | 3-node-IPv4
+
 
 *** Keywords ***
 
 *** Keywords ***
-| L2 xconnect initialized in topology
-| | Setup L2 xconnect | ${nodes['DUT1']} | port1 | port2
-| | Setup L2 xconnect | ${nodes['DUT2']} | port1 | port2
 
 
 
 
-| Setup L2 xconnect | [Arguments] | ${node} | ${src_port} | ${dst_port}
-| | Execute script | l2xconnect.vat | ${node}
-| | Script should have passed
+| L2 xconnect initialized in a 3-node topology
+| | Interfaces on DUT are in "up" state
+| | L2 setup xconnect on DUTs
+
+| L2 setup xconnect on DUTs
+| | Vpp Setup Bidirectional Cross Connect | ${nodes['DUT1']}
+| | ... | ${nodes['DUT1']['interfaces']['port1']['name']}
+| | ... | ${nodes['DUT1']['interfaces']['port3']['name']}
+| | Vpp Setup Bidirectional Cross Connect | ${nodes['DUT2']}
+| | ... | ${nodes['DUT2']['interfaces']['port1']['name']}
+| | ... | ${nodes['DUT2']['interfaces']['port3']['name']}
+
+| L2 bridge domain initialized in a 3-node topology
+| | ${tg}= | Set Variable | ${nodes['TG']}
+| | ${dut1}= | Set Variable | ${nodes['DUT1']}
+| | ${dut2}= | Set Variable | ${nodes['DUT2']}
+| | ${tg_links}= | bridge_domain.Setup TG "${tg}" DUT1 "${dut1}" And DUT2 "${dut2}" For 3 Node L2 Bridge Domain Test
+
+| IPv4 forwarding initialized in a 3-node topology
+| | Setup DUT nodes for IPv4 testing
 
 
+| Interfaces on DUT are in "${state}" state
+| | Node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port1']['name']}" is in "${state}" state
+| | Node "${nodes['DUT1']}" interface "${nodes['DUT1']['interfaces']['port3']['name']}" is in "${state}" state
+| | Node "${nodes['DUT2']}" interface "${nodes['DUT2']['interfaces']['port1']['name']}" is in "${state}" state
+| | Node "${nodes['DUT2']}" interface "${nodes['DUT2']['interfaces']['port3']['name']}" is in "${state}" state
 
 | Traffic should pass with no loss
 
 | Traffic should pass with no loss
-| | [Arguments] | ${duration} | ${rate} | ${framesize}
-| | Send traffic on | ${nodes['TG']} | port1 | port2 | ${duration}
-| | ...             | ${rate} | ${framesize}
+| | [Arguments] | ${duration} | ${rate} | ${framesize} | ${topology_type}
+| | Send traffic on | ${nodes} | ${duration}
+| | ...             | ${rate} | ${framesize} | ${topology_type}
 | | No traffic loss occured
 | | No traffic loss occured