@@ -14,6 +14,8 @@ Post-v2.9.0
- ovs-vsctl: New commands "add-bond-iface" and "del-bond-iface".
- OpenFlow:
* OFPT_ROLE_STATUS is now available in OpenFlow 1.3.
+ * Default selection method for select groups is now dp_hash with improved
+ accuracy.
- Linux kernel 4.14
* Add support for compiling OVS with the latest Linux 4.14 kernel
- ovn:
@@ -1518,12 +1518,17 @@ parse_group_prop_ntr_selection_method(struct ofpbuf *payload,
return OFPERR_OFPBPC_BAD_VALUE;
}
- error = oxm_pull_field_array(payload->data, fields_len,
- &gp->fields);
- if (error) {
- OFPPROP_LOG(&rl, false,
+ if (fields_len > 0) {
+ error = oxm_pull_field_array(payload->data, fields_len,
+ &gp->fields);
+ if (error) {
+ OFPPROP_LOG(&rl, false,
"ntr selection method fields are invalid");
- return error;
+ return error;
+ }
+ } else {
+ /* Selection_method "hash: w/o fields means default hash method. */
+ gp->fields.values_size = 0;
}
return 0;
@@ -4814,39 +4814,54 @@ group_set_selection_method(struct group_dpif *group)
struct ofputil_group_props *props = &group->up.props;
char *selection_method = props->selection_method;
+ VLOG_DBG("Constructing select group %"PRIu32, group->up.group_id);
if (selection_method[0] == '\0') {
- VLOG_INFO("No selection method specified.");
- group->selection_method = SEL_METHOD_DEFAULT;
-
+ VLOG_DBG("No selection method specified. Trying dp_hash.");
+ /* If the controller has not specified a selection method, check if
+ * the dp_hash selection method with max 64 hash values is appropriate
+ * for the given bucket configuration. */
+ if (group_setup_dp_hash_table(group, 64)) {
+ /* Use dp_hash selection method with symmetric L4 hash. */
+ VLOG_DBG("Use dp_hash with %d hash values.",
+ group->hash_mask + 1);
+ group->selection_method = SEL_METHOD_DP_HASH;
+ group->hash_alg = OVS_HASH_ALG_SYM_L4;
+ group->hash_basis = 0xdeadbeef;
+ } else {
+ /* Fall back to original default hashing in slow path. */
+ VLOG_DBG("Falling back to default hash method.");
+ group->selection_method = SEL_METHOD_DEFAULT;
+ }
} else if (!strcmp(selection_method, "dp_hash")) {
- VLOG_INFO("Selection method specified: dp_hash.");
+ VLOG_DBG("Selection method specified: dp_hash.");
/* Try to use dp_hash if possible at all. */
if (group_setup_dp_hash_table(group, 0)) {
group->selection_method = SEL_METHOD_DP_HASH;
group->hash_alg = props->selection_method_param >> 32;
if (group->hash_alg >= __OVS_HASH_MAX) {
- VLOG_INFO(" Invalid dp_hash algorithm %d. "
- "Defaulting to OVS_HASH_ALG_L4", group->hash_alg);
+ VLOG_DBG("Invalid dp_hash algorithm %d. "
+ "Defaulting to OVS_HASH_ALG_L4", group->hash_alg);
group->hash_alg = OVS_HASH_ALG_L4;
}
group->hash_basis = (uint32_t) props->selection_method_param;
} else {
/* Fall back to original default hashing in slow path. */
- VLOG_INFO(" Falling back to default hash method.");
+ VLOG_DBG("Falling back to default hash method.");
group->selection_method = SEL_METHOD_DEFAULT;
}
+
} else if (!strcmp(selection_method, "hash")) {
- VLOG_INFO("Selection method specified: hash.");
+ VLOG_DBG("Selection method specified: hash.");
if (props->fields.values_size > 0) {
/* Controller has specified hash fields. */
struct ds s = DS_EMPTY_INITIALIZER;
oxm_format_field_array(&s, &props->fields);
- VLOG_INFO(" Hash fields: %s", ds_cstr(&s));
+ VLOG_DBG("Hash fields: %s", ds_cstr(&s));
ds_destroy(&s);
group->selection_method = SEL_METHOD_HASH;
} else {
/* No hash fields. Fall back to original default hashing. */
- VLOG_INFO(" No hash fields. Falling back to default hash method.");
+ VLOG_DBG("No hash fields. Falling back to default hash method.");
group->selection_method = SEL_METHOD_DEFAULT;
}
} else {
@@ -61,6 +61,7 @@ struct ofproto_async_msg;
struct ofproto_dpif;
struct uuid;
struct xlate_cache;
+struct xlate_ctx;
/* Number of implemented OpenFlow tables. */
enum { N_TABLES = 255 };
@@ -572,7 +572,7 @@ struct ofgroup {
const struct ovs_list buckets; /* Contains "struct ofputil_bucket"s. */
const uint32_t n_buckets;
- const struct ofputil_group_props props;
+ struct ofputil_group_props props;
struct rule_collection rules OVS_GUARDED; /* Referring rules. */
};
@@ -68,12 +68,18 @@ AT_CHECK([tail -1 stdout], [0],
dnl Test MPLS pop then select group output (group type triggers recirculation)
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=22,tc=0,ttl=64,bos=1)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: pop_mpls(eth_type=0x800),recirc(0x2)
+ [Datapath actions: pop_mpls(eth_type=0x800),hash(hash_l4(0)),recirc(0x2)
])
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(2),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
-AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: 100
+for d in 0 1 2 3; do
+ pkt="in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=22,tc=0,ttl=64,bos=1)"
+ AT_CHECK([ovs-appctl netdev-dummy/receive p0 $pkt])
+done
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/dp_hash(.*\/0xf)/dp_hash(0XXXX\/0xf)/' | sed 's/packets.*actions:1/actions:1/' | strip_used | strip_ufid | sort], [0], [dnl
+flow-dump from non-dpdk interfaces:
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x8847),mpls(label=22/0xfffff,tc=0/0,ttl=64/0x0,bos=1/1), packets:3, bytes:54, used:0.0s, actions:pop_mpls(eth_type=0x800),hash(hash_l4(0)),recirc(0x3)
+recirc_id(0x3),dp_hash(0XXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:100
])
dnl Test MPLS pop then all group output (bucket actions do not trigger recirculation)
@@ -85,10 +91,10 @@ AT_CHECK([tail -1 stdout], [0],
dnl Test MPLS pop then all group output (bucket actions trigger recirculation)
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=24,tc=0,ttl=64,bos=1)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: pop_mpls(eth_type=0x800),recirc(0x3)
+ [Datapath actions: pop_mpls(eth_type=0x800),recirc(0x4)
])
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(3),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(4),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: set(ipv4(ttl=63)),100
])
@@ -96,10 +102,10 @@ AT_CHECK([tail -1 stdout], [0],
dnl Test MPLS pop then all output to patch port
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=25,tc=0,ttl=64,bos=1)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: pop_mpls(eth_type=0x800),recirc(0x4)
+ [Datapath actions: pop_mpls(eth_type=0x800),recirc(0x5)
])
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(4),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(5),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: 101
])
@@ -124,10 +130,10 @@ AT_CHECK([tail -1 stdout], [0],
dnl Double MPLS pop
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=60,tc=0,ttl=64,bos=0,label=50,tc=0,ttl=64,bos=1)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: pop_mpls(eth_type=0x8847),pop_mpls(eth_type=0x800),recirc(0x5)
+ [Datapath actions: pop_mpls(eth_type=0x8847),pop_mpls(eth_type=0x800),recirc(0x7)
])
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(5),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'recirc_id(7),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
AT_CHECK([tail -1 stdout], [0],
[Datapath actions: set(ipv4(ttl=10)),100
])
@@ -337,10 +337,18 @@ OVS_VSWITCHD_START
add_of_ports br0 1 10
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=set_field:192.168.3.90->ip_src,output:10'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=group:1234,output:10'])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
-AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: set(ipv4(src=192.168.3.90,dst=192.168.0.2)),10,set(ipv4(src=192.168.0.1,dst=192.168.0.2)),10
+
+for d in 0 1 2 3; do
+ pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.1.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
+done
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/dp_hash(.*\/0xf)/dp_hash(0xXXXX\/0xf)/' | sed 's/packets.*actions:/actions:/' | strip_ufid | strip_used | sort], [0], [dnl
+flow-dump from non-dpdk interfaces:
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:hash(hash_l4(0)),recirc(0x1)
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.168.0.1,frag=no), actions:set(ipv4(src=192.168.3.90)),10,set(ipv4(src=192.168.0.1)),10
])
+
OVS_VSWITCHD_STOP
AT_CLEANUP
@@ -397,81 +405,245 @@ AT_CLEANUP
AT_SETUP([ofproto-dpif - select group])
+
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
+
+ovs-appctl vlog/set ofproto_dpif:file:dbg
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=output:10,bucket=output:11'])
+AT_CHECK([grep -A6 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1234
+ofproto_dpif|DBG|No selection method specified. Trying dp_hash.
+ofproto_dpif|DBG| Minimum weight: 1, total weight: 2
+ofproto_dpif|DBG| Using 16 hash values:
+ofproto_dpif|DBG| Bucket 0: weight=1, target=8.00 hits=8
+ofproto_dpif|DBG| Bucket 1: weight=1, target=8.00 hits=8
+ofproto_dpif|DBG|Use dp_hash with 16 hash values.
+])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
# Try a bunch of different flows and make sure that they get distributed
-# at least somewhat.
-for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
- AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=1,dl_src=50:54:00:00:00:07,dl_dst=50:54:00:00:00:0$d,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0"], [0], [stdout])
- tail -1 stdout >> results
+# # at least somewhat.
+for d in 0 1 2 3; do
+ for s in 1 2 3 4 ; do
+ pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.0.$s,dst=192.168.1.$d,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
+ done
done
-sort results | uniq -c
-AT_CHECK([sort results | uniq], [0],
- [Datapath actions: 10
-Datapath actions: 11
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | sort| sed 's/dp_hash(.*\/0xf)/dp_hash(0xXXXX\/0xf)/' | strip_ufid | strip_used], [0], [dnl
+flow-dump from non-dpdk interfaces:
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:15, bytes:1590, used:0.0s, actions:hash(hash_l4(0)),recirc(0x1)
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:212, used:0.0s, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:1, bytes:106, used:0.0s, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:2, bytes:212, used:0.0s, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:1, bytes:106, used:0.0s, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:10
])
+
OVS_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([ofproto-dpif - select group with watch port])
+
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=watch_port:10,output:10,bucket=output:11'])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:07,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
-AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: 11
+
+for d in 0 1 2 3; do
+ pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
+done
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | sort| sed 's/dp_hash(.*\/0xf)/dp_hash(0xXXXX\/0xf)/' | strip_ufid | strip_used], [0], [dnl
+flow-dump from non-dpdk interfaces:
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:3, bytes:318, used:0.0s, actions:hash(hash_l4(0)),recirc(0x1)
+recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:3, bytes:318, used:0.0s, actions:11
])
+
OVS_VSWITCHD_STOP
AT_CLEANUP
-AT_SETUP([ofproto-dpif - select group with weight])
+AT_SETUP([ofproto-dpif - select group with weights])
+
OVS_VSWITCHD_START
-add_of_ports br0 1 10 11 12
-AT_CHECK([ovs-ofctl -O OpenFlow12 add-group br0 'group_id=1234,type=select,bucket=output:10,bucket=output:11,weight=2000,bucket=output:12,weight=0'])
+add_of_ports br0 1 10 11 12 13 14
+
+ovs-appctl vlog/set ofproto_dpif:file:dbg
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-group br0 'group_id=1234,type=select,bucket=weight:5,output:10,bucket=weight:10,output:11,bucket=weight:25,output:12,bucket=weight:60,output:13,bucket=weight:0,output:14'])
+AT_CHECK([grep -A9 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1234
+ofproto_dpif|DBG|No selection method specified. Trying dp_hash.
+ofproto_dpif|DBG| Minimum weight: 5, total weight: 100
+ofproto_dpif|DBG| Using 32 hash values:
+ofproto_dpif|DBG| Bucket 0: weight=5, target=1.60 hits=2
+ofproto_dpif|DBG| Bucket 1: weight=10, target=3.20 hits=3
+ofproto_dpif|DBG| Bucket 2: weight=25, target=8.00 hits=8
+ofproto_dpif|DBG| Bucket 3: weight=60, target=19.20 hits=19
+ofproto_dpif|DBG| Bucket 4: weight=0, target=0.00 hits=0
+ofproto_dpif|DBG|Use dp_hash with 32 hash values.
+])
AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 'ip actions=write_actions(group:1234)'])
-AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:07,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'], [0], [stdout])
-AT_CHECK([tail -1 stdout], [0],
- [Datapath actions: 11
+
+# Try 1000 different flows and make sure that they get distributed according to weights
+for d1 in 0 1 2 3 4 5 6 7 8 9 ; do
+ for d2 in 0 1 2 3 4 5 6 7 8 9 ; do
+ for s in 0 1 2 3 4 5 6 7 8 9 ; do
+ pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.1.$s,dst=192.168.$d1.$d2,proto=6,tos=0,ttl=128,frag=no),tcp(src=1000,dst=1000)"
+ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
+ done
+ done
+done
+
+# Check balanced distribution over 32 dp_hash values
+AT_CHECK([ovs-appctl dpctl/dump-flows | sort| sed 's/dp_hash(.*\/0x1f)/dp_hash(0xXXXX\/0x1f)/' | strip_ufid | strip_used], [0], [dnl
+flow-dump from non-dpdk interfaces:
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:117882, used:0.0s, actions:hash(hash_l4(0)),recirc(0x1)
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:36, bytes:4248, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:33, bytes:3894, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:30, bytes:3540, used:0.0s, actions:10
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:28, bytes:3304, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:36, bytes:4248, used:0.0s, actions:12
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:32, bytes:3776, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:31, bytes:3658, used:0.0s, actions:12
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:25, bytes:2950, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:36, bytes:4248, used:0.0s, actions:12
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:30, bytes:3540, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:25, bytes:2950, used:0.0s, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:39, bytes:4602, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:26, bytes:3068, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:35, bytes:4130, used:0.0s, actions:12
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:29, bytes:3422, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:28, bytes:3304, used:0.0s, actions:10
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:35, bytes:4130, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:31, bytes:3658, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:29, bytes:3422, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:16, bytes:1888, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:32, bytes:3776, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:32, bytes:3776, used:0.0s, actions:12
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:27, bytes:3186, used:0.0s, actions:12
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:31, bytes:3658, used:0.0s, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:22, bytes:2596, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:33, bytes:3894, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:27, bytes:3186, used:0.0s, actions:11
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:33, bytes:3894, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:35, bytes:4130, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:33, bytes:3894, used:0.0s, actions:13
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:25, bytes:2950, used:0.0s, actions:12
+recirc_id(0x1),dp_hash(0xXXXX/0x1f),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:28, bytes:3304, used:0.0s, actions:12
+])
+
+# Check that actual distribution over the buckets is reasonably accurate:
+# weights: bucket0: 5%*1000 = 50, bucket1: 10%*1000 = 100, bucket2: 25%*1000 = 250, bucket3: 60%*1000 = 600, bucket4: 0
+# dp_hash: bucket0: 2/32*1000 = 63, bucket1: 3/32*1000 = 94, bucket2: 8/32*1000 = 250, bucket3: 19/32*1000 = 594, bucket4: 0
+ovs-appctl time/warp 1000
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-group-stats br0 | sed 's/duration=[[0-9]]\.[[0-9]]*s,//'], [0], [dnl
+OFPST_GROUP reply (OF1.3) (xid=0x6):
+ group_id=1234,ref_count=1,packet_count=1000,byte_count=118000,bucket0:packet_count=60,byte_count=7080,bucket1:packet_count=86,byte_count=10148,bucket2:packet_count=258,byte_count=30444,bucket3:packet_count=596,byte_count=70328,bucket4:packet_count=0,byte_count=0
])
+
OVS_VSWITCHD_STOP
AT_CLEANUP
-AT_SETUP([ofproto-dpif - select group with hash selection method])
+AT_SETUP([ofproto-dpif - select group with explicit dp_hash selection method])
+
OVS_VSWITCHD_START
add_of_ports br0 1 10 11
-# Check that parse failures after 'fields' parsing work
-AT_CHECK([ovs-ofctl -O OpenFlow10 add-group br0 'group_id=1,type=select,fields(eth_dst),bukket=output:10'], [1], ,[dnl
-ovs-ofctl: unknown keyword bukket
+
+ovs-appctl vlog/set ofproto_dpif:file:dbg
+AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=dp_hash,bucket=output:10,bucket=output:11'])
+AT_CHECK([grep -A5 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1234
+ofproto_dpif|DBG|Selection method specified: dp_hash.
+ofproto_dpif|DBG| Minimum weight: 1, total weight: 2
+ofproto_dpif|DBG| Using 16 hash values:
+ofproto_dpif|DBG| Bucket 0: weight=1, target=8.00 hits=8
+ofproto_dpif|DBG| Bucket 1: weight=1, target=8.00 hits=8
])
-AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=hash,fields(eth_dst,ip_dst,tcp_dst),bucket=output:10,bucket=output:11'])
+
+# Fall back to legacy hash with zero buckets
+AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1235,type=select,selection_method=dp_hash'])
+AT_CHECK([grep -A3 "Constructing select group 1235" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1235
+ofproto_dpif|DBG|Selection method specified: dp_hash.
+ofproto_dpif|DBG| Don't apply dp_hash method without buckets
+ofproto_dpif|DBG|Falling back to default hash method.
+])
+
+# Fall back to legacy hash with zero buckets
+AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1236,type=select,selection_method=dp_hash,bucket=weight=1,output:10,bucket=weight=1000,output:11'])
+AT_CHECK([grep -A4 "Constructing select group 1236" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1236
+ofproto_dpif|DBG|Selection method specified: dp_hash.
+ofproto_dpif|DBG| Minimum weight: 1, total weight: 1001
+ofproto_dpif|DBG| Too many hash values required: 1024
+ofproto_dpif|DBG|Falling back to default hash method.
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - select group with legacy hash selection method])
+
+OVS_VSWITCHD_START
+add_of_ports br0 1 10 11
+
+ovs-appctl vlog/set ofproto_dpif:file:dbg
+AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=hash,bucket=output:10,bucket=output:11'])
+AT_CHECK([grep -A2 "Constructing select group 1234" ovs-vswitchd.log | sed 's/^.*ofproto_dpif/ofproto_dpif/'], [0], [dnl
+ofproto_dpif|DBG|Constructing select group 1234
+ofproto_dpif|DBG|Selection method specified: hash.
+ofproto_dpif|DBG|No hash fields. Falling back to default hash method.
+])
+
AT_CHECK([ovs-ofctl -O OpenFlow15 add-flow br0 'ip actions=write_actions(group:1234)'])
# Try a bunch of different flows and make sure that they get distributed
# at least somewhat.
-for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
- AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=1,dl_src=50:54:00:00:00:07,dl_dst=50:54:00:00:00:0$d,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0"], [0], [stdout])
- tail -1 stdout >> results
+for d in 0 1 2 3; do
+ for s in 1 2 3 4 ; do
+ pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:1),eth_type(0x0800),ipv4(src=192.168.0.$s,dst=192.168.1.$d,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+ AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
+ done
done
-sort results | uniq -c
-AT_CHECK([sort results | uniq], [0],
- [Datapath actions: 10
-Datapath actions: 11
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | strip_ufid | strip_used | sort], [0], [dnl
+flow-dump from non-dpdk interfaces:
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.1.0,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.1.1,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.1.2,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.1.3,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.1.0,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.1.1,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.1.2,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.1.3,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.3,dst=192.168.1.0,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.3,dst=192.168.1.1,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.3,dst=192.168.1.2,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.3,dst=192.168.1.3,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.4,dst=192.168.1.0,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.4,dst=192.168.1.1,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.4,dst=192.168.1.2,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.4,dst=192.168.1.3,proto=1,frag=no),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions:10
])
-> results
-# Try a bunch of different flows and make sure that they are not distributed
-# as they only vary a field that is not hashed
-for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
- AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=1,dl_src=50:54:00:00:00:0$d,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0"], [0], [stdout])
- tail -1 stdout >> results
-done
-sort results | uniq -c
-AT_CHECK([sort results | uniq | sed 's/1[[01]]/1?/'], [0],
- [Datapath actions: 1?
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - select group with custom hash selection method])
+
+OVS_VSWITCHD_START
+add_of_ports br0 1 10 11
+
+# Check that parse failures after 'fields' parsing work
+AT_CHECK([ovs-ofctl -O OpenFlow10 add-group br0 'group_id=1,type=select,fields(eth_dst),bukket=output:10'], [1], ,[dnl
+ovs-ofctl: unknown keyword bukket
])
# Check that fields are rejected without "selection_method=hash".
@@ -484,35 +656,41 @@ AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1235,type=select,selec
ovs-ofctl: selection_method_param is only allowed with "selection_method"
])
-OVS_VSWITCHD_STOP
-AT_CLEANUP
-
-AT_SETUP([ofproto-dpif - select group with dp_hash selection method])
-OVS_VSWITCHD_START
-add_of_ports br0 1 10 11
-AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=dp_hash,bucket=output:10,bucket=output:11'])
-AT_CHECK([ovs-ofctl -O OpenFlow15 add-flow br0 'ip,nw_src=192.168.0.1 actions=group:1234'])
+AT_CHECK([ovs-ofctl -O OpenFlow15 add-group br0 'group_id=1234,type=select,selection_method=hash,fields(eth_dst,ip_dst,tcp_dst),bucket=output:10,bucket=output:11'])
+AT_CHECK([ovs-ofctl -O OpenFlow15 add-flow br0 'ip actions=write_actions(group:1234)'])
-# Try a bunch of different flows and make sure that they get distributed
-# at least somewhat.
-for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
- pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.1.$d,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
+# Try a bunch of flows with differing custom hash and make sure that they
+# get distributed at least somewhat.
+for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+ pkt="in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:$d),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)"
AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
done
-AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/dp_hash(.*\/0xf)/dp_hash(0xXXXX\/0xf)/' | sed 's/packets.*actions:1/actions:1/' | strip_ufid | strip_used | sort], [0], [dnl
+AT_CHECK([ovs-appctl dpctl/dump-flows | strip_ufid | strip_used | sort], [0], [dnl
flow-dump from non-dpdk interfaces:
-recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.168.0.1,frag=no), packets:15, bytes:1590, used:0.0s, actions:hash(hash_l4(0)),recirc(0x1)
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:10
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:10
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:10
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:10
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:10
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:10
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:11
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:11
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:11
-recirc_id(0x1),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:00),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:01),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:02),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:03),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:04),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:06),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:08),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0b),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0d),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0e),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:10
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0f),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:0, bytes:0, used:never, actions:11
+])
+
+ovs-appctl time/warp 1000
+ovs-appctl time/warp 1000
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-group-stats br0 | sed 's/duration=[[0-9]]\.[[0-9]]*s,//'], [0], [dnl
+OFPST_GROUP reply (OF1.3) (xid=0x6):
+ group_id=1234,ref_count=1,packet_count=16,byte_count=1696,bucket0:packet_count=8,byte_count=848,bucket1:packet_count=8,byte_count=848
])
AT_CHECK([ovs-appctl revalidator/purge], [0])
@@ -524,10 +702,16 @@ for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
AT_CHECK([ovs-appctl netdev-dummy/receive p1 $pkt])
done
-AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/dp_hash(.*\/0xf)/dp_hash(0xXXXX\/0xf)/' | sed 's/\(actions:1\)[[01]]/\1X/' | strip_ufid | strip_used | sort], [0], [dnl
+AT_CHECK([ovs-appctl dpctl/dump-flows | strip_ufid | strip_used | sort], [0], [dnl
flow-dump from non-dpdk interfaces:
-recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.168.0.1,frag=no), packets:15, bytes:1590, used:0.0s, actions:hash(hash_l4(0)),recirc(0x2)
-recirc_id(0x2),dp_hash(0xXXXX/0xf),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:15, bytes:1590, used:0.0s, actions:1X
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(dst=192.168.0.2,proto=1,frag=no), packets:15, bytes:1590, used:0.0s, actions:10
+])
+
+ovs-appctl time/warp 1000
+ovs-appctl time/warp 1000
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-group-stats br0 | sed 's/duration=[[0-9]]\.[[0-9]]*s,//'], [0], [dnl
+OFPST_GROUP reply (OF1.3) (xid=0x6):
+ group_id=1234,ref_count=1,packet_count=32,byte_count=3392,bucket0:packet_count=24,byte_count=2544,bucket1:packet_count=8,byte_count=848
])
OVS_VSWITCHD_STOP
@@ -2122,28 +2122,23 @@ The selection method used to select a bucket for a select group.
This is a string of 1 to 15 bytes in length known to lower layers.
This field is optional for \fBadd\-group\fR, \fBadd\-groups\fR and
\fBmod\-group\fR commands on groups of type \fBselect\fR. Prohibited
-otherwise. The default value is the empty string.
+otherwise. If no selection method is specified, Open vSwitch up to
+release 2.9 applies the \fBhash\fR method with default fields. From
+2.10 onwards Open vSwitch defaults to the \fBdp_hash\fR method with symmetric
+L3/L4 hash algorithm, unless the weighted group buckets cannot be mapped to
+a maximum of 64 dp_hash values with sufficient accuracy.
+In those rare cases Open vSwitch 2.10 and later fall back to the \fBhash\fR
+method with the default set of hash fields.
.RS
-.IP \fBhash\fR
-Use a hash computed over the fields specified with the \fBfields\fR
-option, see below. \fBhash\fR uses the \fBselection_method_param\fR
-as the hash basis.
-.IP
-Note that the hashed fields become exact matched by the datapath
-flows. For example, if the TCP source port is hashed, the created
-datapath flows will match the specific TCP source port value present
-in the packet received. Since each TCP connection generally has a
-different source port value, a separate datapath flow will be need to
-be inserted for each TCP connection thus hashed to a select group
-bucket.
.IP \fBdp_hash\fR
Use a datapath computed hash value. The hash algorithm varies accross
different datapath implementations. \fBdp_hash\fR uses the upper 32
bits of the \fBselection_method_param\fR as the datapath hash
-algorithm selector, which currently must always be 0, corresponding to
-hash computation over the IP 5-tuple (selecting specific fields with
-the \fBfields\fR option is not allowed with \fBdp_hash\fR). The lower
-32 bits are used as the hash basis.
+algorithm selector. The supported values are \fB0\fR (corresponding to
+hash computation over the IP 5-tuple) and \fB1\fR (corresponding to a
+\fIsymmetric\fR hash computation over the IP 5-tuple). Selecting specific
+fields with the \fBfields\fR option is not supported with \fBdp_hash\fR).
+The lower 32 bits are used as the hash basis.
.IP
Using \fBdp_hash\fR has the advantage that it does not require the
generated datapath flows to exact match any additional packet header
@@ -2157,9 +2152,23 @@ when needed, and a second match is required to match some bits of its
value. This double-matching incurs a small additional latency cost
for each packet, but this latency is orders of magnitude less than the
latency of creating new datapath flows for new TCP connections.
+.IP \fBhash\fR
+Use a hash computed over the fields specified with the \fBfields\fR
+option, see below. If no hash fields are specified, \fBhash\fR defaults
+to a symmetric hash over the combination of MAC addresses, VLAN tags,
+Ether type, IP addresses and L4 port numbers. \fBhash\fR uses the
+\fBselection_method_param\fR as the hash basis.
+.IP
+Note that the hashed fields become exact matched by the datapath
+flows. For example, if the TCP source port is hashed, the created
+datapath flows will match the specific TCP source port value present
+in the packet received. Since each TCP connection generally has a
+different source port value, a separate datapath flow will be need to
+be inserted for each TCP connection thus hashed to a select group
+bucket.
.RE
.IP
-This option will use a Netronome OpenFlow extension which is only supported
+This option uses a Netronome OpenFlow extension which is only supported
when using Open vSwitch 2.4 and later with OpenFlow 1.5 and later.
.IP \fBselection_method_param\fR=\fIparam\fR
@@ -2169,7 +2178,7 @@ lower-layer that implements the \fBselection_method\fR. It is optional if
the \fBselection_method\fR field is specified as a non-empty string.
Prohibited otherwise. The default value is zero.
.IP
-This option will use a Netronome OpenFlow extension which is only supported
+This option uses a Netronome OpenFlow extension which is only supported
when using Open vSwitch 2.4 and later with OpenFlow 1.5 and later.
.IP \fBfields\fR=\fIfield\fR