summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Horman <simon.horman@netronome.com>2015-03-20 13:50:33 +0900
committerBen Pfaff <blp@nicira.com>2015-03-24 09:22:56 -0700
commitb879391e0f2fed8e52ae20ad21ad8ae52cea8363 (patch)
tree20a8af58ef53c13ce971de45b486471006e59d05
parent7565c3e4fe1f98f5eb1a4b2151ef3d22ceb37b00 (diff)
downloadopenvswitch-b879391e0f2fed8e52ae20ad21ad8ae52cea8363.tar.gz
Support NTR selection method in ovs-ofctl group commands
NTR selection method Signed-off-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: Ben Pfaff <blp@nicira.com>
-rw-r--r--lib/ofp-parse.c94
-rw-r--r--tests/ofproto.at4
-rw-r--r--utilities/ovs-ofctl.8.in34
3 files changed, 130 insertions, 2 deletions
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 8d05681d6..8fce546f4 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -1158,6 +1158,67 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
}
static char * OVS_WARN_UNUSED_RESULT
+parse_select_group_field(char *s, struct field_array *fa,
+ enum ofputil_protocol *usable_protocols)
+{
+ char *save_ptr = NULL;
+ char *name;
+
+ for (name = strtok_r(s, "=, \t\r\n", &save_ptr); name;
+ name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
+ const struct mf_field *mf = mf_from_name(name);
+
+ if (mf) {
+ char *error;
+ const char *value_str;
+ union mf_value value;
+
+ if (bitmap_is_set(fa->used.bm, mf->id)) {
+ return xasprintf("%s: duplicate field", name);
+ }
+
+ value_str = strtok_r(NULL, ", \t\r\n", &save_ptr);
+ if (value_str) {
+ error = mf_parse_value(mf, value_str, &value);
+ if (error) {
+ return error;
+ }
+
+ /* The mask cannot be all-zeros */
+ if (is_all_zeros(&value, mf->n_bytes)) {
+ return xasprintf("%s: values are wildcards here "
+ "and must not be all-zeros", s);
+ }
+
+ /* The values parsed are masks for fields used
+ * by the selection method */
+ if (!mf_is_mask_valid(mf, &value)) {
+ return xasprintf("%s: invalid mask for field %s",
+ value_str, mf->name);
+ }
+ } else {
+ memset(&value, 0xff, mf->n_bytes);
+ }
+
+ field_array_set(mf->id, &value, fa);
+
+ if (is_all_ones(&value, mf->n_bytes)) {
+ *usable_protocols &= mf->usable_protocols_exact;
+ } else if (mf->usable_protocols_bitwise == mf->usable_protocols_cidr
+ || ip_is_cidr(value.be32)) {
+ *usable_protocols &= mf->usable_protocols_cidr;
+ } else {
+ *usable_protocols &= mf->usable_protocols_bitwise;
+ }
+ } else {
+ return xasprintf("%s: unknown field %s", s, name);
+ }
+ }
+
+ return NULL;
+}
+
+static char * OVS_WARN_UNUSED_RESULT
parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
char *string,
enum ofputil_protocol *usable_protocols)
@@ -1327,6 +1388,39 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
} else if (!strcmp(name, "bucket")) {
error = xstrdup("bucket is not needed");
goto out;
+ } else if (!strcmp(name, "selection_method")) {
+ if (!(fields & F_GROUP_TYPE)) {
+ error = xstrdup("selection method is not needed");
+ goto out;
+ }
+ if (strlen(value) >= NTR_MAX_SELECTION_METHOD_LEN) {
+ error = xasprintf("selection method is longer than %u"
+ " bytes long",
+ NTR_MAX_SELECTION_METHOD_LEN - 1);
+ goto out;
+ }
+ memset(gm->props.selection_method, '\0',
+ NTR_MAX_SELECTION_METHOD_LEN);
+ strcpy(gm->props.selection_method, value);
+ *usable_protocols &= OFPUTIL_P_OF15_UP;
+ } else if (!strcmp(name, "selection_method_param")) {
+ if (!(fields & F_GROUP_TYPE)) {
+ error = xstrdup("selection method param is not needed");
+ goto out;
+ }
+ error = str_to_u64(value, &gm->props.selection_method_param);
+ *usable_protocols &= OFPUTIL_P_OF15_UP;
+ } else if (!strcmp(name, "fields")) {
+ if (!(fields & F_GROUP_TYPE)) {
+ error = xstrdup("fields are not needed");
+ goto out;
+ }
+ error = parse_select_group_field(value, &gm->props.fields,
+ usable_protocols);
+ if (error) {
+ goto out;
+ }
+ *usable_protocols &= OFPUTIL_P_OF15_UP;
} else {
error = xasprintf("unknown keyword %s", name);
goto out;
diff --git a/tests/ofproto.at b/tests/ofproto.at
index a3f5e2a1d..62629c099 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -338,14 +338,14 @@ dnl Actions definition listed in both supported formats (w/ actions=)
AT_SETUP([ofproto - del group (OpenFlow 1.5)])
OVS_VSWITCHD_START
AT_DATA([groups.txt], [dnl
-group_id=1234,type=all,bucket=output:10,bucket=output:11
+group_id=1234,type=select,selection_method=hash,bucket=output:10,bucket=output:11
group_id=1235,type=all,bucket=actions=output:12,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
])
AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn add-groups br0 groups.txt])
AT_CHECK([ovs-ofctl -F OXM-OpenFlow15 -O OpenFlow15 -vwarn dump-groups br0 1234], [0], [stdout])
AT_CHECK([STRIP_XIDS stdout], [0], [dnl
OFPST_GROUP_DESC reply (OF1.5):
- group_id=1234,type=all,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
+ group_id=1234,type=select,selection_method=hash,bucket=bucket_id:0,actions=output:10,bucket=bucket_id:1,actions=output:11
])
AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn del-groups br0 group_id=1234])
AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn dump-groups br0], [0], [stdout])
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 7aee788b0..ea3337b93 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -2248,6 +2248,40 @@ remove the in the group whose \fBbucket_id\fR is \fIid\fR.
It is an error if there is no bucket persent group in whose \fBbucket_id\fR is
\fIid\fR.
+.IP \fBselection_method\fR=\fImethod\fR
+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.
+.IP
+This option will use 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
+64-bit integer parameter to the selection method selected by the
+\fBselection_method\fR field. The parameter's use is defined by the
+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
+when using Open vSwitch 2.4 and later with OpenFlow 1.5 and later.
+
+.IP \fBfields\fR=\fIparam\fR
+The field parameters to selection method selected by the
+\fBselection_method\fR field. The syntax is described in \fBFlow Syntax\fR
+with the additional restrictions that if a value is provided it is
+treated as a wildcard mask and wildcard masks following a slash are
+prohibited. The pre-requisites of fields must be provided by any flows that
+output to the group. The use of the fields is defined by the lower-layer
+that implements the \fBselection_method\fR. They are optional if the
+\fBselection_method\fR field is specified as a non-empty string.
+Prohibited otherwise. The default is no fields.
+.IP
+This option will use a Netronome OpenFlow extension which is only supported
+when using Open vSwitch 2.4 and later with OpenFlow 1.5 and later.
+
.IP \fBbucket\fR=\fIbucket_parameters\fR
The \fBadd-group\fR, \fBadd-groups\fR and \fBmod-group\fR commands
require at least one bucket field. Bucket fields must appear after