[ovs-dev] [PATCH/RFC v2 8/8] Implement hash fields select group
Simon Horman
simon.horman at netronome.com
Fri Jan 30 02:41:56 UTC 2015
This is intended as a usable demonstration of how
the NMX selection method extension might may be used.
NMX selection method
Signed-off-by: Simon Horman <simon.horman at netronome.com>
---
v2 Use list of struct field_array of TLVs rather than OF1.1 match
for fields field of NMX selection method property
---
lib/nx-match.c | 2 +-
lib/nx-match.h | 3 +++
ofproto/ofproto-dpif-xlate.c | 43 +++++++++++++++++++++++++++++++++++++++++++
ofproto/ofproto-dpif.c | 12 ++++++++++++
ofproto/ofproto-dpif.h | 2 ++
tests/ofproto-dpif.at | 20 ++++++++++++++++++++
6 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/lib/nx-match.c b/lib/nx-match.c
index a9b9dfd..2673084 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -414,7 +414,7 @@ nx_pull_header(struct ofpbuf *b, const struct mf_field **field, bool *masked)
return error;
}
-static enum ofperr
+enum ofperr
nx_pull_match_entry(struct ofpbuf *b, bool allow_cookie,
const struct mf_field **field,
union mf_value *value, union mf_value *mask)
diff --git a/lib/nx-match.h b/lib/nx-match.h
index 1764aee..033daed 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -71,6 +71,9 @@ enum ofperr nx_pull_entry(struct ofpbuf *, const struct mf_field **,
union mf_value *value, union mf_value *mask);
enum ofperr nx_pull_header(struct ofpbuf *, const struct mf_field **,
bool *masked);
+enum ofperr nx_pull_match_entry(struct ofpbuf *b, bool allow_cookie,
+ const struct mf_field **field,
+ union mf_value *value, union mf_value *mask);
void nx_put_entry(struct ofpbuf *, enum mf_field_id, enum ofp_version,
const union mf_value *value, const union mf_value *mask);
void nx_put_header(struct ofpbuf *, enum mf_field_id, enum ofp_version,
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 5b669d6..a03544d 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -34,6 +34,7 @@
#include "dpif.h"
#include "dynamic-string.h"
#include "in-band.h"
+#include "jhash.h"
#include "lacp.h"
#include "learn.h"
#include "list.h"
@@ -3038,6 +3039,46 @@ xlate_default_select_group(struct xlate_ctx *ctx, struct group_dpif *group)
}
}
+static void
+xlate_hash_fields_select_group(struct xlate_ctx *ctx, struct group_dpif *group)
+{
+ struct flow_wildcards *wc = &ctx->xout->wc;
+ uint64_t selection_method_param;
+ struct ofputil_bucket *bucket;
+ const struct ovs_list *fields;
+ const struct field_array *fa;
+ struct flow flow;
+ uint32_t basis;
+
+ fields = group_dpif_get_fields(group);
+ flow = ctx->xin->flow;
+
+ LIST_FOR_EACH (fa, list_node, fields) {
+ int i;
+ union mf_value value;
+ const struct mf_field *mf = mf_from_id(fa->id);
+
+ mf_get_value(mf, &flow, &value);
+ /* This seems inefficient but so is apply_mask() */
+ for (i = 0; i < mf->n_bytes; i++) {
+ ((uint8_t *) &value)[i] &= ((uint8_t *) &fa->value)[i];
+ }
+ mf_set_flow_value(mf, &value, &flow);
+
+ mf_mask_field(mf, &wc->masks);
+ }
+
+ selection_method_param = group_dpif_get_selection_method_param(group);
+
+ basis = (uint32_t)(selection_method_param & 0xffffffff);
+ basis = jhash_bytes(&flow, sizeof flow, basis);
+ bucket = group_best_live_bucket(ctx, group, basis);
+ if (bucket) {
+ xlate_group_bucket(ctx, bucket);
+ xlate_group_stats(ctx, group, bucket);
+ }
+}
+
static bool
xlate_select_group(struct xlate_ctx *ctx, struct group_dpif *group)
{
@@ -3045,6 +3086,8 @@ xlate_select_group(struct xlate_ctx *ctx, struct group_dpif *group)
if (selection_method[0] == '\0') {
xlate_default_select_group(ctx, group);
+ } else if (!strcasecmp("hash", selection_method)) {
+ xlate_hash_fields_select_group(ctx, group);
} else {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 443f6d4..336ff5e 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -4170,6 +4170,18 @@ group_dpif_get_selection_method(const struct group_dpif *group)
{
return group->up.selection_method;
}
+
+uint64_t
+group_dpif_get_selection_method_param(const struct group_dpif *group)
+{
+ return group->up.selection_method_param;
+}
+
+const struct ovs_list *
+group_dpif_get_fields(const struct group_dpif *group)
+{
+ return &group->up.fields;
+}
/* Sends 'packet' out 'ofport'.
* May modify 'packet'.
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index 8b36a03..4139c84 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -138,6 +138,8 @@ void group_dpif_get_buckets(const struct group_dpif *group,
const struct ovs_list **buckets);
enum ofp11_group_type group_dpif_get_type(const struct group_dpif *group);
const char *group_dpif_get_selection_method(const struct group_dpif *group);
+uint64_t group_dpif_get_selection_method_param(const struct group_dpif *group);
+const struct ovs_list *group_dpif_get_fields(const struct group_dpif *group);
bool ofproto_has_vlan_splinters(const struct ofproto_dpif *);
ofp_port_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index e479e13..3efb462 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -403,6 +403,26 @@ AT_CHECK([tail -1 stdout], [0],
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([ofproto-dpif - select group with 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=hash,fields=eth_dst=ff:ff:ff:ff:ff:ff,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 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
+done
+sort results | uniq -c
+AT_CHECK([sort results | uniq], [0],
+ [Datapath actions: 10
+Datapath actions: 11
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([ofproto-dpif - fast failover group])
OVS_VSWITCHD_START
ADD_OF_PORTS([br0], [1], [10], [11])
--
2.1.4
More information about the dev
mailing list