X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=b2d6526c6b76b6d590edf020e1d25af443c7bd68;hb=965607c850bb14e24905c46845d050f14105d923;hp=2578f6457eca422977a4c1e5ac564512f7ebcfcf;hpb=b90d6ee54a3dea81da58e6e10640fcd165dfb659;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 2578f6457..b2d6526c6 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -43,6 +43,7 @@ #include "ofproto-provider.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" +#include "ovs-rcu.h" #include "packets.h" #include "pinsched.h" #include "pktbuf.h" @@ -182,7 +183,7 @@ struct eviction_group { static bool choose_rule_to_evict(struct oftable *table, struct rule **rulep); static void ofproto_evict(struct ofproto *) OVS_EXCLUDED(ofproto_mutex); -static uint32_t rule_eviction_priority(struct rule *); +static uint32_t rule_eviction_priority(struct ofproto *ofproto, struct rule *); static void eviction_group_add_rule(struct rule *); static void eviction_group_remove_rule(struct rule *); @@ -307,7 +308,7 @@ static size_t allocated_ofproto_classes; struct ovs_mutex ofproto_mutex = OVS_MUTEX_INITIALIZER; unsigned ofproto_flow_limit = OFPROTO_FLOW_LIMIT_DEFAULT; -enum ofproto_flow_miss_model flow_miss_model = OFPROTO_HANDLE_MISS_AUTO; +unsigned ofproto_max_idle = OFPROTO_MAX_IDLE_DEFAULT; size_t n_handlers, n_revalidators; @@ -698,11 +699,12 @@ ofproto_set_flow_limit(unsigned limit) ofproto_flow_limit = limit; } -/* Sets the path for handling flow misses. */ +/* Sets the maximum idle time for flows in the datapath before they are + * expired. */ void -ofproto_set_flow_miss_model(unsigned model) +ofproto_set_max_idle(unsigned max_idle) { - flow_miss_model = model; + ofproto_max_idle = max_idle; } /* If forward_bpdu is true, the NORMAL action will forward frames with @@ -1450,19 +1452,23 @@ ofproto_run(struct ofproto *p) } ovs_mutex_lock(&ofproto_mutex); - HEAP_FOR_EACH (evg, size_node, &table->eviction_groups_by_size) { - heap_rebuild(&evg->rules); - } - fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, NULL); CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { - if (!rule->eviction_group - && (rule->idle_timeout || rule->hard_timeout)) { - eviction_group_add_rule(rule); + if (rule->idle_timeout || rule->hard_timeout) { + if (!rule->eviction_group) { + eviction_group_add_rule(rule); + } else { + heap_raw_change(&rule->evg_node, + rule_eviction_priority(p, rule)); + } } } fat_rwlock_unlock(&table->cls.rwlock); + + HEAP_FOR_EACH (evg, size_node, &table->eviction_groups_by_size) { + heap_rebuild(&evg->rules); + } ovs_mutex_unlock(&ofproto_mutex); } } @@ -1905,11 +1911,9 @@ ofproto_add_flow(struct ofproto *ofproto, const struct match *match, rule = rule_from_cls_rule(classifier_find_match_exactly( &ofproto->tables[0].cls, match, priority)); if (rule) { - ovs_mutex_lock(&rule->mutex); - must_add = !ofpacts_equal(rule->actions->ofpacts, - rule->actions->ofpacts_len, + struct rule_actions *actions = rule_get_actions(rule); + must_add = !ofpacts_equal(actions->ofpacts, actions->ofpacts_len, ofpacts, ofpacts_len); - ovs_mutex_unlock(&rule->mutex); } else { must_add = true; } @@ -1953,14 +1957,16 @@ ofproto_flow_mod(struct ofproto *ofproto, struct ofputil_flow_mod *fm) /* Reading many of the rule fields and writing on 'modified' * requires the rule->mutex. Also, rule->actions may change * if rule->mutex is not held. */ + const struct rule_actions *actions; + ovs_mutex_lock(&rule->mutex); + actions = rule_get_actions(rule); if (rule->idle_timeout == fm->idle_timeout && rule->hard_timeout == fm->hard_timeout && rule->flags == (fm->flags & OFPUTIL_FF_STATE) && (!fm->modify_cookie || (fm->new_cookie == rule->flow_cookie)) && ofpacts_equal(fm->ofpacts, fm->ofpacts_len, - rule->actions->ofpacts, - rule->actions->ofpacts_len)) { + actions->ofpacts, actions->ofpacts_len)) { /* Rule already exists and need not change, only update the modified timestamp. */ rule->modified = time_msec(); @@ -2201,7 +2207,7 @@ ofport_install(struct ofproto *p, if (error) { goto error; } - connmgr_send_port_status(p->connmgr, pp, OFPPR_ADD); + connmgr_send_port_status(p->connmgr, NULL, pp, OFPPR_ADD); return; error: @@ -2218,7 +2224,7 @@ error: static void ofport_remove(struct ofport *ofport) { - connmgr_send_port_status(ofport->ofproto->connmgr, &ofport->pp, + connmgr_send_port_status(ofport->ofproto->connmgr, NULL, &ofport->pp, OFPPR_DELETE); ofport_destroy(ofport); } @@ -2244,7 +2250,8 @@ ofport_modified(struct ofport *port, struct ofputil_phy_port *pp) memcpy(port->pp.hw_addr, pp->hw_addr, ETH_ADDR_LEN); port->pp.config = ((port->pp.config & ~OFPUTIL_PC_PORT_DOWN) | (pp->config & OFPUTIL_PC_PORT_DOWN)); - port->pp.state = pp->state; + port->pp.state = ((port->pp.state & ~OFPUTIL_PS_LINK_DOWN) + | (pp->state & OFPUTIL_PS_LINK_DOWN)); port->pp.curr = pp->curr; port->pp.advertised = pp->advertised; port->pp.supported = pp->supported; @@ -2252,7 +2259,8 @@ ofport_modified(struct ofport *port, struct ofputil_phy_port *pp) port->pp.curr_speed = pp->curr_speed; port->pp.max_speed = pp->max_speed; - connmgr_send_port_status(port->ofproto->connmgr, &port->pp, OFPPR_MODIFY); + connmgr_send_port_status(port->ofproto->connmgr, NULL, + &port->pp, OFPPR_MODIFY); } /* Update OpenFlow 'state' in 'port' and notify controller. */ @@ -2261,8 +2269,8 @@ ofproto_port_set_state(struct ofport *port, enum ofputil_port_state state) { if (port->pp.state != state) { port->pp.state = state; - connmgr_send_port_status(port->ofproto->connmgr, &port->pp, - OFPPR_MODIFY); + connmgr_send_port_status(port->ofproto->connmgr, NULL, + &port->pp, OFPPR_MODIFY); } } @@ -2580,35 +2588,13 @@ ofproto_rule_unref(struct rule *rule) } } -struct rule_actions * -rule_get_actions(const struct rule *rule) - OVS_EXCLUDED(rule->mutex) -{ - struct rule_actions *actions; - - ovs_mutex_lock(&rule->mutex); - actions = rule_get_actions__(rule); - ovs_mutex_unlock(&rule->mutex); - - return actions; -} - -struct rule_actions * -rule_get_actions__(const struct rule *rule) - OVS_REQUIRES(rule->mutex) -{ - rule_actions_ref(rule->actions); - return rule->actions; -} - static void ofproto_rule_destroy__(struct rule *rule) OVS_NO_THREAD_SAFETY_ANALYSIS { cls_rule_destroy(CONST_CAST(struct cls_rule *, &rule->cr)); - rule_actions_unref(rule->actions); + rule_actions_destroy(rule_get_actions(rule)); ovs_mutex_destroy(&rule->mutex); - ovs_refcount_destroy(&rule->ref_count); rule->ofproto->ofproto_class->rule_dealloc(rule); } @@ -2624,7 +2610,6 @@ rule_actions_create(const struct ofproto *ofproto, struct rule_actions *actions; actions = xmalloc(sizeof *actions); - ovs_refcount_init(&actions->ref_count); actions->ofpacts = xmemdup(ofpacts, ofpacts_len); actions->ofpacts_len = ofpacts_len; actions->provider_meter_id @@ -2634,24 +2619,20 @@ rule_actions_create(const struct ofproto *ofproto, return actions; } -/* Increments 'actions''s ref_count. */ -void -rule_actions_ref(struct rule_actions *actions) +static void +rule_actions_destroy_cb(struct rule_actions *actions) { - if (actions) { - ovs_refcount_ref(&actions->ref_count); - } + free(actions->ofpacts); + free(actions); } /* Decrements 'actions''s ref_count and frees 'actions' if the ref_count * reaches 0. */ void -rule_actions_unref(struct rule_actions *actions) +rule_actions_destroy(struct rule_actions *actions) { - if (actions && ovs_refcount_unref(&actions->ref_count) == 1) { - ovs_refcount_destroy(&actions->ref_count); - free(actions->ofpacts); - free(actions); + if (actions) { + ovsrcu_postpone(rule_actions_destroy_cb, actions); } } @@ -2661,9 +2642,13 @@ static bool ofproto_rule_has_out_port(const struct rule *rule, ofp_port_t port) OVS_REQUIRES(ofproto_mutex) { - return (port == OFPP_ANY - || ofpacts_output_to_port(rule->actions->ofpacts, - rule->actions->ofpacts_len, port)); + if (port == OFPP_ANY) { + return true; + } else { + const struct rule_actions *actions = rule_get_actions(rule); + return ofpacts_output_to_port(actions->ofpacts, + actions->ofpacts_len, port); + } } /* Returns true if 'rule' has group and equals group_id. */ @@ -2671,9 +2656,13 @@ static bool ofproto_rule_has_out_group(const struct rule *rule, uint32_t group_id) OVS_REQUIRES(ofproto_mutex) { - return (group_id == OFPG11_ANY - || ofpacts_output_to_group(rule->actions->ofpacts, - rule->actions->ofpacts_len, group_id)); + if (group_id == OFPG_ANY) { + return true; + } else { + const struct rule_actions *actions = rule_get_actions(rule); + return ofpacts_output_to_group(actions->ofpacts, + actions->ofpacts_len, group_id); + } } /* Returns true if a rule related to 'op' has an OpenFlow OFPAT_OUTPUT or @@ -2719,11 +2708,10 @@ run_rule_executes(struct ofproto *ofproto) guarded_list_pop_all(&ofproto->rule_executes, &executes); LIST_FOR_EACH_SAFE (e, next, list_node, &executes) { - union flow_in_port in_port_; struct flow flow; - in_port_.ofp_port = e->in_port; - flow_extract(e->packet, 0, 0, NULL, &in_port_, &flow); + flow_extract(e->packet, NULL, &flow); + flow.in_port.ofp_port = e->in_port; ofproto->ofproto_class->rule_execute(e->rule, &flow, e->packet); rule_execute_destroy(e); @@ -2932,7 +2920,6 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) uint64_t ofpacts_stub[1024 / 8]; struct ofpbuf ofpacts; struct flow flow; - union flow_in_port in_port_; enum ofperr error; COVERAGE_INC(ofproto_packet_out); @@ -2966,8 +2953,8 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) } /* Verify actions against packet, then send packet if successful. */ - in_port_.ofp_port = po.in_port; - flow_extract(payload, 0, 0, NULL, &in_port_, &flow); + flow_extract(payload, NULL, &flow); + flow.in_port.ofp_port = po.in_port; error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len); if (!error) { error = p->ofproto_class->packet_out(p, payload, &flow, @@ -2982,26 +2969,27 @@ exit: } static void -update_port_config(struct ofport *port, +update_port_config(struct ofconn *ofconn, struct ofport *port, enum ofputil_port_config config, enum ofputil_port_config mask) { - enum ofputil_port_config old_config = port->pp.config; - enum ofputil_port_config toggle; + enum ofputil_port_config toggle = (config ^ port->pp.config) & mask; - toggle = (config ^ port->pp.config) & mask; - if (toggle & OFPUTIL_PC_PORT_DOWN) { - if (config & OFPUTIL_PC_PORT_DOWN) { - netdev_turn_flags_off(port->netdev, NETDEV_UP, NULL); - } else { - netdev_turn_flags_on(port->netdev, NETDEV_UP, NULL); - } + if (toggle & OFPUTIL_PC_PORT_DOWN + && (config & OFPUTIL_PC_PORT_DOWN + ? netdev_turn_flags_off(port->netdev, NETDEV_UP, NULL) + : netdev_turn_flags_on(port->netdev, NETDEV_UP, NULL))) { + /* We tried to bring the port up or down, but it failed, so don't + * update the "down" bit. */ toggle &= ~OFPUTIL_PC_PORT_DOWN; } - port->pp.config ^= toggle; - if (port->pp.config != old_config) { + if (toggle) { + enum ofputil_port_config old_config = port->pp.config; + port->pp.config ^= toggle; port->ofproto->ofproto_class->port_reconfigured(port, old_config); + connmgr_send_port_status(port->ofproto->connmgr, ofconn, &port->pp, + OFPPR_MODIFY); } } @@ -3029,7 +3017,7 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh) } else if (!eth_addr_equals(port->pp.hw_addr, pm.hw_addr)) { return OFPERR_OFPPMFC_BAD_HW_ADDR; } else { - update_port_config(port, pm.config, pm.mask); + update_port_config(ofconn, port, pm.config, pm.mask); if (pm.advertise) { netdev_set_advertisements(port->netdev, pm.advertise); } @@ -3204,8 +3192,7 @@ handle_port_desc_stats_request(struct ofconn *ofconn, static uint32_t hash_cookie(ovs_be64 cookie) { - return hash_2words((OVS_FORCE uint64_t)cookie >> 32, - (OVS_FORCE uint64_t)cookie); + return hash_uint64((OVS_FORCE uint64_t)cookie); } static void @@ -3601,27 +3588,25 @@ handle_flow_stats_request(struct ofconn *ofconn, fs.idle_timeout = rule->idle_timeout; fs.hard_timeout = rule->hard_timeout; created = rule->created; - used = rule->used; modified = rule->modified; - actions = rule_get_actions__(rule); + actions = rule_get_actions(rule); flags = rule->flags; ovs_mutex_unlock(&rule->mutex); + ofproto->ofproto_class->rule_get_stats(rule, &fs.packet_count, + &fs.byte_count, &used); + minimatch_expand(&rule->cr.match, &fs.match); fs.table_id = rule->table_id; calc_duration(created, now, &fs.duration_sec, &fs.duration_nsec); fs.priority = rule->cr.priority; fs.idle_age = age_secs(now - used); fs.hard_age = age_secs(now - modified); - ofproto->ofproto_class->rule_get_stats(rule, &fs.packet_count, - &fs.byte_count); fs.ofpacts = actions->ofpacts; fs.ofpacts_len = actions->ofpacts_len; fs.flags = flags; ofputil_append_flow_stats_reply(&fs, &replies); - - rule_actions_unref(actions); } rule_collection_unref(&rules); @@ -3637,13 +3622,13 @@ flow_stats_ds(struct rule *rule, struct ds *results) { uint64_t packet_count, byte_count; struct rule_actions *actions; - long long int created; + long long int created, used; - rule->ofproto->ofproto_class->rule_get_stats(rule, - &packet_count, &byte_count); + rule->ofproto->ofproto_class->rule_get_stats(rule, &packet_count, + &byte_count, &used); ovs_mutex_lock(&rule->mutex); - actions = rule_get_actions__(rule); + actions = rule_get_actions(rule); created = rule->created; ovs_mutex_unlock(&rule->mutex); @@ -3660,8 +3645,6 @@ flow_stats_ds(struct rule *rule, struct ds *results) ofpacts_format(actions->ofpacts, actions->ofpacts_len, results); ds_put_cstr(results, "\n"); - - rule_actions_unref(actions); } /* Adds a pretty-printed description of all flows to 'results', including @@ -3751,9 +3734,10 @@ handle_aggregate_stats_request(struct ofconn *ofconn, struct rule *rule = rules.rules[i]; uint64_t packet_count; uint64_t byte_count; + long long int used; ofproto->ofproto_class->rule_get_stats(rule, &packet_count, - &byte_count); + &byte_count, &used); if (packet_count == UINT64_MAX) { unknown_packets = true; @@ -4055,7 +4039,7 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, ovs_refcount_init(&rule->ref_count); rule->pending = NULL; rule->flow_cookie = fm->new_cookie; - rule->created = rule->modified = rule->used = time_msec(); + rule->created = rule->modified = time_msec(); ovs_mutex_init(&rule->mutex); ovs_mutex_lock(&rule->mutex); @@ -4065,7 +4049,8 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, *CONST_CAST(uint8_t *, &rule->table_id) = table - ofproto->tables; rule->flags = fm->flags & OFPUTIL_FF_STATE; - rule->actions = rule_actions_create(ofproto, fm->ofpacts, fm->ofpacts_len); + ovsrcu_set(&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); @@ -4116,6 +4101,7 @@ modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn, error = OFPERR_OFPBRC_EPERM; for (i = 0; i < rules->n; i++) { struct rule *rule = rules->rules[i]; + const struct rule_actions *actions; struct ofoperation *op; bool actions_changed; bool reset_counters; @@ -4129,9 +4115,10 @@ modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn, continue; } + actions = rule_get_actions(rule); actions_changed = !ofpacts_equal(fm->ofpacts, fm->ofpacts_len, - rule->actions->ofpacts, - rule->actions->ofpacts_len); + actions->ofpacts, + actions->ofpacts_len); op = ofoperation_create(group, rule, type, 0); @@ -4158,13 +4145,11 @@ modify_flows__(struct ofproto *ofproto, struct ofconn *ofconn, if (actions_changed || reset_counters) { struct rule_actions *new_actions; - op->actions = rule->actions; + op->actions = rule_get_actions(rule); new_actions = rule_actions_create(ofproto, fm->ofpacts, fm->ofpacts_len); - ovs_mutex_lock(&rule->mutex); - rule->actions = new_actions; - ovs_mutex_unlock(&rule->mutex); + ovsrcu_set(&rule->actions, new_actions); rule->ofproto->ofproto_class->rule_modify_actions(rule, reset_counters); @@ -4345,6 +4330,7 @@ ofproto_rule_send_removed(struct rule *rule, uint8_t reason) OVS_REQUIRES(ofproto_mutex) { struct ofputil_flow_removed fr; + long long int used; if (ofproto_rule_is_hidden(rule) || !(rule->flags & OFPUTIL_FF_SEND_FLOW_REM)) { @@ -4363,7 +4349,7 @@ ofproto_rule_send_removed(struct rule *rule, uint8_t reason) fr.hard_timeout = rule->hard_timeout; ovs_mutex_unlock(&rule->mutex); rule->ofproto->ofproto_class->rule_get_stats(rule, &fr.packet_count, - &fr.byte_count); + &fr.byte_count, &used); connmgr_send_flow_removed(rule->ofproto->connmgr, &fr); } @@ -4744,7 +4730,7 @@ ofproto_compose_flow_refresh_update(const struct rule *rule, if (!(flags & NXFMF_ACTIONS)) { actions = NULL; } else if (!op) { - actions = rule->actions; + actions = rule_get_actions(rule); } else { /* An operation is in progress. Use the previous version of the flow's * actions, so that when the operation commits we report the change. */ @@ -4754,11 +4740,11 @@ ofproto_compose_flow_refresh_update(const struct rule *rule, case OFOPERATION_MODIFY: case OFOPERATION_REPLACE: - actions = op->actions ? op->actions : rule->actions; + actions = op->actions ? op->actions : rule_get_actions(rule); break; case OFOPERATION_DELETE: - actions = rule->actions; + actions = rule_get_actions(rule); break; default: @@ -5800,11 +5786,21 @@ handle_group_mod(struct ofconn *ofconn, const struct ofp_header *oh) } } +enum ofp_table_config +table_get_config(const struct ofproto *ofproto, uint8_t table_id) +{ + unsigned int value; + atomic_read(&ofproto->tables[table_id].config, &value); + return (enum ofp_table_config)value; +} + static enum ofperr table_mod(struct ofproto *ofproto, const struct ofputil_table_mod *tm) { - /* XXX Reject all configurations because none are currently supported */ - return OFPERR_OFPTMFC_BAD_CONFIG; + /* Only accept currently supported configurations */ + if (tm->config & ~OFPTC11_TABLE_MISS_MASK) { + return OFPERR_OFPTMFC_BAD_CONFIG; + } if (tm->table_id == OFPTT_ALL) { int i; @@ -6235,7 +6231,7 @@ ofopgroup_complete(struct ofopgroup *group) ovs_mutex_lock(&rule->mutex); rule->modified = now; if (op->type == OFOPERATION_REPLACE) { - rule->created = rule->used = now; + rule->created = now; } ovs_mutex_unlock(&rule->mutex); } else { @@ -6248,12 +6244,12 @@ ofopgroup_complete(struct ofopgroup *group) struct rule_actions *old_actions; ovs_mutex_lock(&rule->mutex); - old_actions = rule->actions; - rule->actions = op->actions; + old_actions = rule_get_actions(rule); + ovsrcu_set(&rule->actions, op->actions); ovs_mutex_unlock(&rule->mutex); op->actions = NULL; - rule_actions_unref(old_actions); + rule_actions_destroy(old_actions); } rule->flags = op->flags; } @@ -6339,7 +6335,7 @@ ofoperation_destroy(struct ofoperation *op) hmap_remove(&group->ofproto->deletions, &op->hmap_node); } list_remove(&op->group_node); - rule_actions_unref(op->actions); + rule_actions_destroy(op->actions); free(op); } @@ -6600,26 +6596,34 @@ eviction_group_find(struct oftable *table, uint32_t id) /* Returns an eviction priority for 'rule'. The return value should be * interpreted so that higher priorities make a rule more attractive candidates - * for eviction. */ + * for eviction. + * Called only if have a timeout. */ static uint32_t -rule_eviction_priority(struct rule *rule) +rule_eviction_priority(struct ofproto *ofproto, struct rule *rule) OVS_REQUIRES(ofproto_mutex) { - long long int hard_expiration; - long long int idle_expiration; - long long int expiration; + long long int expiration = LLONG_MAX; + long long int modified; uint32_t expiration_offset; - /* Calculate time of expiration. */ + /* 'modified' needs protection even when we hold 'ofproto_mutex'. */ ovs_mutex_lock(&rule->mutex); - hard_expiration = (rule->hard_timeout - ? rule->modified + rule->hard_timeout * 1000 - : LLONG_MAX); - idle_expiration = (rule->idle_timeout - ? rule->used + rule->idle_timeout * 1000 - : LLONG_MAX); - expiration = MIN(hard_expiration, idle_expiration); + modified = rule->modified; ovs_mutex_unlock(&rule->mutex); + + if (rule->hard_timeout) { + expiration = modified + rule->hard_timeout * 1000; + } + if (rule->idle_timeout) { + uint64_t packets, bytes; + long long int used; + long long int idle_expiration; + + ofproto->ofproto_class->rule_get_stats(rule, &packets, &bytes, &used); + idle_expiration = used + rule->idle_timeout * 1000; + expiration = MIN(expiration, idle_expiration); + } + if (expiration == LLONG_MAX) { return 0; } @@ -6649,9 +6653,9 @@ eviction_group_add_rule(struct rule *rule) struct oftable *table = &ofproto->tables[rule->table_id]; bool has_timeout; - ovs_mutex_lock(&rule->mutex); + /* Timeouts may be modified only when holding 'ofproto_mutex'. We have it + * so no additional protection is needed. */ has_timeout = rule->hard_timeout || rule->idle_timeout; - ovs_mutex_unlock(&rule->mutex); if (table->eviction_fields && has_timeout) { struct eviction_group *evg; @@ -6660,7 +6664,7 @@ eviction_group_add_rule(struct rule *rule) rule->eviction_group = evg; heap_insert(&evg->rules, &rule->evg_node, - rule_eviction_priority(rule)); + rule_eviction_priority(ofproto, rule)); eviction_group_resized(table, evg); } } @@ -6689,7 +6693,6 @@ oftable_destroy(struct oftable *table) oftable_disable_eviction(table); classifier_destroy(&table->cls); free(table->name); - atomic_destroy(&table->config); } /* Changes the name of 'table' to 'name'. If 'name' is NULL or the empty @@ -6814,6 +6817,7 @@ oftable_insert_rule(struct rule *rule) { struct ofproto *ofproto = rule->ofproto; struct oftable *table = &ofproto->tables[rule->table_id]; + struct rule_actions *actions; bool may_expire; ovs_mutex_lock(&rule->mutex); @@ -6826,9 +6830,10 @@ oftable_insert_rule(struct rule *rule) cookies_insert(ofproto, rule); - if (rule->actions->provider_meter_id != UINT32_MAX) { - uint32_t meter_id = ofpacts_get_meter(rule->actions->ofpacts, - rule->actions->ofpacts_len); + actions = rule_get_actions(rule); + if (actions->provider_meter_id != UINT32_MAX) { + uint32_t meter_id = ofpacts_get_meter(actions->ofpacts, + actions->ofpacts_len); struct meter *meter = ofproto->meters[meter_id]; list_insert(&meter->rules, &rule->meter_list_node); }