Commit baba3f1eded447bc43610358e56c5aba0eb17669

Authored by Julien LANGLOIS
1 parent 29763531

regress, secchan, testes, third-party, utilities

Showing 531 changed files with 67615 additions and 0 deletions

Too many changes to show.

To preserve performance only 43 of 531 files are displayed.

regress/CREDITS 0 → 100755
  1 +Credit goes to those who contributed code to the regression suite. Unless
  2 +otherwise noted, the contributors are at Stanford University.
  3 +
  4 +
  5 +Test writers/editors:
  6 + Clay Collier
  7 + David Erickson
  8 + Mikio Hara (NEC)
  9 + Brandon Heller
  10 + Peyman Kazemian
  11 + Masayoshi Kobayashi (NEC)
  12 + Bob Lantz
  13 + Brandon Nefcy
  14 + Rob Sherwood (Deutsche Telekom R&D Labs)
  15 + Jean Tourrilhes (HP Labs)
  16 + Tatsuya Yabe (NEC)
  17 + Yiannis Yiakoumis
  18 +
  19 +Supporting libraries:
  20 + Adam Covington
  21 + Glen Gibb
  22 + Jad Naous
... ...
regress/INSTALL 0 → 100755
  1 + Installation Instructions for OpenFlow Reference Tests
  2 +
  3 +This document describes how to install and execute the OpenFlow reference test
  4 +suite, which provides an automated way to verify that an OpenFlow switch
  5 +adheres to the OpenFlow Protocol. Out of the box, tests work with the OpenFlow
  6 +Reference Linux Switch, but can support other platforms by defining custom
  7 +setup and teardown scripts. Additional tests verify the reference learning
  8 +Ethernet switch controller included with the OpenFlow Reference Linux Switch.
  9 +
  10 +Please send any comments to:
  11 +
  12 + <openflow-discuss@openflowswitch.org>
  13 +
  14 +=== Prerequisites ===
  15 +
  16 +The tests require no other packets to be sent on the testing interfaces.
  17 +Built-in programs like avahi-daemon and/or network-manager may send packets,
  18 +causing the tests to report failure. The simplest way to remove these packets
  19 +is to disable the ipv6 module and reboot, as well as remove avahi-daemon.
  20 +
  21 +All test configurations require the following Perl modules:
  22 + perl-Convert-Binary-C
  23 + perl-Data-HexDump
  24 + perl-Net-Pcap (perl-Net-Pcap-0.16-1)
  25 + perl-Net-RawIP.i386 (perl-Net-RawIP-0.23-1)
  26 + perl-Error.noarch (perl-Error-0.17012-1)
  27 +
  28 +These packages can be installed from source via www.cpan.org, or you can use
  29 +pre-built packages (much faster!).
  30 +
  31 +The code has been tested on CentOS 5.1/5.2, Ubuntu Hardy Heron, and Debian
  32 +Unstable under the following configurations.
  33 +
  34 +** Config 1 - Four virtual Ethernet loopback pairs
  35 +
  36 +To set these up, you must have a kernel version >= 2.6.24 and the veth kernel
  37 +module compiled.
  38 +
  39 +To set up link pairs, you must also have iproute installed.
  40 +
  41 +Scripts to simplify this are included in bin/:
  42 +-bin/veth_setup.pl
  43 +-bin/veth_teardown.pl
  44 +
  45 +Before running any veth tests, make sure to run bin/veth_setup.pl, which will
  46 +create interfaces veth{0..7}. The usual ports of eth{1..8} are remapped to these
  47 +ports via the file veth.map in /bin/. To remove these interfaces, run
  48 +bin/veth_teardown.pl
  49 +
  50 +** Config 2 - Two quad-port Ethernet NICs connected by physical loopback cables
  51 +
  52 +Assign ports as eth{1..8} and connect cables as:
  53 + eth1 to eth5
  54 + eth2 to eth6
  55 + eth3 to eth7
  56 + eth4 to eth8
  57 +
  58 +** Config 3 - Four local ethernet ports connected to external switch
  59 +
  60 +A third configuration is to use four ports of Ethernet on the test machine,
  61 +connected to an external switch. To do this, you must provide custom setup
  62 +and teardown scripts that enable/disable OpenFlow on the external switch via
  63 +SSH, telnet, or SNMP. See the scripts in bin/ for examples of how to create
  64 +these.
  65 +
  66 +** Config 4 - One quad-port Ethernet NIC connected to a NetFPGA
  67 +
  68 +This testing configuration is used to verify the NetFPGA's OpenFlow
  69 +functionality. It requires 4 ports of Ethernet connected to corresponding ports
  70 +on the NetFPGA in the following arrangement:
  71 + eth1 to nf2c0
  72 + eth2 to nf2c1
  73 + eth3 to nf2c2
  74 + eth4 to nf2c3
  75 +
  76 +This test also assumes that you have correctly installed the NetFPGA ahead of
  77 +time. For further information about the NetFPGA please see
  78 +http://www.netfpga.org/
  79 +
  80 +Of particular note, by default installing the NetFPGA also puts the
  81 +NF2/lib/Perl5 directory into your PERL5LIB environment variable, this must be
  82 +removed else the tests will fail. Ensure that your PERL5LIB only contains the
  83 +path set by the env_vars file that will be discussed later in this document.
  84 +
  85 +
  86 +=== Ubuntu Quickstart ===
  87 +
  88 +Follow these instructions to quickly create a VM or physical machine with
  89 +OpenFlow that runs the tests.
  90 +
  91 +Ubuntu is recommended because it is based on Debian sources and has a recent
  92 +kernel version - which removes the need for some steps.
  93 +
  94 +If installing as a VM, you'll need to install VMWare Server (Windows/Linux,
  95 +free) or VMWare Fusion (Mac, $$$).
  96 +
  97 +Download the Ubuntu 8.04 Desktop or Server ISO, and install Ubuntu.
  98 +
  99 +If you prefer, install VMWare Tools to enable better mouse and display support.
  100 +Alternately, install SSH and use it for the rest of the instructions:
  101 + sudo apt-get install ssh
  102 +Install GCC, which is required for OpenFlow:
  103 + sudo apt-get install gcc
  104 +Download and untar OpenFlow v0.8.1
  105 + wget http://openflowswitch.org/downloads/openflow-v0.8.1.tar.gz
  106 + tar xzf openflow-v0.8.1.tar.gz
  107 +Build OpenFlow user-space and kernel-space switches:
  108 + cd openflow-v0.8.1
  109 + ./configure --with-l26=/lib/modules/`uname -r`
  110 + make
  111 + sudo make install
  112 +Now, download and untar the OpenFlow Test Suite:
  113 + wget http://openflowswitch.org/downloads/openflow-test-v0.8.1-r2.tar.gz
  114 +Install required packages for the test suite:
  115 + sudo apt-get install liberror-perl libio-interface-perl liblist-moreutils-perl libpcap0.8-dev
  116 +Download the following:
  117 + wget http://search.cpan.org/CPAN/authors/id/S/SA/SAPER/Net-Pcap-0.14.tar.gz
  118 + wget http://search.cpan.org/CPAN/authors/id/S/SZ/SZABGAB/Net-RawIP-0.21.tar.gz
  119 + wget http://search.cpan.org/CPAN/authors/id/M/MH/MHX/Convert-Binary-C-0.71.tar.gz
  120 + wget http://search.cpan.org/CPAN/authors/id/F/FT/FTASSIN/Data-HexDump-0.02.tar.gz
  121 +For each package:
  122 + tar xzf <package.tar.gz>
  123 + cd <package>
  124 + perl Makefile.PL
  125 + make
  126 + make install
  127 +Remove avahi-daemon, which often causes tests to fail by sending out messages:
  128 + sudo apt-get remove avahi-daemon
  129 +Create a root password, to be used later:
  130 + sudo passwd root
  131 +
  132 +From here, skip to the Running The Tests section below.
  133 +
  134 +
  135 +=== CentOS 5.2 ===
  136 +
  137 +First, download and verify you can build the current version of OpenFlow.
  138 +
  139 +Install the RPMForge repository:
  140 + wget http://dag.wieers.com/rpm/packages/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
  141 + rpm -Uhv rpmforge-release-0.3.6-1.el5.rf.i386.rpm
  142 +
  143 +Install Perl packages:
  144 + yum -y install perl-Convert-Binary-C perl-Data-HexDump perl-Net-Pcap perl-Net-RawIP.i386 perl-Error.noarch
  145 +
  146 +To run tests with Veth pairs, you'll need to upgrade to a newer version of the kernel.
  147 +
  148 +Install iproute:
  149 + yum -y install iproute
  150 +
  151 +From here, skip to the Running The Tests section below.
  152 +
  153 +=== Debian Install ===
  154 +
  155 +These instructions derive from http://netfpga.org/netfpgawiki/index.php/Ubuntu_Compatibility
  156 +
  157 +Some instructions may no longer be necessary.
  158 +
  159 +*The version of libnet-pcap-perl that Debian and Ubuntu 6.06/7.04/7.10 provides is ANCIENT (version 0.04). The latest stable version is 0.14. No newer version is available as a package, so we must build it ourselves.
  160 +*The version of libpcap that Debian and Ubuntu 7.04 provides by default is old (version 0.72). The latest stable version is 0.9.8. Fortunately, the package manager has a newer version called "libpcap0.8" that is really version 0.9.5
  161 +*Remove old packages / install new ones
  162 +
  163 +May not be necessary:
  164 + apt-get remove libpcap0.7 libpcap0.7-dev libpcap-dev libnet-pcap-perl
  165 +
  166 +Will be necessary:
  167 + apt-get install liberror-perl libio-interface-perl liblist-moreutils-perl libpcap0.8 libpcap0.8-dev psmisc
  168 +Listed individually:
  169 + apt-get install liberror-perl
  170 + apt-get install libio-interface-perl (Used to manually build a newer version of Net::PCap)
  171 + apt-get install liblist-moreutils-perl (Used to manually build a newer version of Net::RawIP)
  172 + apt-get install libpcap0.8
  173 + apt-get install libpcap0.8-dev
  174 + apt-get install psmisc (Used to get killall)
  175 +
  176 +Required packages have Debian versions at packages.debian.org, however these packages may not be the newest, or not exist at all. libnet-rawip-perl and libnet-pacp-perl may work, but have not been tested. We'll manually install these two packages:
  177 +http://search.cpan.org/~saper/Net-Pcap-0.14/Pcap.pm
  178 +http://search.cpan.org/~szabgab/Net-RawIP-0.21/lib/Net/RawIP.pm
  179 +http://search.cpan.org/dist/Convert-Binary-C/lib/Convert/Binary/C.pm
  180 +http://search.cpan.org/dist/Data-HexDump/lib/Data/HexDump.pm
  181 +
  182 +Download the following:
  183 + wget http://search.cpan.org/CPAN/authors/id/S/SA/SAPER/Net-Pcap-0.14.tar.gz
  184 + wget http://search.cpan.org/CPAN/authors/id/S/SZ/SZABGAB/Net-RawIP-0.21.tar.gz
  185 + wget http://search.cpan.org/CPAN/authors/id/M/MH/MHX/Convert-Binary-C-0.71.tar.gz
  186 + wget http://search.cpan.org/CPAN/authors/id/F/FT/FTASSIN/Data-HexDump-0.02.tar.gz
  187 +For each package:
  188 + tar xzf <package.tar.gz>
  189 + cd <package>
  190 + perl Makefile.PL
  191 + make
  192 + make install
  193 +
  194 +Install if you want to use veth pairs:
  195 + apt-get install iproute
  196 +
  197 +=== Running the Tests ===
  198 +
  199 +In the sections below, {platform} refers to:
  200 +user
  201 +user_veth
  202 +kmod
  203 +kmod_veth
  204 +nf2
  205 +
  206 +First copy the env_vars file to your home directory:
  207 + cd ~/
  208 + cp <openflow_dir>/regress/scripts/env_vars .
  209 +
  210 +Update the OF_ROOT (openflow) environment variable to point to your OpenFlow
  211 +directory in your setup. These exports can also be added to your ~/.bashrc
  212 +file to load automatically:
  213 + vim env_vars
  214 +
  215 +Enter a root shell session, or set up sudo. The perl-Net-RawIP library requires
  216 +root access to bind to ports.
  217 + su
  218 +
  219 +Source the environment variables:
  220 + source env_vars
  221 +
  222 +For a setup with virtual ethernet pairs, set them up:
  223 + veth_setup.pl
  224 +
  225 +Verify your setup by running regression tests on your platform of choice:
  226 + of_{platform}_test.pl
  227 +For the user-space switch, the tests should show pass for all scripts except
  228 +the _X_controller ones. For the kernel-space switch, all tests should pass.
  229 +
  230 +To see more options for the regression script, type:
  231 + of_{platform}_test.pl --help
  232 +
  233 +== Writing Your Own Tests ==
  234 +
  235 +Look at an example controller test:
  236 + vim <openflow_dir>/regress/projects/learning_switch/regress/test_unicast_unknown/run.pl
  237 +
  238 +Look at an example black box switch test:
  239 + vim <openflow_dir>/regress/projects/black_box/regress/test_hello/run.pl
  240 +
  241 +To run an individual test (learning switch example):
  242 + cd <openflow_dir>/regres/projects/learning_switch/regress/test_unicast_unknown
  243 + of_{platform}_setup.pl; ./run.pl; of_{platform}_teardown.pl
  244 +
  245 +To see traffic when running a black box test, use tcpdump. Secchan and the
  246 +Perl code use the loopback interface to communicate, and you can snoop on this:
  247 + tcpdump -X -i lo -s 256
  248 +
  249 +It can be convenient to run your test in isolation, without setup and teardown
  250 +automatically called. To set up the OF kmod and interfaces, run:
  251 + of_{platform}_setup.pl
  252 +
  253 +To remove the OF kmod cleanly, run:
  254 + of_{platform}_teardown.pl
  255 +Note that the kmod refuses removal until the interfaces and datapaths have been removed.
  256 +
  257 +== Reporting Bugs ==
  258 +
  259 +Please report problems to:
  260 +openflow-discuss@openflowswitch.org
  261 +
  262 +or post them directly to our bug tracking system:
  263 +
  264 +http://www.openflowswitch.org/bugs/openflow
... ...
regress/LICENSE 0 → 100755
  1 +Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
  2 +University
  3 +
  4 +
  5 +We are making the OpenFlow tests and associated documentation (Software)
  6 +available for public use and benefit with the expectation that others will
  7 +use, modify and enhance the Software and contribute those enhancements back
  8 +to the community. However, since we would like to make the Software
  9 +available for broadest use, with as few restrictions as possible permission
  10 +is hereby granted, free of charge, to any person obtaining a copy of this
  11 +Software) to deal in the Software under the copyrights without restriction,
  12 +including without limitation the rights to use, copy, modify, merge,
  13 +publish, distribute, sublicense, and/or sell copies of the Software, and to
  14 +permit persons to whom the Software is furnished to do so, subject to the
  15 +following conditions:
  16 +
  17 +The above copyright notice and this permission notice shall be included in
  18 +all copies or substantial portions of the Software.
  19 +
  20 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  26 +DEALINGS IN THE SOFTWARE.
  27 +
  28 +The name and trademarks of copyright holder(s) may NOT be used in
  29 +advertising or publicity pertaining to the Software or any derivatives
  30 +without specific, written prior permission.
... ...
regress/README 0 → 100755
  1 + OpenFlow Reference Tests <http://openflowswitch.org>
  2 +
  3 +What's here?
  4 +------------
  5 +
  6 +This distribution includes:
  7 +
  8 + - 55+ "black box" tests to verify that an OF switch conforms to the
  9 + OF protocol 0x01
  10 +
  11 + - 7 tests to verify that the reference controller acts as a learning
  12 + Ethernet switch
  13 +
  14 +The tests are intended to simplify the process of creating an OF switch
  15 +that conforms to spec.
  16 +
  17 +Please see INSTALL for instruction on installing and running the tests.
  18 +
  19 +Changelog
  20 +---------------
  21 +1.0.0-r1
  22 + - Added Open vSwitch scripts : kernel + user + interface maps
  23 + - Added VETH scripts for Open vSwitch : kernel + user
  24 + - Updated HP-ProCurve scipts : 5400/3500 and 6600
  25 + - Assorted fixes to libraries :
  26 + accept port > 10
  27 + accept vlan interfaces
  28 + more explicit error messages
  29 + - Assorted fixes to tests :
  30 + test_switch_config/ -> add delay
  31 + test_forward_broadcast_exact_port/ -> run for allports
  32 + test_set_n_match_nw_tos/ -> fixup nw_tos usage
  33 + test_set_nw_dst/ -> cleanup
  34 + test_failover_startup/ -> argv parsing was broken
  35 + - Add new test : test_set_dl_nw_flip -> flip dl & nw addresses
  36 + - Add new command line options : no_vlan, no_slicing and no_barrier,
  37 + no_emerg
  38 + - Add ability to run a single test with --testPath
  39 + - New debugging function : dpctl_show_flows
  40 +
  41 +1.0.0
  42 + - all tests updated to OpenFlow wire protocol 0x01
  43 + - added tests for new features in the OpenFlow 1.0.0 spec
  44 +
  45 +0.9.0
  46 + - all tests updated to OpenFlow wire protocol 0x98
  47 +
  48 +v0.8.2
  49 + - Added support for the NetFPGA
  50 + - Integrated the tests into the OpenFlow directory structure
  51 +
  52 +v0.8.1-r2
  53 + - refactored code to make new test ports easier
  54 + - fixed documentation bug in test_LLC
  55 + - changed all interfaces IPs to 192.168.20X.X to not conflict with the
  56 + IP addrs typically assigned via DHCP by home routers
  57 + - added easy support for testing user-space switch with physical ports
  58 + - added easy support for user-space switch with virtual ports
  59 +
  60 +v0.8.1-r1
  61 + - added instructions for Debian install
  62 + - fixed timing bug in packet_out
  63 +
  64 +v0.8.1-r0
  65 + - all tests updated to OF spec v0.8.1
  66 + - added black box test switch_config
  67 + - fixed timing dependence in learning switch tests
  68 +
  69 +v0.2.1
  70 + - initial release for OF spec v0.5.1, code tested for ref OF code v0.2.1
  71 +
  72 +Platform support
  73 +----------------
  74 +
  75 +The code is written in Perl5, and should in theory work on any system.
  76 +It has been tested with CentOS 5.4, Ubuntu 9.10, Fedora Core 12, and Debian Unstable.
  77 +
  78 +Learning Switch Tests
  79 +----------------
  80 +
  81 +Two tests currently fail with OF Reference v0.8.1:
  82 +
  83 +-Unicast, send to self: the switch is forwarding packets with source and destination on the same port to that port instead of dropping it.
  84 +
  85 +-Unicast, hub connected:the switch is forwarding traffic to the same port it has came out of, although the source and destination are on the same port and switch already knows about that.
  86 +
  87 +Both failing tests can be re-activated by changing
  88 +projects/learning_switch/regress/tests.txt
  89 +
  90 +=== Unicast, unknown dest ===
  91 +:; Name: test_unicast_unknown
  92 +:; Owner: Peyman
  93 +:; Description
  94 +::send packet out p0 to unknown MAC addr
  95 +::verify unmodified packet received at p1..p3
  96 +::verify counters incremented
  97 +
  98 +=== Unicast, known dest ===
  99 +:; Name: test_unicast_known
  100 +:; Owner: Peyman
  101 +:; Description: Send to known unicast address, verify switch sent to only one port
  102 +::send out p0 to p1
  103 +::verify received at p1..p3
  104 +::send out p1 to p0
  105 +::verify received at p0, NOT p2, p3
  106 +::send out p2 to p0
  107 +::verify received at p0, NOT p1, p3
  108 +::send out p3 to p0
  109 +::verify received at p0, NOT p1, p2
  110 +::verify counters
  111 +
  112 +=== Broadcast ===
  113 +:; Name: test_broadcast
  114 +:; Owner: Peyman
  115 +:; Description: Send to broadcast address, verify received on all ports
  116 +::send out p0 to all
  117 +::verify received at p1..p3
  118 +::send out p0 to all, again
  119 +::verify received at p1..p3, again
  120 +::repeat for each port
  121 +::verify counters
  122 +
  123 +=== Unicast, send to self ===
  124 +:; Name: test_unicast_self
  125 +:; Owner: Peyman
  126 +:; Description: Send to self, verify dropped
  127 +
  128 +=== Unicast, change attachment point ===
  129 +:; Name: test_unicast_move
  130 +:; Owner: Peyman
  131 +:; Description: Send normal unicast, but then change attachment point (one MAC sent from multiple ports), verify that new location is used
  132 +::send form host A at p0 to p1
  133 +::verify received at p1..p3
  134 +::send from p1 to host A
  135 +::verify received at p0, NOT p1, p2, p3
  136 +::(original p0 has now moves to p2)
  137 +::send from host A (currently at p2) to p1
  138 +::verify received at p1, NOT p0, p2, p3
  139 +::send from p1 to Host A (currently at p2)
  140 +::verify received p2, NOT p0, p1, p3
  141 +
  142 +=== Unicast, hub connected ===
  143 +:; Name: test_hub_connected
  144 +:; Owner: Peyman
  145 +:; Description: if a port connects to a hub, we may receive traffic for which the sender and receiver are connected to the same port. This traffic should be dropped.
  146 +
  147 +=== Unicast, multiple hosts per port ===
  148 +:; Name: test_unicast_multiple_hosts
  149 +:; Owner: Peyman
  150 +:; Description: assume each port is connected to a switch, so that each port receives traffic from multiple MAC addresses - say, 20 per port. Other than multiple MAC addrs per port, this is just like test_unicast_known. Each port sends to a host at a different port.
  151 +
  152 +
  153 +Black Box Tests
  154 +----------------
  155 +
  156 +One test currently fails with the OF Reference v0.8.1 kmod:
  157 +
  158 +-LLC: Pkt is forwarded to the controller, when it should be dropped.
  159 +
  160 +Two tests are currently failing with the OF Reference v0.8.1 user-space switch:
  161 +
  162 +-test_forward_exact_controller
  163 +-test_forward_wildcard_controller
  164 +
  165 +All failing tests can be re-activated by changing
  166 +projects/black_box/regress/tests.txt
  167 +
  168 +== Basic Functionality ==
  169 +
  170 +=== Hello ===
  171 +:; Name: test_hello
  172 +:; Owner: Brandon Heller
  173 +:; Description: send hello packet to switch, verify reply with correct params
  174 +
  175 +=== Send from Switch to Controller ===
  176 +:; Name: test_packet_in
  177 +:; Owner: Brandon Heller
  178 +:; Description: send packet from switch to SC, verify it is received at the controller
  179 +
  180 +=== Send from Controller to Switch ===
  181 +:; Name: test_packet_out
  182 +:; Owner: Brandon Heller
  183 +:; Description: send packet to switch on secure chan for each output port, ensure packet received at proper ports.
  184 +
  185 +=== Switch Config ===
  186 +:; Name: test_switch_config
  187 +:; Owner: Brandon Heller
  188 +:; Description: verify default switch config, set config, verify that config has changed
  189 +:; Status: done
  190 +
  191 +=== Flow Expired ===
  192 +:; Name: test_flow_expired
  193 +:; Owner: Brandon Heller
  194 +:; Description: send add flow message for short timeout, verify no error message received, plus flow timeout message received within time bounds
  195 +::send a second add flow message and keep it active with packets; verify that flow expires only if idle
  196 +
  197 +=== Miss Send Length ===
  198 +:; Name: test_miss_send_length
  199 +:; Owner: Brandon Heller
  200 +:; Description: get the miss send length from the hello message, then send a packet to switch, verify correct length for forwarded chunk of packet
  201 +
  202 +== Modify State Tests ==
  203 +
  204 +=== Forward Any Port ===
  205 +:; Name: test_forward_any_port
  206 +:; Owner: Brandon Heller
  207 +:; Description: add a flow mod with all wildcards set, and ensure that all packets get diverted to the specified port.
  208 +
  209 +=== Forward Exact Port ===
  210 +:; Name: test_forward_exact_port
  211 +:; Owner: Brandon Heller
  212 +:; Description: add an exact flow entry, verify a packet is forwarded to the correct port, for all port combinations
  213 +
  214 +=== Forward Exact ALL ===
  215 +:; Name: test_forward_exact_all
  216 +:; Owner: Brandon Nefcy
  217 +:; Description: add an exact flow entry, verify a packet is sent out all ports, for all port combinations
  218 +:; Implementation: One packet is sent in to eth0, eth1, eth2, and eth3. An exact match flow entry is set up for each, with the expected action to be flooding the packet out on all ports except the input port.
  219 +
  220 +=== Forward Exact Controller ===
  221 +:; Name: test_forward_exact_controller
  222 +:; Owner: Brandon Nefcy
  223 +:; Description: add an exact flow entry, verify a packet is forwarded to the secure channel
  224 +:; Implementation: One packet is sent in on each of eth0, eth1, eth2, and eth3. Test behavior expects to see each packet arrive via the secchan.
  225 +
  226 +=== Forward Wildcard Port ===
  227 +:; Name: test_forward_wildcard_port
  228 +:; Owner: Brandon Nefcy
  229 +:; Description: Test each individual wildcard field. verify a matching packet is forwarded to the correct port, for all port combinations, and a mismatching packet is sent to secchan
  230 +:; Implementation: For each possible single-input-port to single-output-port combination flows are set up, one at a time, where each flow is wildcarded on a single field, with enough flows rotated in to test every wildcard field. For each, a matching packet is sent in and expected on the appropriate output port, and a mismatching packet is sent in and expected on the secchan output
  231 +
  232 +=== Forward Wildcard ALL ===
  233 +:; Name: test_forward_wildcard_all
  234 +:; Owner: Brandon Nefcy
  235 +:; Description: same as test_forward_wildcard_port, but instead of sending from one input to one output, sends from one input to all outputs.
  236 +:; Implementation: Combination of test_foward_wildcard_port and test_forward_exact_all
  237 +
  238 +=== Forward Wildcard Controller ===
  239 +:; Name: test_forward_wildcard_controller
  240 +:; Owner: Brandon Nefcy
  241 +:; Description: Combination of test_forward_wildcard_port and test_forward_exact_controller. Tests various single wildcard flows where matching packets and mismatching packets are both sent to secchan.
  242 +:; Status: Checked in, working, but with limitations as mentioned in test_forward_wildcard_port
  243 +
  244 +=== Forward After Expiration ===
  245 +:; Name: test_forward_after_expiration
  246 +:; Owner: Brandon Nefcy
  247 +:; Description: insert short-lived flow, use it to forward packet, wait until expiration, send packet again, verify nothing received and counters zeroed
  248 +:; Implementation: An exact match flow entry is inserted for a specific input port -> output port combination (ie eth0->eth1), a packet is sent to match this entry with the test expecting the appropriate output behavior. The test waits for the flow entry to expire and verifies the expiration via a secchan flow expiration message, then proceeds to re-send the same packet from before, expecting a secchan OFPR_NO_MATCH message. The above is repeated for all combinations of input port -> output port.
  249 +
  250 +=== Overlapping Flow Entries ===
  251 +:; Name: test_forward_overlapping_flow_entries
  252 +:; Owner: Brandon Nefcy
  253 +:; Description: insert both wildcard and exact match flow entries that overlap, verify that the exact match takes precedence
  254 +:; Implementation: One packet is sent in on eth0, eth1, eth2, and eth3. Before each packet is sent, two flow entries are set up, one where the entire flow is wildcarded and the action is to send to secchan, and another where the flow is set up to be an exact-match for the packet about to be sent and the action is to flood the packet. The test verifies that the sent packets are flooded out, and no secchan messages are received other than the flows expiring.
  255 +
  256 +=== Delete ===
  257 +:; Name: test_delete
  258 +:; Owner: Masa
  259 +:; Description: insert two flow entries (one wildcard entry and one exact entry where the exact one is covered by the wildcard one). Send packets to verify they are forwarded correctly. Then delete the wildcard entry with DELETE (not strict) -- both the wildcard and the exeact entries should be deleted. To check this, send a packet matching to the exact entry to verify it gets sent to contoller. Re-insert the entry and verify that counters are zeroed.
  260 +::; Note -- Counter reading has not been implemented yet so the last part is not verified (5/2/2008)
  261 +:; Status: Done (rewritten with clean format)
  262 +
  263 +=== Delete Strict ===
  264 +:; Name: test_delete_strict
  265 +:; Owner: Masa
  266 +:; Description: insert two flow entries (one wildcard entry and one exact entry where the exact one is covered by the wildcard one. The output ports of these two entries are different). Send packets to verify they are forwarded correctly. Then delete the wildcard entry with DELETE_STRICT (not strict) -- only the wildcard entry should be deleted (the exeact entry should not be deleted). To check this, send a packet matching to the exact entry to verify it gets forwarded.
  267 +:; Status: Done (rewritten with clean format)
  268 +
  269 +== Unusual Data ==
  270 +
  271 +=== IP Options ===
  272 +:; Name: test_ip_options
  273 +:; Owner: Masa
  274 +:; Description: suggested by Nicira.
  275 +::;(1) Create a flow entry that matches to a UDP flow coming from port eth7 (action = forward to port eth8).
  276 +::;(2) Send UDP packets with IP time stamp option (ip_hdr_len=7) to port eth7.
  277 +::;(3) To see whether the packet comes out from port eth8.
  278 +::; As of May 2, 2008, test succeeded.
  279 +
  280 +=== IP Protocol ===
  281 +:; Name: test_ip_protocol
  282 +:; Owner: Masa
  283 +:; Description:
  284 +:: Added by Masa
  285 +:: see if src/dst port fields are used for matching only for TCP/UDP packets
  286 +:: As of May 2, 2008, the result is the following. Even if protocol is not TCP nor UDP, port number fields seems used for matching. Only when protocol number is specified to zero, port number fields are not used for matching.. It seems a strange behavior.
  287 +:; Status: Done (rewritten w/ clean format)
  288 +:; Note : TCP checksum (in TCP header) is not calculated due to lack of NF2::TCP library (but OF switch won't check it anyway).
  289 +
  290 +=== IP Offset > Pkt Len ===
  291 +:; Name: test_ip_offset
  292 +:; Owner: Masa
  293 +:; Description:
  294 +:: possible security risk, shouldn't be an issue
  295 +:: suggested by Nicira
  296 +:: Create a flow entry. Send several packets matching the entry but whose IP Offset > Pkt Len. Verify all the packets are forwarded to the specified port (specified by the flow entry).
  297 +
  298 +=== TCP Options ===
  299 +:; Name: test_tcp_options
  300 +:; Owner: Masa
  301 +:; Description:
  302 +:: See if TCP options affect operation
  303 +:: Install a TCP flow entry. Sent a TCP pkt that matches to the installed entry but has TCP option. Verify the packet is forwarded to the specified port.
  304 +:; Note : TCP checksum (in TCP header) is not calculated due to lack of NF2::TCP library (but OF switch won't check it anyway).
  305 +
  306 +=== LLC ===
  307 +:; Name: test_llc
  308 +:; Owner: Masa
  309 +:; Description: see LLC packet format; adds 5B to Eth packet
  310 +::; Install a flow entry (exact match to an IP flow). Send an IP packet that matches to the installed entry and has the following Ethernet LLC/SNAP header. Verify it is forwarded to the specified port.
  311 +:::; Dst MAC (6 byte)
  312 +:::; Src MAC (6 byte)
  313 +:::; Length (2 byte) = data length from LLC header to the end of IP packet
  314 +:::; LLC header (3 byte) = 0xAA 0xAA 0x03 (always this value for IP packets)
  315 +:::; SNAP header(5 byte) = OUI(3B)+Type(2B)=0x000000 + 0x0800(IP) (always this value for IP packets)
  316 +:::; IP Packet
  317 +:; NOTE: It fails (pkt is forwarded to the controller) as of June 11, 2008.
  318 +
  319 +
  320 +Bugs/Shortcomings
  321 +-----------------
  322 +
  323 +- test_llc and test_ip_protocol are not actually run when enabled in a tests.txt file
  324 +
  325 +Contact
  326 +-------
  327 +
  328 +e-mail: openflow-discuss@openflowswitch.org
  329 +www: http://openflowswitch.org/
... ...
regress/bin/eth.map 0 → 100755
  1 +eth1:eth1
  2 +eth2:eth2
  3 +eth3:eth3
  4 +eth4:eth4
  5 +eth5:eth5
  6 +eth6:eth6
  7 +eth7:eth7
  8 +eth8:eth8
... ...
regress/bin/nf2.map 0 → 100755
  1 +eth1:eth1
  2 +eth2:eth2
  3 +eth3:eth3
  4 +eth4:eth4
  5 +eth5:nf2c0
  6 +eth6:nf2c1
  7 +eth7:nf2c2
  8 +eth8:nf2c3
... ...
regress/bin/of_hp_eth.map 0 → 100755
  1 +eth1:eth10
  2 +eth2:eth11
  3 +eth3:eth12
  4 +eth4:eth13
  5 +eth5:eth10
  6 +eth6:eth11
  7 +eth7:eth12
  8 +eth8:eth13
... ...
regress/bin/of_hp_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +use Time::HiRes qw(usleep);
  8 +
  9 +my $mapFile;
  10 +my $of_hp_switch_ip;
  11 +my $of_hp_vlan;
  12 +my $of_hp_controller;
  13 +my $of_hp_listener;
  14 +my $of_hp_community;
  15 +
  16 +# Process command line options
  17 +# Don't fail on unrecognised options, those failures are tricky
  18 +# to diagnose. For example projects/controller_disconnect sets --emerg
  19 +# Jean II
  20 +Getopt::Long::Configure( 'pass_through' );
  21 +GetOptions( "map=s" => \$mapFile, );
  22 +Getopt::Long::Configure( 'default' );
  23 +
  24 +# If not specified on command line, use environment variable.
  25 +# Try specific first, then try generic - Jean II
  26 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_HP_MAP_ETH'})) ) {
  27 + $mapFile = "$ENV{OFT_HP_MAP_ETH}";
  28 +}
  29 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_MAP_ETH'})) ) {
  30 + $mapFile = "$ENV{OFT_MAP_ETH}";
  31 +}
  32 +
  33 +if ( defined($mapFile) ) {
  34 + nftest_process_iface_map($mapFile);
  35 +}
  36 +
  37 +setup_pcap_interfaces();
  38 +
  39 +# Get HP switch address and configuration - Jean II
  40 +if (defined($ENV{'OFT_HP_SWITCH_IP'})) {
  41 + $of_hp_switch_ip = $ENV{'OFT_HP_SWITCH_IP'};
  42 +} else {
  43 + $of_hp_switch_ip = "10.10.10.1";
  44 +}
  45 +if (defined($ENV{'OFT_HP_VLAN'})) {
  46 + $of_hp_vlan = $ENV{'OFT_HP_VLAN'};
  47 +} else {
  48 + $of_hp_vlan = 18;
  49 +}
  50 +if (defined($ENV{'OFT_HP_CONTROLLER'})) {
  51 + $of_hp_controller = $ENV{'OFT_HP_CONTROLLER'};
  52 +} else {
  53 + my $of_port = get_of_port();
  54 + $of_hp_controller = "tcp:10.10.10.2:$of_port";
  55 +}
  56 +if (defined($ENV{'OFT_HP_LISTENER'})) {
  57 + # Transform into a passive string
  58 + ($proto, $host, $port) = split(/:/,$ENV{'OFT_HP_LISTENER'});
  59 + $of_hp_listener = "p$proto:$port";
  60 +}
  61 +if (defined($ENV{'OFT_HP_COMMUNITY'})) {
  62 + $of_hp_community = $ENV{'OFT_HP_COMMUNITY'};
  63 +} else {
  64 + $of_hp_community = 'public';
  65 +}
  66 +
  67 +
  68 +# disable OpenFlow module to make sure it restarts
  69 +`snmpset -v2c -c ${of_hp_community} ${of_hp_switch_ip} iso.org.dod.internet.private.enterprises.11.2.14.11.5.1.7.1.35.1.1.2.${of_hp_vlan} i 2`;
  70 +
  71 +# Make sure the snmp commands don't coalesce
  72 +usleep(200000);
  73 +
  74 +# set OpenFlow Controller string
  75 +`snmpset -v2c -c ${of_hp_community} ${of_hp_switch_ip} iso.org.dod.internet.private.enterprises.11.2.14.11.5.1.7.1.35.1.1.3.${of_hp_vlan} s ${of_hp_controller}`;
  76 +
  77 +# set OpenFlow Listener string
  78 +if (defined($of_hp_listener)) {
  79 + `snmpset -v2c -c ${of_hp_community} ${of_hp_switch_ip} iso.org.dod.internet.private.enterprises.11.2.14.11.5.1.7.1.35.1.1.4.${of_hp_vlan} s ${of_hp_listener}`;
  80 +}
  81 +
  82 +# enable OpenFlow module
  83 +`snmpset -v2c -c ${of_hp_community} ${of_hp_switch_ip} iso.org.dod.internet.private.enterprises.11.2.14.11.5.1.7.1.35.1.1.2.${of_hp_vlan} i 1`;
  84 +
  85 +# Starting OpenFlow takes time, give switch a bit of time...
  86 +usleep(900000);
... ...
regress/bin/of_hp_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my $mapFile;
  9 +my $of_hp_switch_ip;
  10 +my $of_hp_community;
  11 +
  12 +# Process command line options
  13 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  14 + print "unrecognized option\n";
  15 + exit 1;
  16 +}
  17 +
  18 +# If not specified on command line, use environment variable.
  19 +# Try specific first, then try generic - Jean II
  20 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_HP_MAP_ETH'})) ) {
  21 + $mapFile = "$ENV{OFT_HP_MAP_ETH}";
  22 +}
  23 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_MAP_ETH'})) ) {
  24 + $mapFile = "$ENV{OFT_MAP_ETH}";
  25 +}
  26 +
  27 +if ( defined($mapFile) ) {
  28 + nftest_process_iface_map($mapFile);
  29 +}
  30 +
  31 +# Get HP switch address - Jean II
  32 +if (defined($ENV{'OFT_HP_SWITCH_IP'})) {
  33 + $of_hp_switch_ip = $ENV{'OFT_HP_SWITCH_IP'};
  34 +} else {
  35 + $of_hp_switch_ip = "10.10.10.1";
  36 +}
  37 +if (defined($ENV{'OFT_HP_VLAN'})) {
  38 + $of_hp_vlan = $ENV{'OFT_HP_VLAN'};
  39 +} else {
  40 + $of_hp_vlan = 18;
  41 +}
  42 +if (defined($ENV{'OFT_HP_COMMUNITY'})) {
  43 + $of_hp_community = $ENV{'OFT_HP_COMMUNITY'};
  44 +} else {
  45 + $of_hp_community = 'public';
  46 +}
  47 +
  48 +# disable OpenFlow module
  49 +`snmpset -v2c -c ${of_hp_community} ${of_hp_switch_ip} iso.org.dod.internet.private.enterprises.11.2.14.11.5.1.7.1.35.1.1.2.${of_hp_vlan} i 2`;
  50 +
... ...
regress/bin/of_hp_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for running OpenFlow regression tests against ProCurve 3500/5400
  6 +# Jean Tourrilhes - HP-Labs - copyright 2009-2010
  7 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  8 +#
  9 +##############################################################################
  10 +
  11 +use OF::Base;
  12 +use Test::RegressTest;
  13 +use strict;
  14 +use OF::OFUtil;
  15 +
  16 +# check vars are set.
  17 +check_OF_vars_set();
  18 +
  19 +sub INT_Handler {
  20 + my $signame = shift;
  21 + print "\nNo interrupt handler implemented yet...\n";
  22 + print "\nExited with SIG$signame\n";
  23 + exit(1);
  24 +}
  25 +
  26 +# For the 5406zl and 3500yl...
  27 +
  28 +# HP switch starts at port 1 == 'A1' or 1 == '1'
  29 +# Test need extra delay due to slow controller socket
  30 +# Add more idle time due to stat resolution
  31 +# byte count is not available - Jean II
  32 +push @ARGV, "--root=$ENV{'OFT_ROOT'}", "--common-st-args=hp", "--controller=".$ENV{'OFT_HP_CONTROLLER'}, "--port_base=1", "--send_delay=300000", "--base_idle=2", "--ignore_byte_count";
  33 +
  34 +# Use a single random port instead of all four
  35 +push @ARGV, "--less_ports";
  36 +
  37 +# For QinQ, you will need the premium license...
  38 +push @ARGV, "--no_vlan";
  39 +
  40 +# The hardware can not support slicing
  41 +push @ARGV, "--no_slicing";
  42 +
  43 +# The hardware can not support barrier
  44 +push @ARGV, "--no_barrier";
  45 +
  46 +# The hardware can not support emergency flow table
  47 +push @ARGV, "--no_emerg";
  48 +
  49 +# Check for listener
  50 +if ( defined($ENV{'OFT_HP_LISTENER'}) ) {
  51 + push @ARGV, "--listener=$ENV{OFT_HP_LISTENER}";
  52 +}
  53 +
  54 +# Check for specific MAP file...
  55 +if ( defined($ENV{'OFT_HP_MAP_ETH'}) ) {
  56 + push @ARGV, "--map=$ENV{OFT_HP_MAP_ETH}";
  57 +}
  58 +
  59 +# Other configuration is through Environment Variables, See of_hp_setup.pl
  60 +# Jean II
  61 +
  62 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_hp_test_6600.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for running OpenFlow regression tests against ProCurve 6600
  6 +# Jean Tourrilhes - HP-Labs - copyright 2009-2010
  7 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  8 +#
  9 +##############################################################################
  10 +
  11 +use OF::Base;
  12 +use Test::RegressTest;
  13 +use strict;
  14 +use OF::OFUtil;
  15 +
  16 +# check vars are set.
  17 +check_OF_vars_set();
  18 +
  19 +sub INT_Handler {
  20 + my $signame = shift;
  21 + print "\nNo interrupt handler implemented yet...\n";
  22 + print "\nExited with SIG$signame\n";
  23 + exit(1);
  24 +}
  25 +
  26 +# For the 6600...
  27 +
  28 +# HP switch starts at port 25 == '1'
  29 +# Test need extra delay due to slow controller socket
  30 +# Add more idle time due to stat resolution
  31 +# byte count is not available - Jean II
  32 +push @ARGV, "--root=$ENV{'OFT_ROOT'}", "--common-st-args=hp", "--controller=".$ENV{'OFT_HP_CONTROLLER'}, "--port_base=25", "--send_delay=650000", "--base_idle=3", "--ignore_byte_count";
  33 +
  34 +# Use a single random port instead of all four
  35 +push @ARGV, "--less_ports";
  36 +
  37 +# For QinQ, you will need the premium license...
  38 +push @ARGV, "--no_vlan";
  39 +
  40 +# The hardware can not support slicing
  41 +push @ARGV, "--no_slicing";
  42 +
  43 +# The hardware can not support barrier
  44 +push @ARGV, "--no_barrier";
  45 +
  46 +# The hardware can not support emergency flow table
  47 +push @ARGV, "--no_emerg";
  48 +
  49 +# Check for listener
  50 +if ( defined($ENV{'OFT_HP_LISTENER'}) ) {
  51 + push @ARGV, "--listener=$ENV{OFT_HP_LISTENER}";
  52 +}
  53 +
  54 +# Check for specific MAP file...
  55 +if ( defined($ENV{'OFT_HP_MAP_ETH'}) ) {
  56 + push @ARGV, "--map=$ENV{OFT_HP_MAP_ETH}";
  57 +}
  58 +
  59 +# Other configuration is through Environment Variables, See of_hp_setup.pl
  60 +# Jean II
  61 +
  62 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_kmod_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my $mapFile, $controller;
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile,
  12 + "emerg" => \$emerg,
  13 + "controller=s", \$controller) ) {
  14 + print "unrecognized option\n";
  15 + exit 1;
  16 +}
  17 +
  18 +if ( defined($mapFile) ) {
  19 + nftest_process_iface_map($mapFile);
  20 +}
  21 +
  22 +setup_kmod($controller, $emerg);
... ...
regress/bin/of_kmod_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my $mapFile;
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  12 + print "unrecognized option\n";
  13 + exit 1;
  14 +}
  15 +
  16 +if ( defined($mapFile) ) {
  17 + nftest_process_iface_map($mapFile);
  18 +}
  19 +
  20 +teardown_kmod();
... ...
regress/bin/of_kmod_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for OpenFlow regression tests
  6 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  7 +#
  8 +##############################################################################
  9 +
  10 +use OF::Base;
  11 +use Test::RegressTest;
  12 +use strict;
  13 +use OF::OFUtil;
  14 +
  15 +# check vars are set.
  16 +check_OF_vars_set();
  17 +
  18 +sub INT_Handler {
  19 + my $signame = shift;
  20 + print "\nNo interrupt handler implemented yet...\n";
  21 + print "\nExited with SIG$signame\n";
  22 + exit(1);
  23 +}
  24 +
  25 +push (@ARGV, "--root=$ENV{'OFT_ROOT'}", "--map=$ENV{'OFT_ROOT'}/bin/eth.map", "--port_base=1", "--common-st-args=kmod");
  26 +
  27 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_kmod_veth_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my ($mapFile, $controller);
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile,
  12 + "emerg" => \$emerg,
  13 + "controller=s", \$controller) ) {
  14 + print "unrecognized option\n";
  15 + exit 1;
  16 +}
  17 +
  18 +if ( defined($mapFile) ) {
  19 + nftest_process_iface_map($mapFile);
  20 +}
  21 +#else, use pre-defined veth map
  22 +else {
  23 + nftest_process_iface_map("$ENV{'OFT_ROOT'}/bin/veth.map");
  24 +}
  25 +
  26 +setup_kmod($controller, $emerg);
... ...
regress/bin/of_kmod_veth_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my $mapFile;
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  12 + print "unrecognized option\n";
  13 + exit 1;
  14 +}
  15 +
  16 +if ( defined($mapFile) ) {
  17 + nftest_process_iface_map($mapFile);
  18 +}
  19 +#else, use pre-defined veth map
  20 +else {
  21 + nftest_process_iface_map("$ENV{'OFT_ROOT'}/bin/veth.map");
  22 +}
  23 +
  24 +teardown_kmod();
... ...
regress/bin/of_kmod_veth_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for OpenFlow regression tests
  6 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  7 +#
  8 +##############################################################################
  9 +
  10 +use OF::Base;
  11 +use Test::RegressTest;
  12 +use strict;
  13 +use OF::OFUtil;
  14 +
  15 +# check vars are set.
  16 +check_OF_vars_set();
  17 +
  18 +sub INT_Handler {
  19 + my $signame = shift;
  20 + print "\nNo interrupt handler implemented yet...\n";
  21 + print "\nExited with SIG$signame\n";
  22 + exit(1);
  23 +}
  24 +
  25 +push (@ARGV, "--map=$ENV{'OFT_ROOT'}/bin/veth.map", "--root=$ENV{'OFT_ROOT'}", "--port_base=1", "--common-st-args=kmod_veth");
  26 +
  27 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_nf2_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +use Data::Dumper;
  5 +
  6 +use OF::OFUtil;
  7 +use Test::TestLib;
  8 +
  9 +my ($mapFile, $controller);
  10 +
  11 +print "Calling of_nf2_setup.pl\n";
  12 +print Dumper(@ARGV) . "\n";
  13 +
  14 +# Process command line options
  15 +unless ( GetOptions( "map=s" => \$mapFile,
  16 + "emerg" => \$emerg,
  17 + "controller=s", \$controller) ) {
  18 + print "unrecognized option\n";
  19 + exit 1;
  20 +}
  21 +
  22 +if ( defined($mapFile) ) {
  23 + nftest_process_iface_map($mapFile);
  24 +}
  25 +
  26 +setup_NF2($controller, $emerg);
... ...
regress/bin/of_nf2_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my $mapFile;
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  12 + print "unrecognized option\n";
  13 + exit 1;
  14 +}
  15 +
  16 +if ( defined($mapFile) ) {
  17 + nftest_process_iface_map($mapFile);
  18 +}
  19 +
  20 +teardown_NF2();
... ...
regress/bin/of_nf2_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for OpenFlow regression tests
  6 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  7 +#
  8 +##############################################################################
  9 +
  10 +use OF::Base;
  11 +use Test::RegressTest;
  12 +use strict;
  13 +use OF::OFUtil;
  14 +
  15 +# check vars are set.
  16 +check_OF_vars_set();
  17 +
  18 +sub INT_Handler {
  19 + my $signame = shift;
  20 + print "\nNo interrupt handler implemented yet...\n";
  21 + print "\nExited with SIG$signame\n";
  22 + exit(1);
  23 +}
  24 +
  25 +push (@ARGV, "--root=$ENV{'OFT_ROOT'}", "--map=$ENV{'OFT_ROOT'}/bin/nf2.map", "--port_base=1", "--common-st-args=nf2");
  26 +push @ARGV, "--no_slicing";
  27 +
  28 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_ovs_eth.map 0 → 100755
  1 +eth1:eth10.91
  2 +eth2:eth10.92
  3 +eth3:eth10.93
  4 +eth4:eth10.94
  5 +eth5:eth11.91
  6 +eth6:eth11.92
  7 +eth7:eth11.93
  8 +eth8:eth11.94
... ...
regress/bin/of_ovs_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +# Jean Tourrilhes - HP-Labs
  3 +
  4 +use Getopt::Long;
  5 +
  6 +use OF::OFUtil;
  7 +use Test::TestLib;
  8 +
  9 +my $mapFile;
  10 +
  11 +# The map file is necessary. It assing the real interface to the
  12 +# fictious names used by the test suite.
  13 +# eth1->eth4 are capture interfaces used to send/receive probe packets
  14 +# eth5->eth8 are configured to run the OpenFlow switch
  15 +# Jean II
  16 +
  17 +# Process command line options
  18 +# Don't fail on unrecognised options, those failures are tricky
  19 +# to diagnose. For example projects/controller_disconnect sets --emerg
  20 +# Jean II
  21 +Getopt::Long::Configure( 'pass_through' );
  22 +GetOptions( "map=s" => \$mapFile, );
  23 +Getopt::Long::Configure( 'default' );
  24 +
  25 +# If not specified on command line, use enviroment variable.
  26 +# Try specific first, then try generic - Jean II
  27 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_OVS_MAP_ETH'})) ) {
  28 + $mapFile = "$ENV{OFT_OVS_MAP_ETH}";
  29 +}
  30 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_MAP_ETH'})) ) {
  31 + $mapFile = "$ENV{OFT_MAP_ETH}";
  32 +}
  33 +
  34 +# Set up the mappings
  35 +if ( defined($mapFile) ) {
  36 + nftest_process_iface_map($mapFile);
  37 +}
  38 +
  39 +# Debug...
  40 +#for ( my $i = 1 ; $i <= 8 ; $i++ ) {
  41 +# my $iface = nftest_get_iface("eth$i");
  42 +# print "iface($i) = $iface\n";
  43 +#}
  44 +
  45 +# Start capturing on eth1->eth4
  46 +setup_pcap_interfaces();
  47 +
  48 +# Get the directly where Open vSwitch resides
  49 +my $ovs_dir = $ENV{'OFT_OVS_ROOT'};
  50 +my $of_port = get_of_port();
  51 +
  52 +# Setup the kernel module
  53 +`insmod ${ovs_dir}/datapath/linux-2.6/openvswitch_mod.ko`;
  54 +`${ovs_dir}/utilities/ovs-dpctl add-dp dp0`;
  55 +
  56 +# Not needed after 0.99.2
  57 +#for ( my $i = 5 ; $i <= 8 ; $i++ ) {
  58 +# my $iface = nftest_get_iface("eth$i");
  59 +# `${ovs_dir}/utilities/ovs-dpctl add-if dp0 $iface`;
  60 +#}
  61 +
  62 +# create command line arguments containing all four ports
  63 +my $if_string = '';
  64 +for ( my $i = 5 ; $i <= 7 ; $i++ ) {
  65 + $if_string .= nftest_get_iface("eth$i") . ',';
  66 +}
  67 +$if_string .= nftest_get_iface("eth8");
  68 +
  69 +# create Open vSwitch openflow switch on four ports eth5->eth9
  70 +system("${ovs_dir}/utilities/ovs-openflowd dp0 --ports=${if_string} tcp:127.0.0.1:${of_port} --listen=ptcp:6634 --fail=closed --inactivity-probe=999999 &");
  71 +
  72 +# For 0.99.0, you'll need to manually add ports as above
  73 +#system("${ovs_dir}/utilities/ovs-openflowd dp0 tcp:127.0.0.1:${of_port} --listen=ptcp:6634 --fail=closed --inactivity-probe=999999 &");
  74 +
  75 +# Up to 0.90.6, you would use secchan, after that you need to use ovs-openflowd
  76 +#system("${ovs_dir}/secchan/secchan dp0 tcp:127.0.0.1:${of_port} --listen=ptcp:6634 --fail=closed --inactivity-probe=999999 &");
... ...
regress/bin/of_ovs_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +# Jean Tourrilhes - HP-Labs
  3 +
  4 +use Getopt::Long;
  5 +
  6 +use OF::OFUtil;
  7 +use Test::TestLib;
  8 +
  9 +my $mapFile;
  10 +
  11 +# Process command line options
  12 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  13 + print "unrecognized option\n";
  14 + exit 1;
  15 +}
  16 +
  17 +# If not specified on command line, use enviroment variable.
  18 +# Try specific first, then try generic - Jean II
  19 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_OVS_MAP_ETH'})) ) {
  20 + $mapFile = "$ENV{OFT_OVS_MAP_ETH}";
  21 +}
  22 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_MAP_ETH'})) ) {
  23 + $mapFile = "$ENV{OFT_MAP_ETH}";
  24 +}
  25 +
  26 +if ( defined($mapFile) ) {
  27 + nftest_process_iface_map($mapFile);
  28 +}
  29 +
  30 +# Get the directly where Open vSwitch resides
  31 +my $ovs_dir = $ENV{'OFT_OVS_ROOT'};
  32 +
  33 +# Start by killing secchan or ovs-openflowd
  34 +`killall secchan`;
  35 +`killall ovs-openflowd`;
  36 +
  37 +# check if openflow kernel module loaded
  38 +my $of_kmod_loaded = `lsmod | grep openvswitch_mod`;
  39 +if ( $of_kmod_loaded eq "" ) { exit 0; }
  40 +
  41 +print "tearing down interfaces and datapaths\n";
  42 +
  43 +# remove interfaces from openflow
  44 +for ( my $i = 5 ; $i <= 8 ; $i++ ) {
  45 + my $iface = nftest_get_iface("eth$i");
  46 + `${ovs_dir}/utilities/ovs-dpctl del-if dp0 $iface`;
  47 +}
  48 +
  49 +`${ovs_dir}/utilities/ovs-dpctl del-dp dp0`;
  50 +
  51 +my $of_kmod_removed = `rmmod openvswitch_mod`;
  52 +if ( $of_kmod_removed ne "" ) {
  53 + die "failed to remove kernel module... please fix!\n";
  54 +}
  55 +
  56 +$of_kmod_loaded = `lsmod | grep openvswitch_mod`;
  57 +if ( $of_kmod_loaded ne "" ) {
  58 + die "failed to remove kernel module... please fix!\n";
  59 +}
... ...
regress/bin/of_ovs_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for running OpenFlow regression tests against Open vSwitch
  6 +# Jean Tourrilhes - HP-Labs - copyright 2009-2010
  7 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  8 +#
  9 +##############################################################################
  10 +
  11 +use OF::Base;
  12 +use Test::RegressTest;
  13 +use strict;
  14 +use OF::OFUtil;
  15 +
  16 +# check vars are set.
  17 +check_OF_vars_set();
  18 +
  19 +sub INT_Handler {
  20 + my $signame = shift;
  21 + print "\nNo interrupt handler implemented yet...\n";
  22 + print "\nExited with SIG$signame\n";
  23 + exit(1);
  24 +}
  25 +
  26 +# For Open vSwitch
  27 +
  28 +# Open vSwitch starts at port 1
  29 +# Get a bit of speedup by tweaking send_delay and base_idle
  30 +# Jean II
  31 +my $of_port = get_of_port();
  32 +push @ARGV, "--root=$ENV{'OFT_ROOT'}", "--common-st-args=ovs", "--controller=tcp:localhost:$of_port,tcp:localhost:$of_port", "--listener=tcp:127.0.0.1:6634", "--port_base=1", "--send_delay=2000", "--base_idle=2";
  33 +
  34 +# Use a single random port instead of all four
  35 +push @ARGV, "--less_ports";
  36 +
  37 +# Don't bother with VLAN if we go outside the box, too many issues...
  38 +#push @ARGV, "--no_vlan";
  39 +
  40 +# Don't bother with QoS currently, it's broken...
  41 +push @ARGV, "--no_slicing";
  42 +
  43 +# The bother with emergency flow table tests, it's not supported...
  44 +push @ARGV, "--no_emerg";
  45 +
  46 +# Don't forget to configure the OVS_ROOT environment variable
  47 +# Jean II
  48 +
  49 +# Check for specific MAP file...
  50 +if ( defined($ENV{'OFT_OVS_MAP_ETH'}) ) {
  51 + push @ARGV, "--map=$ENV{OFT_OVS_MAP_ETH}";
  52 +}
  53 +
  54 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_ovs_user_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +# Jean Tourrilhes - HP-Labs
  3 +
  4 +use Getopt::Long;
  5 +
  6 +use OF::OFUtil;
  7 +use Test::TestLib;
  8 +
  9 +my $mapFile;
  10 +
  11 +# The map file is necessary. It assing the real interface to the
  12 +# fictious names used by the test suite.
  13 +# eth1->eth4 are capture interfaces used to send/receive probe packets
  14 +# eth5->eth8 are configured to run the OpenFlow switch
  15 +# Jean II
  16 +
  17 +# Process command line options
  18 +# Don't fail on unrecognised options, those failures are tricky
  19 +# to diagnose. For example projects/controller_disconnect sets --emerg
  20 +# Jean II
  21 +Getopt::Long::Configure( 'pass_through' );
  22 +GetOptions( "map=s" => \$mapFile, );
  23 +Getopt::Long::Configure( 'default' );
  24 +
  25 +# If not specified on command line, use enviroment variable.
  26 +# Try specific first, then try generic - Jean II
  27 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_OVS_MAP_ETH'})) ) {
  28 + $mapFile = "$ENV{OFT_OVS_MAP_ETH}";
  29 +}
  30 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_MAP_ETH'})) ) {
  31 + $mapFile = "$ENV{OFT_MAP_ETH}";
  32 +}
  33 +
  34 +# Set up the mappings
  35 +if ( defined($mapFile) ) {
  36 + nftest_process_iface_map($mapFile);
  37 +}
  38 +
  39 +# Debug...
  40 +#for ( my $i = 1 ; $i <= 8 ; $i++ ) {
  41 +# my $iface = nftest_get_iface("eth$i");
  42 +# print "iface($i) = $iface\n";
  43 +#}
  44 +
  45 +# Start capturing on eth1->eth4
  46 +setup_pcap_interfaces();
  47 +
  48 +# Get the directly where Open vSwitch resides
  49 +my $ovs_dir = $ENV{'OFT_OVS_ROOT'};
  50 +my $of_port = get_of_port();
  51 +
  52 +# create command line arguments containing all four ports
  53 +my $if_string = '';
  54 +for ( my $i = 5 ; $i <= 7 ; $i++ ) {
  55 + $if_string .= nftest_get_iface("eth$i") . ',';
  56 +}
  57 +$if_string .= nftest_get_iface("eth8");
  58 +
  59 +# create userspace Open vSwitch openflow switch on four ports
  60 +system("${ovs_dir}/utilities/ovs-openflowd netdev\@br0 --ports=${if_string} tcp:127.0.0.1:${of_port} --listen=ptcp:6634 --fail=closed --inactivity-probe=999999 &");
... ...
regress/bin/of_ovs_user_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +# Jean Tourrilhes - HP-Labs
  3 +
  4 +use Getopt::Long;
  5 +
  6 +use OF::OFUtil;
  7 +use Test::TestLib;
  8 +
  9 +my $mapFile;
  10 +
  11 +# Process command line options
  12 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  13 + print "unrecognized option\n";
  14 + exit 1;
  15 +}
  16 +
  17 +# If not specified on command line, use enviroment variable.
  18 +# Try specific first, then try generic - Jean II
  19 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_OVS_MAP_ETH'})) ) {
  20 + $mapFile = "$ENV{OFT_OVS_MAP_ETH}";
  21 +}
  22 +if ( (! defined($mapFile) ) && (defined($ENV{'OFT_MAP_ETH'})) ) {
  23 + $mapFile = "$ENV{OFT_MAP_ETH}";
  24 +}
  25 +
  26 +if ( defined($mapFile) ) {
  27 + nftest_process_iface_map($mapFile);
  28 +}
  29 +
  30 +# Get the directly where Open vSwitch resides
  31 +my $ovs_dir = $ENV{'OFT_OVS_ROOT'};
  32 +
  33 +# Just kill ovs-openflowd
  34 +`killall ovs-openflowd`;
... ...
regress/bin/of_ovs_user_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for OpenFlow regression tests
  6 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  7 +#
  8 +##############################################################################
  9 +
  10 +use OF::Base;
  11 +use Test::RegressTest;
  12 +use strict;
  13 +use OF::OFUtil;
  14 +
  15 +# check vars are set.
  16 +check_OF_vars_set();
  17 +
  18 +sub INT_Handler {
  19 + my $signame = shift;
  20 + print "\nNo interrupt handler implemented yet...\n";
  21 + print "\nExited with SIG$signame\n";
  22 + exit(1);
  23 +}
  24 +
  25 +# For Open vSwitch
  26 +
  27 +# Open vSwitch starts at port 1
  28 +# Get a bit of speedup by tweaking send_delay and base_idle
  29 +# Jean II
  30 +my $of_port = get_of_port();
  31 +push @ARGV, "--root=$ENV{'OFT_ROOT'}", "--common-st-args=ovs_user", "--controller=tcp:localhost:$of_port,tcp:localhost:$of_port", "--listener=tcp:127.0.0.1:6634", "--port_base=1", "--send_delay=2000", "--base_idle=2";
  32 +
  33 +# Use a single random port instead of all four
  34 +push @ARGV, "--less_ports";
  35 +
  36 +# Don't bother with QoS currently, it's broken...
  37 +push @ARGV, "--no_slicing";
  38 +
  39 +# The bother with emergency flow table tests, it's not supported...
  40 +push @ARGV, "--no_emerg";
  41 +
  42 +# Don't forget to configure the OVS_ROOT environment variable
  43 +# Jean II
  44 +
  45 +# Check for specific MAP file...
  46 +if ( defined($ENV{'OFT_OVS_MAP_ETH'}) ) {
  47 + push @ARGV, "--map=$ENV{OFT_OVS_MAP_ETH}";
  48 +}
  49 +
  50 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_ovs_user_veth_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for running OpenFlow regression tests against Open vSwitch
  6 +# using veth
  7 +# Jean Tourrilhes - HP-Labs - copyright 2009-2010
  8 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  9 +#
  10 +##############################################################################
  11 +
  12 +use OF::Base;
  13 +use Test::RegressTest;
  14 +use strict;
  15 +use OF::OFUtil;
  16 +
  17 +# check vars are set.
  18 +check_OF_vars_set();
  19 +
  20 +sub INT_Handler {
  21 + my $signame = shift;
  22 + print "\nNo interrupt handler implemented yet...\n";
  23 + print "\nExited with SIG$signame\n";
  24 + exit(1);
  25 +}
  26 +
  27 +# For Open vSwitch
  28 +
  29 +# Open vSwitch starts at port 1
  30 +# Get a bit of speedup by tweaking send_delay and base_idle
  31 +# Jean II
  32 +my $of_port = get_of_port();
  33 +push @ARGV, "--root=$ENV{'OFT_ROOT'}", "--common-st-args=ovs_user", "--controller=tcp:localhost:$of_port,tcp:localhost:$of_port", "--listener=tcp:127.0.0.1:6634", "--port_base=1", "--send_delay=2000", "--base_idle=2", "--map=$ENV{'OFT_ROOT'}/bin/veth.map";
  34 +
  35 +# Use a single random port instead of all four
  36 +push @ARGV, "--less_ports";
  37 +
  38 +# Don't bother with QoS currently, it's broken...
  39 +push @ARGV, "--no_slicing";
  40 +
  41 +# The bother with emergency flow table tests, it's not supported...
  42 +push @ARGV, "--no_emerg";
  43 +
  44 +# Don't forget to configure the OVS_ROOT environment variable
  45 +# Jean II
  46 +
  47 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_ovs_veth_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for running OpenFlow regression tests against Open vSwitch
  6 +# using veth
  7 +# Jean Tourrilhes - HP-Labs - copyright 2009-2010
  8 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  9 +#
  10 +##############################################################################
  11 +
  12 +use OF::Base;
  13 +use Test::RegressTest;
  14 +use strict;
  15 +use OF::OFUtil;
  16 +
  17 +# check vars are set.
  18 +check_OF_vars_set();
  19 +
  20 +sub INT_Handler {
  21 + my $signame = shift;
  22 + print "\nNo interrupt handler implemented yet...\n";
  23 + print "\nExited with SIG$signame\n";
  24 + exit(1);
  25 +}
  26 +
  27 +# For Open vSwitch
  28 +
  29 +# Open vSwitch starts at port 1
  30 +# Get a bit of speedup by tweaking send_delay and base_idle
  31 +# Jean II
  32 +my $of_port = get_of_port();
  33 +push @ARGV, "--root=$ENV{'OFT_ROOT'}", "--common-st-args=ovs", "--controller=tcp:localhost:$of_port,tcp:localhost:$of_port", "--listener=tcp:127.0.0.1:6634", "--port_base=1", "--send_delay=2000", "--base_idle=2", "--map=$ENV{'OFT_ROOT'}/bin/veth.map";
  34 +
  35 +# Use a single random port instead of all four
  36 +push @ARGV, "--less_ports";
  37 +
  38 +# Don't bother with QoS currently, it's broken...
  39 +push @ARGV, "--no_slicing";
  40 +
  41 +# The bother with emergency flow table tests, it's not supported...
  42 +push @ARGV, "--no_emerg";
  43 +
  44 +# Don't forget to configure the OVS_ROOT environment variable
  45 +# Jean II
  46 +
  47 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_user_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my ($mapFile, $controller);
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile,
  12 + "emerg" => \$emerg,
  13 + "controller=s", \$controller) ) {
  14 + print "unrecognized option\n";
  15 + exit 1;
  16 +}
  17 +
  18 +if ( defined($mapFile) ) {
  19 + nftest_process_iface_map($mapFile);
  20 +}
  21 +
  22 +setup_user($controller, $emerg);
... ...
regress/bin/of_user_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my $mapFile;
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  12 + print "unrecognized option\n";
  13 + exit 1;
  14 +}
  15 +
  16 +if ( defined($mapFile) ) {
  17 + nftest_process_iface_map($mapFile);
  18 +}
  19 +
  20 +teardown_user();
... ...
regress/bin/of_user_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for OpenFlow regression tests
  6 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  7 +#
  8 +##############################################################################
  9 +
  10 +use OF::Base;
  11 +use Test::RegressTest;
  12 +use strict;
  13 +use OF::OFUtil;
  14 +
  15 +# check vars are set.
  16 +check_OF_vars_set();
  17 +
  18 +sub INT_Handler {
  19 + my $signame = shift;
  20 + print "\nNo interrupt handler implemented yet...\n";
  21 + print "\nExited with SIG$signame\n";
  22 + exit(1);
  23 +}
  24 +
  25 +push (@ARGV, "--root=$ENV{'OFT_ROOT'}", "--map=$ENV{'OFT_ROOT'}/bin/eth.map", "--port_base=1", "--common-st-args=user");
  26 +
  27 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/of_user_veth_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my ($mapFile, $controller);
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile,
  12 + "emerg" => \$emerg,
  13 + "controller=s", \$controller) ) {
  14 + print "unrecognized option\n";
  15 + exit 1;
  16 +}
  17 +
  18 +if ( defined($mapFile) ) {
  19 + nftest_process_iface_map($mapFile);
  20 +}
  21 +#else, use pre-defined veth map
  22 +else {
  23 + nftest_process_iface_map("$ENV{'OFT_ROOT'}/bin/veth.map");
  24 +}
  25 +
  26 +setup_user($controller, $emerg);
... ...
regress/bin/of_user_veth_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +use Getopt::Long;
  4 +
  5 +use OF::OFUtil;
  6 +use Test::TestLib;
  7 +
  8 +my $mapFile;
  9 +
  10 +# Process command line options
  11 +unless ( GetOptions( "map=s" => \$mapFile, ) ) {
  12 + print "unrecognized option\n";
  13 + exit 1;
  14 +}
  15 +
  16 +if ( defined($mapFile) ) {
  17 + nftest_process_iface_map($mapFile);
  18 +}
  19 +#else, use pre-defined veth map
  20 +else {
  21 + nftest_process_iface_map("$ENV{'OFT_ROOT'}/bin/veth.map");
  22 +}
  23 +
  24 +teardown_user();
... ...
regress/bin/of_user_veth_test.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +##############################################################################
  4 +#
  5 +# Wrapper for OpenFlow regression tests
  6 +# $Id: of_regress_test.pl 105 2008-06-06 04:07:05Z brandonh $
  7 +#
  8 +##############################################################################
  9 +
  10 +use OF::Base;
  11 +use Test::RegressTest;
  12 +use strict;
  13 +use OF::OFUtil;
  14 +
  15 +# check vars are set.
  16 +check_OF_vars_set();
  17 +
  18 +sub INT_Handler {
  19 + my $signame = shift;
  20 + print "\nNo interrupt handler implemented yet...\n";
  21 + print "\nExited with SIG$signame\n";
  22 + exit(1);
  23 +}
  24 +
  25 +push( @ARGV, "--map=$ENV{'OFT_ROOT'}/bin/veth.map", "--root=$ENV{'OFT_ROOT'}", "--port_base=1", "--common-st-args=user_veth");
  26 +
  27 +run_regress_test( \&INT_Handler, @ARGV );
... ...
regress/bin/veth.map 0 → 100755
  1 +eth1:veth0
  2 +eth2:veth2
  3 +eth3:veth4
  4 +eth4:veth6
  5 +eth5:veth1
  6 +eth6:veth3
  7 +eth7:veth5
  8 +eth8:veth7
... ...
regress/bin/veth_setup.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +`/sbin/modprobe veth`;
  4 +for (my $i = 0; $i < 4; $i++) {
  5 + `/sbin/ip link add type veth`;
  6 +}
  7 +
  8 +for (my $i = 0; $i < 8; $i++) {
  9 + `sudo /sbin/ifconfig veth$i 192.168.1$i.1 netmask 255.255.255.0`;
  10 +}
... ...
regress/bin/veth_teardown.pl 0 → 100755
  1 +#!/usr/bin/perl -w
  2 +
  3 +`/sbin/rmmod veth`;
  4 +
... ...
regress/lib/Perl5/OF/Base.pm 0 → 100755
  1 +#############################################################
  2 +# $Id: Base.pm 3161 2007-12-13 21:08:05Z grg $
  3 +#
  4 +# Module provides basic functions for use by OF Perl scripts.
  5 +#
  6 +# Revisions:
  7 +#
  8 +##############################################################
  9 +
  10 +package OF::Base;
  11 +
  12 +use Exporter;
  13 +@ISA = ('Exporter');
  14 +@EXPORT = qw( &check_OF_vars_set
  15 +);
  16 +
  17 +##############################################################
  18 +#
  19 +# Check that the user has set up their environment correctly.
  20 +#
  21 +##############################################################
  22 +sub check_OF_vars_set {
  23 +
  24 + my @of_vars = qw(OFT_ROOT OF_ROOT);
  25 +
  26 + for (@of_vars) {
  27 + my_die("Please set shell variable $_ and try again.")
  28 + unless defined $ENV{$_};
  29 + }
  30 +
  31 +}
  32 +
  33 +##############################################################
  34 +#
  35 +# Define a my_die function if it doesn't already exist
  36 +#
  37 +##############################################################
  38 +
  39 +if ( !defined(&my_die) ) {
  40 + eval( '
  41 + sub my_die {
  42 + my $mess = shift @_;
  43 + (my $cmd = $0) =~ s/.*\///;
  44 + print STDERR "\n$cmd: $mess\n";
  45 + exit 1;
  46 + }
  47 + ' );
  48 +}
  49 +
  50 +# Always end library in 1
  51 +1;
... ...
regress/lib/Perl5/OF/Includes.pm 0 → 100755
  1 +use Test::TestLib;
  2 +use Test::PacketLib;
  3 +
  4 +use OF::Base;
  5 +use OF::OFUtil;
  6 +use OF::OFPacketLib;
  7 +
  8 +use IO::Socket;
  9 +
  10 +use Data::HexDump;
  11 +
  12 +use Data::Dumper;
  13 +
  14 +use Time::HiRes qw(sleep gettimeofday tv_interval usleep);
  15 +
  16 +1;
0 17 \ No newline at end of file
... ...
regress/lib/Perl5/OF/OFPacketLib.pm 0 → 100755
  1 +####################################
  2 +# vim:set shiftwidth=2 softtabstop=2 expandtab:
  3 +#
  4 +# $Id: PacketLib.pm 3074 2007-12-06 03:01:04Z grg $
  5 +#
  6 +# This provides functions for manipulating packets.
  7 +#
  8 +# The goal is to provide functions that make it easy to create and
  9 +# manipulate packets, so that we can avoid stupid errors.
  10 +#
  11 +#####################################
  12 +
  13 +package OF::OFPacketLib;
  14 +
  15 +use strict;
  16 +
  17 +use Convert::Binary::C;
  18 +use Data::Dumper;
  19 +use Data::HexDump;
  20 +use OF::Base;
  21 +
  22 +use Exporter;
  23 +use vars qw(@ISA @EXPORT); # needed cos strict is on
  24 +@ISA = qw(Exporter);
  25 +@EXPORT = qw($ofp %enums);
  26 +
  27 +our $ofp = Convert::Binary::C->new;
  28 +
  29 +# Convert::Binary::C config generated with `ccconfig`
  30 +# should run this during make to customize to a machine
  31 +my %config = (
  32 + 'Alignment' => 4,
  33 + 'Assert' => [
  34 + 'cpu(i386)',
  35 + 'machine(i386)',
  36 + 'system(linux)',
  37 + 'system(posix)',
  38 + 'system(unix)'
  39 + ],
  40 + 'ByteOrder' => 'LittleEndian',
  41 + 'CharSize' => 1,
  42 + 'CompoundAlignment' => 1,
  43 + 'Define' => [
  44 + '__CHAR_BIT__=8',
  45 + '__DBL_DIG__=15',
  46 + '__DBL_EPSILON__=2.2204460492503131e-16',
  47 + '__DBL_MANT_DIG__=53',
  48 + '__DBL_MAX_10_EXP__=308',
  49 + '__DBL_MAX_EXP__=1024',
  50 + '__DBL_MAX__=1.7976931348623157e+308',
  51 + '__DBL_MIN_10_EXP__=(-307)',
  52 + '__DBL_MIN_EXP__=(-1021)',
  53 + '__DBL_MIN__=2.2250738585072014e-308',
  54 + '__DECIMAL_DIG__=21',
  55 + '__ELF__=1',
  56 + '__FLT_DIG__=6',
  57 + '__FLT_EPSILON__=1.19209290e-7F',
  58 + '__FLT_EVAL_METHOD__=2',
  59 + '__FLT_MANT_DIG__=24',
  60 + '__FLT_MAX_10_EXP__=38',
  61 + '__FLT_MAX_EXP__=128',
  62 + '__FLT_MAX__=3.40282347e+38F',
  63 + '__FLT_MIN_10_EXP__=(-37)',
  64 + '__FLT_MIN_EXP__=(-125)',
  65 + '__FLT_MIN__=1.17549435e-38F',
  66 + '__FLT_RADIX__=2',
  67 + '__GNUC_MINOR__=1',
  68 + '__GNUC_PATCHLEVEL__=2',
  69 + '__GNUC_RH_RELEASE__=14',
  70 + '__GNUC__=4',
  71 + '__INT_MAX__=2147483647',
  72 + '__LDBL_DIG__=18',
  73 + '__LDBL_EPSILON__=1.08420217248550443401e-19L',
  74 + '__LDBL_MANT_DIG__=64',
  75 + '__LDBL_MAX_10_EXP__=4932',
  76 + '__LDBL_MAX_EXP__=16384',
  77 + '__LDBL_MAX__=1.18973149535723176502e+4932L',
  78 + '__LDBL_MIN_10_EXP__=(-4931)',
  79 + '__LDBL_MIN_EXP__=(-16381)',
  80 + '__LDBL_MIN__=3.36210314311209350626e-4932L',
  81 + '__LONG_LONG_MAX__=9223372036854775807LL',
  82 + '__LONG_MAX__=2147483647L',
  83 + '__NO_INLINE__=1',
  84 + '__PTRDIFF_TYPE__=int',
  85 + '__SCHAR_MAX__=127',
  86 + '__SHRT_MAX__=32767',
  87 + '__SIZE_TYPE__=unsigned int',
  88 + '__USER_LABEL_PREFIX__=',
  89 + '__WCHAR_TYPE__=long int',
  90 + '__WINT_TYPE__=unsigned int',
  91 + '__attribute__(x)=',
  92 + '__builtin_va_list=int',
  93 + '__gnu_linux__=1',
  94 + '__i386=1',
  95 + '__i386__=1',
  96 + '__linux=1',
  97 + '__linux__=1',
  98 + '__unix=1',
  99 + '__unix__=1',
  100 + 'i386=1',
  101 + 'linux=1',
  102 + 'unix=1'
  103 + ],
  104 + 'DisabledKeywords' => [
  105 + 'restrict'
  106 + ],
  107 + 'DoubleSize' => 8,
  108 + 'EnumSize' => 4,
  109 + 'FloatSize' => 4,
  110 + 'HasCPPComments' => 1,
  111 + 'Include' => [
  112 + '/usr/lib/gcc/i386-redhat-linux/4.1.2/include',
  113 + '/usr/include'
  114 + ],
  115 + 'IntSize' => 4,
  116 + 'KeywordMap' => {
  117 + '__asm' => 'asm',
  118 + '__asm__' => 'asm',
  119 + '__complex' => undef,
  120 + '__complex__' => undef,
  121 + '__const' => 'const',
  122 + '__const__' => 'const',
  123 + '__extension__' => undef,
  124 + '__imag' => undef,
  125 + '__imag__' => undef,
  126 + '__inline' => 'inline',
  127 + '__inline__' => 'inline',
  128 + '__real' => undef,
  129 + '__real__' => undef,
  130 + '__restrict' => 'restrict',
  131 + '__restrict__' => 'restrict',
  132 + '__signed' => 'signed',
  133 + '__signed__' => 'signed',
  134 + '__volatile' => 'volatile',
  135 + '__volatile__' => 'volatile'
  136 + },
  137 + 'LongDoubleSize' => 12,
  138 + 'LongLongSize' => 8,
  139 + 'LongSize' => 4,
  140 + 'PointerSize' => 4,
  141 + 'ShortSize' => 2,
  142 + 'UnsignedChars' => 0
  143 + );
  144 +
  145 +
  146 +#!!!
  147 +$ofp->configure(%config);
  148 +
  149 +#$ofp->configure('Include' => ['/usr/include']);
  150 +
  151 +# set to big endian for network order, regardless of machine endianness
  152 +$ofp->configure(ByteOrder => 'BigEndian');
  153 +
  154 +# ensure environment variables set before reading C file
  155 +check_OF_vars_set();
  156 +
  157 +# load C structs and enums
  158 +my $of_file = $ENV{'OF_ROOT'}.'/include/openflow/openflow.h';
  159 +#print "$of_file\n";
  160 +
  161 +eval { $ofp->parse_file($of_file) };
  162 +if ($@) { die "error in parse_file $@\n"; }
  163 +
  164 +#!!!
  165 +#print $ofp->sizeof('ofp_action') . "\n";
  166 +#print $ofp->sizeof('ofp_packet_in') . "\n";
  167 +#print $ofp->sizeof('ofp_flow_mod') . "\n";
  168 +#print $ofp->offsetof('ofp_action', 'arg.output') . "\n";
  169 +#exit 1;
  170 +
  171 +my @enum_list = $ofp->enum;
  172 +our %enums; # "global" enum hash
  173 +#print Dumper(@enum_list);
  174 +foreach my $enum_hash_ref (@enum_list) {
  175 + my %enum_hash = %{$enum_hash_ref->{'enumerators'}};
  176 + while( my($key, $val) = each(%enum_hash) ) {
  177 + $enums{$key} = $val;
  178 + }
  179 +}
  180 +
  181 +1;
  182 +
  183 +__END__
... ...
regress/lib/Perl5/OF/OFUtil.pm 0 → 100755
  1 +#############################################################
  2 +# $Id: OFUtil.pm 3161 2007-12-13 21:08:05Z bdh $
  3 +#
  4 +# Module provides basic functions for use by OF Perl scripts.
  5 +#
  6 +# Revisions:
  7 +#
  8 +##############################################################
  9 +
  10 +package OF::OFUtil;
  11 +
  12 +use Getopt::Long;
  13 +use Test::TestLib;
  14 +use Error qw(:try);
  15 +use OF::OFPacketLib;
  16 +use Test::PacketLib;
  17 +use Exporter;
  18 +use Data::Dumper;
  19 +use Socket qw(:all);
  20 +use IO::Socket;
  21 +#use IO::Socket::INET;
  22 +use Data::HexDump;
  23 +use Time::HiRes qw(sleep gettimeofday tv_interval usleep);
  24 +
  25 +@ISA = ('Exporter');
  26 +@EXPORT = qw(
  27 + &trim
  28 + &send_and_count
  29 + &expect_and_count
  30 + &save_counters
  31 + &verify_counters
  32 + &setup_pcap_interfaces
  33 + &setup_kmod
  34 + &setup_user
  35 + &setup_NF2
  36 + &teardown_kmod
  37 + &teardown_user
  38 + &teardown_NF2
  39 + &compare
  40 + &create_controller_socket
  41 + &run_learning_switch_test
  42 + &do_hello_sequence
  43 + &enter_barrier
  44 + &wait_for_barrier_exit
  45 + &send_get_config_request
  46 + &wait_for_get_config_reply
  47 + &get_switch_features
  48 + &get_config
  49 + &set_config
  50 + &run_black_box_test
  51 + &create_flow_mod_from_udp
  52 + &create_flow_mod_from_udp_actionbytes
  53 + &create_flow_mod_from_udp_action
  54 + &wait_for_flow_expired
  55 + &wait_for_flow_expired_all
  56 + &wait_for_flow_expired_readone
  57 + &wait_for_flow_expired_readsize
  58 + &wait_for_flow_expired_total_bytes
  59 + &wait_for_one_packet_in
  60 + &verify_header
  61 + &get_of_ver
  62 + &get_of_port
  63 + &get_of_miss_send_len_default
  64 + &get_default_black_box_pkt
  65 + &get_default_black_box_pkt_len
  66 + &for_all_port_pairs
  67 + &for_all_ports
  68 + &for_all_wildcards
  69 + &for_all_port_triplets
  70 + &forward_simple
  71 + &flow_mod_length
  72 + &combine_args
  73 + &get_original_value
  74 + &generate_expect_packet
  75 + &replace_sending_pkt
  76 + &create_vlan_pkt
  77 + &forward_simple_icmp
  78 + &get_default_black_box_pkt_len_icmp
  79 + &create_flow_mod_from_icmp_action
  80 + &create_flow_mod_from_icmp
  81 + &forward_simple_arp
  82 + &get_default_black_box_pkt_len_arp
  83 + &create_flow_mod_from_arp_action
  84 + &create_flow_mod_from_arp
  85 + &wait_for_two_flow_expired
  86 + &get_dpinst
  87 + &wait_for_echo_request
  88 + &dpctl_del_flows
  89 + &dpctl_show_flows
  90 +);
  91 +
  92 +my $nf2_kernel_module_path = 'datapath/linux-2.6';
  93 +my $nf2_kernel_module_name_no_ext = 'ofdatapath_netfpga';
  94 +my $nf2_kernel_module_name = $nf2_kernel_module_name_no_ext . '.ko';
  95 +my $openflow_dir = $ENV{OF_ROOT};
  96 +
  97 +if (! -e "$openflow_dir/include/openflow/openflow.h") {
  98 + die "please set OF_ROOT in path so that OFUtil.pm can extract constants"
  99 +}
  100 +
  101 +sub get_define {
  102 + my $val = shift;
  103 + my $retval = `grep \"#define $val \" \$OF_ROOT/include/openflow/openflow.h | awk '{print \$3}'`;
  104 + chomp $retval;
  105 + return $retval;
  106 +}
  107 +
  108 +# extract #defines from openflow.h
  109 +my $of_ver = get_define('OFP_VERSION');
  110 +my $of_port = get_define('OFP_TCP_PORT');
  111 +my $of_miss_send_len = get_define('OFP_DEFAULT_MISS_SEND_LEN');
  112 +
  113 +# sending/receiving interfaces - NOT OpenFlow ones
  114 +my @interfaces = ( "eth1", "eth2", "eth3", "eth4" );
  115 +
  116 +##############################################################
  117 +
  118 +sub trim($) {
  119 + my $string = shift;
  120 + $string =~ s/^\s+//;
  121 + $string =~ s/\s+$//;
  122 + return $string;
  123 +}
  124 +
  125 +sub get_if_rx {
  126 + my $interface = shift;
  127 + return
  128 +`/sbin/ifconfig $interface | grep \'RX packets:\' | awk \'{print \$2}\' | awk -F : \'{print \$2}\'`;
  129 +}
  130 +
  131 +sub get_if_tx {
  132 + my $interface = shift;
  133 + return
  134 +`/sbin/ifconfig $interface | grep \'TX packets:\' | awk \'{print \$2}\' | awk -F : \'{print \$2}\'`;
  135 +}
  136 +
  137 +sub send_and_count {
  138 + my ( $interface, $pkt, $counters ) = @_;
  139 + nftest_send( $interface, $pkt );
  140 + $$counters{$interface}{tx_pkts}++;
  141 +}
  142 +
  143 +sub expect_and_count {
  144 + my ( $interface, $pkt, $counters ) = @_;
  145 + nftest_expect( $interface, $pkt );
  146 + $$counters{$interface}{rx_pkts}++;
  147 +}
  148 +
  149 +sub save_counters {
  150 + my $counters = @_;
  151 + foreach my $i ( keys %counters ) {
  152 + $$counters{$i}{rx_pkts} = get_if_rx($i);
  153 + $$counters{$i}{tx_pkts} = get_if_tx($i);
  154 + }
  155 +}
  156 +
  157 +sub verify_counters {
  158 + my ( %c1, %c2, %delta );
  159 + my $errors = 0;
  160 + foreach my $i ( keys %c1 ) {
  161 + if ( $c1{$i}{rx_pkts} + $delta{$i}{rx_pkts} != $c2{$i}{rx_pkts} ) {
  162 + $errors++;
  163 + print "rx_pkts comparison failed for interface $i, please fix\n";
  164 + }
  165 + if ( $c1{$i}{tx_pkts} + $delta{$i}{tx_pkts} != $c2{$i}{tx_pkts} ) {
  166 + $errors++;
  167 + print "tx_init + tx_pkts != tx_final for interface $i, please fix\n";
  168 + }
  169 + }
  170 + return $errors;
  171 +}
  172 +
  173 +sub setup_pcap_interfaces {
  174 +
  175 + # ensure all interfaces use an address
  176 + for ( my $i = 1 ; $i <= 4 ; $i++ ) {
  177 + my $iface = nftest_get_iface("eth$i");
  178 + `/sbin/ifconfig $iface 192.168.10$i.1`;
  179 + }
  180 +}
  181 +
  182 +sub start_ofprotocol {
  183 +
  184 + my ( $dpinst, $controller, $emerg ) = @_;
  185 + if ( !$controller) { $controller = nftest_default_controllers(); }
  186 + my $cmd;
  187 + if (defined $emerg) {
  188 + $cmd = "${openflow_dir}/secchan/ofprotocol $dpinst $controller --emerg-flow --inactivity-probe=10 &";
  189 + } else {
  190 + $cmd = "${openflow_dir}/secchan/ofprotocol $dpinst $controller --inactivity-probe=999999 &";
  191 + }
  192 + print "about to run $cmd\n";
  193 + system($cmd);
  194 +}
  195 +
  196 +sub setup_kmod {
  197 +
  198 + setup_pcap_interfaces();
  199 +
  200 + # verify kernel module not loaded
  201 + my $of_kmod_loaded = `lsmod | grep ofdatapath`;
  202 + if ( $of_kmod_loaded ne "" ) {
  203 + print "openflow kernel module already loaded... please fix!\n";
  204 + exit 1;
  205 + }
  206 +
  207 + # verify controller not already running
  208 + my $controller_loaded = `ps -A | grep controller`;
  209 + if ( $controller_loaded ne "" ) {
  210 + print "controller already loaded... please remove and try again!\n";
  211 + exit 1;
  212 + }
  213 +
  214 + my $openflow_dir = $ENV{'OF_ROOT'};
  215 +
  216 + # create openflow switch on four ports
  217 + `insmod ${openflow_dir}/datapath/linux-2.6/ofdatapath.ko`;
  218 +
  219 + `${openflow_dir}/utilities/dpctl adddp nl:0`;
  220 +
  221 + for ( my $i = 5 ; $i <= 8 ; $i++ ) {
  222 + my $iface = nftest_get_iface("eth$i");
  223 + `${openflow_dir}/utilities/dpctl addif nl:0 $iface`;
  224 + }
  225 +
  226 + start_ofprotocol("nl:0", @_);
  227 +}
  228 +
  229 +sub setup_NF2 {
  230 +
  231 + setup_pcap_interfaces();
  232 +
  233 + # load the openflow bitfile on the NetFPGA
  234 + system("nf2_download ${openflow_dir}/hw-lib/nf2/openflow_switch.bit");
  235 + sleep(2);
  236 +
  237 + # turn on phy(0-3) interrupt mask
  238 + # in order to avoid asynchronous port_mod_change message
  239 + `regwrite 0x04c006c 0xffff`;
  240 + `regwrite 0x04c00ec 0xffff`;
  241 + `regwrite 0x04c016c 0xffff`;
  242 + `regwrite 0x04c01ec 0xffff`;
  243 +
  244 + # create openflow switch on four ports
  245 + my $if_string = '';
  246 + for (my $i = 5 ; $i <= 7 ; $i++) {
  247 + $if_string .= nftest_get_iface("eth$i") . ',';
  248 + }
  249 + $if_string .= nftest_get_iface("eth8");
  250 +
  251 + print "about to create ofdatapath` punix:/var/run/test -i $if_string \& \n";
  252 + system("${openflow_dir}/udatapath/ofdatapath punix:/var/run/test -i $if_string \&");
  253 +
  254 + sleep(1);
  255 +
  256 + start_ofprotocol("unix:/var/run/test", @_);
  257 +}
  258 +
  259 +
  260 +sub setup_user {
  261 + setup_pcap_interfaces();
  262 +
  263 + # create openflow switch on four ports
  264 + my $if_string = '';
  265 + for (my $i = 5 ; $i <= 7 ; $i++) {
  266 + $if_string .= nftest_get_iface("eth$i") . ',';
  267 + }
  268 + $if_string .= nftest_get_iface("eth8");
  269 +
  270 + print "about to create ofdatapath` punix:/var/run/test -i $if_string \& \n";
  271 + system("${openflow_dir}/udatapath/ofdatapath punix:/var/run/test -i $if_string \&");
  272 +
  273 + start_ofprotocol("unix:/var/run/test", @_);
  274 +
  275 + #create a queue in each port
  276 + for ($i = 1;$i <= 4; $i++) {
  277 + system("${openflow_dir}/utilities/dpctl add-queue unix:/var/run/test $i 1 10");
  278 + }
  279 +
  280 +
  281 +}
  282 +
  283 +sub teardown_kmod {
  284 +
  285 + # check that we're root?
  286 + my $who = `whoami`;
  287 + if ( trim($who) ne 'root' ) { die "must be root\n"; }
  288 +
  289 + `killall ofprotocol`;
  290 +
  291 + # check if openflow kernel module loaded
  292 + my $of_kmod_loaded = `lsmod | grep ofdatapath`;
  293 + if ( $of_kmod_loaded eq "" ) { exit 0; }
  294 +
  295 + print "tearing down interfaces and datapaths\n";
  296 +
  297 + # remove interfaces from openflow
  298 + for ( my $i = 5 ; $i <= 8 ; $i++ ) {
  299 + my $iface = nftest_get_iface("eth$i");
  300 + `${openflow_dir}/utilities/dpctl delif nl:0 $iface`;
  301 + }
  302 +
  303 + `${openflow_dir}/utilities/dpctl deldp nl:0`;
  304 +
  305 + my $of_kmod_removed = `rmmod ofdatapath`;
  306 + if ( $of_kmod_removed ne "" ) {
  307 + die "failed to remove kernel module... please fix!\n";
  308 + }
  309 +
  310 + $of_kmod_loaded = `lsmod | grep ofdatapath`;
  311 + if ( $of_kmod_loaded ne "" ) {
  312 + die "failed to remove kernel module... please fix!\n";
  313 + }
  314 +
  315 + exit 0;
  316 +}
  317 +
  318 +sub teardown_NF2 {
  319 + teardown_user();
  320 +}
  321 +
  322 +sub teardown_user {
  323 +
  324 + # check that we're root?
  325 + my $who = `whoami`;
  326 + if ( trim($who) ne 'root' ) { die "must be root\n"; }
  327 +
  328 + `killall ofdatapath`;
  329 + `killall ofprotocol`;
  330 +
  331 + exit 0;
  332 +}
  333 +
  334 +sub compare {
  335 + my ( $test, $val, $op, $expected ) = @_;
  336 + my $success = eval "$val $op $expected" ? 1 : 0;
  337 + if ( !$success ) { die "$test: error $val not $op $expected\n"; }
  338 +}
  339 +
  340 +sub create_controller_socket {
  341 + my ($host, $port) = @_;
  342 + print "about to make socket: tcp:$host:$port\n";
  343 + my $sock = new IO::Socket::INET(
  344 + LocalHost => $host,
  345 + LocalPort => $port,
  346 + Proto => 'tcp',
  347 + Listen => 1,
  348 + Reuse => 1
  349 + );
  350 + die "Could not create socket: $!\n" unless $sock;
  351 + # Don't hold to data - Jean II
  352 + # This does NOT work, as it apply only to SOL_SOCKET
  353 + $sock->sockopt(TCP_NODELAY, 1) or die "\$sock->sockopt NODELAY, 1: $! ($^E)";
  354 + # This works properly - Jean II
  355 + setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die "\$sock->sockopt NODELAY, 1: $! ($^E)";
  356 + $sock->autoflush();
  357 + # It also tried $| = 1; before the print but it did not help - Jean II
  358 + print "made socket\n";
  359 + return $sock;
  360 +}
  361 +
  362 +# This does not look like it's used ? - Jean II
  363 +sub process_command_line() {
  364 + my %options = ();
  365 +
  366 + GetOptions( \%options, "map=s" );
  367 +
  368 + # Process the mappings if specified
  369 + if ( defined( $options{'map'} ) ) {
  370 + nftest_process_iface_map( $options{'map'} );
  371 + } else {
  372 + # If not specified on command line, use enviroment variable
  373 + # Jean II
  374 + if (defined($ENV{'OFT_MAP_ETH'})) {
  375 + nftest_process_iface_map( $ENV{OFT_MAP_ETH} );
  376 + }
  377 + }
  378 +
  379 + return %options;
  380 +}
  381 +
  382 +sub run_learning_switch_test {
  383 +
  384 + # test is a function pointer
  385 + my ( $test_ref, $argv_ref) = @_;
  386 +
  387 + my %options = nftest_init( $argv_ref, \@interfaces, );
  388 +
  389 + my ( %init_counters, %final_counters, %delta );
  390 +
  391 + my $pid;
  392 +
  393 + # Fork off a process for controller
  394 + if ( !( $pid = fork ) ) {
  395 +
  396 + # extract host and port from controller string if passed in
  397 + if (defined $options{'controller'}) {
  398 + # Assume fully qualified string :
  399 + # tcp:<controller>:<port>
  400 + # Jean II
  401 + ($controller, $failover) = split(/,/,$options{'controller'});
  402 + ($proto, $host, $port) = split(/:/,$controller);
  403 + # Check for string missing the protocol - Jean II
  404 + if ( ! defined ($port) ) {
  405 + die "Invalid controller string $options{'controller'}"
  406 + }
  407 + #!!!
  408 + print "Controller : using protocol $proto and port $port\n";
  409 + }
  410 + # Run controller from this process
  411 + if ( ! defined ($port) ) {
  412 + exec "$ENV{'OF_ROOT'}/controller/controller", "ptcp:";
  413 + } else {
  414 + exec "$ENV{'OF_ROOT'}/controller/controller", "p$proto:$port";
  415 + }
  416 + die "Failed to launch controller: $!";
  417 + }
  418 + else {
  419 + my $exitCode = 1;
  420 + try {
  421 +
  422 + # Run control from this process
  423 + print "added controller...\n";
  424 +
  425 + # Wait for controller to load
  426 + sleep(1);
  427 +
  428 + nftest_start( \@interfaces, );
  429 +
  430 + save_counters( \%init_counters );
  431 +
  432 + # Run test
  433 + my %delta = &$test_ref();
  434 +
  435 + # sleep as long as needed for the test to finish
  436 + sleep 5;
  437 +
  438 + # check counter values
  439 + save_counters( \%final_counters );
  440 + my $total_errors = verify_counters( %init_counters, %final_counters, %delta );
  441 +
  442 + #print "about to nftest_finish()\n";
  443 + my $unmatched = nftest_finish();
  444 +
  445 + print "Checking pkt errors\n";
  446 + $total_errors += nftest_print_errors($unmatched);
  447 +
  448 + if ( $total_errors == 0 ) {
  449 + print "SUCCESS!\n";
  450 + $exitCode = 0;
  451 + }
  452 + else {
  453 + print "FAIL: $total_errors errors\n";
  454 + $exitCode = 1;
  455 + }
  456 +
  457 + }
  458 + catch Error with {
  459 +
  460 + # Catch and print any errors that occurred during control processing
  461 + my $ex = shift;
  462 + if ($ex) {
  463 + print $ex->stringify();
  464 + }
  465 + }
  466 + finally {
  467 +
  468 + # Ensure controller killed even if we have an error
  469 + kill 9, $pid;
  470 +
  471 + # Exit with the resulting exit code
  472 + exit($exitCode);
  473 + };
  474 + }
  475 +}
  476 +
  477 +sub do_hello_sequence {
  478 +
  479 + my ( $ofp, $sock ) = @_;
  480 +
  481 + my $hdr_args_hello = {
  482 + version => $of_ver,
  483 + type => $enums{'OFPT_HELLO'},
  484 + length => $ofp->sizeof('ofp_header'),
  485 + xid => 0
  486 + };
  487 + my $hello = $ofp->pack( 'ofp_header', $hdr_args_hello);
  488 +
  489 + # Send 'hello' message
  490 + syswrite( $sock, $hello );
  491 +
  492 + # Should add timeout here - will crash if no reply
  493 + my $recvd_mesg;
  494 + sysread( $sock, $recvd_mesg, 1512 ) || die "Failed to receive message: $!";
  495 +
  496 + #print "received message after features request\n";
  497 +
  498 + # Inspect message
  499 + my $msg_size = length($recvd_mesg);
  500 + my $expected_size = $ofp->sizeof('ofp_header');
  501 +# my $expected_size = $ofp->sizeof('ofp_switch_features') + 4 * $ofp->sizeof('ofp_phy_port');
  502 +
  503 + # should probably account for the expected 4 ports' info
  504 + # !!! disabled until we can inspect these
  505 + #compare( "msg size", length($recvd_mesg), '==', $expected_size );
  506 +
  507 + #my $msg = $ofp->unpack( 'ofp_switch_features', $recvd_mesg );
  508 + my $msg = $ofp->unpack( 'ofp_hello', $recvd_mesg );
  509 +
  510 + #print HexDump ($recvd_mesg);
  511 + #print Dumper($msg);
  512 +
  513 + # Verify fields
  514 + verify_header( $msg, 'OFPT_HELLO', $msg_size );
  515 +
  516 + print "received Hello\n";
  517 +}
  518 +
  519 +sub enter_barrier {
  520 + my ($ofp, $sock, $xid) = @_;
  521 +
  522 + my $hdr_args = {
  523 + version => $of_ver,
  524 + type => $enums{'OFPT_BARRIER_REQUEST'},
  525 + length => $ofp->sizeof('ofp_header'),
  526 + xid => $xid
  527 + };
  528 + my $request = $ofp->pack('ofp_header', $hdr_args);
  529 +
  530 + syswrite($sock, $request);
  531 +
  532 + print "Sent barrier request, xid:$xid\n";
  533 +}
  534 +
  535 +sub wait_for_barrier_exit {
  536 + my ($ofp, $sock, $xid) = @_;
  537 +
  538 + my $rcvd_msg;
  539 +
  540 + print "Receiving barrier reply, xid = $xid\n";
  541 +
  542 + sysread($sock, $rcvd_msg, 256)
  543 + || die "Failed to receive message: $!";
  544 +
  545 + my $num_read = length($rcvd_msg);
  546 + my $msg_size = $ofp->sizeof('ofp_header');
  547 + my $msg = $ofp->unpack('ofp_hello', $rcvd_msg);
  548 +
  549 + print Dumper($msg);
  550 + compare("MsgVer", $$msg{'header'}{'version'}, '==', get_of_ver());
  551 + compare("MsgType", $$msg{'header'}{'type'}, '==', $enums{'OFPT_BARRIER_REPLY'});
  552 + compare("MsgLen", $$msg{'header'}{'length'}, '==', $msg_size);
  553 +
  554 + print "Received barrier reply, xid:$xid\n";
  555 +
  556 + return $msg;
  557 +}
  558 +
  559 +sub send_get_config_request {
  560 + my ($ofp, $sock, $xid) = @_;
  561 +
  562 + my $hdr_args = {
  563 + version => $of_ver,
  564 + type => $enums{'OFPT_GET_CONFIG_REQUEST'},
  565 + length => $ofp->sizeof('ofp_header'),
  566 + xid => $xid
  567 + };
  568 + my $request = $ofp->pack('ofp_header', $hdr_args);
  569 +
  570 + syswrite($sock, $request);
  571 +
  572 + print "Sent get config request, xid:$xid\n";
  573 +}
  574 +
  575 +sub wait_for_get_config_reply {
  576 + my ($ofp, $sock, $xid) = @_;
  577 +
  578 + my $rcvd_msg;
  579 +
  580 + print "Receiving get config reply, xid = $xid\n";
  581 +
  582 + sysread($sock, $rcvd_msg, 256)
  583 + || die "Failed to receive message: $!";
  584 +
  585 + my $num_read = length($rcvd_msg);
  586 + my $msg_size = $ofp->sizeof('ofp_switch_config');
  587 + my $msg = $ofp->unpack('ofp_switch_config', $rcvd_msg);
  588 +
  589 + print Dumper($msg);
  590 + compare("MsgVer", $$msg{'header'}{'version'}, '==', get_of_ver());
  591 + compare("MsgType", $$msg{'header'}{'type'}, '==', $enums{'OFPT_GET_CONFIG_REPLY'});
  592 + compare("MsgLen", $$msg{'header'}{'length'}, '==', $msg_size);
  593 +
  594 + print "Received get config reply, xid = $xid\n";
  595 +
  596 + return $msg;
  597 +}
  598 +
  599 +sub get_switch_features {
  600 +
  601 + my ( $ofp, $sock ) = @_;
  602 +
  603 + my $hdr_args_features_request = {
  604 + version => $of_ver,
  605 + type => $enums{'OFPT_FEATURES_REQUEST'},
  606 + length => $ofp->sizeof('ofp_header'), # should generate automatically!
  607 + xid => 0x00000000
  608 + };
  609 + my $features_request = $ofp->pack( 'ofp_header', $hdr_args_features_request );
  610 +
  611 + # Send 'features_request' message
  612 + syswrite( $sock, $features_request );
  613 +
  614 + # Should add timeout here - will crash if no reply
  615 + my $recvd_mesg;
  616 + sysread( $sock, $recvd_mesg, 1512 ) || die "Failed to receive message: $!";
  617 +
  618 + #print "received message after features request\n";
  619 +
  620 + # Inspect message
  621 + my $msg_size = length($recvd_mesg);
  622 + #my $expected_size = $ofp->sizeof('ofp_switch_config');
  623 +
  624 + #compare( "msg size", length($recvd_mesg), '==', $expected_size );
  625 +
  626 + my $msg = $ofp->unpack( 'ofp_switch_features', $recvd_mesg );
  627 +
  628 + #print HexDump ($recvd_mesg);
  629 + #print Dumper($msg);
  630 +
  631 + # Verify header fields
  632 + verify_header( $msg, 'OFPT_FEATURES_REPLY', $msg_size );
  633 +
  634 + return $msg;
  635 +}
  636 +
  637 +sub get_config {
  638 +
  639 + my ( $ofp, $sock ) = @_;
  640 +
  641 + my $hdr_args_get_config_request = {
  642 + version => $of_ver,
  643 + type => $enums{'OFPT_GET_CONFIG_REQUEST'},
  644 + length => $ofp->sizeof('ofp_header'),
  645 + xid => 0x0000000
  646 + };
  647 +
  648 + my $get_config_request = $ofp->pack( 'ofp_header', $hdr_args_get_config_request );
  649 +
  650 + # Send 'get_config_request' message
  651 + syswrite( $sock, $get_config_request );
  652 +
  653 + # Should add timeout here - will crash if no reply
  654 + my $recvd_mesg;
  655 + sysread( $sock, $recvd_mesg, 1512 ) || die "Failed to receive message: $!";
  656 +
  657 + #print "received message after features request\n";
  658 +
  659 + # Inspect message
  660 + my $msg_size = length($recvd_mesg);
  661 + my $expected_size = $ofp->sizeof('ofp_switch_config');
  662 +
  663 + compare( "get_config msg size", length($recvd_mesg), '==', $expected_size );
  664 +
  665 + my $msg = $ofp->unpack( 'ofp_switch_config', $recvd_mesg );
  666 +
  667 + #print HexDump ($recvd_mesg);
  668 + #print Dumper($msg);
  669 +
  670 + # Verify header fields
  671 + verify_header( $msg, 'OFPT_GET_CONFIG_REPLY', $msg_size );
  672 +
  673 + return $msg;
  674 +}
  675 +
  676 +sub set_config {
  677 +
  678 + my ( $ofp, $sock, $options_ref, $flags, $miss_send_len ) = @_;
  679 + my $hdr_args = {
  680 + version => $of_ver,
  681 + type => $enums{'OFPT_SET_CONFIG'},
  682 + length => $ofp->sizeof('ofp_switch_config'),
  683 + xid => 0x0000000
  684 + };
  685 +
  686 + my $set_config_args = {
  687 + header => $hdr_args,
  688 + flags => $flags,
  689 + miss_send_len => $miss_send_len
  690 + };
  691 +
  692 + my $set_config = $ofp->pack( 'ofp_switch_config', $set_config_args );
  693 +
  694 + # Send 'set_config_request' message
  695 + syswrite( $sock, $set_config );
  696 +
  697 + # Give OF switch time to process the set_config
  698 + usleep($$options_ref{'send_delay'});
  699 +}
  700 +
  701 +
  702 +sub run_black_box_test {
  703 +
  704 + my ( $test_ref, $argv_ref, $dont_exit ) = @_;
  705 +
  706 + my %options = nftest_init( $argv_ref, \@interfaces, );
  707 +
  708 + my ($proto, $host, $port) = nftest_parse_controllers( $options{'controller'} );
  709 + print "using host $host and port $port\n";
  710 +
  711 + $sock = create_controller_socket($host, $port);
  712 +
  713 + my $total_errors = 0;
  714 + try {
  715 +
  716 + # Wait for ofprotocol to connect
  717 + print "waiting for ofprotocol to connect\n";
  718 + my $new_sock = $sock->accept();
  719 +
  720 + do_hello_sequence( $ofp, $new_sock );
  721 +
  722 + # Launch PCAP listening interface
  723 + nftest_start( \@interfaces );
  724 +
  725 + &$test_ref( $new_sock, \%options );
  726 +
  727 + # Sleep as long as needed for the test to finish
  728 + sleep 0.5;
  729 + }
  730 + catch Error with {
  731 +
  732 + # Catch and print any errors that occurred during control processing
  733 + my $ex = shift;
  734 + if ($ex) {
  735 + print $ex->stringify();
  736 + }
  737 + $total_errors = 1;
  738 + }
  739 + finally {
  740 +
  741 + close($sock);
  742 +
  743 + my $unmatched = nftest_finish();
  744 + print "Checking pkt errors\n";
  745 + $total_errors += nftest_print_errors($unmatched);
  746 +
  747 + # if no errors earlier, and packets match, then success
  748 + my $exitCode;
  749 + if ( $total_errors == 0 ) {
  750 + print "SUCCESS!\n";
  751 + $exitCode = 0;
  752 + }
  753 + else {
  754 + print "FAIL: $total_errors errors\n";
  755 + $exitCode = 1;
  756 + }
  757 + if (!$dont_exit ) { exit($exitCode); }
  758 + };
  759 +}
  760 +
  761 +sub create_flow_mod_from_udp {
  762 + my ( $ofp, $udp_pkt, $in_port, $out_port, $max_idle, $flags,
  763 + $wildcards, $chg_field, $chg_val, $vlan_id, $nw_tos, $cookie ) = @_;
  764 +
  765 + my $flow_mod_pkt;
  766 +
  767 + $flow_mod_pkt = create_flow_mod_from_udp_action( $ofp, $udp_pkt, $in_port,
  768 + $out_port, $max_idle, $flags, $wildcards, 'OFPFC_ADD', $chg_field,
  769 + $chg_val, $vlan_id, $nw_tos, $cookie );
  770 +
  771 + return $flow_mod_pkt;
  772 +}
  773 +
  774 +sub flow_mod_length {
  775 + my ($mod_type, $chg_field) = @_;
  776 +
  777 + my $action_length = 0;
  778 +
  779 + if ($mod_type eq 'drop') {
  780 + $action_length = 0;
  781 + } elsif (defined $chg_field) {
  782 + if (($chg_field eq 'dl_src') || ($chg_field eq 'dl_dst')) {
  783 + $action_length = $ofp->sizeof('ofp_action_dl_addr')
  784 + + $ofp->sizeof('ofp_action_output');
  785 + } elsif (($chg_field eq 'nw_src') || ($chg_field eq 'nw_dst')) {
  786 + $action_length = $ofp->sizeof('ofp_action_nw_addr')
  787 + + $ofp->sizeof('ofp_action_output');
  788 + } elsif ($chg_field eq 'nw_tos') {
  789 + $action_length = $ofp->sizeof('ofp_action_nw_tos')
  790 + + $ofp->sizeof('ofp_action_output');
  791 + } elsif (($chg_field eq 'tp_src') || ($chg_field eq 'tp_dst')) {
  792 + $action_length = $ofp->sizeof('ofp_action_tp_port')
  793 + + $ofp->sizeof('ofp_action_output');
  794 + } elsif ($chg_field eq 'strip_vlan') {
  795 + $action_length = $ofp->sizeof('ofp_action_header')
  796 + + $ofp->sizeof('ofp_action_output');
  797 + } elsif ($chg_field eq 'vlan_vid') {
  798 + $action_length = $ofp->sizeof('ofp_action_vlan_vid')
  799 + + $ofp->sizeof('ofp_action_output');
  800 + } elsif ($chg_field eq 'vlan_pcp') {
  801 + $action_length = $ofp->sizeof('ofp_action_vlan_pcp')
  802 + + $ofp->sizeof('ofp_action_output');
  803 + } else {
  804 + $action_length = $ofp->sizeof('ofp_action_output');
  805 + }
  806 + } elsif ($mod_type eq 'enqueue') {
  807 + $action_length = $ofp->sizeof('ofp_action_enqueue');
  808 + }
  809 + else {
  810 + $action_length = $ofp->sizeof('ofp_action_output');
  811 + }
  812 +
  813 + my $length = $ofp->sizeof('ofp_flow_mod') + $action_length;
  814 + return $length;
  815 +}
  816 +
  817 +sub combine_args {
  818 + my ($mod_type, $out_port, $chg_field, $chg_val, $queue_id) = @_;
  819 +
  820 + my @pad_6 = (0,0,0,0,0,0);
  821 + my @pad_4 = (0,0,0,0);
  822 + my @pad_3 = (0,0,0);
  823 + my @pad_2 = (0,0);
  824 +
  825 + my $nw_addr_org;
  826 + my $ok_org;
  827 +
  828 + my @dl_addr_org;
  829 + my $chg_vlan_pcp_val;
  830 +
  831 + #OUTPUT
  832 + #and No action for drops
  833 + my $action_output_args;
  834 + my $action_output;
  835 +
  836 + my $max_len;
  837 + if ($out_port != $enums{'OFPP_CONTROLLER'}) {
  838 + $max_len = 0;
  839 + } else {
  840 + $max_len = 65535;
  841 + }
  842 + if ($mod_type ne 'drop') {
  843 + if ($mod_type eq 'enqueue') {
  844 + $action_enqueue_args = {
  845 + type => $enums{'OFPAT_ENQUEUE'},
  846 + len => $ofp->sizeof('ofp_action_enqueue'),
  847 + port => $out_port,
  848 + pad => \@pad_6,
  849 + queue_id => $queue_id,
  850 + };
  851 + $action_enqueue = $ofp->pack('ofp_action_enqueue', $action_enqueue_args);
  852 + }
  853 + else {
  854 + $action_output_args = {
  855 + type => $enums{'OFPAT_OUTPUT'},
  856 + len => $ofp->sizeof('ofp_action_output'),
  857 + port => $out_port,
  858 + max_len => $max_len,
  859 + };
  860 + $action_output = $ofp->pack('ofp_action_output', $action_output_args);
  861 + }
  862 + }
  863 +
  864 + #MODIFY ACTION
  865 + my $action_mod_args;
  866 + my $action_mod;
  867 + if (defined $chg_field) {
  868 + if ($chg_field eq 'dl_src') { #SET_DL_SRC
  869 + @dl_addr_org = NF2::PDU::get_MAC_address($chg_val);
  870 + $action_mod_args = {
  871 + type => $enums{'OFPAT_SET_DL_SRC'},
  872 + len => $ofp->sizeof('ofp_action_dl_addr'),
  873 + dl_addr => \@dl_addr_org,
  874 + pad => \@pad_6,
  875 + };
  876 + $action_mod = $ofp->pack('ofp_action_dl_addr', $action_mod_args);
  877 + } elsif ($chg_field eq 'dl_dst') { #SET_DL_DST
  878 + @dl_addr_org = NF2::PDU::get_MAC_address($chg_val);
  879 + $action_mod_args = {
  880 + type => $enums{'OFPAT_SET_DL_DST'},
  881 + len => $ofp->sizeof('ofp_action_dl_addr'),
  882 + dl_addr => \@dl_addr_org,
  883 + pad => \@pad_6,
  884 + };
  885 + $action_mod = $ofp->pack('ofp_action_dl_addr', $action_mod_args);
  886 + } elsif ($chg_field eq 'nw_src') { #SET_NW_SRC
  887 + ($nw_addr_org, $ok_org) = NF2::IP_hdr::getIP($chg_val);
  888 + $action_mod_args = {
  889 + type => $enums{'OFPAT_SET_NW_SRC'},
  890 + len => $ofp->sizeof('ofp_action_nw_addr'),
  891 + nw_addr => $nw_addr_org,
  892 + };
  893 + $action_mod = $ofp->pack('ofp_action_nw_addr', $action_mod_args);
  894 + } elsif ($chg_field eq 'nw_dst') { #SET_NW_DST
  895 + ($nw_addr_org, $ok_org) = NF2::IP_hdr::getIP($chg_val);
  896 + $action_mod_args = {
  897 + type => $enums{'OFPAT_SET_NW_DST'},
  898 + len => $ofp->sizeof('ofp_action_nw_addr'),
  899 + nw_addr => $nw_addr_org,
  900 + };
  901 + $action_mod = $ofp->pack('ofp_action_nw_addr', $action_mod_args);
  902 + } elsif ($chg_field eq 'nw_tos') { #SET_NW_TOS
  903 + $action_mod_args = {
  904 + type => $enums{'OFPAT_SET_NW_TOS'},
  905 + len => $ofp->sizeof('ofp_action_nw_tos'),
  906 + nw_tos => $chg_val,
  907 + pad => \@pad_3,
  908 + };
  909 + $action_mod = $ofp->pack('ofp_action_nw_tos', $action_mod_args);
  910 + } elsif ($chg_field eq 'tp_src') { #SET_TP_SRC
  911 + $action_mod_args = {
  912 + type => $enums{'OFPAT_SET_TP_SRC'},
  913 + len => $ofp->sizeof('ofp_action_tp_port'),
  914 + tp_port => $chg_val,
  915 + pad => \@pad_2,
  916 + };
  917 + $action_mod = $ofp->pack('ofp_action_tp_port', $action_mod_args);
  918 + } elsif ($chg_field eq 'tp_dst') { #SET_TP_DST
  919 + $action_mod_args = {
  920 + type => $enums{'OFPAT_SET_TP_DST'},
  921 + len => $ofp->sizeof('ofp_action_tp_port'),
  922 + tp_port => $chg_val,
  923 + pad => \@pad_2,
  924 + };
  925 + $action_mod = $ofp->pack('ofp_action_tp_port', $action_mod_args);
  926 + } elsif ($chg_field eq 'strip_vlan') { #STRIP_VLAN
  927 + $action_mod_args = {
  928 + type => $enums{'OFPAT_STRIP_VLAN'},
  929 + len => $ofp->sizeof('ofp_action_header'),
  930 + pad => \@pad_4,
  931 + };
  932 + $action_mod = $ofp->pack('ofp_action_header', $action_mod_args);
  933 + } elsif ($chg_field eq 'vlan_vid') { #SET_VLAN_VID
  934 + $action_mod_args = {
  935 + type => $enums{'OFPAT_SET_VLAN_VID'},
  936 + len => $ofp->sizeof('ofp_action_vlan_vid'),
  937 + vlan_vid => $chg_val & 0x0fff,
  938 + pad => \@pad_2,
  939 + };
  940 + $action_mod = $ofp->pack('ofp_action_vlan_vid', $action_mod_args);
  941 + } elsif ($chg_field eq 'vlan_pcp') { #SET_VLAN_PCP
  942 + $chg_vlan_pcp_val = ($chg_val>>13) & 0x0007;
  943 + $action_mod_args = {
  944 + type => $enums{'OFPAT_SET_VLAN_PCP'},
  945 + len => $ofp->sizeof('ofp_action_vlan_pcp'),
  946 + vlan_pcp => $chg_vlan_pcp_val,
  947 + pad => \@pad_3,
  948 + };
  949 + $action_mod = $ofp->pack('ofp_action_vlan_pcp', $action_mod_args);
  950 + } else {
  951 + $action_mod = undef;
  952 + }
  953 + } else {
  954 + $action_mod = undef;
  955 + }
  956 +
  957 + if (defined $action_mod) {
  958 + $flow_mod_actions = $action_mod . $action_output;
  959 + } elsif (defined $action_enqueue) {
  960 + $flow_mod_actions = $action_enqueue;
  961 + } else {
  962 + $flow_mod_actions = $action_output;
  963 + }
  964 +
  965 + return $flow_mod_actions;
  966 +}
  967 +
  968 +sub create_flow_mod_from_udp_actionbytes {
  969 + my ( $ofp, $udp_pkt, $in_port, $max_idle, $flags,
  970 + $wildcards, $mod_type, $action_bytes, $vlan_id,
  971 + $nw_tos, $cookie) = @_;
  972 +
  973 + $cookie = 0 if !defined($cookie);
  974 +
  975 + my $length = $ofp->sizeof('ofp_flow_mod') + length $action_bytes;
  976 +
  977 + my $hdr_args = {
  978 + version => $of_ver,
  979 + type => $enums{'OFPT_FLOW_MOD'},
  980 + length => $length,
  981 + xid => 0x0000000
  982 + };
  983 +
  984 + # might be cleaner to convert the exported colon-hex MAC addrs
  985 + #print ${$udp_pkt->{Ethernet_hdr}}->SA . "\n";
  986 + #print ${$test_pkt->{Ethernet_hdr}}->SA . "\n";
  987 + my $ref_to_eth_hdr = ( $udp_pkt->{'Ethernet_hdr'} );
  988 + my $ref_to_ip_hdr = ( $udp_pkt->{'IP_hdr'} );
  989 +
  990 + # pointer to array
  991 + my $eth_hdr_bytes = $$ref_to_eth_hdr->{'bytes'};
  992 + my $ip_hdr_bytes = $$ref_to_ip_hdr->{'bytes'};
  993 + my @dst_mac_subarray = @{$eth_hdr_bytes}[ 0 .. 5 ];
  994 + my @src_mac_subarray = @{$eth_hdr_bytes}[ 6 .. 11 ];
  995 +
  996 + my @src_ip_subarray = @{$ip_hdr_bytes}[ 12 .. 15 ];
  997 + my @dst_ip_subarray = @{$ip_hdr_bytes}[ 16 .. 19 ];
  998 +
  999 + my $src_ip =
  1000 + ( ( 2**24 ) * $src_ip_subarray[0] +
  1001 + ( 2**16 ) * $src_ip_subarray[1] +
  1002 + ( 2**8 ) * $src_ip_subarray[2] +
  1003 + $src_ip_subarray[3] );
  1004 +
  1005 + my $dst_ip =
  1006 + ( ( 2**24 ) * $dst_ip_subarray[0] +
  1007 + ( 2**16 ) * $dst_ip_subarray[1] +
  1008 + ( 2**8 ) * $dst_ip_subarray[2] +
  1009 + $dst_ip_subarray[3] );
  1010 +
  1011 + my $dl_vlan;
  1012 + my $dl_vlan_pcp;
  1013 + if (defined $vlan_id) {
  1014 + $dl_vlan = $vlan_id & 0x0fff;
  1015 + $dl_vlan_pcp = (($vlan_id >> 13) & 0x0007);
  1016 + } else {
  1017 + $dl_vlan = 0xffff;
  1018 + $dl_vlan_pcp = 0x0;
  1019 + }
  1020 +
  1021 + my $match_nw_tos;
  1022 + if (defined $nw_tos) {
  1023 + $match_nw_tos = $nw_tos & 0xfc;
  1024 + } else {
  1025 + $match_nw_tos = 0;
  1026 + }
  1027 +
  1028 + my $match_args = {
  1029 + wildcards => $wildcards,
  1030 + in_port => $in_port,
  1031 + dl_src => \@src_mac_subarray,
  1032 + dl_dst => \@dst_mac_subarray,
  1033 + dl_vlan => $dl_vlan,
  1034 + dl_type => 0x0800,
  1035 + dl_vlan_pcp => $dl_vlan_pcp,
  1036 + nw_src => $src_ip,
  1037 + nw_dst => $dst_ip,
  1038 + nw_tos => $match_nw_tos,
  1039 + nw_proto => 17, #udp
  1040 + tp_src => ${ $udp_pkt->{UDP_pdu} }->SrcPort,
  1041 + tp_dst => ${ $udp_pkt->{UDP_pdu} }->DstPort
  1042 + };
  1043 +
  1044 + # organize flow_mod packet
  1045 + my $flow_mod_args = {
  1046 + header => $hdr_args,
  1047 + match => $match_args,
  1048 + command => $enums{"$mod_type"},
  1049 + idle_timeout => $max_idle,
  1050 + hard_timeout => $max_idle,
  1051 + flags => $flags,
  1052 + priority => 0,
  1053 + buffer_id => -1,
  1054 + out_port => $enums{'OFPP_NONE'},
  1055 + cookie => $cookie,
  1056 + };
  1057 + my $flow_mod = $ofp->pack( 'ofp_flow_mod', $flow_mod_args );
  1058 + my $flow_mod_pkt = $flow_mod . $action_bytes;
  1059 + return $flow_mod_pkt;
  1060 +}
  1061 +
  1062 +sub create_flow_mod_from_udp_action {
  1063 + my ( $ofp, $udp_pkt, $in_port, $out_port, $max_idle, $flags,
  1064 + $wildcards, $mod_type, $chg_field, $chg_val, $vlan_id,
  1065 + $nw_tos, $cookie, $queue_id) = @_;
  1066 +
  1067 + if ( $mod_type ne 'drop'
  1068 + && $mod_type ne 'enqueue'
  1069 + && $mod_type ne 'OFPFC_ADD'
  1070 + && $mod_type ne 'OFPFC_DELETE'
  1071 + && $mod_type ne 'OFPFC_DELETE_STRICT')
  1072 + {
  1073 + die "Undefined flow mod type: $mod_type\n";
  1074 + }
  1075 +
  1076 + my $length_expect = flow_mod_length($mod_type, $chg_field);
  1077 + my $flow_mod_actions = combine_args($mod_type, $out_port, $chg_field, $chg_val, $queue_id);
  1078 + my $length = $ofp->sizeof('ofp_flow_mod') + length $flow_mod_actions;
  1079 + if( $length != $length_expect) {
  1080 + die "Mismatching length for $mod_type, $length != $length_expect\n";
  1081 + }
  1082 +
  1083 + $flow_mod_pkt =
  1084 + create_flow_mod_from_udp_actionbytes( $ofp, $udp_pkt, $in_port, $max_idle, $flags, $wildcards, $mod_type, $flow_mod_actions, $vlan_id, $nw_tos, $cookie);
  1085 +
  1086 + return $flow_mod_pkt;
  1087 +}
  1088 +
  1089 +
  1090 +sub wait_for_flow_expired {
  1091 +
  1092 + my ( $ofp, $sock, $options_ref, $pkt_len, $pkt_total, $idle_timeout,
  1093 + $cookie ) = @_;
  1094 +
  1095 + wait_for_flow_expired_readsize( $ofp, $sock, $options_ref, $pkt_len,
  1096 + $pkt_total, $idle_timeout, $cookie, undef);
  1097 +}
  1098 +
  1099 +sub wait_for_flow_expired_all {
  1100 +
  1101 + my ( $ofp, $sock, $options_ref, $cookie ) = @_;
  1102 +
  1103 + wait_for_flow_expired_readsize( $ofp, $sock, $options_ref,
  1104 + $$options_ref{'pkt_len'}, $$options_ref{'pkt_total'},
  1105 + $cookie, undef );
  1106 +}
  1107 +
  1108 +sub wait_for_flow_expired_readone {
  1109 +
  1110 + my ( $ofp, $sock, $options_ref, $pkt_len, $pkt_total, $idle_timeout,
  1111 + $cookie ) = @_;
  1112 +
  1113 + wait_for_flow_expired_readsize( $ofp, $sock, $options_ref, $pkt_len, $pkt_total, $idle_timeout,
  1114 + $cookie, $ofp->sizeof('ofp_flow_removed') );
  1115 +}
  1116 +
  1117 +sub wait_for_flow_expired_readsize {
  1118 +
  1119 + # can specify the reading size from socket (by the last argument, $read_size_)
  1120 +
  1121 + my ( $ofp, $sock, $options_ref, $pkt_len, $pkt_total, $idle_timeout,
  1122 + $cookie, $read_size_ ) = @_;
  1123 + wait_for_flow_expired_total_bytes( $ofp, $sock, $options_ref, ( $pkt_len * $pkt_total ),
  1124 + $pkt_total, $idle_timeout, $cookie, $read_size_ );
  1125 +}
  1126 +
  1127 +sub wait_for_flow_expired_total_bytes {
  1128 + my ( $ofp, $sock, $options_ref, $bytes, $pkt_total, $idle_timeout,
  1129 + $cookie, $read_size_ ) = @_;
  1130 + my $read_size;
  1131 +
  1132 + if ( defined $read_size_ ) {
  1133 + $read_size = $read_size_;
  1134 + } else {
  1135 + $read_size = 1512;
  1136 + }
  1137 +
  1138 + my $recvd_mesg;
  1139 + sysread( $sock, $recvd_mesg, $read_size )
  1140 + || die "Failed to receive ofp_flow_removed message: $!";
  1141 +
  1142 + #print HexDump ($recvd_mesg);
  1143 +
  1144 + # Inspect message
  1145 + my $msg_size = length($recvd_mesg);
  1146 + my $expected_size = $ofp->sizeof('ofp_flow_removed');
  1147 + compare( "ofp_flow_removed msg size", length($recvd_mesg), '==', $expected_size );
  1148 +
  1149 + my $msg = $ofp->unpack( 'ofp_flow_removed', $recvd_mesg );
  1150 +
  1151 + #print Dumper($msg);
  1152 +
  1153 + # Verify fields
  1154 + compare( "ofp_flow_removed header version", $$msg{'header'}{'version'}, '==', $of_ver );
  1155 + compare( "ofp_flow_removed header type", $$msg{'header'}{'type'}, '==', $enums{'OFPT_FLOW_REMOVED'} );
  1156 + compare( "ofp_flow_removed header length", $$msg{'header'}{'length'}, '==', $msg_size );
  1157 +
  1158 + # Disable for platforms that don't have byte counts... - Jean II
  1159 + if ( not defined( $$options_ref{'ignore_byte_count'} ) ) {
  1160 + compare( "ofp_flow_removed byte_count", $$msg{'byte_count'}, '==', $bytes );
  1161 + }
  1162 + compare( "ofp_flow_removed packet_count", $$msg{'packet_count'}, '==', $pkt_total );
  1163 +
  1164 + if ( defined $idle_timeout ) {
  1165 + compare( "ofp_flow_removed idle_timeout", $$msg{'idle_timeout'}, '==', $idle_timeout );
  1166 + }
  1167 +
  1168 + if ( defined $cookie ) {
  1169 + compare( "ofp_flow_removed cookie", $$msg{'cookie'}, '==', $cookie );
  1170 + }
  1171 +}
  1172 +
  1173 +sub wait_for_one_packet_in {
  1174 +
  1175 + # wait for a packet which arrives via socket, and verify it is the expected packet
  1176 + # $sock: socket
  1177 + # $pkt_len: packet length of the expected packet to receive
  1178 + # $pkt : expected packet to receive
  1179 +
  1180 + my ( $ofp, $sock, $pkt_len, $pkt ) = @_;
  1181 +
  1182 + my $pkt_in_msg_size; # read size from socket
  1183 + if ( $pkt_len < $of_miss_send_len ) {
  1184 +
  1185 + # Due to padding, the size of ofp_packet_in header is $ofp->sizeof('ofp_packet_in')-2
  1186 + $pkt_in_msg_size = ( $ofp->sizeof('ofp_packet_in') - 2 ) + $pkt_len;
  1187 + }
  1188 + else {
  1189 + $pkt_in_msg_size = ( $ofp->sizeof('ofp_packet_in') - 2 ) + $of_miss_send_len;
  1190 + }
  1191 +
  1192 + my $recvd_mesg;
  1193 + sysread( $sock, $recvd_mesg, $pkt_in_msg_size )
  1194 + || die "Failed to receive message: $!";
  1195 +
  1196 + # Inspect message
  1197 + my $msg_size = length($recvd_mesg);
  1198 + my $expected_size = $pkt_in_msg_size;
  1199 + compare( "ofp_packet_in msg size", length($recvd_mesg), '==', $expected_size );
  1200 +
  1201 + my $msg = $ofp->unpack( 'ofp_packet_in', $recvd_mesg );
  1202 +
  1203 + # print Dumper($msg);
  1204 +
  1205 + # Verify fields
  1206 + compare( "ofp_packet_in header version", $$msg{'header'}{'version'}, '==', $of_ver );
  1207 + compare( "ofp_packet_in header type", $$msg{'header'}{'type'}, '==', $enums{'OFPT_PACKET_IN'} );
  1208 + compare( "ofp_packet_in header length", $$msg{'header'}{'length'}, '==', $msg_size );
  1209 + compare( "ofp_packet_in header length", $$msg{'total_len'}, '==', $pkt_len );
  1210 +
  1211 + my $recvd_pkt_data = substr( $recvd_mesg, $ofp->offsetof( 'ofp_packet_in', 'data' ) );
  1212 +
  1213 + # print "packet expecting\n";
  1214 + # print HexDump ($pkt);
  1215 + # print "packet received\n";
  1216 + # print HexDump ($recvd_pkt_data);
  1217 +
  1218 + if ( $recvd_pkt_data ne $pkt ) {
  1219 + die "ERROR: received packet data didn't match the expecting packet\n";
  1220 + }
  1221 +}
  1222 +
  1223 +sub verify_header {
  1224 +
  1225 + my ( $msg, $ofpt, $msg_size ) = @_;
  1226 +
  1227 + compare( "header version", $$msg{'header'}{'version'}, '==', $of_ver );
  1228 + compare( "header type", $$msg{'header'}{'type'}, '==', $enums{$ofpt} );
  1229 + compare( "header length", $$msg{'header'}{'length'}, '==', $msg_size );
  1230 +}
  1231 +
  1232 +sub get_of_ver {
  1233 + return $of_ver;
  1234 +}
  1235 +
  1236 +sub get_of_port {
  1237 + return $of_port;
  1238 +}
  1239 +
  1240 +sub get_of_miss_send_len_default {
  1241 + return $of_miss_send_len;
  1242 +}
  1243 +
  1244 +sub get_default_black_box_pkt {
  1245 + my ($in_port, $out_port) = @_;
  1246 +
  1247 + return get_default_black_box_pkt_len($in_port, $out_port, 64);
  1248 +}
  1249 +
  1250 +sub get_default_black_box_pkt_len {
  1251 + my ($in_port, $out_port, $len, $vlan_id) = @_;
  1252 +
  1253 + my $pkt_args = {
  1254 + DA => "00:00:00:00:00:" . sprintf( "%02d", $out_port ),
  1255 + SA => "00:00:00:00:00:" . sprintf( "%02d", $in_port ),
  1256 + VLAN_ID => $vlan_id,
  1257 + src_ip => "192.168.200." . ( $in_port ),
  1258 + dst_ip => "192.168.201." . ( $out_port ),
  1259 + ttl => 64,
  1260 + len => $len,
  1261 + src_port => 1,
  1262 + dst_port => 0
  1263 + };
  1264 + return new NF2::UDP_pkt(%$pkt_args);
  1265 +}
  1266 +
  1267 +sub for_all_port_pairs {
  1268 +
  1269 + my ( $ofp, $sock, $options_ref, $fcn_ref, $wc ) = @_;
  1270 +
  1271 + my $port_base = $$options_ref{'port_base'};
  1272 + my $num_ports = $$options_ref{'num_ports'};
  1273 +
  1274 + # Check if we need to be exhaustive or not...
  1275 + if ( defined( $$options_ref{'less_ports'} ) ) {
  1276 + # Just pick a pair of random ports
  1277 + my $source_port = int(rand($num_ports));
  1278 + my $offset = int(rand($num_ports - 1)) + 1;
  1279 + my $dest_port = ($source_port + $offset) % $num_ports;
  1280 + print "sending from port offset $source_port to $dest_port\n";
  1281 + &$fcn_ref( $ofp, $sock, $options_ref, $source_port, $dest_port, $wc);
  1282 + } else {
  1283 + # send from every port to every other port
  1284 + for ( my $i = 0 ; $i < $num_ports ; $i++ ) {
  1285 + for ( my $j = 0 ; $j < $num_ports ; $j++ ) {
  1286 + if ( $i != $j ) {
  1287 + print "sending from port offset $i to $j\n";
  1288 + &$fcn_ref( $ofp, $sock, $options_ref, $i, $j, $wc);
  1289 + }
  1290 + }
  1291 + }
  1292 + }
  1293 +}
  1294 +
  1295 +sub for_all_ports {
  1296 +
  1297 + my ( $ofp, $sock, $options_ref, $fcn_ref, $wc ) = @_;
  1298 +
  1299 + my $port_base = $$options_ref{'port_base'};
  1300 + my $num_ports = $$options_ref{'num_ports'};
  1301 +
  1302 +
  1303 + # Check if we need to be exhaustive or not...
  1304 + if ( defined( $$options_ref{'less_ports'} ) ) {
  1305 + # Just pick one random port
  1306 + my $random_port = int(rand($num_ports));
  1307 + print "sending from port offset $random_port to (all port offsets but $random_port)\n";
  1308 + &$fcn_ref( $ofp, $sock, $options_ref, $random_port, -1, $wc);
  1309 + } else {
  1310 + # send from every port
  1311 + for ( my $i = 0 ; $i < $num_ports ; $i++ ) {
  1312 + print "sending from port offset $i to (all port offsets but $i)\n";
  1313 + &$fcn_ref( $ofp, $sock, $options_ref, $i, -1, $wc);
  1314 + }
  1315 + }
  1316 +}
  1317 +
  1318 +sub for_all_wildcards {
  1319 +
  1320 + my ( $ofp, $sock, $options_ref, $fcn_ref) = @_;
  1321 +
  1322 + my $port_base = $$options_ref{'port_base'};
  1323 + my $num_ports = $$options_ref{'num_ports'};
  1324 +
  1325 + my %wildcards = (
  1326 + 0x000001 => 'IN_PORT',
  1327 + 0x000002 => 'DL_VLAN',
  1328 + 0x000004 => 'DL_SRC',
  1329 + 0x000008 => 'DL_DST',
  1330 + #0x000010 => 'DL_TYPE', # currently fixed at 0x0800
  1331 + #0x000020 => 'NW_PROTO', # currently fixed at 0x17
  1332 + 0x000040 => 'TP_SRC',
  1333 + 0x000080 => 'TP_DST',
  1334 + 0x003f00 => 'NW_SRC',
  1335 + 0x0fc000 => 'NW_DST',
  1336 + 0x100000 => 'DL_VLAN_PCP',
  1337 + 0x200000 => 'NW_TOS',
  1338 + );
  1339 +
  1340 + # Disable "1 ||" below for a more complete test
  1341 + # Check if we need to be exhaustive or not...
  1342 + if ( 1 || defined( $$options_ref{'less_ports'} ) ) {
  1343 + # Just pick a pair of random ports
  1344 + my $source_port = int(rand($num_ports));
  1345 + my $offset = int(rand($num_ports - 1)) + 1;
  1346 + my $dest_port = ($source_port + $offset) % $num_ports;
  1347 +
  1348 + print "sending from $source_port to $dest_port\n";
  1349 +
  1350 + for my $wc (sort keys %wildcards) {
  1351 + printf ("wildcards: 0x%04x ".$wildcards{$wc}."\n", $wc);
  1352 + &$fcn_ref( $ofp, $sock, $options_ref, $source_port, $dest_port, $wc);
  1353 + }
  1354 + } else {
  1355 + # send from every port
  1356 + for ( $i = 0 ; $i < $num_ports ; $i++ ) {
  1357 + my $j = ($i + 1) % 4;
  1358 + print "sending from $i to $j\n";
  1359 + for my $wc (sort keys %wildcards) {
  1360 + printf ("wildcards: 0x%04x ".$wildcards{$wc}."\n", $wc);
  1361 + &$fcn_ref( $ofp, $sock, $options_ref, $i, $j, $wc);
  1362 + }
  1363 + }
  1364 + }
  1365 +}
  1366 +
  1367 +sub for_all_port_triplets {
  1368 + my ( $ofp, $sock, $options_ref, $fcn_ref, $wc ) = @_;
  1369 +
  1370 + my $port_base = $$options_ref{'port_base'};
  1371 + my $num_ports = $$options_ref{'num_ports'};
  1372 +
  1373 + # Check if we need to be exhaustive or not...
  1374 + if ( defined( $$options_ref{'less_ports'} ) ) {
  1375 + # Just pick a triplet of random ports
  1376 + my $source_port = int(rand($num_ports));
  1377 + my $offset = int(rand($num_ports - 1)) + 1;
  1378 + my $dest_port = ($source_port + $offset) % $num_ports;
  1379 + my $offset2 = int(rand($num_ports - 2)) + 1;
  1380 + if( $offset2 >= $offset) {
  1381 + $offset2++;
  1382 + }
  1383 + my $dest2_port = ($source_port + $offset2) % $num_ports;
  1384 +
  1385 + &$fcn_ref( $ofp, $sock, $options_ref, $source_port, $dest_port, $dest2_port, $wc);
  1386 + } else {
  1387 + # send from every port to every other port
  1388 + for ( my $i = 0 ; $i < $num_ports ; $i++ ) {
  1389 + for ( my $j = 0 ; $j < $num_ports ; $j++ ) {
  1390 + my $o_port2 = ( ( $j + 1 ) % 4 );
  1391 + if ( $i != $j && $i != $o_port2) {
  1392 + &$fcn_ref( $ofp, $sock, $options_ref, $i, $j, $o_port2, $wc);
  1393 + }
  1394 + }
  1395 + }
  1396 + }
  1397 +}
  1398 +
  1399 +sub get_original_value {
  1400 + my ($chg_field, $test_pkt, $vlan_id) = @_;
  1401 +
  1402 + my $chg_val;
  1403 + if ($chg_field eq 'dl_src') {
  1404 + $chg_val = ${$test_pkt->{Ethernet_hdr}}->SA;
  1405 + } elsif ($chg_field eq 'dl_dst') {
  1406 + $chg_val = ${$test_pkt->{Ethernet_hdr}}->DA;
  1407 + } elsif ($chg_field eq 'nw_src') {
  1408 + $chg_val = ${$test_pkt->{IP_hdr}}->src_ip;
  1409 + } elsif ($chg_field eq 'nw_dst') {
  1410 + $chg_val = ${$test_pkt->{IP_hdr}}->dst_ip;
  1411 + } elsif ($chg_field eq 'tp_src') {
  1412 + $chg_val = ${$test_pkt->{UDP_pdu}}->SrcPort;
  1413 + } elsif ($chg_field eq 'tp_dst') {
  1414 + $chg_val = ${$test_pkt->{UDP_pdu}}->DstPort;
  1415 + } elsif ($chg_field eq 'vlan_vid') {
  1416 + if (defined $vlan_id) {
  1417 + $chg_val = ${$test_pkt->{Ethernet_hdr}}->VLAN_ID;
  1418 + } else {
  1419 + $chg_val = 0x999; #12-bit value
  1420 + }
  1421 + } elsif ($chg_field eq 'vlan_pcp') {
  1422 + if (defined $vlan_id) {
  1423 + $chg_val = ${$test_pkt->{Ethernet_hdr}}->VLAN_ID;
  1424 + } else {
  1425 + $chg_val = 0x6000; #Upper 3-bit is valid
  1426 + }
  1427 + } else {
  1428 + $chg_val = 0;
  1429 + }
  1430 + return $chg_val;
  1431 +}
  1432 +
  1433 +sub create_vlan_pkt {
  1434 + my ($in_port, $out_port, $pkt_len, $vlan_id, $chg_field) = @_;
  1435 +
  1436 + my $test_pkt_vlan;
  1437 + if ((defined $chg_field) && !(defined $vlan_id)) {
  1438 + if ($chg_field eq 'vlan_vid') {
  1439 + $test_pkt_vlan = get_default_black_box_pkt_len( $in_port, $out_port, $pkt_len, 0x999 );
  1440 + } elsif ($chg_field eq 'vlan_pcp') {
  1441 + $test_pkt_vlan = get_default_black_box_pkt_len( $in_port, $out_port, $pkt_len, 0x6000 );
  1442 + }
  1443 + }
  1444 + return $test_pkt_vlan;
  1445 +}
  1446 +
  1447 +sub replace_sending_pkt {
  1448 + my ($chg_field, $chg_val, $test_pkt, $vlan_id) = @_;
  1449 +
  1450 + my $dummy_chg_val;
  1451 + my $vlan_vid_val;
  1452 + my $vlan_pcp_val;
  1453 + if ($chg_field eq 'dl_src') {
  1454 + ${$test_pkt->{Ethernet_hdr}}->SA("12:34:56:78:9a:bc");
  1455 + } elsif ($chg_field eq 'dl_dst') {
  1456 + ${$test_pkt->{Ethernet_hdr}}->DA("12:34:56:78:9a:bc");
  1457 + } elsif ($chg_field eq 'nw_src') {
  1458 + ${$test_pkt->{IP_hdr}}->src_ip("111.122.133.144");
  1459 + #Dummy rewrite in order to get re-calculated UDP checksum
  1460 + $dummy_chg_val = ${$test_pkt->{UDP_pdu}}->SrcPort;
  1461 + ${$test_pkt->{UDP_pdu}}->SrcPort($dummy_chg_val);
  1462 + } elsif ($chg_field eq 'nw_dst') {
  1463 + ${$test_pkt->{IP_hdr}}->dst_ip("111.122.133.144");
  1464 + #Dummy rewrite in order to get re-calculated UDP checksum
  1465 + $dummy_chg_val = ${$test_pkt->{UDP_pdu}}->SrcPort;
  1466 + ${$test_pkt->{UDP_pdu}}->SrcPort($dummy_chg_val);
  1467 + } elsif ($chg_field eq 'tp_src') {
  1468 + ${$test_pkt->{UDP_pdu}}->SrcPort(55);
  1469 + } elsif ($chg_field eq 'tp_dst') {
  1470 + ${$test_pkt->{UDP_pdu}}->DstPort(55);
  1471 + } elsif ($chg_field eq 'vlan_vid') {
  1472 + if (defined $vlan_id) {
  1473 + $vlan_pcp_val = $chg_val & 0xe000;
  1474 + ${$test_pkt->{Ethernet_hdr}}->VLAN_ID(0x0987 | $vlan_pcp_val);
  1475 + }
  1476 + } elsif ($chg_field eq 'vlan_pcp') {
  1477 + if (defined $vlan_id) {
  1478 + $vlan_vid_val = $chg_val & 0x0fff;
  1479 + ${$test_pkt->{Ethernet_hdr}}->VLAN_ID(0x6000 | $vlan_vid_val);
  1480 + }
  1481 + }
  1482 + return $test_pkt;
  1483 +}
  1484 +
  1485 +sub generate_expect_packet {
  1486 + my ( $chg_field, $chg_val, $ip_checksum_org, $udp_checksum_org, $test_pkt, $test_pkt_novlan, $test_pkt_vlan, $vlan_id ) = @_;
  1487 +
  1488 + # Need to expect modified header value when modify action has been issued.
  1489 + # Replace the value accordingly.
  1490 + if ($chg_field eq 'dl_src') {
  1491 + ${$test_pkt->{Ethernet_hdr}}->SA("$chg_val");
  1492 + }
  1493 + if ($chg_field eq 'dl_dst') {
  1494 + ${$test_pkt->{Ethernet_hdr}}->DA("$chg_val");
  1495 + }
  1496 + if ($chg_field eq 'nw_src') {
  1497 + ${$test_pkt->{IP_hdr}}->src_ip("$chg_val");
  1498 + ${$test_pkt->{IP_hdr}}->checksum($ip_checksum_org);
  1499 + ${$test_pkt->{UDP_pdu}}->Checksum($udp_checksum_org);
  1500 + }
  1501 + if ($chg_field eq 'nw_dst') {
  1502 + ${$test_pkt->{IP_hdr}}->dst_ip("$chg_val");
  1503 + ${$test_pkt->{IP_hdr}}->checksum($ip_checksum_org);
  1504 + ${$test_pkt->{UDP_pdu}}->Checksum($udp_checksum_org);
  1505 + }
  1506 + if ($chg_field eq 'tp_src') {
  1507 + ${$test_pkt->{UDP_pdu}}->SrcPort("$chg_val");
  1508 + }
  1509 + if ($chg_field eq 'tp_dst') {
  1510 + ${$test_pkt->{UDP_pdu}}->DstPort("$chg_val");
  1511 + }
  1512 + if ($chg_field eq 'strip_vlan') {
  1513 + $test_pkt_novlan->{UDP_pdu} = $test_pkt->{UDP_pdu};
  1514 + $test_pkt = $test_pkt_novlan;
  1515 + }
  1516 + if (($chg_field eq 'vlan_vid') || ($chg_field eq 'vlan_pcp')) {
  1517 + if (defined $vlan_id) {
  1518 + ${$test_pkt->{Ethernet_hdr}}->VLAN_ID("$chg_val");
  1519 + } else {
  1520 + $test_pkt_vlan->{UDP_pdu} = $test_pkt->{UDP_pdu};
  1521 + $test_pkt = $test_pkt_vlan;
  1522 + }
  1523 + }
  1524 + return $test_pkt;
  1525 +}
  1526 +
  1527 +sub forward_simple {
  1528 +
  1529 + my ( $ofp, $sock, $options_ref, $in_port_offset, $out_port_offset,
  1530 + $wildcards, $type, $nowait, $chg_field, $vlan_id, $cookie ) = @_;
  1531 +
  1532 + my $in_port = $in_port_offset + $$options_ref{'port_base'};
  1533 + my $out_port;
  1534 + if ($type eq 'all') {
  1535 + $out_port = $enums{'OFPP_ALL'}; # all physical ports except the input
  1536 + }
  1537 + elsif ($type eq 'controller') {
  1538 + $out_port = $enums{'OFPP_CONTROLLER'}; #send to the secure channel
  1539 + }
  1540 + else {
  1541 + $out_port = $out_port_offset + $$options_ref{'port_base'};
  1542 + }
  1543 +
  1544 + my $test_pkt = get_default_black_box_pkt_len( $in_port, $out_port, $$options_ref{'pkt_len'}, $vlan_id );
  1545 + my $test_pkt_novlan = get_default_black_box_pkt_len( $in_port, $out_port, $$options_ref{'pkt_len'}) ;
  1546 + my $test_pkt_vlan = create_vlan_pkt( $in_port, $out_port, $$options_ref{'pkt_len'}, $vlan_id, $chg_field);
  1547 +
  1548 + #print HexDump ($test_pkt->packed);
  1549 + #print HexDump ($test_pkt_novlan->packed);
  1550 + #print HexDump ($test_pkt_vlan->packed);
  1551 +
  1552 + my $ip_checksum_org = ${$test_pkt->{IP_hdr}}->checksum;
  1553 + my $udp_checksum_org = ${$test_pkt->{UDP_pdu}}->Checksum;
  1554 +
  1555 + my $chg_val;
  1556 + my $send_pkt;
  1557 + if (defined $chg_field) {
  1558 + #Save original value
  1559 + $chg_val = get_original_value($chg_field, $test_pkt, $vlan_id);
  1560 + #Replace the test packet
  1561 + $test_pkt = replace_sending_pkt($chg_field, $chg_val, $test_pkt, $vlan_id);
  1562 + #Get the replaced vlan id
  1563 + if (defined $vlan_id) {
  1564 + $vlan_id = ${$test_pkt->{Ethernet_hdr}}->VLAN_ID;
  1565 + }
  1566 + }
  1567 +
  1568 + my $flow_mod_pkt;
  1569 + my $flags = $enums{'OFPFF_SEND_FLOW_REM'};
  1570 + if ($type eq 'drop') {
  1571 + $flow_mod_pkt = create_flow_mod_from_udp_action( $ofp, $test_pkt, $in_port, $out_port,
  1572 + $$options_ref{'max_idle'}, $flags,
  1573 + $wildcards, 'drop', undef, undef,
  1574 + $vlan_id, undef, $cookie, undef);
  1575 + } elsif ($type eq 'enqueue') {
  1576 + my $queue_id = 1;
  1577 + $flow_mod_pkt = create_flow_mod_from_udp_action( $ofp, $test_pkt, $in_port, $out_port,
  1578 + $$options_ref{'max_idle'}, $flags,
  1579 + $wildcards, 'enqueue', undef, undef,
  1580 + $vlan_id, undef, $cookie, $queue_id);
  1581 + } else {
  1582 + $flow_mod_pkt = create_flow_mod_from_udp( $ofp, $test_pkt, $in_port, $out_port,
  1583 + $$options_ref{'max_idle'}, $flags,
  1584 + $wildcards, $chg_field, $chg_val, $vlan_id,
  1585 + undef, $cookie);
  1586 + }
  1587 +
  1588 + print HexDump($flow_mod_pkt);
  1589 + #print Dumper($flow_mod_pkt);
  1590 +
  1591 + # Send 'flow_mod' message
  1592 + syswrite( $sock, $flow_mod_pkt );
  1593 + print "sent flow_mod message\n";
  1594 +
  1595 + # Give OF switch time to process the flow mod
  1596 + usleep($$options_ref{'send_delay'});
  1597 +
  1598 + nftest_send( "eth" . ($in_port_offset + 1), $test_pkt->packed );
  1599 +
  1600 + my $expect_pkt;
  1601 + # Regenerate expected packet in case of performing modify_action
  1602 + if (defined $chg_field) {
  1603 + $expect_pkt = generate_expect_packet($chg_field, $chg_val, $ip_checksum_org,
  1604 + $udp_checksum_org, $test_pkt, $test_pkt_novlan, $test_pkt_vlan, $vlan_id);
  1605 + } else {
  1606 + $expect_pkt = $test_pkt;
  1607 + }
  1608 +
  1609 + if ($type eq 'any' || $type eq 'port' || $type eq 'enqueue') {
  1610 + # expect single packet
  1611 + print "expect single packet\n";
  1612 + nftest_expect( "eth" . ( $out_port_offset + 1 ), $expect_pkt->packed );
  1613 + }
  1614 + elsif ($type eq 'all') {
  1615 + # expect packets on all other interfaces
  1616 + print "expect multiple packets\n";
  1617 + for ( my $k = 0 ; $k < $$options_ref{'num_ports'} ; $k++ ) {
  1618 + if ( $k != $in_port_offset ) {
  1619 + nftest_expect( "eth" . ( $k + 1), $expect_pkt->packed );
  1620 + }
  1621 + }
  1622 + }
  1623 + elsif ($type eq 'controller') {
  1624 + # expect at controller
  1625 +
  1626 + my $recvd_mesg;
  1627 + sysread( $sock, $recvd_mesg, 1512 ) || die "Failed to receive message: $!";
  1628 +
  1629 + # Inspect message
  1630 + my $msg_size = length($recvd_mesg);
  1631 + my $expected_size = $ofp->offsetof( 'ofp_packet_in', 'data' ) + length( $expect_pkt->packed );
  1632 + compare( "ofp_packet_in msg size", $msg_size, '==', $expected_size );
  1633 +
  1634 + my $msg = $ofp->unpack( 'ofp_packet_in', $recvd_mesg );
  1635 +
  1636 + #print HexDump ($recvd_mesg);
  1637 + #print Dumper($msg);
  1638 +
  1639 + # Verify fields
  1640 + print "Verifying ofprotocol message for packet sent in to eth" . ( $in_port + 1 ) . "\n";
  1641 +
  1642 + verify_header( $msg, 'OFPT_PACKET_IN', $msg_size );
  1643 +
  1644 + compare( "ofp_packet_in total len", $$msg{'total_len'}, '==', length( $test_pkt->packed ) );
  1645 + compare( "ofp_packet_in in_port", $$msg{'in_port'}, '==', $in_port );
  1646 + compare( "ofp_packet_in reason", $$msg{'reason'}, '==', $enums{'OFPR_ACTION'} );
  1647 +
  1648 + # verify packet was unchanged!
  1649 + my $recvd_pkt_data = substr( $recvd_mesg, $ofp->offsetof( 'ofp_packet_in', 'data' ) );
  1650 + if ( $recvd_pkt_data ne $test_pkt->packed ) {
  1651 + die "ERROR: sending from eth"
  1652 + . ($in_port_offset + 1)
  1653 + . " received packet data didn't match packet sent\n";
  1654 + }
  1655 + }
  1656 + elsif ($type eq 'drop') {
  1657 + # do nothing!
  1658 + }
  1659 + else {
  1660 + die "invalid input to forward_simple\n";
  1661 + }
  1662 +
  1663 + my $pkt_len = $$options_ref{'pkt_len'};
  1664 + if (defined $vlan_id) {
  1665 + $$options_ref{'pkt_len'} = $pkt_len + 4;
  1666 + }
  1667 +
  1668 + if (not defined($nowait)) {
  1669 + print "wait \n";
  1670 + wait_for_flow_expired_all( $ofp, $sock, $options_ref );
  1671 + }
  1672 +
  1673 + $$options_ref{'pkt_len'} = $pkt_len;
  1674 +}
  1675 +
  1676 +
  1677 +#Sub functions for ICMP handling tests
  1678 +
  1679 +sub get_default_black_box_pkt_len_icmp {
  1680 + my ($in_port, $out_port, $len) = @_;
  1681 +
  1682 + my $pkt_args = {
  1683 + DA => "00:00:00:00:00:" . sprintf( "%02d", $out_port ),
  1684 + SA => "00:00:00:00:00:" . sprintf( "%02d", $in_port ),
  1685 + src_ip => "192.168.200." . ( $in_port ),
  1686 + dst_ip => "192.168.201." . ( $out_port ),
  1687 + ttl => 64,
  1688 + len => $len,
  1689 + src_port => 1,
  1690 + dst_port => 0
  1691 + };
  1692 + return new_icmp_test_pkt NF2::ICMP_pkt(%$pkt_args);
  1693 +}
  1694 +
  1695 +#Sub functions for ICMP handling tests
  1696 +
  1697 +sub get_default_black_box_pkt_len_arp {
  1698 + my ($in_port, $out_port, $len) = @_;
  1699 +
  1700 + my $pkt_args = {
  1701 + DA => "00:00:00:00:00:" . sprintf( "%02d", $out_port ),
  1702 + SA => "00:00:00:00:00:" . sprintf( "%02d", $in_port ),
  1703 + SenderIpAddr => "192.168.200." . ( $in_port ),
  1704 + SenderEthAddr => "00:00:00:00:01:" . sprintf("%02d", $in_port),
  1705 + TargetIpAddr => "192.168.201." . ( $out_port ),
  1706 + TargetEthAddr => "ff:ff:ff:ff:ff:ff",
  1707 + len => $len,
  1708 + };
  1709 + return new_arp_test_pkt NF2::ARP_pkt(%$pkt_args);
  1710 +}
  1711 +
  1712 +sub create_flow_mod_from_icmp {
  1713 +
  1714 + my ( $ofp, $icmp_pkt, $in_port, $out_port, $max_idle, $flags, $wildcards, $fool ) = @_;
  1715 +
  1716 + my $flow_mod_pkt;
  1717 +
  1718 + $flow_mod_pkt =
  1719 + create_flow_mod_from_icmp_action( $ofp, $icmp_pkt, $in_port, $out_port, $max_idle, $flags, $wildcards,
  1720 + 'OFPFC_ADD', $fool, $cookie );
  1721 +
  1722 + return $flow_mod_pkt;
  1723 +}
  1724 +
  1725 +sub create_flow_mod_from_icmp_action {
  1726 +
  1727 + my ( $ofp, $udp_pkt, $in_port, $out_port, $max_idle, $flags,
  1728 + $wildcards, $mod_type, $fool, $cookie ) = @_;
  1729 +
  1730 + $cookie = 0 if !defined($cookie);
  1731 +
  1732 + if ( $mod_type ne 'OFPFC_ADD'
  1733 + && $mod_type ne 'OFPFC_DELETE'
  1734 + && $mod_type ne 'OFPFC_DELETE_STRICT' )
  1735 + {
  1736 + die "Undefined flow mod type: $mod_type\n";
  1737 + }
  1738 +
  1739 + my $hdr_args = {
  1740 + version => $of_ver,
  1741 + type => $enums{'OFPT_FLOW_MOD'},
  1742 + length => $ofp->sizeof('ofp_flow_mod') + $ofp->sizeof('ofp_action_output'),
  1743 + xid => 0x0000000
  1744 + };
  1745 +
  1746 + # might be cleaner to convert the exported colon-hex MAC addrs
  1747 + #print ${$udp_pkt->{Ethernet_hdr}}->SA . "\n";
  1748 + #print ${$test_pkt->{Ethernet_hdr}}->SA . "\n";
  1749 + my $ref_to_eth_hdr = ( $udp_pkt->{'Ethernet_hdr'} );
  1750 + my $ref_to_ip_hdr = ( $udp_pkt->{'IP_hdr'} );
  1751 +
  1752 + # pointer to array
  1753 + my $eth_hdr_bytes = $$ref_to_eth_hdr->{'bytes'};
  1754 + my $ip_hdr_bytes = $$ref_to_ip_hdr->{'bytes'};
  1755 + my @dst_mac_subarray = @{$eth_hdr_bytes}[ 0 .. 5 ];
  1756 + my @src_mac_subarray = @{$eth_hdr_bytes}[ 6 .. 11 ];
  1757 +
  1758 + my @src_ip_subarray = @{$ip_hdr_bytes}[ 12 .. 15 ];
  1759 + my @dst_ip_subarray = @{$ip_hdr_bytes}[ 16 .. 19 ];
  1760 +
  1761 + my $src_ip =
  1762 + ( ( 2**24 ) * $src_ip_subarray[0] +
  1763 + ( 2**16 ) * $src_ip_subarray[1] +
  1764 + ( 2**8 ) * $src_ip_subarray[2] +
  1765 + $src_ip_subarray[3] );
  1766 +
  1767 + my $dst_ip =
  1768 + ( ( 2**24 ) * $dst_ip_subarray[0] +
  1769 + ( 2**16 ) * $dst_ip_subarray[1] +
  1770 + ( 2**8 ) * $dst_ip_subarray[2] +
  1771 + $dst_ip_subarray[3] );
  1772 +
  1773 + my $icmp_type;
  1774 + if ($fool == 1) {
  1775 + $icmp_type = ~(${ $udp_pkt->{ICMP_pdu} }->Type);
  1776 + } else {
  1777 + $icmp_type = (${ $udp_pkt->{ICMP_pdu} }->Type);
  1778 + }
  1779 +
  1780 + my $icmp_code = ${ $udp_pkt->{ICMP_pdu} }->Code;
  1781 +
  1782 + my $match_args = {
  1783 + wildcards => $wildcards,
  1784 + in_port => $in_port,
  1785 + dl_src => \@src_mac_subarray,
  1786 + dl_dst => \@dst_mac_subarray,
  1787 + dl_vlan => 0xffff,
  1788 + dl_type => 0x0800,
  1789 + dl_vlan_pcp => 0x00,
  1790 + nw_src => $src_ip,
  1791 + nw_dst => $dst_ip,
  1792 + nw_tos => 0,
  1793 + nw_proto => 1, #ICMP
  1794 + tp_src => $icmp_type,
  1795 + tp_dst => $icmp_code
  1796 + };
  1797 +
  1798 + my $max_len;
  1799 + if ($out_port != $enums{'OFPP_CONTROLLER'}) {
  1800 + $max_len = 0;
  1801 + } else {
  1802 + $max_len = 65535;
  1803 + }
  1804 + my $action_output_args = {
  1805 + type => $enums{'OFPAT_OUTPUT'},
  1806 + len => $ofp->sizeof('ofp_action_output'),
  1807 + port => $out_port,
  1808 + max_len => $max_len,
  1809 + };
  1810 +
  1811 + my $action_output = $ofp->pack( 'ofp_action_output', $action_output_args );
  1812 +
  1813 + my $flow_mod_args = {
  1814 + header => $hdr_args,
  1815 + match => $match_args,
  1816 +
  1817 + # command => $enums{$mod_type},
  1818 + command => $enums{"$mod_type"},
  1819 + idle_timeout => $max_idle,
  1820 + hard_timeout => $max_idle,
  1821 + flags => $flags,
  1822 + priority => 0,
  1823 + buffer_id => -1,
  1824 + out_port => $enums{'OFPP_NONE'},
  1825 + cookie => $cookie,
  1826 + };
  1827 + my $flow_mod = $ofp->pack( 'ofp_flow_mod', $flow_mod_args );
  1828 +
  1829 + my $flow_mod_pkt = $flow_mod . $action_output;
  1830 +
  1831 + return $flow_mod_pkt;
  1832 +}
  1833 +
  1834 +sub create_flow_mod_from_arp {
  1835 +
  1836 + my ( $ofp, $icmp_pkt, $in_port, $out_port, $max_idle, $flags, $wildcards, $fool ) = @_;
  1837 +
  1838 + my $flow_mod_pkt;
  1839 +
  1840 + $flow_mod_pkt =
  1841 + create_flow_mod_from_arp_action( $ofp, $icmp_pkt, $in_port, $out_port, $max_idle, $flags, $wildcards,
  1842 + 'OFPFC_ADD', $fool );
  1843 +
  1844 + return $flow_mod_pkt;
  1845 +}
  1846 +
  1847 +sub create_flow_mod_from_arp_action {
  1848 +
  1849 + my ( $ofp, $udp_pkt, $in_port, $out_port, $max_idle, $flags, $wildcards, $mod_type, $fool ) = @_;
  1850 +
  1851 + if ( $mod_type ne 'OFPFC_ADD'
  1852 + && $mod_type ne 'OFPFC_DELETE'
  1853 + && $mod_type ne 'OFPFC_DELETE_STRICT' )
  1854 + {
  1855 + die "Undefined flow mod type: $mod_type\n";
  1856 + }
  1857 +
  1858 + my $hdr_args = {
  1859 + version => $of_ver,
  1860 + type => $enums{'OFPT_FLOW_MOD'},
  1861 + length => $ofp->sizeof('ofp_flow_mod') + $ofp->sizeof('ofp_action_output'),
  1862 + xid => 0x0000000
  1863 + };
  1864 +
  1865 + # might be cleaner to convert the exported colon-hex MAC addrs
  1866 + #print ${$udp_pkt->{Ethernet_hdr}}->SA . "\n";
  1867 + #print ${$test_pkt->{Ethernet_hdr}}->SA . "\n";
  1868 + my $ref_to_eth_hdr = ( $udp_pkt->{'Ethernet_hdr'} );
  1869 + my $ref_to_arp_hdr = ( $udp_pkt->{'ARP_hdr'} );
  1870 +
  1871 + # pointer to array
  1872 + my $eth_hdr_bytes = $$ref_to_eth_hdr->{'bytes'};
  1873 + my $arp_hdr_bytes = $$ref_to_arp_hdr->{'bytes'};
  1874 + my @dst_mac_subarray = @{$eth_hdr_bytes}[ 0 .. 5 ];
  1875 + my @src_mac_subarray = @{$eth_hdr_bytes}[ 6 .. 11 ];
  1876 +
  1877 + my @src_ip_subarray = @{$arp_hdr_bytes}[ 14 .. 17 ];
  1878 + my @dst_ip_subarray = @{$arp_hdr_bytes}[ 24 .. 27 ];
  1879 +
  1880 + my $src_ip =
  1881 + ( ( 2**24 ) * $src_ip_subarray[0] +
  1882 + ( 2**16 ) * $src_ip_subarray[1] +
  1883 + ( 2**8 ) * $src_ip_subarray[2] +
  1884 + $src_ip_subarray[3] );
  1885 +
  1886 + my $dst_ip =
  1887 + ( ( 2**24 ) * $dst_ip_subarray[0] +
  1888 + ( 2**16 ) * $dst_ip_subarray[1] +
  1889 + ( 2**8 ) * $dst_ip_subarray[2] +
  1890 + $dst_ip_subarray[3] );
  1891 +
  1892 + my $arp_opcode;
  1893 + if ($fool == 1) {
  1894 + $arp_opcode = ~(${$ref_to_arp_hdr}->Op);
  1895 + } else {
  1896 + $arp_opcode = (${$ref_to_arp_hdr}->Op);
  1897 + }
  1898 +
  1899 + my $match_args = {
  1900 + wildcards => $wildcards,
  1901 + in_port => $in_port,
  1902 + dl_src => \@src_mac_subarray,
  1903 + dl_dst => \@dst_mac_subarray,
  1904 + dl_vlan => 0xffff,
  1905 + dl_type => 0x0806,
  1906 + dl_vlan_pcp => 0x00,
  1907 + nw_src => $src_ip,
  1908 + nw_dst => $dst_ip,
  1909 + nw_proto => $arp_opcode,
  1910 + tp_src => 0x0000,
  1911 + tp_dst => 0x0000
  1912 + };
  1913 +
  1914 + my $max_len;
  1915 + if ($out_port != $enums{'OFPP_CONTROLLER'}) {
  1916 + $max_len = 0;
  1917 + } else {
  1918 + $max_len = 65535;
  1919 + }
  1920 + my $action_output_args = {
  1921 + type => $enums{'OFPAT_OUTPUT'},
  1922 + len => $ofp->sizeof('ofp_action_output'),
  1923 + port => $out_port,
  1924 + max_len => $max_len,
  1925 + };
  1926 +
  1927 + my $action_output = $ofp->pack( 'ofp_action_output', $action_output_args );
  1928 +
  1929 + my $flow_mod_args = {
  1930 + header => $hdr_args,
  1931 + match => $match_args,
  1932 +
  1933 + # command => $enums{$mod_type},
  1934 + command => $enums{"$mod_type"},
  1935 + idle_timeout => $max_idle,
  1936 + hard_timeout => $max_idle,
  1937 + flags => $flags,
  1938 + priority => 0,
  1939 + buffer_id => -1,
  1940 + out_port => $enums{'OFPP_NONE'}
  1941 + };
  1942 + my $flow_mod = $ofp->pack( 'ofp_flow_mod', $flow_mod_args );
  1943 +
  1944 + my $flow_mod_pkt = $flow_mod . $action_output;
  1945 +
  1946 + return $flow_mod_pkt;
  1947 +}
  1948 +
  1949 +sub forward_simple_icmp {
  1950 +
  1951 + my ( $ofp, $sock, $options_ref, $in_port_offset, $out_port_offset, $wildcards, $type, $fool, $nowait ) = @_;
  1952 +
  1953 + my $in_port = $in_port_offset + $$options_ref{'port_base'};
  1954 + my $out_port;
  1955 +
  1956 + my $fool_port = 0;
  1957 + my $flow_mod_pkt_fool;
  1958 +
  1959 + my $flags = $enums{'OFPFF_SEND_FLOW_REM'};
  1960 +
  1961 + if ($type eq 'all') {
  1962 + $out_port = $enums{'OFPP_ALL'}; # all physical ports except the input
  1963 + }
  1964 + elsif ($type eq 'controller') {
  1965 + $out_port = $enums{'OFPP_CONTROLLER'}; #send to the secure channel
  1966 + }
  1967 + else {
  1968 + $out_port = $out_port_offset + $$options_ref{'port_base'};
  1969 + }
  1970 +
  1971 + if ($fool == 1) {
  1972 + $fool_port = ($out_port_offset + $$options_ref{'port_base'} + 1) % $$options_ref{'num_ports'};
  1973 + if ($fool_port == $in_port) {
  1974 + $fool_port = ($out_port_offset + $$options_ref{'port_base'} + 2) % $$options_ref{'num_ports'};
  1975 + }
  1976 + }
  1977 +
  1978 + my $test_pkt = get_default_black_box_pkt_len_icmp( $in_port, $out_port, $$options_ref{'pkt_len'} );
  1979 +
  1980 + #print HexDump ( $test_pkt->packed );
  1981 +
  1982 + if (($fool == 1) && ($type eq 'port') && ($wildcards != 0x40)) {
  1983 + my $flow_mod_pkt_fool =
  1984 + create_flow_mod_from_icmp( $ofp, $test_pkt, $in_port, $fool_port, $$options_ref{'max_idle'}, $flags, $wildcards, $fool );
  1985 + print HexDump($flow_mod_pkt_fool);
  1986 + #print Dumper($flow_mod_pkt_fool);
  1987 + # Send 'flow_mod' message
  1988 + print $sock $flow_mod_pkt_fool;
  1989 + print "sent flow_mod message\n";
  1990 + # Give OF switch time to process the flow mod
  1991 + usleep($$options_ref{'send_delay'});
  1992 + }
  1993 +
  1994 + my $flow_mod_pkt =
  1995 + create_flow_mod_from_icmp( $ofp, $test_pkt, $in_port, $out_port, $$options_ref{'max_idle'}, $flags, $wildcards, 0 );
  1996 +
  1997 + #print HexDump($flow_mod_pkt);
  1998 + #print Dumper($flow_mod_pkt);
  1999 +
  2000 + # Send 'flow_mod' message
  2001 + print $sock $flow_mod_pkt;
  2002 + print "sent flow_mod message\n";
  2003 +
  2004 + # Give OF switch time to process the flow mod
  2005 + usleep($$options_ref{'send_delay'});
  2006 +
  2007 + nftest_send( "eth" . ($in_port_offset + 1), $test_pkt->packed );
  2008 + #print HexDump($test_pkt->packed);
  2009 +
  2010 + if ($type eq 'any' || $type eq 'port') {
  2011 + # expect single packet
  2012 + print "expect single packet\n";
  2013 + nftest_expect( "eth" . ( $out_port_offset + 1 ), $test_pkt->packed );
  2014 + }
  2015 + elsif ($type eq 'all') {
  2016 + # expect packets on all other interfaces
  2017 + print "expect multiple packets\n";
  2018 + for ( my $k = 0 ; $k < $$options_ref{'num_ports'} ; $k++ ) {
  2019 + if ( $k != $in_port_offset ) {
  2020 + nftest_expect( "eth" . ( $k + 1), $test_pkt->packed );
  2021 + }
  2022 + }
  2023 + }
  2024 + elsif ($type eq 'controller') {
  2025 + # expect at controller
  2026 +
  2027 + my $recvd_mesg;
  2028 + sysread( $sock, $recvd_mesg, 1512 ) || die "Failed to receive message: $!";
  2029 +
  2030 + # Inspect message
  2031 + my $msg_size = length($recvd_mesg);
  2032 + my $expected_size = $ofp->offsetof( 'ofp_packet_in', 'data' ) + length( $test_pkt->packed );
  2033 + compare( "ofp_packet_in icmp msg size", $msg_size, '==', $expected_size );
  2034 +
  2035 + my $msg = $ofp->unpack( 'ofp_packet_in', $recvd_mesg );
  2036 +
  2037 + #print HexDump ($recvd_mesg);
  2038 + #print Dumper($msg);
  2039 +
  2040 + # Verify fields
  2041 + print "Verifying ofprotocol message for packet sent in to eth" . ( $in_port + 1 ) . "\n";
  2042 +
  2043 + verify_header( $msg, 'OFPT_PACKET_IN', $msg_size );
  2044 +
  2045 + compare( "ofp_packet_in icmp total len", $$msg{'total_len'}, '==', length( $test_pkt->packed ) );
  2046 + compare( "ofp_packet_in icmp in_port", $$msg{'in_port'}, '==', $in_port );
  2047 + compare( "ofp_packet_in icmp reason", $$msg{'reason'}, '==', $enums{'OFPR_ACTION'} );
  2048 +
  2049 + # verify packet was unchanged!
  2050 + my $recvd_pkt_data = substr( $recvd_mesg, $ofp->offsetof( 'ofp_packet_in', 'data' ) );
  2051 + if ( $recvd_pkt_data ne $test_pkt->packed ) {
  2052 + die "ERROR: sending from eth"
  2053 + . ($in_port_offset + 1)
  2054 + . " received packet data didn't match packet sent\n";
  2055 + }
  2056 + }
  2057 + else {
  2058 + die "invalid input to forward_simple_icmp\n";
  2059 + }
  2060 +
  2061 + my $pkt_len = $$options_ref{'pkt_len'};
  2062 + if (defined $vlan_id) {
  2063 + $$options_ref{'pkt_len'} = $pkt_len + 4;
  2064 + }
  2065 +
  2066 + if (not defined($nowait)) {
  2067 + print "wait \n";
  2068 + if ($fool == 1) {
  2069 + print "wait for two flow exprired\n";
  2070 + wait_for_two_flow_expired( $ofp, $sock, $$options_ref{'pkt_len'}, $$options_ref{'pkt_total'} );
  2071 + } else {
  2072 + print "wait for flow expired\n";
  2073 + wait_for_flow_expired( $ofp, $sock, $options_ref, $$options_ref{'pkt_len'}, $$options_ref{'pkt_total'} );
  2074 + }
  2075 + }
  2076 +}
  2077 +
  2078 +sub forward_simple_arp {
  2079 +
  2080 + my ( $ofp, $sock, $options_ref, $in_port_offset, $out_port_offset, $wildcards, $type, $fool, $nowait ) = @_;
  2081 +
  2082 + my $in_port = $in_port_offset + $$options_ref{'port_base'};
  2083 + my $out_port;
  2084 +
  2085 + my $fool_port = 0;
  2086 + my $flow_mod_pkt_fool;
  2087 +
  2088 + my $flags = $enums{'OFPFF_SEND_FLOW_REM'};
  2089 +
  2090 + if ($type eq 'all') {
  2091 + $out_port = $enums{'OFPP_ALL'}; # all physical ports except the input
  2092 + }
  2093 + elsif ($type eq 'controller') {
  2094 + $out_port = $enums{'OFPP_CONTROLLER'}; #send to the secure channel
  2095 + }
  2096 + else {
  2097 + $out_port = $out_port_offset + $$options_ref{'port_base'};
  2098 + }
  2099 +
  2100 + if ($fool == 1) {
  2101 + $fool_port = ($out_port_offset + $$options_ref{'port_base'} + 1) % $$options_ref{'num_ports'};
  2102 + if ($fool_port == $in_port) {
  2103 + $fool_port = ($out_port_offset + $$options_ref{'port_base'} + 2) % $$options_ref{'num_ports'};
  2104 + }
  2105 + }
  2106 +
  2107 + my $test_pkt = get_default_black_box_pkt_len_arp( $in_port, $out_port, $$options_ref{'pkt_len'} );
  2108 +
  2109 + #print HexDump ( $test_pkt->packed );
  2110 +
  2111 + if (($fool == 1) && ($type eq 'port') && ($wildcards != 0x40)) {
  2112 + my $flow_mod_pkt_fool =
  2113 + create_flow_mod_from_arp( $ofp, $test_pkt, $in_port, $fool_port, $$options_ref{'max_idle'}, $flags, $wildcards, $fool );
  2114 + print HexDump($flow_mod_pkt_fool);
  2115 + #print Dumper($flow_mod_pkt_fool);
  2116 + # Send 'flow_mod' message
  2117 + print $sock $flow_mod_pkt_fool;
  2118 + print "sent flow_mod message\n";
  2119 + # Give OF switch time to process the flow mod
  2120 + usleep($$options_ref{'send_delay'});
  2121 + }
  2122 +
  2123 + my $flow_mod_pkt =
  2124 + create_flow_mod_from_arp( $ofp, $test_pkt, $in_port, $out_port, $$options_ref{'max_idle'}, $flags, $wildcards, 0 );
  2125 +
  2126 + #print HexDump($flow_mod_pkt);
  2127 + #print Dumper($flow_mod_pkt);
  2128 +
  2129 + # Send 'flow_mod' message
  2130 + print $sock $flow_mod_pkt;
  2131 + print "sent flow_mod message\n";
  2132 +
  2133 + # Give OF switch time to process the flow mod
  2134 + usleep($$options_ref{'send_delay'});
  2135 +
  2136 + nftest_send( "eth" . ($in_port_offset + 1), $test_pkt->packed );
  2137 + #print HexDump($test_pkt->packed);
  2138 +
  2139 + if ($type eq 'any' || $type eq 'port') {
  2140 + # expect single packet
  2141 + print "expect single packet\n";
  2142 + nftest_expect( "eth" . ( $out_port_offset + 1 ), $test_pkt->packed );
  2143 + }
  2144 + elsif ($type eq 'all') {
  2145 + # expect packets on all other interfaces
  2146 + print "expect multiple packets\n";
  2147 + for ( my $k = 0 ; $k < $$options_ref{'num_ports'} ; $k++ ) {
  2148 + if ( $k != $in_port_offset ) {
  2149 + nftest_expect( "eth" . ( $k + 1), $test_pkt->packed );
  2150 + }
  2151 + }
  2152 + }
  2153 + elsif ($type eq 'controller') {
  2154 + # expect at controller
  2155 +
  2156 + my $recvd_mesg;
  2157 + sysread( $sock, $recvd_mesg, 1512 ) || die "Failed to receive message: $!";
  2158 +
  2159 + # Inspect message
  2160 + my $msg_size = length($recvd_mesg);
  2161 + my $expected_size = $ofp->offsetof( 'ofp_packet_in', 'data' ) + length( $test_pkt->packed );
  2162 + compare( "ofp_packet_in arp msg size", $msg_size, '==', $expected_size );
  2163 +
  2164 + my $msg = $ofp->unpack( 'ofp_packet_in', $recvd_mesg );
  2165 +
  2166 + #print HexDump ($recvd_mesg);
  2167 + #print Dumper($msg);
  2168 +
  2169 + # Verify fields
  2170 + print "Verifying ofprotocol message for packet sent in to eth" . ( $in_port + 1 ) . "\n";
  2171 +
  2172 + verify_header( $msg, 'OFPT_PACKET_IN', $msg_size );
  2173 +
  2174 + compare( "ofp_packet_in arp total len", $$msg{'total_len'}, '==', length( $test_pkt->packed ) );
  2175 + compare( "ofp_packet_in arp in_port", $$msg{'in_port'}, '==', $in_port );
  2176 + compare( "ofp_packet_in arp reason", $$msg{'reason'}, '==', $enums{'OFPR_ACTION'} );
  2177 +
  2178 + # verify packet was unchanged!
  2179 + my $recvd_pkt_data = substr( $recvd_mesg, $ofp->offsetof( 'ofp_packet_in', 'data' ) );
  2180 + if ( $recvd_pkt_data ne $test_pkt->packed ) {
  2181 + die "ERROR: sending from eth"
  2182 + . ($in_port_offset + 1)
  2183 + . " received packet data didn't match packet sent\n";
  2184 + }
  2185 + }
  2186 + else {
  2187 + die "invalid input to forward_simple_arp\n";
  2188 + }
  2189 +
  2190 + my $pkt_len = $$options_ref{'pkt_len'};
  2191 + if (defined $vlan_id) {
  2192 + $$options_ref{'pkt_len'} = $pkt_len + 4;
  2193 + }
  2194 +
  2195 + if (not defined($nowait)) {
  2196 + print "wait \n";
  2197 + if ($fool == 1) {
  2198 + print "wait for two flow exprired\n";
  2199 + wait_for_two_flow_expired( $ofp, $sock, $$options_ref{'pkt_len'}, $$options_ref{'pkt_total'} );
  2200 + } else {
  2201 + print "wait for flow expired\n";
  2202 + wait_for_flow_expired( $ofp, $sock, $options_ref, $$options_ref{'pkt_len'}, $$options_ref{'pkt_total'} );
  2203 + }
  2204 + }
  2205 +}
  2206 +
  2207 +sub wait_for_two_flow_expired {
  2208 +
  2209 + my ( $ofp, $sock, $pkt_len, $pkt_total ) = @_;
  2210 + my $read_size = 1512;
  2211 + my $pkt_total_size = $pkt_len * $pkt_total;
  2212 +
  2213 + my $recvd_mesg;
  2214 +
  2215 + sysread( $sock, $recvd_mesg, $read_size )
  2216 + || die "Failed to receive message: $!";
  2217 +
  2218 + #print HexDump ($recvd_mesg);
  2219 +
  2220 + # Inspect message
  2221 + my $msg_size = length($recvd_mesg);
  2222 + my $expected_size = $ofp->sizeof('ofp_flow_removed');
  2223 + #compare( "msg size", length($recvd_mesg), '==', $expected_size );
  2224 +
  2225 + my $msg = $ofp->unpack( 'ofp_flow_removed', $recvd_mesg );
  2226 +
  2227 + #print Dumper($msg);
  2228 +
  2229 + # Verify fields
  2230 + #compare( "header version", $$msg{'header'}{'version'}, '==', $of_ver );
  2231 + #compare( "header type", $$msg{'header'}{'type'}, '==', $enums{'OFPT_FLOW_REMOVED'} );
  2232 + #compare( "header length", $$msg{'header'}{'length'}, '==', $msg_size );
  2233 + #compare( "byte_count", $$msg{'byte_count'}, '==', $bytes );
  2234 + #compare( "packet_count", $$msg{'packet_count'}, '==', $pkt_total_size );
  2235 + sleep 3;
  2236 +}
  2237 +
  2238 +sub wait_for_echo_request {
  2239 +
  2240 + my ( $ofp, $sock, $options_ref, $read_size_ ) = @_;
  2241 + my $read_size;
  2242 +
  2243 + if ( defined $read_size_ ) {
  2244 + $read_size = $read_size_;
  2245 + } else {
  2246 + $read_size = 1512;
  2247 + }
  2248 +
  2249 + my $recvd_mesg;
  2250 + sysread( $sock, $recvd_mesg, $read_size )
  2251 + || die "Failed to receive ofp_echo_request message: $!";
  2252 +
  2253 + #print HexDump ($recvd_mesg);
  2254 +
  2255 + # Inspect message
  2256 + my $msg_size = length($recvd_mesg);
  2257 + my $expected_size = $ofp->sizeof('ofp_header');
  2258 + compare( "ofp_echo_reply msg size", length($recvd_mesg), '==', $expected_size );
  2259 +
  2260 + my $msg = $ofp->unpack( 'ofp_header', $recvd_mesg );
  2261 +
  2262 + #print Dumper($msg);
  2263 + # Verify fields
  2264 + compare( "header version", $$msg{'version'}, '==', $of_ver );
  2265 + compare( "header type", $$msg{'type'}, '==', $enums{'OFPT_ECHO_REQUEST'} );
  2266 + compare( "header length", $$msg{'length'}, '==', $msg_size );
  2267 +
  2268 + return $$msg{'xid'};
  2269 +}
  2270 +
  2271 +sub get_dpinst {
  2272 + my ($options_ref) = @_;
  2273 +
  2274 + my $platform = $$options_ref{'common-st-args'};
  2275 + my $kmod_dpinst = "nl:0";
  2276 + my $user_dpinst = "unix:/var/run/test";
  2277 + my $dpinst;
  2278 +
  2279 + if ( not defined( $$options_ref{'listener'} ) ) {
  2280 + if (($platform eq 'user') or ($platform eq 'user_veth')) {
  2281 + $dpinst = $user_dpinst;
  2282 + } else {
  2283 + $dpinst = $kmod_dpinst;
  2284 + }
  2285 + } else {
  2286 + # For some platform, we have absolutely no way to guess
  2287 + # the proper argument to dpctl.
  2288 + # For example, on the HP test, it means guessing the IP
  2289 + # address and the port. So, we need a bit of help...
  2290 + # Jean II
  2291 + $dpinst = $$options_ref{'listener'};
  2292 + }
  2293 +
  2294 + return $dpinst;
  2295 +}
  2296 +
  2297 +sub dpctl_del_flows {
  2298 + my ($options_ref) = @_;
  2299 +
  2300 + my $dpinst = get_dpinst($options_ref);
  2301 + `$ENV{'OF_ROOT'}/utilities/dpctl del-flows $dpinst`;
  2302 +}
  2303 +
  2304 +sub dpctl_show_flows {
  2305 + my ($options_ref) = @_;
  2306 +
  2307 + my $dpinst = get_dpinst($options_ref);
  2308 + system("$ENV{'OF_ROOT'}/utilities/dpctl dump-flows $dpinst");
  2309 +}
  2310 +
  2311 +# Always end library in 1
  2312 +1;
... ...
regress/lib/Perl5/Test/Base.pm 0 → 100755
  1 +#############################################################
  2 +# $Id: Base.pm 3909 2008-06-06 03:31:57Z brandonh $
  3 +#
  4 +# Module provides basic functions for use by NF2 Perl scripts.
  5 +#
  6 +# Revisions:
  7 +#
  8 +##############################################################
  9 +
  10 +package Test::Base;
  11 +use Exporter;
  12 +@ISA = ('Exporter');
  13 +@EXPORT = qw( &check_NF2_vars_set
  14 + );
  15 +
  16 +##############################################################
  17 +#
  18 +# Define a my_die function if it doesn't already exist
  19 +#
  20 +##############################################################
  21 +
  22 +if (!defined(&my_die)) {
  23 + eval('
  24 + sub my_die {
  25 + my $mess = shift @_;
  26 + (my $cmd = $0) =~ s/.*\///;
  27 + print STDERR "\n$cmd: $mess\n";
  28 + exit 1;
  29 + }
  30 + ');
  31 +}
  32 +
  33 +# Always end library in 1
  34 +1;
... ...