Based heavily on work by Isaku Yamahata <yamah...@valinux.co.jp> Cc: Isaku Yamahata <yamah...@valinux.co.jp> Signed-off-by: Simon Horman <ho...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev