Signed-off-by: Ben Pfaff <b...@nicira.com>
---
 lib/ofp-actions.c |   12 +++++-----
 lib/ofp-actions.h |    2 -
 ofproto/ofproto.c |   60 ++++++++++++++++++++++++++++++-----------------------
 3 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 22d8cad..e1b44d8 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -1202,9 +1202,9 @@ exit:
     return error;
 }
 
-enum ofperr
-ofpacts_check_action(const struct ofpact *a, const struct flow *flow,
-                     ovs_be16 *new_dl_type, ofp_port_t max_ports)
+/* 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)
 {
     const struct ofpact_enqueue *enqueue;
 
@@ -1277,11 +1277,11 @@ ofpacts_check_action(const struct ofpact *a, const 
struct flow *flow,
         return 0;
 
     case OFPACT_PUSH_MPLS:
-        *new_dl_type = ofpact_get_PUSH_MPLS(a)->ethertype;
+        flow->dl_type = ofpact_get_PUSH_MPLS(a)->ethertype;
         return 0;
 
     case OFPACT_POP_MPLS:
-        *new_dl_type = ofpact_get_POP_MPLS(a)->ethertype;
+        flow->dl_type = ofpact_get_POP_MPLS(a)->ethertype;
         return 0;
 
     case OFPACT_SAMPLE:
@@ -1318,7 +1318,7 @@ ofpacts_check(const struct ofpact ofpacts[], size_t 
ofpacts_len,
     enum ofperr error = 0;
 
     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        error = ofpacts_check_action(a, flow, &flow->dl_type, max_ports);
+        error = ofpact_check__(a, flow, max_ports);
         if (error) {
             break;
         }
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index e5318b5..ddd94d4 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -501,8 +501,6 @@ enum ofperr ofpacts_pull_openflow11_instructions(struct 
ofpbuf *openflow,
                                                  unsigned int instructions_len,
                                                  uint8_t table_id,
                                                  struct ofpbuf *ofpacts);
-enum ofperr ofpacts_check_action(const struct ofpact *, const struct flow *,
-                                 ovs_be16 *new_dl_type, ofp_port_t max_ports);
 enum ofperr ofpacts_check(const struct ofpact[], size_t ofpacts_len,
                           struct flow *, ofp_port_t max_ports);
 enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 6d87972..341cf10 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2384,44 +2384,52 @@ reject_slave_controller(struct ofconn *ofconn)
     }
 }
 
+static uint32_t
+find_meter(const struct ofpact ofpacts[], size_t ofpacts_len)
+{
+    const struct ofpact *a;
+
+    OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+        enum ovs_instruction_type inst;
+
+        inst = ovs_instruction_type_from_ofpact_type(a->type);
+        if (a->type == OFPACT_METER) {
+            return ofpact_get_METER(a)->meter_id;
+        } else if (inst > OVSINST_OFPIT13_METER) {
+            break;
+        }
+    }
+
+    return 0;
+}
+
 /* Checks that the 'ofpacts_len' bytes of actions in 'ofpacts' are
  * appropriate for a packet with the prerequisites satisfied by 'flow'.
  * 'flow' may be temporarily modified, but is restored at return.
- * If the actions include a meter action, and a non-NULL 'meter_id' is
- * provided, the meter_id is stored at '*meter_id', if valid.
+ * On success, if 'meter_id' is nonnull, stores the meter ID from any meter
+ * action in 'ofpacts' into '*meter_id', or 0 if no meter action is present.
  */
 static enum ofperr
 ofproto_check_ofpacts(struct ofproto *ofproto,
                       const struct ofpact ofpacts[], size_t ofpacts_len,
                       struct flow *flow, uint32_t *meter_id)
 {
-    const struct ofpact *a;
-    ovs_be16 dl_type = flow->dl_type;
-    enum ofperr error = 0;
-
-    OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
-        if (a->type == OFPACT_METER) {
-            uint32_t mid = 0;
+    enum ofperr error;
+    uint32_t mid;
 
-            mid = ofpact_get_METER(a)->meter_id;
+    error = ofpacts_check(ofpacts, ofpacts_len, flow, ofproto->max_ports);
+    if (error) {
+        return error;
+    }
 
-            if (ofproto_get_provider_meter_id(ofproto, mid) != UINT32_MAX) {
-                if (meter_id) {
-                    *meter_id = mid;
-                }
-            } else {
-                error = OFPERR_OFPMMFC_INVALID_METER;
-            }
-        } else {
-            error = ofpacts_check_action(a, flow, &flow->dl_type,
-                                         ofproto->max_ports);
-        }
-        if (error) {
-            break;
-        }
+    mid = find_meter(ofpacts, ofpacts_len);
+    if (mid && ofproto_get_provider_meter_id(ofproto, mid) == UINT32_MAX) {
+        return OFPERR_OFPMMFC_INVALID_METER;
     }
-    flow->dl_type = dl_type; /* Restore. */
-    return error;
+    if (meter_id) {
+        *meter_id = mid;
+    }
+    return 0;
 }
 
 static enum ofperr
-- 
1.7.2.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to