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