clang: Fix the alignment warning.
[sliver-openvswitch.git] / lib / ofp-actions.c
index b934be1..61e2854 100644 (file)
@@ -336,7 +336,7 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
         break;
 
     case OFPUTIL_NXAST_WRITE_METADATA:
-        nawm = (const struct nx_action_write_metadata *) a;
+        nawm = ALIGNED_CAST(const struct nx_action_write_metadata *, a);
         error = metadata_from_nxast(nawm, out);
         break;
 
@@ -356,7 +356,7 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
 
     case OFPUTIL_NXAST_REG_LOAD:
         error = nxm_reg_load_from_openflow(
-            (const struct nx_action_reg_load *) a, out);
+            ALIGNED_CAST(const struct nx_action_reg_load *, a), out);
         break;
 
     case OFPUTIL_NXAST_STACK_PUSH:
@@ -375,7 +375,7 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
         break;
 
     case OFPUTIL_NXAST_SET_TUNNEL64:
-        nast64 = (const struct nx_action_set_tunnel64 *) a;
+        nast64 = ALIGNED_CAST(const struct nx_action_set_tunnel64 *, a);
         tunnel = ofpact_put_SET_TUNNEL(out);
         tunnel->ofpact.compat = code;
         tunnel->tun_id = ntohll(nast64->tun_id);
@@ -402,7 +402,8 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
         break;
 
     case OFPUTIL_NXAST_LEARN:
-        error = learn_from_openflow((const struct nx_action_learn *) a, out);
+        error = learn_from_openflow(
+            ALIGNED_CAST(const struct nx_action_learn *, a), out);
         break;
 
     case OFPUTIL_NXAST_EXIT:
@@ -881,7 +882,7 @@ ofpacts_from_openflow11(const union ofp_action *in, size_t n_in,
     instruction_get_##ENUM(const struct ofp11_instruction *inst)\
     {                                                           \
         ovs_assert(inst->type == htons(ENUM));                  \
-        return (struct STRUCT *)inst;                           \
+        return ALIGNED_CAST(struct STRUCT *, inst);             \
     }                                                           \
                                                                 \
     static inline void                                          \
@@ -931,6 +932,58 @@ ovs_instruction_type_from_name(const char *name)
     return -1;
 }
 
+enum ovs_instruction_type
+ovs_instruction_type_from_ofpact_type(enum ofpact_type type)
+{
+    switch (type) {
+    case OFPACT_METER:
+        return OVSINST_OFPIT13_METER;
+    case OFPACT_CLEAR_ACTIONS:
+        return OVSINST_OFPIT11_CLEAR_ACTIONS;
+    case OFPACT_WRITE_METADATA:
+        return OVSINST_OFPIT11_WRITE_METADATA;
+    case OFPACT_GOTO_TABLE:
+        return OVSINST_OFPIT11_GOTO_TABLE;
+    case OFPACT_OUTPUT:
+    case OFPACT_CONTROLLER:
+    case OFPACT_ENQUEUE:
+    case OFPACT_OUTPUT_REG:
+    case OFPACT_BUNDLE:
+    case OFPACT_SET_VLAN_VID:
+    case OFPACT_SET_VLAN_PCP:
+    case OFPACT_STRIP_VLAN:
+    case OFPACT_PUSH_VLAN:
+    case OFPACT_SET_ETH_SRC:
+    case OFPACT_SET_ETH_DST:
+    case OFPACT_SET_IPV4_SRC:
+    case OFPACT_SET_IPV4_DST:
+    case OFPACT_SET_IPV4_DSCP:
+    case OFPACT_SET_L4_SRC_PORT:
+    case OFPACT_SET_L4_DST_PORT:
+    case OFPACT_REG_MOVE:
+    case OFPACT_REG_LOAD:
+    case OFPACT_STACK_PUSH:
+    case OFPACT_STACK_POP:
+    case OFPACT_DEC_TTL:
+    case OFPACT_SET_MPLS_TTL:
+    case OFPACT_DEC_MPLS_TTL:
+    case OFPACT_PUSH_MPLS:
+    case OFPACT_POP_MPLS:
+    case OFPACT_SET_TUNNEL:
+    case OFPACT_SET_QUEUE:
+    case OFPACT_POP_QUEUE:
+    case OFPACT_FIN_TIMEOUT:
+    case OFPACT_RESUBMIT:
+    case OFPACT_LEARN:
+    case OFPACT_MULTIPATH:
+    case OFPACT_NOTE:
+    case OFPACT_EXIT:
+    case OFPACT_SAMPLE:
+    default:
+        return OVSINST_OFPIT11_APPLY_ACTIONS;
+    }
+}
+
 static inline struct ofp11_instruction *
 instruction_next(const struct ofp11_instruction *inst)
 {
@@ -1018,10 +1071,10 @@ decode_openflow11_instructions(const struct ofp11_instruction insts[],
 
 static void
 get_actions_from_instruction(const struct ofp11_instruction *inst,
-                         const union ofp_action **actions,
-                         size_t *n_actions)
+                             const union ofp_action **actions,
+                             size_t *n_actions)
 {
-    *actions = (const union ofp_action *) (inst + 1);
+    *actions = ALIGNED_CAST(const union ofp_action *, inst + 1);
     *n_actions = (ntohs(inst->len) - sizeof *inst) / OFP11_INSTRUCTION_ALIGN;
 }
 
@@ -1051,7 +1104,6 @@ ofpacts_pull_openflow11_actions(struct ofpbuf *openflow,
 enum ofperr
 ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
                                      unsigned int instructions_len,
-                                     uint8_t table_id,
                                      struct ofpbuf *ofpacts)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
@@ -1089,8 +1141,8 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
         const struct ofp13_instruction_meter *oim;
         struct ofpact_meter *om;
 
-        oim = (const struct ofp13_instruction_meter *)
-            insts[OVSINST_OFPIT13_METER];
+        oim = ALIGNED_CAST(const struct ofp13_instruction_meter *,
+                           insts[OVSINST_OFPIT13_METER]);
 
         om = ofpact_put_METER(ofpacts);
         om->meter_id = ntohl(oim->meter_id);
@@ -1116,8 +1168,8 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
         const struct ofp11_instruction_write_metadata *oiwm;
         struct ofpact_metadata *om;
 
-        oiwm = (const struct ofp11_instruction_write_metadata *)
-            insts[OVSINST_OFPIT11_WRITE_METADATA];
+        oiwm = ALIGNED_CAST(const struct ofp11_instruction_write_metadata *,
+                            insts[OVSINST_OFPIT11_WRITE_METADATA]);
 
         om = ofpact_put_WRITE_METADATA(ofpacts);
         om->metadata = oiwm->metadata;
@@ -1129,10 +1181,6 @@ ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
 
         oigt = instruction_get_OFPIT11_GOTO_TABLE(
             insts[OVSINST_OFPIT11_GOTO_TABLE]);
-        if (table_id >= oigt->table_id) {
-            error = OFPERR_OFPBRC_BAD_TABLE_ID;
-            goto exit;
-        }
         ogt = ofpact_put_GOTO_TABLE(ofpacts);
         ogt->table_id = oigt->table_id;
     }
@@ -1152,7 +1200,8 @@ exit:
 \f
 /* May modify flow->dl_type, caller must restore it. */
 static enum ofperr
-ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports)
+ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports,
+               uint8_t table_id)
 {
     const struct ofpact_enqueue *enqueue;
 
@@ -1237,8 +1286,20 @@ ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports)
 
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_WRITE_METADATA:
-    case OFPACT_METER:
+        return 0;
+
+    case OFPACT_METER: {
+        uint32_t mid = ofpact_get_METER(a)->meter_id;
+        if (mid == 0 || mid > OFPM13_MAX) {
+            return OFPERR_OFPMMFC_INVALID_METER;
+        }
+        return 0;
+    }
+
     case OFPACT_GOTO_TABLE:
+        if (ofpact_get_GOTO_TABLE(a)->table_id <= table_id) {
+            return OFPERR_OFPBRC_BAD_TABLE_ID;
+        }
         return 0;
 
     default:
@@ -1253,14 +1314,14 @@ ofpact_check__(const struct ofpact *a, struct flow *flow, ofp_port_t max_ports)
  * May temporarily modify 'flow', but restores the changes before returning. */
 enum ofperr
 ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len,
-              struct flow *flow, ofp_port_t max_ports)
+              struct flow *flow, ofp_port_t max_ports, uint8_t table_id)
 {
     const struct ofpact *a;
     ovs_be16 dl_type = flow->dl_type;
     enum ofperr error = 0;
 
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        error = ofpact_check__(a, flow, max_ports);
+        error = ofpact_check__(a, flow, max_ports, table_id);
         if (error) {
             break;
         }
@@ -1281,18 +1342,7 @@ ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len)
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
         enum ovs_instruction_type next;
 
-        if (a->type == OFPACT_METER) {
-            next = OVSINST_OFPIT13_METER;
-        } else if (a->type == OFPACT_CLEAR_ACTIONS) {
-            next = OVSINST_OFPIT11_CLEAR_ACTIONS;
-        } else if (a->type == OFPACT_WRITE_METADATA) {
-            next = OVSINST_OFPIT11_WRITE_METADATA;
-        } else if (a->type == OFPACT_GOTO_TABLE) {
-            next = OVSINST_OFPIT11_GOTO_TABLE;
-        } else {
-            next = OVSINST_OFPIT11_APPLY_ACTIONS;
-        }
-
+        next = ovs_instruction_type_from_ofpact_type(a->type);
         if (inst != OVSINST_OFPIT11_APPLY_ACTIONS && next <= inst) {
             const char *name = ovs_instruction_name_from_type(inst);
             const char *next_name = ovs_instruction_name_from_type(next);
@@ -1387,7 +1437,7 @@ ofpact_note_to_nxast(const struct ofpact_note *note, struct ofpbuf *out)
     if (remainder) {
         ofpbuf_put_zeros(out, OFP_ACTION_ALIGN - remainder);
     }
-    nan = (struct nx_action_note *)((char *)out->data + start_ofs);
+    nan = ofpbuf_at(out, start_ofs, sizeof *nan);
     nan->len = htons(out->size - start_ofs);
 }
 
@@ -1892,17 +1942,20 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
     const struct ofpact *a;
 
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        /* XXX Write-Actions */
-
-        if (a->type == OFPACT_CLEAR_ACTIONS) {
+        switch (ovs_instruction_type_from_ofpact_type(a->type)) {
+        case OVSINST_OFPIT11_CLEAR_ACTIONS:
             instruction_put_OFPIT11_CLEAR_ACTIONS(openflow);
-        } else if (a->type == OFPACT_GOTO_TABLE) {
-            struct ofp11_instruction_goto_table *oigt;
+            break;
 
+        case OVSINST_OFPIT11_GOTO_TABLE: {
+            struct ofp11_instruction_goto_table *oigt;
             oigt = instruction_put_OFPIT11_GOTO_TABLE(openflow);
             oigt->table_id = ofpact_get_GOTO_TABLE(a)->table_id;
             memset(oigt->pad, 0, sizeof oigt->pad);
-        } else if (a->type == OFPACT_WRITE_METADATA) {
+            break;
+        }
+
+        case OVSINST_OFPIT11_WRITE_METADATA: {
             const struct ofpact_metadata *om;
             struct ofp11_instruction_write_metadata *oiwm;
 
@@ -1910,15 +1963,20 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
             oiwm = instruction_put_OFPIT11_WRITE_METADATA(openflow);
             oiwm->metadata = om->metadata;
             oiwm->metadata_mask = om->mask;
-        } else if (a->type == OFPACT_METER) {
+            break;
+        }
+
+        case OVSINST_OFPIT13_METER: {
             const struct ofpact_meter *om;
             struct ofp13_instruction_meter *oim;
 
             om = ofpact_get_METER(a);
             oim = instruction_put_OFPIT13_METER(openflow);
             oim->meter_id = htonl(om->meter_id);
-        } else if (!ofpact_is_instruction(a)) {
-            /* Apply-actions */
+            break;
+        }
+
+        case OVSINST_OFPIT11_APPLY_ACTIONS: {
             const size_t ofs = openflow->size;
             const size_t ofpacts_len_left =
                 (uint8_t*)ofpact_end(ofpacts, ofpacts_len) - (uint8_t*)a;
@@ -1927,7 +1985,8 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
 
             instruction_put_OFPIT11_APPLY_ACTIONS(openflow);
             OFPACT_FOR_EACH(action, a, ofpacts_len_left) {
-                if (ofpact_is_instruction(action)) {
+                if (ovs_instruction_type_from_ofpact_type(action->type)
+                    != OVSINST_OFPIT11_APPLY_ACTIONS) {
                     break;
                 }
                 ofpact_to_openflow11(action, openflow);
@@ -1935,6 +1994,11 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
             }
             ofpacts_update_instruction_actions(openflow, ofs);
             a = processed;
+            break;
+        }
+
+        case OVSINST_OFPIT11_WRITE_ACTIONS:
+            NOT_REACHED();
         }
     }
 }