From f5c45121cf59ef3099ba669c3590d844bedf53e9 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 28 Sep 2012 14:59:10 +0900 Subject: [PATCH] ofp-actions: Add parsing of set_field actions Based heavily on work by Isaku Yamahata Cc: Isaku Yamahata Signed-off-by: Simon Horman [blp@nicira.com adjusted documentation, added test] Signed-off-by: Ben Pfaff --- 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 ++++++++++ tests/ovs-ofctl.at | 2 ++ utilities/ovs-ofctl.8.in | 9 ++++++++ 8 files changed, 82 insertions(+), 10 deletions(-) diff --git a/lib/nx-match.c b/lib/nx-match.c index 6ea06425..4254747d 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 7da42437..a58f8dba 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 46e2d79a..fd53e62c 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 e3b7dc12..2d2daa41 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -314,6 +314,48 @@ parse_dec_ttl(struct ofpbuf *b, char *arg) ofpact_update_len(b, &ids->ofpact); } +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 79ae01db..4d451b05 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 af7b7ca5..fb82e017 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/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index 947f9852..81858275 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -10,6 +10,7 @@ tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:1 udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1 cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note +actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src ]]) AT_CHECK([ovs-ofctl parse-flows flows.txt @@ -24,6 +25,7 @@ OFPT_FLOW_MOD: ADD tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output: OFPT_FLOW_MOD: ADD udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1 OFPT_FLOW_MOD: ADD priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTROLLER:65535 OFPT_FLOW_MOD: ADD actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00 +OFPT_FLOW_MOD: ADD actions=load:0xa6badbfffefe59fa->NXM_NX_IPV6_SRC[0..63],load:0xfe8001234567890a->NXM_NX_IPV6_SRC[64..127] ]]) AT_CLEANUP diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index be71f184..4f62c666 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -1005,6 +1005,15 @@ 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" +Writes the literal \fIvalue\fR into the field \fIdst\fR, which should +be specified as a name used for matching. (This is similar to +\fBload\fR but more closely matches the set-field action defined in +Open Flow 1.2 and above.) +. +.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 -- 2.30.2