ONF-JIRA: EXT-320 Signed-off-by: Ben Pfaff <b...@nicira.com> --- NEWS | 1 + lib/ofp-actions.c | 80 ++++++++++++++++++++++++++++++++++++++++++-------- tests/ofp-actions.at | 24 +++++++++++++++ 3 files changed, 93 insertions(+), 12 deletions(-)
diff --git a/NEWS b/NEWS index 94232b7..15abe45 100644 --- a/NEWS +++ b/NEWS @@ -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). diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 3799cfd..e2266cd 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -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. ## */ /* ## ------------------------- ## */ @@ -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, @@ -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 @@ -1728,6 +1750,29 @@ 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->ofpact.raw = OFPAT_RAW15_COPY_FIELD; + 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) { @@ -1746,17 +1791,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 diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at index 9c6f228..569f4ae 100644 --- a/tests/ofp-actions.at +++ b/tests/ofp-actions.at @@ -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 -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev