[ovs-dev] [PATCH v3] ofp-actions: Add parsing of set_field actions
Simon Horman
horms at verge.net.au
Fri Sep 28 05:59:10 UTC 2012
Based heavily on work by Isaku Yamahata <yamahata at valinux.co.jp>
Cc: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Simon Horman <horms at verge.net.au>
--
v3
* Add entry to ovs-ofctl(8)
* Add test
v2
* Manual rebase
---
lib/nx-match.c | 7 +------
lib/ofp-actions.c | 12 ++++++++++++
lib/ofp-actions.h | 3 +++
lib/ofp-parse.c | 46 +++++++++++++++++++++++++++++++++++++++++++---
lib/ofp-util.def | 2 +-
tests/ofproto.at | 11 +++++++++++
utilities/ovs-ofctl.8.in | 13 +++++++++++++
7 files changed, 84 insertions(+), 10 deletions(-)
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 6ea0642..4254747 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -1119,12 +1119,7 @@ nxm_reg_load_from_openflow12_set_field(
return OFPERR_OFPBAC_BAD_ARGUMENT;
}
load = ofpact_put_REG_LOAD(ofpacts);
- load->ofpact.compat = OFPUTIL_OFPAT12_SET_FIELD;
- load->dst.field = mf;
- load->dst.ofs = 0;
- load->dst.n_bits = mf->n_bits;
- bitwise_copy(oasf + 1, mf->n_bytes, load->dst.ofs,
- &load->subvalue, sizeof load->subvalue, 0, mf->n_bits);
+ ofpact_set_field_init(load, mf, oasf + 1);
return nxm_reg_load_check(load, NULL);
}
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 7da4243..a58f8db 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1892,3 +1892,15 @@ ofpact_pad(struct ofpbuf *ofpacts)
ofpbuf_put_zeros(ofpacts, OFPACT_ALIGNTO - rem);
}
}
+
+void
+ofpact_set_field_init(struct ofpact_reg_load *load, const struct mf_field *mf,
+ const void *src)
+{
+ load->ofpact.compat = OFPUTIL_OFPAT12_SET_FIELD;
+ load->dst.field = mf;
+ load->dst.ofs = 0;
+ load->dst.n_bits = mf->n_bits;
+ bitwise_copy(src, mf->n_bytes, load->dst.ofs,
+ &load->subvalue, sizeof load->subvalue, 0, mf->n_bits);
+}
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 46e2d79..fd53e62 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -569,4 +569,7 @@ enum {
const char *ofpact_instruction_name_from_type(enum ovs_instruction_type type);
int ofpact_instruction_type_from_name(const char *name);
+void ofpact_set_field_init(struct ofpact_reg_load *load,
+ const struct mf_field *mf, const void *src);
+
#endif /* ofp-actions.h */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index e3b7dc1..2d2daa4 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -315,6 +315,48 @@ parse_dec_ttl(struct ofpbuf *b, char *arg)
}
static void
+set_field_parse(const char *arg, struct ofpbuf *ofpacts)
+{
+ char *orig = xstrdup(arg);
+ struct ofpact_reg_load *load = ofpact_put_REG_LOAD(ofpacts);
+ char *value;
+ char *delim;
+ char *key;
+ const struct mf_field *mf;
+ const char *error;
+ union mf_value mf_value;
+
+ value = orig;
+ delim = strstr(orig, "->");
+ if (!delim) {
+ ovs_fatal(0, "%s: missing `->'", orig);
+ }
+ if (strlen(delim) <= strlen("->")) {
+ ovs_fatal(0, "%s: missing field name following `->'", orig);
+ }
+
+ key = delim + strlen("->");
+ mf = mf_from_name(key);
+ if (!mf) {
+ ovs_fatal(0, "%s is not valid oxm field name", key);
+ }
+ if (!mf->writable) {
+ ovs_fatal(0, "%s is not allowed to set", key);
+ }
+
+ delim[0] = '\0';
+ error = mf_parse_value(mf, value, &mf_value);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
+ if (!mf_is_value_valid(mf, &mf_value)) {
+ ovs_fatal(0, "%s is not valid valid for field %s", value, key);
+ }
+ ofpact_set_field_init(load, mf, &mf_value);
+ free(orig);
+}
+
+static void
parse_named_action(enum ofputil_action_code code, const struct flow *flow,
char *arg, struct ofpbuf *ofpacts)
{
@@ -352,9 +394,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
break;
case OFPUTIL_OFPAT12_SET_FIELD:
- NOT_REACHED(); /* This will be implemented by later patch and
- * enabled using a non-NULL name in
- * OFPAT12_ACTION(OFPAT12_SET_FIELD, ...) */
+ set_field_parse(arg, ofpacts);
break;
case OFPUTIL_OFPAT10_STRIP_VLAN:
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index 79ae01d..4d451b0 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -35,7 +35,7 @@ OFPAT11_ACTION(OFPAT11_SET_TP_DST, ofp_action_tp_port, 0, "mod_tp_dst")
//OFPAT11_ACTION(OFPAT11_SET_QUEUE, ofp11_action_set_queue, 0, "set_queue")
//OFPAT11_ACTION(OFPAT11_SET_NW_TTL, ofp11_action_nw_ttl, 0, "set_nw_ttl")
//OFPAT11_ACTION(OFPAT11_DEC_NW_TTL, ofp_action_header, 0, "dec_ttl")
-OFPAT11_ACTION(OFPAT12_SET_FIELD, ofp12_action_set_field, 1, NULL)
+OFPAT11_ACTION(OFPAT12_SET_FIELD, ofp12_action_set_field, 1, "set_field")
#ifndef NXAST_ACTION
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME)
diff --git a/tests/ofproto.at b/tests/ofproto.at
index af7b7ca..fb82e01 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -148,6 +148,17 @@ AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip], [0], [OFPST_FLO
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([ofproto - set-field flow_mod commands (NXM)])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-ofctl add-flow br0 ipv6,table=1,in_port=3,actions=drop])
+AT_CHECK([ovs-ofctl add-flow br0 ipv6,table=1,in_port=3,actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa-\>ipv6_src])
+AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
+ table=1, ipv6,in_port=3 actions=load:0xa6badbfffefe59fa->NXM_NX_IPV6_SRC[[0..63]],load:0xfe8001234567890a->NXM_NX_IPV6_SRC[[64..127]]
+NXST_FLOW reply:
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_SETUP([ofproto - dump flows with cookie])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1])
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index be71f18..f4ea766 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1005,6 +1005,19 @@ in field \fIdst\fR.
Example: \fBload:55\->NXM_NX_REG2[0..5]\fR loads value 55 (bit pattern
\fB110111\fR) into bits 0 through 5, inclusive, in register 2.
.
+.IP "\fBset_field:\fIvalue\fB\->\fIdst"
+.
+This is similar to the first form of the load action
+and is provided in prepration for supporting the set-feild action
+defined in Open Flow 1.1 and above.
+.IP
+It writes the literal \fIvalue\fR into
+the field \fIdst\fR. The syntax differs from load as field names
+are the same as the coresponding match name.
+.
+.IP
+Example: \fBset_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa\->ipv6_src\fR
+.
.IP "\fBmultipath(\fIfields\fB, \fIbasis\fB, \fIalgorithm\fB, \fIn_links\fB, \fIarg\fB, \fIdst\fB[\fIstart\fB..\fIend\fB])\fR"
Hashes \fIfields\fR using \fIbasis\fR as a universal hash parameter,
then the applies multipath link selection \fIalgorithm\fR (with
--
1.7.10.4
More information about the dev
mailing list