Catalli's threaded switch
[sliver-openvswitch.git] / tests / test-classifier.c
index 0307e48..57a1e2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -111,7 +110,7 @@ tcls_insert(struct tcls *tcls, const struct test_rule *rule)
             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;
         }
     }
@@ -238,8 +237,10 @@ static uint32_t nw_src_values[] = { T_HTONL(0xc0a80001),
                                     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) };
@@ -249,18 +250,25 @@ static uint8_t dl_src_values[][6] = { { 0x00, 0x02, 0xe3, 0x0f, 0x80, 0xa4 },
 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];
 
@@ -279,6 +287,9 @@ init_values(void)
     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];
 
@@ -288,25 +299,31 @@ init_values(void)
 
 #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)
@@ -335,21 +352,25 @@ lookup_with_include_bits(const struct classifier *cls,
 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)];
@@ -358,7 +379,8 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls)
         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);
@@ -446,9 +468,9 @@ make_rule(int wc_fields, unsigned int priority, int value_pat)
         }
     }
 
-    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;
 }
 
@@ -465,7 +487,7 @@ shuffle(unsigned int *p, size_t n)
 \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;
@@ -481,14 +503,14 @@ test_empty(void)
 
 /* 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. */
 
@@ -526,14 +548,14 @@ test_single_rule(void)
 
 /* 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);
@@ -543,14 +565,14 @@ test_rule_replacement(void)
 
         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);
@@ -577,7 +599,7 @@ random_wcf_in_table(int table, int seed)
 /* 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;
 
@@ -666,7 +688,7 @@ test_two_rules_in_one_bucket(void)
 /* 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;
 
@@ -742,7 +764,8 @@ test_two_rules_in_one_table(void)
 /* 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;
 
@@ -811,7 +834,7 @@ test_two_rules_in_different_tables(void)
 /* 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;
@@ -855,7 +878,7 @@ test_many_rules_in_one_bucket(void)
 /* 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;
@@ -898,7 +921,8 @@ test_many_rules_in_one_table(void)
 /* 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;
@@ -943,36 +967,32 @@ test_many_rules_in_different_tables(void)
             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;
 }