* OFPERR_* OpenFlow error code on failure, or OFPROTO_POSTPONE if the
* operation cannot be initiated now but may be retried later.
*
- * This is a helper function for in-band control and fail-open. */
+ * This is a helper function for in-band control and fail-open and the "learn"
+ * action. */
int
ofproto_flow_mod(struct ofproto *ofproto, struct ofputil_flow_mod *fm)
OVS_EXCLUDED(ofproto_mutex)
rule->ofproto->ofproto_class->rule_dealloc(rule);
}
+static uint32_t get_provider_meter_id(const struct ofproto *,
+ uint32_t of_meter_id);
+
/* Creates and returns a new 'struct rule_actions', with a ref_count of 1,
* whose actions are a copy of from the 'ofpacts_len' bytes of 'ofpacts'. */
struct rule_actions *
-rule_actions_create(const struct ofpact *ofpacts, size_t ofpacts_len)
+rule_actions_create(const struct ofproto *ofproto,
+ const struct ofpact *ofpacts, size_t ofpacts_len)
{
struct rule_actions *actions;
atomic_init(&actions->ref_count, 1);
actions->ofpacts = xmemdup(ofpacts, ofpacts_len);
actions->ofpacts_len = ofpacts_len;
- actions->meter_id = ofpacts_get_meter(ofpacts, ofpacts_len);
+ actions->provider_meter_id
+ = get_provider_meter_id(ofproto,
+ ofpacts_get_meter(ofpacts, ofpacts_len));
+
return actions;
}
}
mid = ofpacts_get_meter(ofpacts, ofpacts_len);
- if (mid && ofproto_get_provider_meter_id(ofproto, mid) == UINT32_MAX) {
+ if (mid && get_provider_meter_id(ofproto, mid) == UINT32_MAX) {
return OFPERR_OFPMMFC_INVALID_METER;
}
return 0;
for (i = 0; i < p->n_tables; i++) {
ots[i].table_id = i;
sprintf(ots[i].name, "table%zu", i);
- ots[i].match = htonll(OFPXMT12_MASK);
- ots[i].wildcards = htonll(OFPXMT12_MASK);
+ ots[i].match = htonll(OFPXMT13_MASK);
+ ots[i].wildcards = htonll(OFPXMT13_MASK);
ots[i].write_actions = htonl(OFPAT11_OUTPUT);
ots[i].apply_actions = htonl(OFPAT11_OUTPUT);
- ots[i].write_setfields = htonll(OFPXMT12_MASK);
- ots[i].apply_setfields = htonll(OFPXMT12_MASK);
+ ots[i].write_setfields = htonll(OFPXMT13_MASK);
+ ots[i].apply_setfields = htonll(OFPXMT13_MASK);
ots[i].metadata_match = htonll(UINT64_MAX);
ots[i].metadata_write = htonll(UINT64_MAX);
ots[i].instructions = htonl(OFPIT11_ALL);
*CONST_CAST(uint8_t *, &rule->table_id) = table - ofproto->tables;
rule->flags = fm->flags & OFPUTIL_FF_STATE;
- rule->actions = rule_actions_create(fm->ofpacts, fm->ofpacts_len);
+ rule->actions = rule_actions_create(ofproto, fm->ofpacts, fm->ofpacts_len);
list_init(&rule->meter_list_node);
rule->eviction_group = NULL;
list_init(&rule->expirable);
struct rule_actions *new_actions;
op->actions = rule->actions;
- new_actions = rule_actions_create(fm->ofpacts, fm->ofpacts_len);
+ new_actions = rule_actions_create(ofproto,
+ fm->ofpacts, fm->ofpacts_len);
ovs_mutex_lock(&rule->mutex);
rule->actions = new_actions;
/*
* This is used in instruction validation at flow set-up time,
* as flows may not use non-existing meters.
- * This is also used by ofproto-providers to translate OpenFlow meter_ids
- * in METER instructions to the corresponding provider meter IDs.
* Return value of UINT32_MAX signifies an invalid meter.
*/
-uint32_t
-ofproto_get_provider_meter_id(const struct ofproto * ofproto,
- uint32_t of_meter_id)
+static uint32_t
+get_provider_meter_id(const struct ofproto *ofproto, uint32_t of_meter_id)
{
if (of_meter_id && of_meter_id <= ofproto->meter_features.max_meters) {
const struct meter *meter = ofproto->meters[of_meter_id];
ovs_assert(provider_meter_id.uint32 != UINT32_MAX);
*meterp = meter_create(&mm->meter, provider_meter_id);
}
- return 0;
+ return error;
}
static enum ofperr
{
struct meter *meter = ofproto->meters[mm->meter.meter_id];
enum ofperr error;
+ uint32_t provider_meter_id;
if (!meter) {
return OFPERR_OFPMMFC_UNKNOWN_METER;
}
+ provider_meter_id = meter->provider_meter_id.uint32;
error = ofproto->ofproto_class->meter_set(ofproto,
&meter->provider_meter_id,
&mm->meter);
- ovs_assert(meter->provider_meter_id.uint32 != UINT32_MAX);
+ ovs_assert(meter->provider_meter_id.uint32 == provider_meter_id);
if (!error) {
meter_update(meter, &mm->meter);
}
cookies_insert(ofproto, rule);
- if (rule->actions->meter_id) {
- struct meter *meter = ofproto->meters[rule->actions->meter_id];
+ if (rule->actions->provider_meter_id != UINT32_MAX) {
+ uint32_t meter_id = ofpacts_get_meter(rule->actions->ofpacts,
+ rule->actions->ofpacts_len);
+ struct meter *meter = ofproto->meters[meter_id];
list_insert(&meter->rules, &rule->meter_list_node);
}
ovs_rwlock_wrlock(&table->cls.rwlock);