Branch data Line data Source code
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 : : #undef NDEBUG
19 : : #include <assert.h>
20 : : #include <getopt.h>
21 : : #include <math.h>
22 : : #include <stdio.h>
23 : : #include <stdlib.h>
24 : : #include "flow.h"
25 : : #include "multipath.h"
26 : : #include "openvswitch/ofp-actions.h"
27 : : #include "ovstest.h"
28 : : #include "util.h"
29 : :
30 : : static void
31 : 4 : test_multipath_main(int argc, char *argv[])
32 : : {
33 : : enum { MP_MAX_LINKS = 63 };
34 : : struct ofpact_multipath mp;
35 : 4 : bool ok = true;
36 : : char *error;
37 : : int n;
38 : :
39 : 4 : set_program_name(argv[0]);
40 : :
41 [ - + ]: 4 : if (argc != 2) {
42 : 0 : ovs_fatal(0, "usage: %s multipath_action", program_name);
43 : : }
44 : :
45 : 4 : error = multipath_parse(&mp, argv[1]);
46 [ - + ]: 4 : if (error) {
47 : 0 : ovs_fatal(0, "%s", error);
48 : : }
49 : :
50 [ + + ]: 256 : for (n = 1; n <= MP_MAX_LINKS; n++) {
51 : : enum { N_FLOWS = 65536 };
52 : : double disruption, perfect, distribution;
53 : : int histogram[MP_MAX_LINKS];
54 : : double sum_dev2, stddev;
55 : : int changed;
56 : : int i;
57 : :
58 : 252 : changed = 0;
59 : 252 : memset(histogram, 0, sizeof histogram);
60 [ + + ]: 16515324 : for (i = 0; i < N_FLOWS; i++) {
61 : : int old_link, new_link;
62 : : struct flow_wildcards wc;
63 : : struct flow flow;
64 : :
65 : 16515072 : flow_random_hash_fields(&flow);
66 : :
67 : 16515072 : mp.max_link = n - 1;
68 : 16515072 : multipath_execute(&mp, &flow, &wc);
69 : 16515072 : old_link = flow.regs[0];
70 : :
71 : 16515072 : mp.max_link = n;
72 : 16515072 : multipath_execute(&mp, &flow, &wc);
73 : 16515072 : new_link = flow.regs[0];
74 : :
75 [ + - ][ - + ]: 16515072 : assert(old_link >= 0 && old_link < n);
76 [ + - ][ - + ]: 16515072 : assert(new_link >= 0 && new_link < n + 1);
77 : :
78 : 16515072 : histogram[old_link]++;
79 : 16515072 : changed += old_link != new_link;
80 : : }
81 : :
82 : 252 : sum_dev2 = 0.0;
83 [ + + ]: 8316 : for (i = 0; i < n; i++) {
84 : 8064 : double mean = (double) N_FLOWS / n;
85 : 8064 : double deviation = histogram[i] - mean;
86 : :
87 : 8064 : sum_dev2 += deviation * deviation;
88 : : }
89 : 252 : stddev = sqrt(sum_dev2 / n);
90 : :
91 : 252 : disruption = (double) changed / N_FLOWS;
92 : 252 : perfect = 1.0 / (n + 1);
93 : 252 : distribution = stddev / ((double) N_FLOWS / n);
94 : 252 : printf("%2d -> %2d: disruption=%.2f (perfect=%.2f); "
95 : : "stddev/expected=%.4f\n",
96 : : n, n + 1, disruption, perfect, distribution);
97 : :
98 [ + + + + : 252 : switch (mp.algorithm) {
- ]
99 : : case NX_MP_ALG_MODULO_N:
100 [ + + ][ - + ]: 63 : if (disruption < (n < 2 ? .25 : .5)) {
101 : 0 : fprintf(stderr, "%d -> %d: disruption=%.2f < .5\n",
102 : : n, n + 1, disruption);
103 : 0 : ok = false;
104 : : }
105 : 63 : break;
106 : :
107 : : case NX_MP_ALG_HASH_THRESHOLD:
108 [ + - ][ - + ]: 63 : if (disruption < .48 || disruption > .52) {
109 : 0 : fprintf(stderr, "%d -> %d: disruption=%.2f not approximately "
110 : : ".5\n", n, n + 1, disruption);
111 : 0 : ok = false;
112 : : }
113 : 63 : break;
114 : :
115 : : case NX_MP_ALG_ITER_HASH:
116 [ + + ]: 63 : if (!(n & (n - 1))) {
117 : 6 : break;
118 : : }
119 : : /* Fall through. */
120 : : case NX_MP_ALG_HRW:
121 [ - + ]: 120 : if (fabs(disruption - perfect) >= .01) {
122 : 0 : fprintf(stderr, "%d -> %d: disruption=%.5f differs from "
123 : : "perfect=%.5f by more than .01\n",
124 : : n, n + 1, disruption, perfect);
125 : 0 : ok = false;
126 : : }
127 : 120 : break;
128 : :
129 : : default:
130 : 0 : OVS_NOT_REACHED();
131 : : }
132 : : }
133 : :
134 [ + - ]: 4 : exit(ok ? 0 : 1);
135 : : }
136 : :
137 : 1178 : OVSTEST_REGISTER("test-multipath", test_multipath_main);
|