Signed-off-by: Ben Pfaff <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev