From 0fab7c69aedde080f3181341f154ac4c44d7bc5d Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Fri, 26 Sep 2008 14:58:17 -0700 Subject: [PATCH] Remove kernel datapath unit tests. 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. --- configure.ac | 1 - datapath/Makefile.am | 2 +- datapath/Modules.mk | 14 +- datapath/crc_t.c | 47 -- datapath/forward_t.c | 584 --------------------- datapath/table_t.c | 874 -------------------------------- datapath/tests/.gitignore | 4 - datapath/tests/Makefile.am | 7 - datapath/tests/example.pcap | Bin 82 -> 0 bytes datapath/tests/gen_forward_t.pl | 80 --- datapath/tests/ofp_pcap.c | 97 ---- datapath/tests/ofp_pcap.h | 64 --- datapath/unit-exports.c | 24 - datapath/unit.c | 105 ---- datapath/unit.h | 21 - 15 files changed, 4 insertions(+), 1920 deletions(-) delete mode 100644 datapath/crc_t.c delete mode 100644 datapath/forward_t.c delete mode 100644 datapath/table_t.c delete mode 100644 datapath/tests/.gitignore delete mode 100644 datapath/tests/Makefile.am delete mode 100644 datapath/tests/example.pcap delete mode 100755 datapath/tests/gen_forward_t.pl delete mode 100644 datapath/tests/ofp_pcap.c delete mode 100644 datapath/tests/ofp_pcap.h delete mode 100644 datapath/unit-exports.c delete mode 100644 datapath/unit.c delete mode 100644 datapath/unit.h diff --git a/configure.ac b/configure.ac index 69e00470..aa1ce99f 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/datapath/Makefile.am b/datapath/Makefile.am index 97855378..88e66c74 100644 --- a/datapath/Makefile.am +++ b/datapath/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = tests +SUBDIRS = if L26_ENABLED SUBDIRS += linux-2.6 endif diff --git a/datapath/Modules.mk b/datapath/Modules.mk index f21af16b..516ebd9d 100644 --- a/datapath/Modules.mk +++ b/datapath/Modules.mk @@ -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 index 1e8274aa..00000000 --- a/datapath/crc_t.c +++ /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 -#include - -#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 index da5de50c..00000000 --- a/datapath/forward_t.c +++ /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 -#include -#include -#include -#include -#include -#include -#include - -#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 index a824804b..00000000 --- a/datapath/table_t.c +++ /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 -#include -#include -#include -#include - -#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 index 35e75b7a..00000000 --- a/datapath/tests/.gitignore +++ /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 index fc5fd8f8..00000000 --- a/datapath/tests/Makefile.am +++ /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 index 7bda45893ee5616ff72e8046f28cdab28835a275..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmca|c+)~A1{MYwNB}Yzfw-k2!2Jj>7lRg%4Z{DyfMLNIjg?b4*ccc&7}!{V3c>sX OD;R} 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 index e1b0d226..00000000 --- a/datapath/tests/ofp_pcap.c +++ /dev/null @@ -1,97 +0,0 @@ -/* A cheap knock-off of the pcap library to remove that dependency. */ - -#include -#include -#include -#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 index 6bd2dcb3..00000000 --- a/datapath/tests/ofp_pcap.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef OFP_PCAP_H -#define OFP_PCAP_H - -#include -#include -#include - -#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 index 324e77a7..00000000 --- a/datapath/unit-exports.c +++ /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 - -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 index 73aee7bd..00000000 --- a/datapath/unit.c +++ /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 -#include -#include -#include -#include -#include - -#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 index 6d180a8b..00000000 --- a/datapath/unit.h +++ /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_ 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 */ -- 2.30.2