Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.git] / tests / test-multipath.c
1 /*
2  * Copyright (c) 2010, 2012, 2013, 2014 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include "multipath.h"
20
21 #include <assert.h>
22 #include <getopt.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #include "flow.h"
28 #include "ofp-actions.h"
29 #include "util.h"
30 #include "ovstest.h"
31
32 static void
33 test_multipath_main(int argc, char *argv[])
34 {
35     enum { MP_MAX_LINKS = 63 };
36     struct ofpact_multipath mp;
37     bool ok = true;
38     char *error;
39     int n;
40
41     set_program_name(argv[0]);
42
43     if (argc != 2) {
44         ovs_fatal(0, "usage: %s multipath_action", program_name);
45     }
46
47     error = multipath_parse(&mp, argv[1]);
48     if (error) {
49         ovs_fatal(0, "%s", error);
50     }
51
52     for (n = 1; n <= MP_MAX_LINKS; n++) {
53         enum { N_FLOWS = 65536 };
54         double disruption, perfect, distribution;
55         int histogram[MP_MAX_LINKS];
56         double sum_dev2, stddev;
57         int changed;
58         int i;
59
60         changed = 0;
61         memset(histogram, 0, sizeof histogram);
62         for (i = 0; i < N_FLOWS; i++) {
63             int old_link, new_link;
64             struct flow_wildcards wc;
65             struct flow flow;
66
67             flow_random_hash_fields(&flow);
68
69             mp.max_link = n - 1;
70             multipath_execute(&mp, &flow, &wc);
71             old_link = flow.regs[0];
72
73             mp.max_link = n;
74             multipath_execute(&mp, &flow, &wc);
75             new_link = flow.regs[0];
76
77             assert(old_link >= 0 && old_link < n);
78             assert(new_link >= 0 && new_link < n + 1);
79
80             histogram[old_link]++;
81             changed += old_link != new_link;
82         }
83
84         sum_dev2 = 0.0;
85         for (i = 0; i < n; i++) {
86             double mean = (double) N_FLOWS / n;
87             double deviation = histogram[i] - mean;
88
89             sum_dev2 += deviation * deviation;
90         }
91         stddev = sqrt(sum_dev2 / n);
92
93         disruption = (double) changed / N_FLOWS;
94         perfect = 1.0 / (n + 1);
95         distribution = stddev / ((double) N_FLOWS / n);
96         printf("%2d -> %2d: disruption=%.2f (perfect=%.2f); "
97                "stddev/expected=%.4f\n",
98                n, n + 1, disruption, perfect, distribution);
99
100         switch (mp.algorithm) {
101         case NX_MP_ALG_MODULO_N:
102             if (disruption < (n < 2 ? .25 : .5)) {
103                 fprintf(stderr, "%d -> %d: disruption=%.2f < .5\n",
104                         n, n + 1, disruption);
105                 ok = false;
106             }
107             break;
108
109         case NX_MP_ALG_HASH_THRESHOLD:
110             if (disruption < .48 || disruption > .52) {
111                 fprintf(stderr, "%d -> %d: disruption=%.2f not approximately "
112                         ".5\n", n, n + 1, disruption);
113                 ok = false;
114             }
115             break;
116
117         case NX_MP_ALG_ITER_HASH:
118             if (!(n & (n - 1))) {
119                 break;
120             }
121             /* Fall through. */
122         case NX_MP_ALG_HRW:
123             if (fabs(disruption - perfect) >= .01) {
124                 fprintf(stderr, "%d -> %d: disruption=%.5f differs from "
125                         "perfect=%.5f by more than .01\n",
126                         n, n + 1, disruption, perfect);
127                 ok = false;
128             }
129             break;
130
131         default:
132             OVS_NOT_REACHED();
133         }
134     }
135
136     exit(ok ? 0 : 1);
137 }
138
139 OVSTEST_REGISTER("test-multipath", test_multipath_main);