Remove kernel datapath unit tests.
authorJustin Pettit <jpettit@nicira.com>
Fri, 26 Sep 2008 21:58:17 +0000 (14:58 -0700)
committerJustin Pettit <jpettit@nicira.com>
Fri, 26 Sep 2008 21:58:33 +0000 (14:58 -0700)
The tests haven't been seeing much love and are suffering from bit-rot at
this point.  We're removing them, since we have other ways to test at
this point.

15 files changed:
configure.ac
datapath/Makefile.am
datapath/Modules.mk
datapath/crc_t.c [deleted file]
datapath/forward_t.c [deleted file]
datapath/table_t.c [deleted file]
datapath/tests/.gitignore [deleted file]
datapath/tests/Makefile.am [deleted file]
datapath/tests/example.pcap [deleted file]
datapath/tests/gen_forward_t.pl [deleted file]
datapath/tests/ofp_pcap.c [deleted file]
datapath/tests/ofp_pcap.h [deleted file]
datapath/unit-exports.c [deleted file]
datapath/unit.c [deleted file]
datapath/unit.h [deleted file]

index 69e00470f75c3dd73186cb5833075a48d2654fdf..aa1ce99f4b1b6e03974743363176042083aeb341 100644 (file)
@@ -72,7 +72,6 @@ utilities/Makefile
 secchan/Makefile
 switch/Makefile
 tests/Makefile
-datapath/tests/Makefile
 third-party/Makefile
 debian/Makefile
 datapath/linux-2.6/Kbuild
index 978553787608d89849458326a1605b73b0682e9a..88e66c74546580f210d9322035dd4d6b2d66d298 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = tests
+SUBDIRS = 
 if L26_ENABLED
 SUBDIRS += linux-2.6
 endif
index f21af16b442b6dad39eb0f6e709ef8276f042556..516ebd9df09227a5164b3c2ba16d473760167853 100644 (file)
@@ -1,5 +1,5 @@
 all_modules = $(dist_modules)
-dist_modules = openflow unit
+dist_modules = openflow 
 
 openflow_sources = \
        chain.c \
@@ -10,8 +10,7 @@ openflow_sources = \
        flow.c \
        forward.c \
        table-hash.c \
-       table-linear.c \
-       unit-exports.c
+       table-linear.c 
 
 openflow_headers = \
        chain.h \
@@ -22,14 +21,7 @@ openflow_headers = \
        flow.h \
        forward.h \
        snap.h \
-       table.h \
-       unit.h
-
-unit_sources = \
-       crc_t.c \
-       forward_t.c \
-       table_t.c \
-       unit.c
+       table.h 
 
 dist_sources = $(foreach module,$(dist_modules),$($(module)_sources))
 dist_headers = $(foreach module,$(dist_modules),$($(module)_headers))
diff --git a/datapath/crc_t.c b/datapath/crc_t.c
deleted file mode 100644 (file)
index 1e8274a..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008 The Board of Trustees of The Leland 
- * Stanford Junior University
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include "crc32.h"
-#include "unit.h"
-
-
-static void
-print_error(unsigned int poly, char *data,
-                       unsigned int expected, unsigned int calculated)
-{
-       unit_fail("crc error: poly=%x data=%s expected=%x calculated=%x\n",
-                               poly, data, expected, calculated);
-}
-
-void
-run_crc_t(void)
-{
-       struct crc32 crc;
-       unsigned int val, i, j;
-
-       char *data[3] = { "h3rei$@neX@mp13da7@sTr117G0fCH@r$",
-                               "1324lkqasdf0-[LKJD0;asd,.cv;/asd0:\"'~`co29",
-                               "6" };
-
-       unsigned int polys[2] = { 0x04C11DB7,
-                               0x1EDC6F41 };
-
-       unsigned int crc_values[2][3] = { 
-                               { 0xDE1040C3, 0x65343A0B, 0xCEB42022 },
-                               { 0x6C149FAE, 0x470A6B73, 0x4D3AA134 } };
-       for (i = 0; i < 2; i++) {
-               crc32_init(&crc, polys[i]);
-               for (j = 0; j < 3; j++) {
-                       val = crc32_calculate(&crc, data[j], strlen(data[j]));
-                       if (val != crc_values[i][j]) {
-                               print_error(polys[i], data[j], crc_values[i][j], val);
-                       }
-               }
-       }
-}
diff --git a/datapath/forward_t.c b/datapath/forward_t.c
deleted file mode 100644 (file)
index da5de50..0000000
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008 The Board of Trustees of The Leland 
- * Stanford Junior University
- */
-
-#include <linux/skbuff.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/random.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-
-#include "forward.h"
-#include "tests/forward_t.h"
-#include "openflow.h"
-#include "unit.h"
-#include "flow.h"
-
-/*
- * Tests execute_settings() in forward.c to check that actions are
- * appropriately taken on packets, meaning:
- *
- * 1. Checksums are correct.
- * 2. Actions are only taken on compatible packets (IP action not taken on
- * non-IP packet)
- * 3. Other packet data remains untouched.
-
- * forward_t.h contains static packet definitions.  forward_t.h should be
- * generated using gen_forward_t.c.  This test is run on whatever packets are
- * defined in forward_t.h.
- *
- * NOTE:  Tests assume packets in forward_t.h are present in full and IP and
- * transport checksums are correct. (Can prevent offloading of checksum
- * computation using ethtool.
- */
-
-/*
- * Sets 'a->data'.  If 'key' != NULL, sets 'data' to equal 'key's value for type
- * specified by 'a->type'.  If 'key' == NULL, sets data to a random value.
- */
-
-static void
-set_action_data(struct sk_buff *skb, struct sw_flow_key *key, struct ofp_action *a)
-{
-       if (key != NULL) {
-               switch(ntohs(a->type)) {
-               case(OFPAT_SET_DL_SRC):
-                       memcpy(a->arg.dl_addr, key->dl_src, sizeof key->dl_src);
-                       break;
-               case(OFPAT_SET_DL_DST):
-                       memcpy(a->arg.dl_addr, key->dl_dst, sizeof key->dl_dst);
-                       break;
-               case(OFPAT_SET_NW_SRC):
-                       if (key->dl_type == htons(ETH_P_IP))
-                               a->arg.nw_addr = key->nw_src;
-                       else
-                               a->arg.nw_addr = random32();
-                       break;
-               case(OFPAT_SET_NW_DST):
-                       if (key->dl_type == htons(ETH_P_IP))
-                               a->arg.nw_addr = key->nw_dst;
-                       else
-                               a->arg.nw_addr = random32();
-                       break;
-               case(OFPAT_SET_TP_SRC):
-                       if (key->nw_proto == IPPROTO_TCP || key->nw_proto == IPPROTO_UDP)
-                               a->arg.tp = key->tp_src;
-                       else
-                               a->arg.tp = (uint16_t) random32();
-                       break;
-               case(OFPAT_SET_TP_DST):
-                       if (key->nw_proto == IPPROTO_TCP || key->nw_proto == IPPROTO_UDP)
-                               a->arg.tp = key->tp_dst;
-                       else
-                               a->arg.tp = (uint16_t) random32();
-                       break;
-               default:
-                       BUG();
-               }
-       } else {
-               ((uint32_t*)a->arg.dl_addr)[0] = random32();
-               ((uint16_t*)a->arg.dl_addr)[2] = random32();
-       }
-}
-
-
-/*
- * Checks the IP sum of an IP packet.  Returns 0 if correct, else -1.
- */
-
-static void
-check_IP_csum(struct iphdr *ih)
-{
-       uint16_t check, *data;
-       uint32_t n_bytes, sum;
-
-       check = ih->check;
-       ih->check = 0;
-       data = (uint16_t*) ih;
-       sum = 0;
-       n_bytes = ih->ihl * 4;
-
-       while (n_bytes > 1) {
-               sum += ntohs(*data);
-               sum = (sum >> 16) + (uint16_t)sum;
-               data++;
-               n_bytes -= 2;
-       }
-
-       if (n_bytes == 1) {
-               sum += *(uint8_t*)data;
-               sum = (sum >> 16) + (uint16_t)sum;
-       }
-
-       ih->check = htons((uint16_t)(~sum));
-       if (ih->check != check) {
-               unit_fail("IP checksum %hu does not match %hu",
-                         ntohs(ih->check), ntohs(check));
-       }
-}
-
-/*
- * Partially computes TCP checksum over 'n_bytes' pointed to by 'data'.  Can be
- * called multiple times if data csum is to be computed on is fragmented.  If
- * 'is_last' == 0, assumes will be called again on more data and returns the
- * value that should be passed in as 'incr_sum' on the next call.  Else if
- * 'is_last' == 1, returns the final checksum.  On the first call, 'incr_sum'
- * should equal 0.  If 'is_last' == 0, 'n_bytes' must be even.  i.e. Should
- * first be called on pseudo header fields that are multiples of two, and then
- * on the TCP packet.
- */
-static uint32_t
-compute_transport_checksum(uint16_t *data, uint32_t n_bytes,
-                       uint32_t incr_sum, uint8_t is_last)
-{
-       uint8_t arr[2];
-
-       if (n_bytes % 2 != 0 && is_last == 0)
-               BUG();
-
-       while (n_bytes > 1) {
-               incr_sum += ntohs(*data);
-               incr_sum = (incr_sum >> 16) + (uint16_t)incr_sum;
-               data++;
-               n_bytes -= 2;
-       }
-
-       if (is_last == 0)
-               return incr_sum;
-
-       if(n_bytes == 1) {
-               arr[0] = *(uint8_t*)data;
-               arr[1] = 0;
-               incr_sum += ntohs(*((uint16_t*)arr));
-               incr_sum = (incr_sum >> 16) + (uint16_t)incr_sum;
-       }
-
-       return ~incr_sum;
-}
-
-/*
- * Checks the transport layer's checksum of a packet.  Returns '0' if correct,
- * else '1'.  'ih' should point to the IP header of the packet, if TCP, 'th'
- * should point the TCP header, and if UDP, 'uh' should point to the UDP
- * header.
- */
-static int
-check_transport_csum(struct iphdr *ih, struct tcphdr *th,
-                        struct udphdr *uh)
-{
-       uint32_t tmp;
-       uint16_t len, check;
-       uint8_t arr[2];
-
-       tmp = compute_transport_checksum((uint16_t*)(&ih->saddr),
-                                        2 * sizeof ih->saddr, 0, 0);
-       arr[0] = 0;
-       arr[1] = ih->protocol;
-       tmp = compute_transport_checksum((uint16_t*)arr, 2, tmp, 0);
-       len = ntohs(ih->tot_len) - (ih->ihl * 4);
-       *((uint16_t*)arr) = htons(len);
-       tmp = compute_transport_checksum((uint16_t*)arr, 2, tmp, 0);
-
-       if (th != NULL) {
-               check = th->check;
-               th->check = 0;
-               th->check = htons((uint16_t)compute_transport_checksum((uint16_t*)th,
-                                                                       len, tmp, 1));
-               if (th->check != check) {
-                       unit_fail("TCP checksum %hu does not match %hu",
-                                 ntohs(th->check), ntohs(check));
-                       return -1;
-               }
-       } else if (uh != NULL) {
-               check = uh->check;
-               uh->check = 0;
-               uh->check = htons((uint16_t)compute_transport_checksum((uint16_t*)uh,
-                                                                       len, tmp, 1));
-               if (uh->check != check) {
-                       unit_fail("UDP checksum %hu does not match %hu",
-                                 ntohs(uh->check), ntohs(check));
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-
-/*
- * Compares 'pkt_len' bytes of 'data' to 'pkt'.  excl_start and excl_end point
- * together delineate areas of 'data' that are not supposed to match 'pkt'.
- * 'num_excl' specify how many such areas exist.  An 'excl_start' entry is
- * ignored if it equals NULL.  See 'check_packet()' for usage.
- */
-
-static void
-compare(uint8_t *data, uint8_t *pkt, uint32_t pkt_len,
-       uint8_t **excl_start, uint8_t **excl_end, uint32_t num_excl)
-{
-       uint32_t i;
-       uint8_t *d, *p, *end;
-       int ret;
-
-       end = data + pkt_len;
-       d = data;
-       p = pkt;
-       ret = 0;
-
-       for (i = 0; i < num_excl; i++) {
-               if(*excl_start != NULL) {
-                       if ((ret = memcmp(d, p, *excl_start - d)) != 0)
-                               break;
-                       p += (*excl_end - d);
-                       d = *excl_end;
-               }
-               excl_start++;
-               excl_end++;
-       }
-
-       if (ret == 0)
-               ret = memcmp(d, p, end - d);
-
-       if (ret != 0) {
-               unit_fail("skb and packet comparison failed:");
-               for (i = 0; i < pkt_len; i++) {
-                       if (data[i] != pkt[i]) {
-                               unit_fail("skb[%u] = 0x%x != 0x%x",
-                                         i, data[i], pkt[i]);
-                       }
-               }
-       }
-}
-
-
-/*
- * Checks that a packet's data has remained consistent after an action has been
- * applied.  'skb' is the modified packet, 'a' is the action that was taken on
- * the packet, 'p' is a copy of the packet's data before action 'a' was taken.
- * Checks that the action was in fact taken, that the checksums of the packet
- * are correct, and that no other data in the packet was altered.
- */
-
-static void
-check_packet(struct sk_buff *skb, struct ofp_action *a, struct pkt *p)
-{
-       struct ethhdr *eh;
-       struct iphdr *ih;
-       struct tcphdr *th;
-       struct udphdr *uh;
-       uint8_t *excl_start[5], *excl_end[5];
-
-       eh = eth_hdr(skb);
-       ih = NULL;
-       th = NULL;
-       uh = NULL;
-
-       memset(excl_start, 0, sizeof excl_start);
-       memset(excl_end, 0, sizeof excl_end);
-
-       if (eh->h_proto == htons(ETH_P_IP)) {
-               ih = ip_hdr(skb);
-               excl_start[1] = (uint8_t*)&ih->check;
-               excl_end[1] = (uint8_t*)(&ih->check + 1);
-               if (ih->protocol == IPPROTO_TCP) {
-                       th = tcp_hdr(skb);
-                       excl_start[4] = (uint8_t*)&th->check;
-                       excl_end[4] = (uint8_t*)(&th->check + 1);
-               } else if (ih->protocol == IPPROTO_UDP) {
-                       uh = udp_hdr(skb);
-                       excl_start[4] = (uint8_t*)&uh->check;
-                       excl_end[4] = (uint8_t*)(&uh->check + 1);
-               }
-       }
-
-       if (a != NULL) {
-               switch(ntohs(a->type)) {
-               case(OFPAT_SET_DL_SRC):
-                       if (memcmp(a->arg.dl_addr, eh->h_source, sizeof eh->h_source) != 0) {
-                               unit_fail("Source eth addr has not been set");
-                               return;
-                       }
-                       excl_start[0] = (uint8_t*)(&eh->h_source);
-                       excl_end[0] = (uint8_t*)(&eh->h_proto);
-                       break;
-               case(OFPAT_SET_DL_DST):
-                       if (memcmp(a->arg.dl_addr, eh->h_dest, sizeof eh->h_dest) != 0) {
-                               unit_fail("Dest eth addr has not been set");
-                               return;
-                       }
-                       excl_start[0] = (uint8_t*)(&eh->h_dest);
-                       excl_end[0] = (uint8_t*)(&eh->h_source);
-                       break;
-               case(OFPAT_SET_NW_SRC):
-                       if (ih != NULL) {
-                               if (a->arg.nw_addr != ih->saddr) {
-                                       unit_fail("Source IP addr has not been set");
-                                       return;
-                               }
-                               excl_start[2] = (uint8_t*)(&ih->saddr);
-                               excl_end[2] = (uint8_t*)(&ih->saddr + 1);
-                       }
-                       break;
-               case(OFPAT_SET_NW_DST):
-                       if (ih != NULL) {
-                               if (a->arg.nw_addr != ih->daddr) {
-                                       unit_fail("Dest IP addr has not been set");
-                                       return;
-                               }
-                               excl_start[2] = (uint8_t*)(&ih->daddr);
-                               excl_end[2] = (uint8_t*)(&ih->daddr + 1);
-                       }
-                       break;
-               case(OFPAT_SET_TP_SRC):
-                       if (th != NULL) {
-                               if (a->arg.tp != th->source) {
-                                       unit_fail("Source port has not been set");
-                                       return;
-                               }
-                               excl_start[3] = (uint8_t*)(&th->source);
-                               excl_end[3] = (uint8_t*)(&th->source + 1);
-                       } else if (uh != NULL) {
-                               if (a->arg.tp != uh->source) {
-                                       unit_fail("Source port has not been set");
-                                       return;
-                               }
-                               excl_start[3] = (uint8_t*)(&uh->source);
-                               excl_end[3] = (uint8_t*)(&uh->source + 1);
-                       }
-                       break;
-               case(OFPAT_SET_TP_DST):
-                       if (th != NULL) {
-                               if (a->arg.tp != th->dest) {
-                                       unit_fail("Dest port has not been set");
-                                       return;
-                               }
-                               excl_start[3] = (uint8_t*)(&th->dest);
-                               excl_end[3] = (uint8_t*)(&th->dest + 1);
-                       } else if (uh != NULL) {
-                               if (a->arg.tp != uh->dest) {
-                                       unit_fail("Dest port has not been set");
-                                       return;
-                               }
-                               excl_start[3] = (uint8_t*)(&uh->dest);
-                               excl_end[3] = (uint8_t*)(&uh->dest + 1);
-                       }
-                       break;
-               default:
-                       BUG();
-               }
-       }
-
-       compare(skb->data, p->data, p->len, excl_start, excl_end, 5);
-       if (unit_failed())
-               return;
-
-       if (ih == NULL)
-               return;
-
-       check_IP_csum(ih);
-       if (unit_failed())
-               return;
-
-       if (th == NULL && uh == NULL)
-               return;
-
-       check_transport_csum(ih, th, uh);
-}
-
-/*
- * Layers 3 & 4 Tests:  Given packets in forward_t.h, executes all actions 
- * with random data, checking for consistency described in check_packet().
- */
-
-void
-test_l3_l4(void)
-{
-       struct ofp_action action;
-       uint16_t a_type;
-       struct sk_buff *skb;
-       struct sw_flow_key key;
-       unsigned int i, j;
-       uint16_t eth_proto;
-       int ret = 0;
-
-       for (i = 0; i < num_packets; i++) {
-               skb = alloc_skb(packets[i].len, GFP_KERNEL);
-               if (!skb) {
-                       unit_fail("Couldn't allocate %uth skb", i);
-                       return;
-               }
-
-               memcpy(skb_put(skb, packets[i].len), packets[i].data,
-                                       packets[i].len);
-
-               skb_set_mac_header(skb, 0);
-               flow_extract(skb, 0, &key);
-               eth_proto = ntohs(key.dl_type);
-
-               check_packet(skb, NULL, packets+i);
-               if (unit_failed())
-                       return;
-
-               for (a_type = OFPAT_SET_DL_SRC;
-                        a_type <= OFPAT_SET_TP_DST;
-                        a_type++)
-               {
-                       action.type = htons(a_type);
-                       set_action_data(skb, NULL, &action);
-                       for(j = 0; j < 2; j++) {
-                               skb = execute_setter(skb, eth_proto, &key, &action);
-                               check_packet(skb, &action, packets+i);
-                               if (unit_failed()) {
-                                       unit_fail("Packet %u inconsistent "
-                                                 "after setter on action "
-                                                 "type %d, iteration %u",
-                                                 i, action.type, j);
-                                       return;
-                               }
-                               set_action_data(skb, &key, &action);
-                       }
-               }
-
-               kfree_skb(skb);
-
-               if (ret != 0)
-                       break;
-       }
-
-       if (ret == 0)
-               printk("\nL3/L4 actions test passed.\n");
-}
-
-int
-test_vlan(void)
-{
-       struct ofp_action action;
-       struct sk_buff *skb;
-       struct sw_flow_key key;
-       unsigned int i;
-       uint16_t eth_proto;
-       int ret = 0;
-       struct vlan_ethhdr *vh;
-       struct ethhdr *eh;
-       struct net_device dev;
-       uint16_t new_id, orig_id;
-
-
-       memset((char *)&dev, '\0', sizeof(dev));
-
-       printk("Testing vlan\n");
-       for (i = 0; i < num_packets; i++) {
-               skb = alloc_skb(packets[i].len, GFP_KERNEL);
-               if (!skb) {
-                       unit_fail("Couldn't allocate %uth skb", i);
-                       return -ENOMEM;
-               }
-
-               memcpy(skb_put(skb, packets[i].len), packets[i].data,
-                                       packets[i].len);
-               skb->dev = &dev;
-
-               skb_set_mac_header(skb, 0);
-               flow_extract(skb, 0, &key);
-               eth_proto = ntohs(key.dl_type);
-
-#if 0
-               if ((ret = check_packet(skb, NULL, packets+i)) < 0) {
-                       unit_fail("Packet %u has incorrect checksum unmodified",
-                                       i);
-                       goto free_skb;
-               }
-#endif
-
-               eh = eth_hdr(skb);
-               orig_id = eh->h_proto;
-
-               action.type = htons(OFPAT_SET_VLAN_VID);
-
-               // Add a random vlan tag
-               new_id = (uint16_t) random32() & VLAN_VID_MASK;
-               action.arg.vlan_vid = new_id;
-               skb = execute_setter(skb, eth_proto, &key, &action);
-               vh = vlan_eth_hdr(skb);
-               if (ntohs(vh->h_vlan_TCI) != new_id) {
-                       unit_fail("add: vlan id doesn't match: %#x != %#x", 
-                                       ntohs(vh->h_vlan_TCI), new_id);
-                       return -1;
-               }
-               flow_extract(skb, 0, &key);
-#if 0
-               if ((ret = check_packet(skb, NULL, packets+i)) < 0) {
-                       unit_fail("Packet %u has incorrect checksum after adding vlan",
-                                 i);
-                       goto free_skb;
-               }
-#endif
-
-               // Modify the tag
-               new_id = (uint16_t) random32() & VLAN_VID_MASK;
-               action.arg.vlan_vid = new_id;
-               skb = execute_setter(skb, eth_proto, &key, &action);
-               vh = vlan_eth_hdr(skb);
-               if (ntohs(vh->h_vlan_TCI) != new_id) {
-                       unit_fail("mod: vlan id doesn't match: %#x != %#x", 
-                                       ntohs(vh->h_vlan_TCI), new_id);
-                       return -1;
-               }
-               flow_extract(skb, 0, &key);
-#if 0
-               if ((ret = check_packet(skb, NULL, packets+i)) < 0) {
-                       unit_fail("Packet %u has incorrect checksum after modifying vlan",
-                                 i);
-                       goto free_skb;
-               }
-#endif
-
-               // Remove the tag
-               action.type = htons(OFPAT_STRIP_VLAN);
-               skb = execute_setter(skb, eth_proto, &key, &action);
-
-               eh = eth_hdr(skb);
-
-               if (eh->h_proto != orig_id) {
-                       unit_fail("del: vlan id doesn't match: %#x != %#x", 
-                         ntohs(eh->h_proto), ntohs(orig_id));
-                       return -1;
-               }
-#if 0
-               if ((ret = check_packet(skb, NULL, packets+i)) < 0) {
-                       unit_fail("Packet %u has incorrect checksum after removing vlan",
-                                 i);
-                       goto free_skb;
-               }
-
-       free_skb:
-#endif
-
-               kfree_skb(skb);
-
-               if (ret != 0)
-                       break;
-       }
-
-       if (ret == 0)
-               printk("\nVLAN actions test passed.\n");
-
-       return ret;
-}
-
-/*
- * Actual test:  Given packets in forward_t.h, executes all actions with random
- * data, checking for consistency described in check_packet().
- */
-
-void
-run_forward_t(void)
-{
-       test_vlan();
-       test_l3_l4();
-}
diff --git a/datapath/table_t.c b/datapath/table_t.c
deleted file mode 100644 (file)
index a824804..0000000
+++ /dev/null
@@ -1,874 +0,0 @@
-/*
- * Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008 The Board of Trustees of The Leland 
- * Stanford Junior University
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/random.h>
-#include <linux/rcupdate.h>
-
-#include "flow.h"
-#include "table.h"
-#include "openflow.h"
-#include "unit.h"
-
-static const char *
-table_name(struct sw_table *table)
-{
-       struct sw_table_stats stats;
-       table->stats(table, &stats);
-       return stats.name;
-}
-
-static unsigned long int
-table_max_flows(struct sw_table *table)
-{
-       struct sw_table_stats stats;
-       table->stats(table, &stats);
-       return stats.max_flows;
-}
-
-static struct sw_flow *flow_zalloc(int n_actions, gfp_t flags) 
-{
-       struct sw_flow *flow = flow_alloc(n_actions, flags);
-       if (flow) {
-               struct sw_flow_actions *sfa = flow->sf_acts;
-               memset(flow, 0, sizeof *flow);
-               flow->sf_acts = sfa;
-       }
-       return flow;
-}
-
-static void
-simple_insert_delete(struct sw_table *swt, uint32_t wildcards)
-{
-       struct sw_flow *a_flow = flow_zalloc(0, GFP_KERNEL);
-       struct sw_flow *b_flow = flow_zalloc(0, GFP_KERNEL);
-       struct sw_flow *found;
-
-       if (!swt) {
-               unit_fail("table creation failed");
-               return;
-       }
-
-       printk("simple_insert_delete: testing %s table\n", table_name(swt));
-       *((uint32_t*)a_flow->key.dl_src) = 0x12345678;
-       *((uint32_t*)b_flow->key.dl_src) = 0x87654321;
-
-       a_flow->key.nw_src      = 0xdeadbeef;
-       b_flow->key.nw_src      = 0x001dd0d0;
-
-       a_flow->key.wildcards = wildcards;
-       b_flow->key.wildcards = wildcards;
-
-       if (!(swt->insert(swt, a_flow)))
-               unit_fail("insert failed");
-       found = swt->lookup(swt, &a_flow->key);
-       if(found != a_flow)
-               unit_fail("%p != %p", found, a_flow);
-       if (swt->lookup(swt, &b_flow->key))
-               unit_fail("lookup should not succeed (1)");
-
-       swt->delete(swt, &a_flow->key, 0, 0);
-       if (swt->lookup(swt, &a_flow->key))
-               unit_fail("lookup should not succeed (3)");
-
-       flow_free(b_flow);
-       swt->destroy(swt);
-}
-
-static void
-multiple_insert_destroy(struct sw_table *swt, int inserts, uint32_t wildcards,
-                       int min_collisions, int max_collisions)
-{
-       int i;
-       int col = 0;
-
-       if (!swt) {
-               unit_fail("table creation failed");
-               return;
-       }
-
-       printk("inserting %d flows into %s table with max %lu flows: ",
-                               inserts, table_name(swt), table_max_flows(swt));
-       for(i = 0; i < inserts; ++i){
-               struct sw_flow *a_flow = flow_zalloc(0, GFP_KERNEL);
-               *((uint32_t*)&(a_flow->key.dl_src[0])) = random32();
-               a_flow->key.nw_src    = random32();
-               a_flow->key.wildcards = wildcards;
-
-               if(!swt->insert(swt, a_flow)) {
-                       col++;
-                       flow_free(a_flow);
-               }
-       }
-       printk("%d failures\n", col);
-       if (min_collisions <= col && col <= max_collisions)
-               printk("\tmin = %d <= %d <= %d = max, OK.\n",
-                                       min_collisions, col, max_collisions);
-       else {
-               if (col < min_collisions)
-                       unit_fail("too few collisions (%d < %d)",
-                                 col, min_collisions);
-               else if (col > max_collisions)
-                       unit_fail("too many collisions (%d > %d)",
-                                 col, max_collisions);
-               printk("(This is statistically possible "
-                                       "but should not occur often.)\n");
-       }
-       
-       swt->destroy(swt);
-}
-
-static void
-set_random_key(struct sw_flow_key *key, uint32_t wildcards)
-{
-       key->nw_src = random32();
-       key->nw_dst = random32();
-       key->in_port = (uint16_t) random32();
-       key->dl_vlan = (uint16_t) random32();
-       key->dl_type = (uint16_t) random32();
-       key->tp_src = (uint16_t) random32();
-       key->tp_dst = (uint16_t) random32();
-       key->wildcards = wildcards;
-       *((uint32_t*)key->dl_src) = random32();
-       *(((uint32_t*)key->dl_src) + 1) = random32();
-       *((uint32_t*)key->dl_dst) = random32();
-       *(((uint32_t*)key->dl_dst) + 1) = random32();
-       key->nw_proto = (uint8_t) random32();
-}
-
-struct flow_key_entry {
-       struct sw_flow_key key;
-       struct list_head node;
-};
-
-/*
- * Allocates memory for 'n_keys' flow_key_entrys.  Initializes the allocated
- * keys with random values, setting their wildcard values to 'wildcards', and
- * places them all in a list.  Returns a pointer to a flow_key_entry that
- * serves solely as the list's head (its key has not been set).  If allocation
- * fails, returns NULL.  Returned pointer should be freed with vfree (which
- * frees the memory associated with the keys as well.)
- */
-
-static struct flow_key_entry *
-allocate_random_keys(int n_keys, uint32_t wildcards)
-{
-       struct flow_key_entry *entries, *pos;
-       struct list_head *keys;
-
-       if (n_keys < 0)
-               return NULL;
-
-       entries = vmalloc((n_keys+1) * sizeof *entries);
-       if (entries == NULL) {
-               unit_fail("cannot allocate memory for %u keys",
-                                       n_keys);
-               return NULL;
-       }
-
-       keys = &entries->node;
-       INIT_LIST_HEAD(keys);
-
-       for(pos = entries+1; pos < (entries + n_keys + 1); pos++) {
-               set_random_key(&pos->key, wildcards);
-               list_add(&pos->node, keys);
-       }
-
-       return entries;
-}
-
-/*
- * Attempts to insert the first 'n_flows' flow keys in list 'keys' into table
- * 'swt', where 'keys' is a list of flow_key_entrys.  key_entrys that are
- * inserted into the table are removed from the 'keys' list and placed in
- * 'added' list.  Returns -1 if flow memory allocation fails, else returns the
- * number of flows that were actually inserted (some attempts might fail due to
- * collisions).
- */
-
-static int
-insert_flows(struct sw_table *swt, struct list_head *keys, struct list_head *added, int n_flows)
-{
-       struct flow_key_entry *pos, *next;
-       int cnt;
-
-       cnt = 0;
-
-
-       list_for_each_entry_safe (pos, next, keys, node) {
-               struct sw_flow *flow = flow_zalloc(0, GFP_KERNEL);
-               if (flow == NULL) {
-                       unit_fail("Could only allocate %u flows", cnt);
-                       return -1;
-               }
-
-               flow->key = pos->key;
-
-               if (!swt->insert(swt, flow)) {
-                       flow_free(flow);
-                       list_del(&pos->node);
-               } else {
-                       list_del(&pos->node);
-                       list_add(&pos->node, added);
-                       cnt++;
-                       if (n_flows != -1 && cnt == n_flows)
-                               break;
-               }
-       }
-
-       return cnt;
-}
-
-/*
- * Finds and returns the flow_key_entry in list 'keys' matching the passed in
- * flow's key.  If not found, returns NULL.
- */
-
-static struct flow_key_entry *
-find_flow(struct list_head *keys, struct sw_flow *flow)
-{
-       struct flow_key_entry *pos;
-
-       list_for_each_entry(pos, keys, node) {
-               if(!memcmp(&pos->key, &flow->key, sizeof(struct sw_flow_key)))
-                       return pos;
-       }
-
-       return NULL;
-}
-
-/*
- * Checks that all flow_key_entrys in list 'keys' return successful lookups on
- * the table 'swt'.
- */
-
-static int
-check_lookup(struct sw_table *swt, struct list_head *keys)
-{
-       struct flow_key_entry *pos;
-
-       list_for_each_entry(pos, keys, node) {
-               if(swt->lookup(swt, &pos->key) == NULL)
-                       return -1;
-       }
-
-       return 0;
-}
-
-/*
- * Checks that all flow_key_entrys in list 'keys' DO NOT return successful
- * lookups in the 'swt' table.
- */
-
-static int
-check_no_lookup(struct sw_table *swt, struct list_head *keys)
-{
-       struct flow_key_entry *pos;
-
-       list_for_each_entry(pos, keys, node) {
-               if(swt->lookup(swt, &pos->key) != NULL)
-                       return -1;
-       }
-
-       return 0;
-}
-
-
-struct check_iteration_state
-{
-       int n_found;
-       struct list_head *to_find;
-       struct list_head *found;
-};
-
-static int
-check_iteration_callback(struct sw_flow *flow, void *private) 
-{
-       struct check_iteration_state *s = private;
-       struct flow_key_entry *entry;
-
-       entry = find_flow(s->to_find, flow);
-       if (entry == NULL) {
-               unit_fail("UNKNOWN ITERATOR FLOW %p", flow);
-               rcu_read_unlock();
-               return 1;
-       }
-       s->n_found++;
-       list_del(&entry->node);
-       list_add(&entry->node, s->found);
-       return 0;
-}
-
-/*
- * Compares an iterator's view of the 'swt' table to the list of
- * flow_key_entrys in 'to_find'.  flow_key_entrys that are matched are removed
- * from the 'to_find' list and placed in the 'found' list.  Returns -1 if the
- * iterator cannot be initialized or it encounters a flow with a key not in
- * 'to_find'.  Else returns the number of flows found by the iterator
- * (i.e. there might still be flow keys in the 'to_find' list that were not
- * encountered by the iterator.  it is up to the caller to determine if that is
- * acceptable behavior)
- */
-
-static int
-check_iteration(struct sw_table *swt, struct list_head *to_find, struct list_head *found)
-{
-       struct sw_flow_key key;
-       struct sw_table_position position;
-       struct check_iteration_state state;
-
-       memset(&key, 0, sizeof key);
-       key.wildcards = -1;
-
-       memset(&position, 0, sizeof position);
-
-       state.n_found = 0;
-       state.to_find = to_find;
-       state.found = found;
-
-       rcu_read_lock();
-       swt->iterate(swt, &key, &position, check_iteration_callback, &state);
-       rcu_read_unlock();
-
-       return state.n_found;
-}
-
-/*
- * Deletes from table 'swt' keys from the list of flow_key_entrys 'keys'.
- * Removes flow_key_entrys of deleted flows from 'keys' and places them in the
- * 'deleted' list.  If 'del_all' == 1, all flows in 'keys' will be deleted,
- * else only every third key will be deleted.  Returns the number flows deleted
- * from the table.
- */
-
-static int
-delete_flows(struct sw_table *swt, struct list_head *keys,
-                struct list_head *deleted, uint8_t del_all)
-{
-       struct flow_key_entry *pos, *next;
-       int i, n_del, total_del;
-
-       total_del = 0;
-       i = 0;
-
-       list_for_each_entry_safe (pos, next, keys, node) {
-               if (del_all == 1 || i % 3 == 0) {
-                       n_del = swt->delete(swt, &pos->key, 0, 0);
-                       if (n_del > 1) {
-                               unit_fail("%d flows deleted for one entry", n_del);
-                               unit_fail("\tfuture 'errors' could just be product duplicate flow_key_entries");
-                               unit_fail("THIS IS VERY UNLIKELY...SHOULDN'T HAPPEN OFTEN");
-                       }
-                       total_del += n_del;
-                       list_del(&pos->node);
-                       list_add(&pos->node, deleted);
-               }
-               i++;
-       }
-
-       return total_del;
-}
-
-/*
- * Checks that both iteration and lookups are consistent with the caller's view
- * of the table.  In particular, checks that all keys in flow_key_entry list
- * 'deleted' do not show up in lookup or iteration, and keys in flow_key_entry
- * list 'added' do show up.  'tmp' should be an empty list that can be used for
- * iteration.  References to list_head pointers are needed for 'added' and 'tmp'
- * because iteration will cause the list_heads to change.  Function thus
- * switches 'added' to point to the list of added keys after the iteration.
- */
-
-static int
-check_lookup_and_iter(struct sw_table *swt, struct list_head *deleted,
-                         struct list_head **added, struct list_head **tmp)
-{
-       struct list_head *tmp2;
-       int ret;
-
-       if (check_no_lookup(swt, deleted) < 0) {
-               unit_fail("Uninserted flows returning lookup");
-               return -1;
-       }
-
-       if (check_lookup(swt, *added) < 0) {
-               unit_fail("Inserted flows not returning lookup");
-               return -1;
-       }
-
-       ret = check_iteration(swt, *added, *tmp);
-
-       tmp2 = *added;
-       *added = *tmp;
-       *tmp = tmp2;
-
-       if ((*tmp)->next != *tmp) {
-               unit_fail("WARNING: not all flows in 'added' found by iterator");
-               unit_fail("\tcould be a product of duplicate flow_key_entrys, though should be VERY rare.");
-               /* To avoid reoccurence */
-               (*tmp)->next = (*tmp)->prev = *tmp;
-       }
-
-       return ret;
-}
-
-/*
- * Verifies iteration and lookup after inserting 'n_flows', then after deleting
- * some flows, and once again after deleting all flows in table 'swt'.
- */
-
-static int
-iterator_test(struct sw_table *swt, int n_flows, uint32_t wildcards)
-{
-       struct flow_key_entry *allocated, h1, h2;
-       struct list_head *added, *deleted, *tmp;
-       int ret, n_del, success;
-
-       INIT_LIST_HEAD(&h1.node);
-       INIT_LIST_HEAD(&h2.node);
-
-       success = -1;
-
-       allocated = allocate_random_keys(n_flows, wildcards);
-       if(allocated == NULL)
-               return success;
-
-       deleted = &allocated->node;
-       added = &h1.node;
-       tmp = &h2.node;
-
-       ret = insert_flows(swt, deleted, added, -1);
-       if (ret < 0)
-               goto iterator_test_destr;
-
-       n_flows = ret;
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup after insertion");
-               goto iterator_test_destr;
-       } else if (ret != n_flows) {
-               unit_fail("Iterator only found %d of %d flows",
-                         ret, n_flows);
-               goto iterator_test_destr;
-       }
-
-       n_del = delete_flows(swt, added, deleted, 0);
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup after some deletion");
-               goto iterator_test_destr;
-       } else if (ret + n_del != n_flows) {
-               unit_fail("iterator after deletion inconsistent");
-               unit_fail("\tn_del = %d, n_found = %d, n_flows = %d",
-                         n_del, ret, n_flows);
-               goto iterator_test_destr;
-       }
-
-       n_flows -= n_del;
-
-       n_del = delete_flows(swt, added, deleted, 1);
-       if (n_del != n_flows) {
-               unit_fail("Not all flows deleted - only %d of %d",
-                         n_del, n_flows);
-               goto iterator_test_destr;
-       }
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup after all deletion");
-               goto iterator_test_destr;
-       } else if (ret != 0) {
-               unit_fail("Empty table iterator failed.  %d flows found",
-                         ret);
-               goto iterator_test_destr;
-       }
-
-       success = 0;
-
-iterator_test_destr:
-       allocated->key.wildcards = OFPFW_ALL;
-       swt->delete(swt, &allocated->key, 0, 0);
-       vfree(allocated);
-       return success;
-}
-
-
-/*
- * Checks lookup and iteration consistency after adding one flow, adding the
- * flow again, and then deleting the flow from table 'swt'.
- */
-
-static int
-add_test(struct sw_table *swt, uint32_t wildcards)
-{
-       struct flow_key_entry *allocated, h1, h2;
-       struct list_head *added, *deleted, *tmp, *tmp2;
-       int ret, success = -1;
-
-       INIT_LIST_HEAD(&h1.node);
-       INIT_LIST_HEAD(&h2.node);
-
-       allocated = allocate_random_keys(2, wildcards);
-       if (allocated == NULL)
-               return success;
-
-       deleted = &allocated->node;
-       added = &h1.node;
-       tmp = &h2.node;
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup before table modification");
-               goto add_test_destr;
-       } else if (ret != 0) {
-               unit_fail("Iterator on empty table found %d flows",
-                         ret);
-               goto add_test_destr;
-       }
-
-       if (insert_flows(swt, deleted, added, 1) != 1) {
-               unit_fail("Cannot add one flow to table");
-               goto add_test_destr;
-       }
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup after single add");
-               goto add_test_destr;
-       } else if (ret != 1) {
-               unit_fail("Iterator on single add found %d flows",
-                         ret);
-               goto add_test_destr;
-       }
-
-       /* Re-adding flow */
-       if (insert_flows(swt, added, tmp, 1) != 1) {
-               unit_fail("Cannot insert same flow twice");
-               goto add_test_destr;
-       }
-
-       tmp2 = added;
-       added = tmp;
-       tmp = tmp2;
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup after double add");
-               goto add_test_destr;
-       } else if (ret != 1) {
-               unit_fail("Iterator on double add found %d flows",
-                         ret);
-               goto add_test_destr;
-       }
-
-       ret = delete_flows(swt, added, deleted, 1);
-       if (ret != 1) {
-               unit_fail("Unexpected %d flows deleted", ret);
-               goto add_test_destr;
-       }
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup after delete.");
-               goto add_test_destr;
-       } else if (ret != 0) {
-               unit_fail("unexpected %d flows found delete", ret);
-               goto add_test_destr;
-       }
-
-       success = 0;
-
-add_test_destr:
-       allocated->key.wildcards = OFPFW_ALL;
-       swt->delete(swt, &allocated->key, 0, 0);
-       vfree(allocated);
-       return success;
-}
-
-/*
- * Checks lookup and iteration consistency after each deleting a non-existent
- * flow, adding and then deleting a flow, adding the flow again, and then
- * deleting the flow twice in table 'swt'.
- */
-
-static int
-delete_test(struct sw_table *swt, uint32_t wildcards)
-{
-       struct flow_key_entry *allocated, h1, h2;
-       struct list_head *added, *deleted, *tmp, *tmp2;
-       int i, ret, success = -1;
-
-       INIT_LIST_HEAD(&h1.node);
-       INIT_LIST_HEAD(&h2.node);
-
-       allocated = allocate_random_keys(2, wildcards);
-       if (allocated == NULL)
-               return success;
-
-       /* Not really added...*/
-
-       added = &allocated->node;
-       deleted = &h1.node;
-       tmp = &h2.node;
-
-       ret = delete_flows(swt, added, deleted, 1);
-       if (ret != 0) {
-               unit_fail("Deleting non-existent keys from table returned unexpected value %d",
-                         ret);
-                       goto delete_test_destr;
-       }
-
-       for (i = 0; i < 3; i++) {
-               ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-               if (ret < 0) {
-                       if (i == 0)
-                               unit_fail("Loop %d. Bad lookup before modification.", i);
-                       else
-                               unit_fail("Loop %d. Bad lookup after delete.", i);
-                       goto delete_test_destr;
-               } else if (ret != 0) {
-                       if(i == 0)
-                               unit_fail("Loop %d. Unexpected %d flows found before modification",
-                                         i, ret);
-                       else
-                               unit_fail("Loop %d. Unexpected %d flows found after delete",
-                                         i, ret);
-                       goto delete_test_destr;
-               }
-
-               if(i == 2)
-                       break;
-
-               if (insert_flows(swt, deleted, added, 1) != 1) {
-                       unit_fail("loop %d: cannot add flow to table", i);
-                       goto delete_test_destr;
-               }
-
-               ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-               if (ret < 0) {
-                       unit_fail("loop %d: bad lookup after single add.", i);
-                       goto delete_test_destr;
-               } else if (ret != 1) {
-                       unit_fail("loop %d: unexpected %d flows found after single add",
-                                 i, ret);
-                       goto delete_test_destr;
-               }
-
-               ret = delete_flows(swt, added, deleted, 1);
-               if (ret != 1) {
-                       unit_fail("loop %d: deleting inserted key from table returned unexpected value %d",
-                                               i, ret);
-                       goto delete_test_destr;
-               }
-       }
-
-
-       ret = delete_flows(swt, deleted, tmp, 1);
-
-       tmp2 = deleted;
-       deleted = tmp2;
-       tmp = tmp2;
-
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup after double delete.");
-               goto delete_test_destr;
-       } else if (ret != 0) {
-               unit_fail("Unexpected %d flows found after double delete", ret);
-               goto delete_test_destr;
-       }
-
-       success = 0;
-
-delete_test_destr:
-       allocated->key.wildcards = OFPFW_ALL;
-       swt->delete(swt, &allocated->key, 0, 0);
-       vfree(allocated);
-       return success;
-}
-
-/*
- * Randomly adds and deletes from a set of size 'n_flows', looping for 'i'
- * iterations.
- */
-
-static int
-complex_add_delete_test(struct sw_table *swt, int n_flows, int i, uint32_t wildcards)
-{
-       struct flow_key_entry *allocated, h1, h2;
-       struct list_head *added, *deleted, *tmp;
-       int cnt, ret, n_added, n_deleted, success = -1;
-       uint8_t del_all;
-
-       INIT_LIST_HEAD(&h1.node);
-       INIT_LIST_HEAD(&h2.node);
-
-       allocated = allocate_random_keys(n_flows, wildcards);
-       if (allocated == NULL)
-               return success;
-
-       deleted = &allocated->node;
-       added = &h1.node;
-       tmp = &h2.node;
-
-       n_deleted = n_flows;
-       n_added = 0;
-
-       for (;i > 0; i--) {
-               if (n_deleted != 0 && random32() % 2 == 0) {
-                       cnt = random32() % n_deleted;
-                       cnt = insert_flows(swt, deleted, added, cnt);
-                       if (cnt < 0)
-                               goto complex_test_destr;
-                       n_deleted -= cnt;
-                       n_added += cnt;
-               } else {
-                       if (random32() % 7 == 0)
-                               del_all = 1;
-                       else
-                               del_all = 0;
-                       cnt = delete_flows(swt, added, deleted, del_all);
-                       n_deleted += cnt;
-                       n_added -= cnt;
-               }
-
-               ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-               if (ret < 0) {
-                       unit_fail("Bad lookup on iteration %d.", i);
-                       goto complex_test_destr;
-               }
-       }
-
-       delete_flows(swt, added, deleted, 1);
-       ret = check_lookup_and_iter(swt, deleted, &added, &tmp);
-       if (ret < 0) {
-               unit_fail("Bad lookup on end deletion.");
-               goto complex_test_destr;
-       } else if (ret != 0) {
-               unit_fail("Unexpected %d flows found on end deletion", ret);
-               goto complex_test_destr;
-       }
-
-       success = 0;
-
-complex_test_destr:
-       allocated->key.wildcards = OFPFW_ALL;
-       swt->delete(swt, &allocated->key, 0, 0);
-       vfree(allocated);
-       return success;
-
-}
-
-void run_table_t(void)
-{
-       int linear_max, hash_buckets, hash2_buckets1;
-       int hash2_buckets2, num_flows, num_iterations;
-       int i;
-
-       struct sw_table *swt;
-
-       /* Most basic operations. */
-       simple_insert_delete(table_linear_create(2048), 0);
-       simple_insert_delete(table_hash_create(0x04C11DB7, 2048), 0);
-       simple_insert_delete(table_hash2_create(0x04C11DB7, 2048,
-                                               0x1EDC6F41, 2048), 0);
-
-       /* Linear table operations. */
-       multiple_insert_destroy(table_linear_create(2048), 1024, 0, 0, 0);
-       multiple_insert_destroy(table_linear_create(2048), 2048, 0, 0, 0);
-       multiple_insert_destroy(table_linear_create(2048), 8192, 0,
-                               8192 - 2048, 8192 - 2048);
-
-       /* Hash table operations. */
-       multiple_insert_destroy(table_hash_create(0x04C11DB7, 2048), 1024, 0,
-                               100, 300);
-       multiple_insert_destroy(table_hash_create(0x04C11DB7, 2048), 2048, 0,
-                               500, 1000);
-       multiple_insert_destroy(table_hash_create(0x04C11DB7, 1 << 20), 8192, 0,
-                               0, 50);
-       multiple_insert_destroy(table_hash_create(0x04C11DB7, 1 << 20), 65536, 0,
-                               1500, 3000);
-
-       /* Hash table 2, two hash functions. */
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 2048,
-                                               0x1EDC6F41, 2048), 1024, 0, 0, 20);
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 2048,
-                                               0x1EDC6F41, 2048), 2048, 0, 50, 200);
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 1<<20,
-                                               0x1EDC6F41, 1<<20), 8192, 0, 0, 20);
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 1<<20,
-                                               0x1EDC6F41, 1<<20), 65536, 0, 0, 20);
-
-       /* Hash table 2, one hash function. */
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 2048,
-                                               0x04C11DB7, 2048), 1024, 0, 0, 50);
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 2048,
-                                               0x04C11DB7, 2048), 2048, 0, 100, 300);
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 1<<20,
-                                               0x04C11DB7, 1<<20), 8192, 0, 0, 20);
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 1<<20,
-                                               0x04C11DB7, 1<<20), 65536, 0, 0, 100);
-       multiple_insert_destroy(table_hash2_create(0x04C11DB7, 1<<20,
-                                               0x04C11DB7, 1<<20), 1<<16, 0, 0, 100);
-
-       linear_max = 2048;
-       hash_buckets = 2048;
-       hash2_buckets1 = 1024;
-       hash2_buckets2 = 1024;
-
-       num_flows = 2300;
-       num_iterations = 100;
-
-       printk("\nTesting on each table type:\n");
-       printk("  iteration_test on 0 flows\n");
-       printk("  iteration_test on %d flows\n", num_flows);
-       printk("  add_test\n");
-       printk("  delete_test\n");
-       printk("  complex_add_delete_test with %d flows and %d iterations\n\n",
-                               num_flows, num_iterations);
-
-       for (i = 0; i < 3; i++) {
-               unsigned int mask = i == 0 ?  : 0;
-
-               if (unit_failed())
-                       return;
-
-               mask = 0;
-               switch (i) {
-               case 0:
-                       swt = table_linear_create(linear_max);
-                       break;
-               case 1:
-                       swt = table_hash_create (0x04C11DB7, hash_buckets);
-                       break;
-               case 2:
-                       swt = table_hash2_create(0x04C11DB7, hash2_buckets1,
-                                                0x1EDC6F41, hash2_buckets2);
-                       break;
-               default:
-                       BUG();
-                       return;
-               }
-
-               if (swt == NULL) {
-                       unit_fail("failed to allocate table %d", i);
-                       return;
-               }
-               printk("Testing %s table with %d buckets and %d max flows...\n",
-                                       table_name(swt), hash_buckets, num_flows);
-               iterator_test(swt, 0, mask);
-               iterator_test(swt, num_flows, mask);
-               add_test(swt, mask);
-               delete_test(swt, mask);
-               complex_add_delete_test(swt, num_flows, num_iterations, mask);
-               swt->destroy(swt);
-       }
-}
-
diff --git a/datapath/tests/.gitignore b/datapath/tests/.gitignore
deleted file mode 100644 (file)
index 35e75b7..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/Makefile
-/Makefile.in
-/forward_t.h
-/fwdhgen
diff --git a/datapath/tests/Makefile.am b/datapath/tests/Makefile.am
deleted file mode 100644 (file)
index fc5fd8f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-noinst_HEADERS = forward_t.h
-
-forward_t.h: gen_forward_t.pl example.pcap
-       perl $(srcdir)/gen_forward_t.pl $(srcdir)/example.pcap > forward_t.h.tmp
-       mv forward_t.h.tmp forward_t.h
-
-EXTRA_DIST = gen_forward_t.pl example.pcap
diff --git a/datapath/tests/example.pcap b/datapath/tests/example.pcap
deleted file mode 100644 (file)
index 7bda458..0000000
Binary files a/datapath/tests/example.pcap and /dev/null differ
diff --git a/datapath/tests/gen_forward_t.pl b/datapath/tests/gen_forward_t.pl
deleted file mode 100755 (executable)
index 6e12e2c..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#! /usr/bin/perl
-
-use warnings;
-use strict;
-
-if (@ARGV != 1) {
-    print "usage: $0 input.pcap > output.h\n";
-    print "where input.pcap is a packet capture in pcap format\n";
-    print "and output.c is a C header file containing the packets\n";
-    exit(1);
-}
-my ($in_file_name) = $ARGV[0];
-open(INPUT, '<', $in_file_name) or die "$in_file_name: open: $!\n";
-
-my ($file_header);
-if (read(INPUT, $file_header, 24) != 24) {
-    die "$in_file_name: could not read pcap header\n";
-}
-
-my ($s, $l);
-if (substr($file_header, 0, 4) eq pack('V', 0xa1b2c3d4)) {
-    ($s, $l) = ('v', 'V');
-} elsif (substr($file_header, 0, 4) eq pack('N', 0xa1b2c3d4)) {
-    ($s, $l) = ('n', 'N');
-} else {
-    die "$in_file_name: not a pcap file\n";
-}
-
-print <<'EOF';
-#ifndef DP_TEST_PACKETS_H
-#define DP_TEST_PACKETS_H 1
-
-struct pkt {
-       unsigned char *data;
-       unsigned int len;
-};
-EOF
-
-my ($n_packets) = 0;
-for (;;) {
-    my ($pkt_hdr) = must_read(16);
-    last if $pkt_hdr eq '';
-
-    my ($ts_sec, $ts_usec, $incl_len, $orig_len) = unpack("${l}4", $pkt_hdr);
-    print STDERR "warning: captured less than len %u\n"
-      if $incl_len < $orig_len;
-
-    my ($pkt) = must_read($incl_len);
-    die "$in_file_name: unexpected end of file\n" if !$pkt;
-
-    print "\nstatic unsigned char p${n_packets}[] = {";
-    my ($line_bytes) = 0;
-    for my $c (map(ord($_), split(//, $pkt))) {
-        if ($line_bytes++ % 13 == 0) {
-            print "\n";
-        }
-        printf " 0x%02x,", $c;
-    }
-    print "\n};\n";
-    $n_packets++;
-}
-
-print "\nstatic int num_packets = $n_packets;\n";
-print "\nstatic struct pkt packets[] = {\n";
-for my $i (0..$n_packets - 1) {
-    print "  { p$i, sizeof p$i },\n";
-}
-print "};\n";
-
-print "\n#endif\n";
-
-sub must_read {
-    my ($rq_bytes) = @_;
-    my ($data);
-    my ($nbytes) = read(INPUT, $data, $rq_bytes);
-    die "$in_file_name: read: $!\n" if !defined $nbytes;
-    die "$in_file_name: unexpected end of file\n"
-      if $nbytes && $nbytes != $rq_bytes;
-    return $data;
-}
diff --git a/datapath/tests/ofp_pcap.c b/datapath/tests/ofp_pcap.c
deleted file mode 100644 (file)
index e1b0d22..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* A cheap knock-off of the pcap library to remove that dependency. */
-
-#include <stdlib.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include "ofp_pcap.h"
-
-int
-ofp_pcap_open(struct ofp_pcap *p, const char *fname, char *errbuf)
-{
-       FILE *fp;
-       struct pcap_file_header hdr;
-       size_t amt_read;
-
-       fp = fopen(fname, "r");
-
-       memset((char *)p, 0, sizeof(*p));
-
-       amt_read = fread((char *)&hdr, 1, sizeof(hdr), fp);
-       if (amt_read != sizeof(hdr)) {
-               snprintf(errbuf, OFP_PCAP_ERRBUF_SIZE, "error reading dump file");
-               goto error;
-       }
-
-       if (hdr.magic != TCPDUMP_MAGIC) {
-               hdr.magic         = SWAPLONG(hdr.magic);
-               hdr.version_major = SWAPSHORT(hdr.version_major);
-               hdr.version_minor = SWAPSHORT(hdr.version_minor);
-               hdr.thiszone      = SWAPLONG(hdr.thiszone);
-               hdr.sigfigs       = SWAPLONG(hdr.sigfigs);
-               hdr.snaplen       = SWAPLONG(hdr.snaplen);
-               hdr.linktype      = SWAPLONG(hdr.linktype);
-
-               p->swapped = 1;
-       }
-
-       p->fp = fp;
-       p->errbuf = errbuf;
-       p->bufsize = hdr.snaplen+sizeof(struct pcap_pkthdr);
-       p->buf = malloc(p->bufsize);
-       if (!p->buf) {
-               snprintf(errbuf, OFP_PCAP_ERRBUF_SIZE, "error allocating buffer");
-               goto error;
-       }
-
-       if (hdr.version_major < OFP_PCAP_VERSION_MAJOR) {
-               snprintf(errbuf, OFP_PCAP_ERRBUF_SIZE, "archaic file format");
-               goto error;
-       }
-
-       return 0;
-
-error:
-       if (p->buf)
-               free(p->buf);
-       return 1;
-}
-
-char *
-ofp_pcap_next(struct ofp_pcap *p, struct pcap_pkthdr *hdr)
-{
-       size_t amt_read;
-
-       amt_read = fread(hdr, 1, sizeof(*hdr), p->fp);
-       if (amt_read != sizeof(*hdr)) {
-               snprintf(p->errbuf, OFP_PCAP_ERRBUF_SIZE, "error reading dump file");
-               return NULL;
-       }
-
-       if (p->swapped) {
-               hdr->caplen = SWAPLONG(hdr->caplen);
-               hdr->len = SWAPLONG(hdr->len);
-               hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
-               hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
-       }
-
-       if (hdr->caplen > p->bufsize) {
-               snprintf(p->errbuf, OFP_PCAP_ERRBUF_SIZE, "error reading dump file");
-               return NULL;
-       }
-
-       amt_read = fread((char *)p->buf, 1, hdr->caplen, p->fp);
-       if (amt_read != hdr->caplen){
-               snprintf(p->errbuf, OFP_PCAP_ERRBUF_SIZE, "error reading dump file");
-               return NULL;
-       }
-
-       return p->buf;
-}
-
-void
-ofp_pcap_close(struct ofp_pcap *p)
-{
-       fclose(p->fp);
-       free(p->buf);
-}
-
diff --git a/datapath/tests/ofp_pcap.h b/datapath/tests/ofp_pcap.h
deleted file mode 100644 (file)
index 6bd2dcb..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef OFP_PCAP_H
-#define OFP_PCAP_H
-
-#include <stdint.h>
-#include <sys/time.h>
-#include <stdio.h>
-
-#define OFP_PCAP_VERSION_MAJOR 2
-#define OFP_PCAP_VERSION_MINOR 4
-
-#define TCPDUMP_MAGIC 0xa1b2c3d4
-
-#define OFP_LINKTYPE_ETHERNET 1
-
-#define OFP_PCAP_ERRBUF_SIZE  256
-
-/* Swap the byte order regardless of the architecture */
-#define SWAPLONG(x) \
-       ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24))
-#define SWAPSHORT(x) \
-       ((((x)&0xff)<<8) | (((x)&0xff00)>>8))
-
-struct ofp_pcap {
-       FILE *fp;               /* File pointer to currently processed file */
-       int swapped;            /* Indicate whether endian-ness needs to change */
-       char *buf;              /* Buffer to hold packet data */
-       size_t bufsize;         /* Size of buffer */
-       char *errbuf;               /* Pointer to buffer to hold error message */
-};
-
-struct pcap_file_header {
-       uint32_t magic;         /* Magic number */
-       uint16_t version_major; /* Version number major */
-       uint16_t version_minor; /* Version number minor */
-       int32_t  thiszone;      /* Gmt to local correction */
-       uint32_t sigfigs;       /* Accuracy of timestamps */
-       uint32_t snaplen;       /* Max length saved portion of each pkt */
-       uint32_t linktype;      /* Data link type (LINKTYPE_*) */
-};
-
-/*
- * This is a timeval as stored in disk in a dumpfile.
- * It has to use the same types everywhere, independent of the actual
- * `struct timeval'
- */
-struct pcap_timeval {
-       int32_t tv_sec;         /* Seconds */
-       int32_t tv_usec;        /* Microseconds */
-};
-
-/*
- * How a `pcap_pkthdr' is actually stored in the dumpfile.
- */
-struct pcap_pkthdr {
-       struct pcap_timeval ts; /* Time stamp */
-       uint32_t caplen;        /* Length of portion present */
-       uint32_t len;           /* Length this packet (off wire) */
-};
-
-int ofp_pcap_open(struct ofp_pcap *p, const char *fname, char *errbuf);
-char *ofp_pcap_next(struct ofp_pcap *p, struct pcap_pkthdr *hdr);
-void ofp_pcap_close(struct ofp_pcap *p);
-
-#endif /* ofp_pcap.h */
diff --git a/datapath/unit-exports.c b/datapath/unit-exports.c
deleted file mode 100644 (file)
index 324e77a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008 The Board of Trustees of The Leland 
- * Stanford Junior University
- */
-
-#include "table.h"
-#include "flow.h"
-#include "crc32.h"
-#include "forward.h"
-#include <linux/module.h>
-
-EXPORT_SYMBOL(flow_alloc);
-EXPORT_SYMBOL(flow_cache);
-
-EXPORT_SYMBOL(table_hash_create);
-EXPORT_SYMBOL(table_hash2_create);
-EXPORT_SYMBOL(table_linear_create);
-
-EXPORT_SYMBOL(crc32_init);
-EXPORT_SYMBOL(crc32_calculate);
-
-EXPORT_SYMBOL(flow_extract);
-EXPORT_SYMBOL(execute_setter);
diff --git a/datapath/unit.c b/datapath/unit.c
deleted file mode 100644 (file)
index 73aee7b..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Distributed under the terms of the GNU GPL version 2.
- * Copyright (c) 2007, 2008 The Board of Trustees of The Leland 
- * Stanford Junior University
- */
-
-#include <linux/autoconf.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/version.h>
-#include <linux/errno.h>
-
-#include "unit.h"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-static char run[1024];
-module_param_string(run, run, sizeof run, 0);
-MODULE_PARM_DESC(run_tests, "run=\"test1,[test2,...]\"\n");
-#else
-static char *run;
-MODULE_PARM(run, "s");
-#endif
-
-static int test_failed;
-static const char *test_name;
-
-void unit_fail_function(const char *function, const char *msg, ...) 
-{
-       va_list args;
-
-       printk("%s: FAIL: %s: ", test_name, function);
-       va_start(args, msg);
-       vprintk(msg, args);
-       va_end(args);
-       printk("\n");
-       test_failed = 1;
-}
-
-int unit_failed(void) 
-{
-       return test_failed;
-}
-
-static int run_test(const char *name, size_t len)
-{
-       static const struct test {
-               const char *name;
-               void (*func)(void);
-       } tests[] = {
-#define UNIT_TEST(NAME) {#NAME, run_##NAME},
-               UNIT_TESTS
-#undef UNIT_TEST
-       };
-
-       const struct test *p;
-
-       for (p = tests; p < &tests[ARRAY_SIZE(tests)]; p++)
-               if (len == strlen(p->name)
-                       && !memcmp(name, p->name, len)) {
-                       test_name = p->name;
-                       test_failed = 0;
-                       p->func();
-                       printk("%s: %s\n", test_name,
-                                               test_failed ? "FAIL" : "PASS");
-                       return !test_failed;
-               }
-       printk("unknown unit test %.*s\n", (int) len, name);
-       return 0;
-}
-
-int unit_init(void)
-{
-       int n_pass = 0, n_fail = 0;
-       char *p = run;
-
-       if (p == NULL) {
-               p = "";
-       }
-       for (;;) {
-               static const char white_space[] = " \t\r\n\v,";
-               int len;
-
-               p += strspn(p, white_space);
-               if (!*p)
-                       break;
-
-               len = strcspn(p, white_space);
-               if (run_test(p, len))
-                       n_pass++;
-               else
-                       n_fail++;
-               p += len;
-       }
-
-       if (n_pass + n_fail == 0)
-               printk("no tests specified (use run=\"test1 [test2...]\")\n");
-       else
-               printk("%d tests passed, %d failed\n", n_pass, n_fail);
-
-       return -ENODEV;
-}
-
-module_init(unit_init);
-MODULE_LICENSE("GPL");
diff --git a/datapath/unit.h b/datapath/unit.h
deleted file mode 100644 (file)
index 6d180a8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef UNIT_H
-#define UNIT_H 1
-
-/* List of unit tests. */
-#define UNIT_TESTS                             \
-       UNIT_TEST(table_t)                                        \
-       UNIT_TEST(crc_t)                                                \
-       UNIT_TEST(forward_t)
-
-/* Prototype a function run_<NAME> for each of the unit tests. */
-#define UNIT_TEST(NAME) void run_##NAME(void);
-UNIT_TESTS
-#undef UNIT_TEST
-
-void unit_fail_function(const char *function, const char *msg, ...)
-       __attribute__((format(printf, 2, 3)));
-#define unit_fail(...) unit_fail_function(__func__, __VA_ARGS__)
-
-int unit_failed(void);
-
-#endif /* unit.h */