[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