Skip to content

Commit

Permalink
ofp-actions: Add support for OpenFlow 1.5 (draft) Copy-Field action.
Browse files Browse the repository at this point in the history
ONF-JIRA: EXT-320
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Jarno Rajahalme <[email protected]>
  • Loading branch information
blp committed Aug 11, 2014
1 parent 65a8a59 commit 73178f2
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 12 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Post-v2.3.0
release. See ovs-vswitchd(8) for details.
- OpenFlow:
* OpenFlow 1.5 (draft) extended registers are now supported.
* OpenFlow 1.5 (draft) Copy-Field action is now supported.
* OpenFlow 1.3+ table features requests are now supported (read-only).


Expand Down
79 changes: 67 additions & 12 deletions lib/ofp-actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ enum ofp_raw_action_type {
/* NX1.0+(7): struct nx_action_reg_load. */
NXAST_RAW_REG_LOAD,

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

/* ## ------------------------- ## */
/* ## Nicira extension actions. ## */
/* ## ------------------------- ## */
Expand All @@ -225,9 +230,6 @@ enum ofp_raw_action_type {
/* NX1.0+(5): void. */
NXAST_RAW_POP_QUEUE,

/* NX1.0+(6): struct nx_action_reg_move. */
NXAST_RAW_REG_MOVE,

/* NX1.0+(8): struct nx_action_note, ... */
NXAST_RAW_NOTE,

Expand Down Expand Up @@ -1622,6 +1624,26 @@ format_SET_L4_DST_PORT(const struct ofpact_l4_port *a, struct ds *s)
ds_put_format(s, "mod_tp_dst:%d", a->port);
}

/* Action structure for OFPAT_COPY_FIELD. */
struct ofp15_action_copy_field {
ovs_be16 type; /* OFPAT_COPY_FIELD. */
ovs_be16 len; /* Length is padded to 64 bits. */
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. */
ovs_be16 oxm_id_len; /* Length of oxm_ids. */

/* OpenFlow allows for experimenter OXM fields whose expression is longer
* than a standard 32-bit OXM. Thus, in the OpenFlow specification, the
* following is variable-length. Open vSwitch does not yet support
* experimenter OXM fields, so until it does we leave these as fixed
* size. */
ovs_be32 src; /* OXM for source field. */
ovs_be32 dst; /* OXM for destination field. */
uint8_t pad[4]; /* Must be zero. */
};
OFP_ASSERT(sizeof(struct ofp15_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 @@ -1727,6 +1749,28 @@ struct nx_action_reg_move {
};
OFP_ASSERT(sizeof(struct nx_action_reg_move) == 24);

static enum ofperr
decode_OFPAT_RAW15_COPY_FIELD(const struct ofp15_action_copy_field *oacf,
struct ofpbuf *ofpacts)
{
struct ofpact_reg_move *move;

if (oacf->oxm_id_len != htons(8)) {
/* We only support 4-byte OXM IDs so far. */
return OFPERR_OFPBAC_BAD_LEN;
}

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

return nxm_reg_move_check(move, NULL);
}

static enum ofperr
decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,
struct ofpbuf *ofpacts)
Expand All @@ -1746,17 +1790,28 @@ decode_NXAST_RAW_REG_MOVE(const struct nx_action_reg_move *narm,

static void
encode_REG_MOVE(const struct ofpact_reg_move *move,
enum ofp_version ofp_version OVS_UNUSED,
struct ofpbuf *out)
enum ofp_version ofp_version, struct ofpbuf *out)
{
struct nx_action_reg_move *narm;
if (ofp_version >= OFP15_VERSION) {
struct ofp15_action_copy_field *copy;

narm = put_NXAST_REG_MOVE(out);
narm->n_bits = htons(move->dst.n_bits);
narm->src_ofs = htons(move->src.ofs);
narm->dst_ofs = htons(move->dst.ofs);
narm->src = htonl(move->src.field->nxm_header);
narm->dst = htonl(move->dst.field->nxm_header);
copy = put_OFPAT15_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);
copy->oxm_id_len = htons(8);
copy->src = htonl(mf_oxm_header(move->src.field->id, ofp_version));
copy->dst = htonl(mf_oxm_header(move->dst.field->id, ofp_version));
} else {
struct nx_action_reg_move *narm;

narm = put_NXAST_REG_MOVE(out);
narm->n_bits = htons(move->dst.n_bits);
narm->src_ofs = htons(move->src.ofs);
narm->dst_ofs = htons(move->dst.ofs);
narm->src = htonl(move->src.field->nxm_header);
narm->dst = htonl(move->dst.field->nxm_header);
}
}

static char * WARN_UNUSED_RESULT
Expand Down
24 changes: 24 additions & 0 deletions tests/ofp-actions.at
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,30 @@ AT_CHECK(
[0], [expout], [experr])
AT_CLEANUP

dnl Our primary goal here is to verify that the copy_field action gets
dnl used instead of the Nicira extension reg_move in OpenFlow 1.5, so
dnl the list of action tests is very short.
AT_SETUP([OpenFlow 1.5 action translation])
AT_KEYWORDS([ofp-actions OF1.5])
AT_DATA([test-data], [dnl
# actions=LOCAL
0000 0010 fffffffe 04d2 000000000000

# actions=move:NXM_OF_IN_PORT[]->NXM_OF_VLAN_TCI[]
001c 0018 0010 0000 0000 0008 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 OpenFlow15 < input.txt],
[0], [expout], [experr])
AT_CLEANUP

AT_SETUP([ofp-actions - inconsistent MPLS actions])
OVS_VSWITCHD_START
dnl OK: Use fin_timeout action on TCP flow
Expand Down

0 comments on commit 73178f2

Please sign in to comment.