ovs-xapi-sync: Retry getting bridge-ids in case xapi is not ready.
[sliver-openvswitch.git] / lib / ofp-actions.c
index 068699f..c9e000f 100644 (file)
@@ -209,9 +209,9 @@ dec_ttl_cnt_ids_from_openflow(const struct nx_action_cnt_ids *nac_ids,
     for (i = 0; i < ids->n_controllers; i++) {
         uint16_t id = ntohs(((ovs_be16 *)(nac_ids + 1))[i]);
         ofpbuf_put(out, &id, sizeof id);
+        ids = out->l2;
     }
 
-    ids = out->l2;
     ofpact_update_len(out, &ids->ofpact);
 
     return 0;
@@ -1052,6 +1052,7 @@ 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);
@@ -1119,6 +1120,10 @@ 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;
     }
@@ -1181,13 +1186,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
         return nxm_reg_move_check(ofpact_get_REG_MOVE(a), flow);
 
     case OFPACT_REG_LOAD:
-        if (*dl_type != flow->dl_type) {
-            struct flow updated_flow = *flow;
-            updated_flow.dl_type = *dl_type;
-            return nxm_reg_load_check(ofpact_get_REG_LOAD(a), &updated_flow);
-        } else {
-            return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow);
-        }
+        return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow);
 
     case OFPACT_STACK_PUSH:
         return nxm_stack_push_check(ofpact_get_STACK_PUSH(a), flow);
@@ -1245,9 +1244,23 @@ ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len,
 {
     const struct ofpact *a;
     ovs_be16 dl_type = flow->dl_type;
+    struct flow updated_flow;
 
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        enum ofperr error = ofpact_check__(a, flow, max_ports, &dl_type);
+        enum ofperr error;
+
+        /* If the dl_type was changed by an action then its new value
+         * should be present in the flow passed to ofpact_check__(). */
+        if (flow->dl_type != dl_type) {
+            /* Only copy flow at most once */
+            if (flow != &updated_flow) {
+                updated_flow = *flow;
+                flow = &updated_flow;
+            }
+            updated_flow.dl_type = dl_type;
+        }
+
+        error = ofpact_check__(a, flow, max_ports, &dl_type);
         if (error) {
             return error;
         }
@@ -2077,8 +2090,11 @@ ofpact_format(const struct ofpact *a, struct ds *s)
 
             ds_put_cstr(s, "controller(");
             if (reason != OFPR_ACTION) {
+                char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
+
                 ds_put_format(s, "reason=%s,",
-                              ofputil_packet_in_reason_to_string(reason));
+                              ofputil_packet_in_reason_to_string(
+                                  reason, reasonbuf, sizeof reasonbuf));
             }
             if (controller->max_len != UINT16_MAX) {
                 ds_put_format(s, "max_len=%"PRIu16",", controller->max_len);