Skip to content

Commit

Permalink
ofp-actions: Support "copy_field" ONF extension to OpenFlow 1.3.
Browse files Browse the repository at this point in the history
ONF-JIRA: EXT-320
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Thomas Graf <[email protected]>
  • Loading branch information
blp committed Dec 5, 2014
1 parent 232c1e1 commit 914624f
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 12 deletions.
1 change: 1 addition & 0 deletions build-aux/extract-ofp-actions
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ version_reverse_map = dict((v, k) for (k, v) in version_map.iteritems())

# Map from vendor name to the length of the action header.
vendor_map = {"OF": (0x00000000, 4),
"ONF": (0x4f4e4600, 10),
"NX": (0x00002320, 10)}

# Basic types used in action arguments.
Expand Down
76 changes: 67 additions & 9 deletions lib/ofp-actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ enum ofp_raw_action_type {

/* OF1.5+(28): struct ofp15_action_copy_field, ... */
OFPAT_RAW15_COPY_FIELD,
/* ONF1.3-1.4(3200): struct onf_action_copy_field, ... */
ONFACT_RAW13_COPY_FIELD,
/* NX1.0-1.4(6): struct nx_action_reg_move, ... */
NXAST_RAW_REG_MOVE,

Expand Down Expand Up @@ -1720,6 +1722,26 @@ struct ofp15_action_copy_field {
};
OFP_ASSERT(sizeof(struct ofp15_action_copy_field) == 16);

/* Action structure for OpenFlow 1.3 extension copy-field action.. */
struct onf_action_copy_field {
ovs_be16 type; /* OFPAT_EXPERIMENTER. */
ovs_be16 len; /* Length is padded to 64 bits. */
ovs_be32 experimenter; /* ONF_VENDOR_ID. */
ovs_be16 exp_type; /* 3200. */
uint8_t pad[2]; /* Not used. */
ovs_be16 n_bits; /* Number of bits to copy. */
ovs_be16 src_offset; /* Starting bit offset in source. */
ovs_be16 dst_offset; /* Starting bit offset in destination. */
uint8_t pad2[2]; /* Not used. */
/* Followed by:
* - OXM header for source field.
* - OXM header for destination field.
* - Padding with 0-bytes (either 0 or 4 of them) to a multiple of 8 bytes.
* The "pad3" member is the beginning of the above. */
uint8_t pad3[4]; /* Not used. */
};
OFP_ASSERT(sizeof(struct onf_action_copy_field) == 24);

/* Action structure for NXAST_REG_MOVE.
*
* Copies src[src_ofs:src_ofs+n_bits] to dst[dst_ofs:dst_ofs+n_bits], where
Expand Down Expand Up @@ -1828,21 +1850,23 @@ struct nx_action_reg_move {
OFP_ASSERT(sizeof(struct nx_action_reg_move) == 16);

static enum ofperr
decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
struct ofpbuf *ofpacts)
decode_copy_field__(ovs_be16 src_offset, ovs_be16 dst_offset, ovs_be16 n_bits,
const void *action, ovs_be16 action_len, size_t oxm_offset,
struct ofpbuf *ofpacts)
{
struct ofpact_reg_move *move;
enum ofperr error;
struct ofpbuf b;

move = ofpact_put_REG_MOVE(ofpacts);
move->src.ofs = ntohs(oacf->src_offset);
move->src.n_bits = ntohs(oacf->n_bits);
move->dst.ofs = ntohs(oacf->dst_offset);
move->dst.n_bits = ntohs(oacf->n_bits);

ofpbuf_use_const(&b, oacf, ntohs(oacf->len));
ofpbuf_pull(&b, offsetof(struct ofp15_action_copy_field, pad2));
move->ofpact.raw = ONFACT_RAW13_COPY_FIELD;
move->src.ofs = ntohs(src_offset);
move->src.n_bits = ntohs(n_bits);
move->dst.ofs = ntohs(dst_offset);
move->dst.n_bits = ntohs(n_bits);

ofpbuf_use_const(&b, action, ntohs(action_len));
ofpbuf_pull(&b, oxm_offset);
error = nx_pull_header(&b, &move->src.field, NULL);
if (error) {
return error;
Expand All @@ -1859,6 +1883,24 @@ decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
return nxm_reg_move_check(move, NULL);
}

static enum ofperr
decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
struct ofpbuf *ofpacts)
{
return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
oacf->n_bits, oacf, oacf->len,
OBJECT_OFFSETOF(oacf, pad2), ofpacts);
}

static enum ofperr
decode_ONFACT_RAW13_COPY_FIELD(const struct onf_action_copy_field *oacf,
struct ofpbuf *ofpacts)
{
return decode_copy_field__(oacf->src_offset, oacf->dst_offset,
oacf->n_bits, oacf, oacf->len,
OBJECT_OFFSETOF(oacf, pad3), ofpacts);
}

static enum ofperr
decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
struct ofpbuf *ofpacts)
Expand All @@ -1868,6 +1910,7 @@ decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
struct ofpbuf b;

move = ofpact_put_REG_MOVE(ofpacts);
move->ofpact.raw = NXAST_RAW_REG_MOVE;
move->src.ofs = ntohs(narm->src_ofs);
move->src.n_bits = ntohs(narm->n_bits);
move->dst.ofs = ntohs(narm->dst_ofs);
Expand All @@ -1894,6 +1937,12 @@ static void
encode_REG_MOVE(const struct ofpact_reg_move *move,
enum ofp_version ofp_version, struct ofpbuf *out)
{
/* For OpenFlow 1.3, the choice of ONFACT_RAW13_COPY_FIELD versus
* NXAST_RAW_REG_MOVE is somewhat difficult. Neither one is guaranteed to
* be supported by every OpenFlow 1.3 implementation. It would be ideal to
* probe for support. Until we have that ability, we currently prefer
* NXAST_RAW_REG_MOVE for backward compatibility with older Open vSwitch
* versions. */
size_t start_ofs = ofpbuf_size(out);
if (ofp_version >= OFP15_VERSION) {
struct ofp15_action_copy_field *copy = put_OFPAT15_COPY_FIELD(out);
Expand All @@ -1903,6 +1952,15 @@ encode_REG_MOVE(const struct ofpact_reg_move *move,
ofpbuf_set_size(out, ofpbuf_size(out) - sizeof copy->pad2);
nx_put_header(out, move->src.field->id, ofp_version, false);
nx_put_header(out, move->dst.field->id, ofp_version, false);
} else if (ofp_version == OFP13_VERSION
&& move->ofpact.raw == ONFACT_RAW13_COPY_FIELD) {
struct onf_action_copy_field *copy = put_ONFACT13_COPY_FIELD(out);
copy->n_bits = htons(move->dst.n_bits);
copy->src_offset = htons(move->src.ofs);
copy->dst_offset = htons(move->dst.ofs);
ofpbuf_set_size(out, ofpbuf_size(out) - sizeof copy->pad3);
nx_put_header(out, move->src.field->id, ofp_version, false);
nx_put_header(out, move->dst.field->id, ofp_version, false);
} else {
struct nx_action_reg_move *narm = put_NXAST_REG_MOVE(out);
narm->n_bits = htons(move->dst.n_bits);
Expand Down
28 changes: 28 additions & 0 deletions tests/ofp-actions.at
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,34 @@ AT_CHECK(
[0], [expout], [experr])
AT_CLEANUP

dnl Our primary goal here is to verify OpenFlow 1.3-specific changes,
dnl so the list of tests is short.
AT_SETUP([OpenFlow 1.3 action translation])
AT_KEYWORDS([ofp-actions OF1.3])
AT_DATA([test-data], [dnl
# actions=LOCAL
0000 0010 fffffffe 04d2 000000000000

dnl Check the Nicira extension form of "move".
# actions=move:NXM_OF_IN_PORT[]->NXM_OF_VLAN_TCI[]
ffff 0018 00002320 0006 0010 0000 0000 00000002 00000802

dnl Check the ONF extension form of "copy_field".
# actions=move:NXM_OF_IN_PORT[]->NXM_OF_VLAN_TCI[]
ffff 0020 4f4e4600 0c80 0000 0010 0000 0000 0000 00000002 00000802 00000000

])
sed '/^[[#&]]/d' < test-data > input.txt
sed -n 's/^# //p; /^$/p' < test-data > expout
sed -n 's/^& //p' < test-data > experr
AT_CAPTURE_FILE([input.txt])
AT_CAPTURE_FILE([expout])
AT_CAPTURE_FILE([experr])
AT_CHECK(
[ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-actions OpenFlow13 < input.txt],
[0], [expout], [experr])
AT_CLEANUP

dnl Our primary goal here is to verify that OpenFlow 1.5-specific changes,
dnl so the list of tests is short.
AT_SETUP([OpenFlow 1.5 action translation])
Expand Down
10 changes: 7 additions & 3 deletions utilities/ovs-ofctl.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -1442,9 +1442,13 @@ through 31, inclusive;
\fBmove:NXM_NX_REG0[0..15]\->NXM_OF_VLAN_TCI[]\fR copies the least
significant 16 bits of register 0 into the VLAN TCI field.
.IP
In OpenFlow 1.0 through 1.4, \fBmove\fR uses an Open vSwitch extension
to OpenFlow. In OpenFlow 1.5, \fBmove\fR uses the OpenFlow 1.5
(draft) standard \fBcopy_field\fR action.
In OpenFlow 1.0 through 1.4, \fBmove\fR ordinarily uses an Open
vSwitch extension to OpenFlow. In OpenFlow 1.5, \fBmove\fR uses the
OpenFlow 1.5 (draft) standard \fBcopy_field\fR action. The ONF has
also made \fBcopy_field\fR available as an extension to OpenFlow 1.3.
Open vSwitch 2.4 and later understands this extension and uses it if a
controller uses it, but for backward compatibility with older versions
of Open vSwitch, \fBovs\-ofctl\fR does not use it.
.
.IP "\fBset_field:\fIvalue\fR[/\fImask\fR]\fB\->\fIdst"
.IQ "\fBload:\fIvalue\fB\->\fIdst\fB[\fIstart\fB..\fIend\fB]"
Expand Down

0 comments on commit 914624f

Please sign in to comment.