/*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include <config.h>
-#include <limits.h>
#include "classifier.h"
#include <errno.h>
#include <limits.h>
+#include "command-line.h"
#include "flow.h"
-#include <limits.h>
#include "packets.h"
#undef NDEBUG
free(tcls->rules[i]);
tcls->rules[i] = xmemdup(rule, sizeof *rule);
return tcls->rules[i];
- } else if (pos->priority <= rule->cls_rule.priority) {
+ } else if (pos->priority < rule->cls_rule.priority) {
break;
}
}
T_HTONL(0xc0a04455) };
static uint32_t nw_dst_values[] = { T_HTONL(0xc0a80002),
T_HTONL(0xc0a04455) };
+static uint32_t tun_id_values[] = { 0, 0xffff0000 };
static uint16_t in_port_values[] = { T_HTONS(1), T_HTONS(OFPP_LOCAL) };
static uint16_t dl_vlan_values[] = { T_HTONS(101), T_HTONS(0) };
+static uint8_t dl_vlan_pcp_values[] = { 7, 0 };
static uint16_t dl_type_values[]
= { T_HTONS(ETH_TYPE_IP), T_HTONS(ETH_TYPE_ARP) };
static uint16_t tp_src_values[] = { T_HTONS(49362), T_HTONS(80) };
static uint8_t dl_dst_values[][6] = { { 0x4a, 0x27, 0x71, 0xae, 0x64, 0xc1 },
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
static uint8_t nw_proto_values[] = { IP_TYPE_TCP, IP_TYPE_ICMP };
+static uint8_t nw_tos_values[] = { 49, 0 };
static void *values[CLS_N_FIELDS][2];
static void
init_values(void)
{
+ values[CLS_F_IDX_TUN_ID][0] = &tun_id_values[0];
+ values[CLS_F_IDX_TUN_ID][1] = &tun_id_values[1];
+
values[CLS_F_IDX_IN_PORT][0] = &in_port_values[0];
values[CLS_F_IDX_IN_PORT][1] = &in_port_values[1];
values[CLS_F_IDX_DL_VLAN][0] = &dl_vlan_values[0];
values[CLS_F_IDX_DL_VLAN][1] = &dl_vlan_values[1];
+ values[CLS_F_IDX_DL_VLAN_PCP][0] = &dl_vlan_pcp_values[0];
+ values[CLS_F_IDX_DL_VLAN_PCP][1] = &dl_vlan_pcp_values[1];
+
values[CLS_F_IDX_DL_SRC][0] = dl_src_values[0];
values[CLS_F_IDX_DL_SRC][1] = dl_src_values[1];
values[CLS_F_IDX_NW_PROTO][0] = &nw_proto_values[0];
values[CLS_F_IDX_NW_PROTO][1] = &nw_proto_values[1];
+ values[CLS_F_IDX_NW_TOS][0] = &nw_tos_values[0];
+ values[CLS_F_IDX_NW_TOS][1] = &nw_tos_values[1];
+
values[CLS_F_IDX_TP_SRC][0] = &tp_src_values[0];
values[CLS_F_IDX_TP_SRC][1] = &tp_src_values[1];
#define N_NW_SRC_VALUES ARRAY_SIZE(nw_src_values)
#define N_NW_DST_VALUES ARRAY_SIZE(nw_dst_values)
+#define N_TUN_ID_VALUES ARRAY_SIZE(tun_id_values)
#define N_IN_PORT_VALUES ARRAY_SIZE(in_port_values)
#define N_DL_VLAN_VALUES ARRAY_SIZE(dl_vlan_values)
+#define N_DL_VLAN_PCP_VALUES ARRAY_SIZE(dl_vlan_pcp_values)
#define N_DL_TYPE_VALUES ARRAY_SIZE(dl_type_values)
#define N_TP_SRC_VALUES ARRAY_SIZE(tp_src_values)
#define N_TP_DST_VALUES ARRAY_SIZE(tp_dst_values)
#define N_DL_SRC_VALUES ARRAY_SIZE(dl_src_values)
#define N_DL_DST_VALUES ARRAY_SIZE(dl_dst_values)
#define N_NW_PROTO_VALUES ARRAY_SIZE(nw_proto_values)
+#define N_NW_TOS_VALUES ARRAY_SIZE(nw_tos_values)
#define N_FLOW_VALUES (N_NW_SRC_VALUES * \
N_NW_DST_VALUES * \
+ N_TUN_ID_VALUES * \
N_IN_PORT_VALUES * \
N_DL_VLAN_VALUES * \
+ N_DL_VLAN_PCP_VALUES * \
N_DL_TYPE_VALUES * \
N_TP_SRC_VALUES * \
N_TP_DST_VALUES * \
N_DL_SRC_VALUES * \
N_DL_DST_VALUES * \
- N_NW_PROTO_VALUES)
+ N_NW_PROTO_VALUES * \
+ N_NW_TOS_VALUES)
static unsigned int
get_value(unsigned int *x, unsigned n_values)
static void
compare_classifiers(struct classifier *cls, struct tcls *tcls)
{
+ static const int confidence = 500;
unsigned int i;
assert(classifier_count(cls) == tcls->n_rules);
assert(classifier_count_exact(cls) == tcls_count_exact(tcls));
- for (i = 0; i < N_FLOW_VALUES; i++) {
+ for (i = 0; i < confidence; i++) {
struct cls_rule *cr0, *cr1;
flow_t flow;
unsigned int x;
int include;
- x = i;
+ x = rand () % N_FLOW_VALUES;
flow.nw_src = nw_src_values[get_value(&x, N_NW_SRC_VALUES)];
flow.nw_dst = nw_dst_values[get_value(&x, N_NW_DST_VALUES)];
+ flow.tun_id = tun_id_values[get_value(&x, N_TUN_ID_VALUES)];
flow.in_port = in_port_values[get_value(&x, N_IN_PORT_VALUES)];
flow.dl_vlan = dl_vlan_values[get_value(&x, N_DL_VLAN_VALUES)];
+ flow.dl_vlan_pcp = dl_vlan_pcp_values[get_value(&x,
+ N_DL_VLAN_PCP_VALUES)];
flow.dl_type = dl_type_values[get_value(&x, N_DL_TYPE_VALUES)];
flow.tp_src = tp_src_values[get_value(&x, N_TP_SRC_VALUES)];
flow.tp_dst = tp_dst_values[get_value(&x, N_TP_DST_VALUES)];
memcpy(flow.dl_dst, dl_dst_values[get_value(&x, N_DL_DST_VALUES)],
ETH_ADDR_LEN);
flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)];
- flow.reserved = 0;
+ flow.nw_tos = nw_tos_values[get_value(&x, N_NW_TOS_VALUES)];
+ memset(flow.reserved, 0, sizeof flow.reserved);
for (include = 1; include <= 3; include++) {
cr0 = lookup_with_include_bits(cls, &flow, include);
}
}
- rule = xcalloc(1, sizeof *rule);
- cls_rule_from_flow(&rule->cls_rule, &flow, wildcards,
- !wildcards ? UINT_MAX : priority);
+ rule = xzalloc(sizeof *rule);
+ cls_rule_from_flow(&flow, wildcards, !wildcards ? UINT_MAX : priority,
+ &rule->cls_rule);
return rule;
}
\f
/* Tests an empty classifier. */
static void
-test_empty(void)
+test_empty(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
struct classifier cls;
struct tcls tcls;
/* Destroys a null classifier. */
static void
-test_destroy_null(void)
+test_destroy_null(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
classifier_destroy(NULL);
}
/* Tests classification with one rule at a time. */
static void
-test_single_rule(void)
+test_single_rule(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
unsigned int wc_fields; /* Hilarious. */
/* Tests replacing one rule by another. */
static void
-test_rule_replacement(void)
+test_rule_replacement(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
unsigned int wc_fields;
for (wc_fields = 0; wc_fields < (1u << CLS_N_FIELDS); wc_fields++) {
struct classifier cls;
- struct test_rule *rule1, *tcls_rule1;
- struct test_rule *rule2, *tcls_rule2;
+ struct test_rule *rule1;
+ struct test_rule *rule2;
struct tcls tcls;
rule1 = make_rule(wc_fields, OFP_DEFAULT_PRIORITY, UINT_MAX);
classifier_init(&cls);
tcls_init(&tcls);
- tcls_rule1 = tcls_insert(&tcls, rule1);
+ tcls_insert(&tcls, rule1);
assert(!classifier_insert(&cls, &rule1->cls_rule));
check_tables(&cls, 1, 1, 1);
compare_classifiers(&cls, &tcls);
tcls_destroy(&tcls);
tcls_init(&tcls);
- tcls_rule2 = tcls_insert(&tcls, rule2);
+ tcls_insert(&tcls, rule2);
assert(test_rule_from_cls_rule(
classifier_insert(&cls, &rule2->cls_rule)) == rule1);
free(rule1);
/* Tests classification with two rules at a time that fall into the same
* bucket. */
static void
-test_two_rules_in_one_bucket(void)
+test_two_rules_in_one_bucket(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
int table, rel_pri, wcf_pat, value_pat;
/* Tests classification with two rules at a time that fall into the same
* table but different buckets. */
static void
-test_two_rules_in_one_table(void)
+test_two_rules_in_one_table(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
int table, rel_pri, wcf_pat;
/* Tests classification with two rules at a time that fall into different
* tables. */
static void
-test_two_rules_in_different_tables(void)
+test_two_rules_in_different_tables(int argc OVS_UNUSED,
+ char *argv[] OVS_UNUSED)
{
int table1, table2, rel_pri, wcf_pat;
/* Tests classification with many rules at a time that fall into the same
* bucket but have unique priorities (and various wildcards). */
static void
-test_many_rules_in_one_bucket(void)
+test_many_rules_in_one_bucket(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
enum { MAX_RULES = 50 };
int iteration, table;
/* Tests classification with many rules at a time that fall into the same
* table but random buckets. */
static void
-test_many_rules_in_one_table(void)
+test_many_rules_in_one_table(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
enum { MAX_RULES = 50 };
int iteration, table;
/* Tests classification with many rules at a time that fall into random buckets
* in random tables. */
static void
-test_many_rules_in_different_tables(void)
+test_many_rules_in_different_tables(int argc OVS_UNUSED,
+ char *argv[] OVS_UNUSED)
{
enum { MAX_RULES = 50 };
int iteration;
compare_classifiers(&cls, &tcls);
free(rule);
}
- putchar('.');
- fflush(stdout);
destroy_classifier(&cls);
tcls_destroy(&tcls);
}
}
\f
-static void
-run_test(void (*function)(void))
-{
- function();
- putchar('.');
- fflush(stdout);
-}
+static const struct command commands[] = {
+ {"empty", 0, 0, test_empty},
+ {"destroy-null", 0, 0, test_destroy_null},
+ {"single-rule", 0, 0, test_single_rule},
+ {"rule-replacement", 0, 0, test_rule_replacement},
+ {"two-rules-in-one-bucket", 0, 0, test_two_rules_in_one_bucket},
+ {"two-rules-in-one-table", 0, 0, test_two_rules_in_one_table},
+ {"two-rules-in-different-tables", 0, 0,
+ test_two_rules_in_different_tables},
+ {"many-rules-in-one-bucket", 0, 0, test_many_rules_in_one_bucket},
+ {"many-rules-in-one-table", 0, 0, test_many_rules_in_one_table},
+ {"many-rules-in-different-tables", 0, 0,
+ test_many_rules_in_different_tables},
+ {NULL, 0, 0, NULL},
+};
int
-main(void)
+main(int argc, char *argv[])
{
init_values();
- run_test(test_empty);
- run_test(test_destroy_null);
- run_test(test_single_rule);
- run_test(test_rule_replacement);
- run_test(test_two_rules_in_one_bucket);
- run_test(test_two_rules_in_one_table);
- run_test(test_two_rules_in_different_tables);
- run_test(test_many_rules_in_one_bucket);
- run_test(test_many_rules_in_one_table);
- run_test(test_many_rules_in_different_tables);
- putchar('\n');
+ run_command(argc - 1, argv + 1, commands);
return 0;
}