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);
}
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);
+}
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 */
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)
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:
//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)
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])
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
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
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