2010-12-17 14:38:50 -08:00
|
|
|
/*
|
2014-04-01 00:47:01 -07:00
|
|
|
* Copyright (c) 2010, 2012, 2013, 2014 Nicira, Inc.
|
2010-12-17 14:38:50 -08:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
2014-10-29 11:34:40 -07:00
|
|
|
#undef NDEBUG
|
2010-12-17 14:38:50 -08:00
|
|
|
#include <assert.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "flow.h"
|
2016-04-14 15:20:19 -07:00
|
|
|
#include "multipath.h"
|
|
|
|
#include "openvswitch/ofp-actions.h"
|
2014-04-01 00:47:01 -07:00
|
|
|
#include "ovstest.h"
|
2014-10-29 11:34:40 -07:00
|
|
|
#include "util.h"
|
2010-12-17 14:38:50 -08:00
|
|
|
|
2014-04-01 00:47:01 -07:00
|
|
|
static void
|
|
|
|
test_multipath_main(int argc, char *argv[])
|
2010-12-17 14:38:50 -08:00
|
|
|
{
|
|
|
|
enum { MP_MAX_LINKS = 63 };
|
2012-07-03 22:17:14 -07:00
|
|
|
struct ofpact_multipath mp;
|
2010-12-17 14:38:50 -08:00
|
|
|
bool ok = true;
|
2013-07-08 10:15:00 -07:00
|
|
|
char *error;
|
2010-12-17 14:38:50 -08:00
|
|
|
int n;
|
|
|
|
|
|
|
|
set_program_name(argv[0]);
|
|
|
|
|
|
|
|
if (argc != 2) {
|
|
|
|
ovs_fatal(0, "usage: %s multipath_action", program_name);
|
|
|
|
}
|
|
|
|
|
2013-07-08 10:15:00 -07:00
|
|
|
error = multipath_parse(&mp, argv[1]);
|
|
|
|
if (error) {
|
|
|
|
ovs_fatal(0, "%s", error);
|
|
|
|
}
|
|
|
|
|
2010-12-17 14:38:50 -08:00
|
|
|
for (n = 1; n <= MP_MAX_LINKS; n++) {
|
|
|
|
enum { N_FLOWS = 65536 };
|
|
|
|
double disruption, perfect, distribution;
|
|
|
|
int histogram[MP_MAX_LINKS];
|
|
|
|
double sum_dev2, stddev;
|
|
|
|
int changed;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
changed = 0;
|
|
|
|
memset(histogram, 0, sizeof histogram);
|
|
|
|
for (i = 0; i < N_FLOWS; i++) {
|
|
|
|
int old_link, new_link;
|
2013-05-14 18:24:43 -07:00
|
|
|
struct flow_wildcards wc;
|
2010-12-17 14:38:50 -08:00
|
|
|
struct flow flow;
|
|
|
|
|
2013-10-17 14:28:20 -07:00
|
|
|
flow_random_hash_fields(&flow);
|
2024-11-28 13:29:42 +01:00
|
|
|
flow_wildcards_init_catchall(&wc);
|
2010-12-17 14:38:50 -08:00
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
mp.max_link = n - 1;
|
2013-05-14 18:24:43 -07:00
|
|
|
multipath_execute(&mp, &flow, &wc);
|
2010-12-17 14:38:50 -08:00
|
|
|
old_link = flow.regs[0];
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
mp.max_link = n;
|
2013-05-14 18:24:43 -07:00
|
|
|
multipath_execute(&mp, &flow, &wc);
|
2010-12-17 14:38:50 -08:00
|
|
|
new_link = flow.regs[0];
|
|
|
|
|
|
|
|
assert(old_link >= 0 && old_link < n);
|
|
|
|
assert(new_link >= 0 && new_link < n + 1);
|
|
|
|
|
|
|
|
histogram[old_link]++;
|
|
|
|
changed += old_link != new_link;
|
|
|
|
}
|
|
|
|
|
|
|
|
sum_dev2 = 0.0;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
double mean = (double) N_FLOWS / n;
|
|
|
|
double deviation = histogram[i] - mean;
|
|
|
|
|
|
|
|
sum_dev2 += deviation * deviation;
|
|
|
|
}
|
|
|
|
stddev = sqrt(sum_dev2 / n);
|
|
|
|
|
|
|
|
disruption = (double) changed / N_FLOWS;
|
|
|
|
perfect = 1.0 / (n + 1);
|
|
|
|
distribution = stddev / ((double) N_FLOWS / n);
|
|
|
|
printf("%2d -> %2d: disruption=%.2f (perfect=%.2f); "
|
|
|
|
"stddev/expected=%.4f\n",
|
|
|
|
n, n + 1, disruption, perfect, distribution);
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
switch (mp.algorithm) {
|
2010-12-17 14:38:50 -08:00
|
|
|
case NX_MP_ALG_MODULO_N:
|
|
|
|
if (disruption < (n < 2 ? .25 : .5)) {
|
|
|
|
fprintf(stderr, "%d -> %d: disruption=%.2f < .5\n",
|
|
|
|
n, n + 1, disruption);
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NX_MP_ALG_HASH_THRESHOLD:
|
|
|
|
if (disruption < .48 || disruption > .52) {
|
|
|
|
fprintf(stderr, "%d -> %d: disruption=%.2f not approximately "
|
|
|
|
".5\n", n, n + 1, disruption);
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NX_MP_ALG_ITER_HASH:
|
|
|
|
if (!(n & (n - 1))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Fall through. */
|
|
|
|
case NX_MP_ALG_HRW:
|
|
|
|
if (fabs(disruption - perfect) >= .01) {
|
|
|
|
fprintf(stderr, "%d -> %d: disruption=%.5f differs from "
|
|
|
|
"perfect=%.5f by more than .01\n",
|
|
|
|
n, n + 1, disruption, perfect);
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
OVS_NOT_REACHED();
|
2010-12-17 14:38:50 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-01 00:47:01 -07:00
|
|
|
exit(ok ? 0 : 1);
|
2010-12-17 14:38:50 -08:00
|
|
|
}
|
2014-04-01 00:47:01 -07:00
|
|
|
|
|
|
|
OVSTEST_REGISTER("test-multipath", test_multipath_main);
|