Fix remaining "void function returning a value" warning by MSVC.
[cascardo/ovs.git] / lib / ofp-actions.c
index c6aba51..5df36a2 100644 (file)
@@ -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);
 }
 \f
+/* 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
@@ -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)
@@ -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;
+
+        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);
+        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
@@ -1910,7 +1965,7 @@ decode_OFPAT_RAW12_SET_FIELD(const struct ofp12_action_set_field *oasf,
     }
 
     if (NXM_HASMASK(oxm_header)) {
-        return OFPERR_OFPBAC_BAD_SET_TYPE;
+        return OFPERR_OFPBAC_BAD_SET_MASK;
     }
     mf = mf_from_nxm_header(oxm_header);
     if (!mf) {
@@ -4105,14 +4160,14 @@ format_GOTO_TABLE(const struct ofpact_goto_table *a, struct ds *s)
 }
 \f
 static void
-log_bad_action(const struct ofp_action_header *actions, size_t max_actions,
+log_bad_action(const struct ofp_action_header *actions, size_t actions_len,
                const struct ofp_action_header *bad_action, enum ofperr error)
 {
     if (!VLOG_DROP_WARN(&rl)) {
         struct ds s;
 
         ds_init(&s);
-        ds_put_hex_dump(&s, actions, max_actions * OFP_ACTION_ALIGN, 0, false);
+        ds_put_hex_dump(&s, actions, actions_len, 0, false);
         VLOG_WARN("bad action at offset %#"PRIxPTR" (%s):\n%s",
                   (char *)bad_action - (char *)actions,
                   ofperr_get_name(error), ds_cstr(&s));
@@ -4139,7 +4194,7 @@ ofpacts_decode(const void *actions, size_t actions_len,
         }
 
         if (error) {
-            log_bad_action(actions, actions_len * 8, action, error);
+            log_bad_action(actions, actions_len, action, error);
             return error;
         }
     }
@@ -4221,13 +4276,15 @@ ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
 
 /* True if an action sets the value of a field
  * in a way that is compatibile with the action set.
+ * The field can be set via either a set or a move action.
  * False otherwise. */
 static bool
-ofpact_is_set_action(const struct ofpact *a)
+ofpact_is_set_or_move_action(const struct ofpact *a)
 {
     switch (a->type) {
     case OFPACT_SET_FIELD:
     case OFPACT_REG_LOAD:
+    case OFPACT_REG_MOVE:
     case OFPACT_SET_ETH_DST:
     case OFPACT_SET_ETH_SRC:
     case OFPACT_SET_IP_DSCP:
@@ -4265,7 +4322,6 @@ ofpact_is_set_action(const struct ofpact *a)
     case OFPACT_POP_QUEUE:
     case OFPACT_PUSH_MPLS:
     case OFPACT_PUSH_VLAN:
-    case OFPACT_REG_MOVE:
     case OFPACT_RESUBMIT:
     case OFPACT_SAMPLE:
     case OFPACT_STACK_POP:
@@ -4293,6 +4349,7 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
     case OFPACT_PUSH_MPLS:
     case OFPACT_PUSH_VLAN:
     case OFPACT_REG_LOAD:
+    case OFPACT_REG_MOVE:
     case OFPACT_SET_FIELD:
     case OFPACT_SET_ETH_DST:
     case OFPACT_SET_ETH_SRC:
@@ -4327,7 +4384,6 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
     case OFPACT_NOTE:
     case OFPACT_OUTPUT_REG:
     case OFPACT_POP_QUEUE:
-    case OFPACT_REG_MOVE:
     case OFPACT_RESUBMIT:
     case OFPACT_SAMPLE:
     case OFPACT_STACK_POP:
@@ -4416,7 +4472,7 @@ ofpacts_execute_action_set(struct ofpbuf *action_list,
     ofpacts_copy_last(action_list, action_set, OFPACT_PUSH_VLAN);
     ofpacts_copy_last(action_list, action_set, OFPACT_DEC_TTL);
     ofpacts_copy_last(action_list, action_set, OFPACT_DEC_MPLS_TTL);
-    ofpacts_copy_all(action_list, action_set, ofpact_is_set_action);
+    ofpacts_copy_all(action_list, action_set, ofpact_is_set_or_move_action);
     ofpacts_copy_last(action_list, action_set, OFPACT_SET_QUEUE);
 
     /* If both OFPACT_GROUP and OFPACT_OUTPUT are present, OpenFlow says that
@@ -4426,7 +4482,8 @@ ofpacts_execute_action_set(struct ofpbuf *action_list,
      * all the actions because there's no point in modifying a packet that will
      * not be sent anywhere. */
     if (!ofpacts_copy_last(action_list, action_set, OFPACT_GROUP) &&
-        !ofpacts_copy_last(action_list, action_set, OFPACT_OUTPUT)) {
+        !ofpacts_copy_last(action_list, action_set, OFPACT_OUTPUT) &&
+        !ofpacts_copy_last(action_list, action_set, OFPACT_RESUBMIT)) {
         ofpbuf_clear(action_list);
     }
 }
@@ -5253,7 +5310,8 @@ encode_ofpact(const struct ofpact *a, enum ofp_version ofp_version,
     switch (a->type) {
 #define OFPACT(ENUM, STRUCT, MEMBER, NAME)                              \
         case OFPACT_##ENUM:                                             \
-            return encode_##ENUM(ofpact_get_##ENUM(a), ofp_version, out);
+            encode_##ENUM(ofpact_get_##ENUM(a), ofp_version, out);      \
+            return;
         OFPACTS
 #undef OFPACT
     default: