X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=7117e1fb63a11f8de99ec20d21f4eed341611746;hb=d2ad7ef178c39427f2e93ea5c70b3ffc51b7ad1f;hp=2578f6457eca422977a4c1e5ac564512f7ebcfcf;hpb=b90d6ee54a3dea81da58e6e10640fcd165dfb659;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 2578f6457..7117e1fb6 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -182,7 +182,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 +307,6 @@ 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; size_t n_handlers, n_revalidators; @@ -698,13 +697,6 @@ ofproto_set_flow_limit(unsigned limit) ofproto_flow_limit = limit; } -/* Sets the path for handling flow misses. */ -void -ofproto_set_flow_miss_model(unsigned model) -{ - flow_miss_model = model; -} - /* If forward_bpdu is true, the NORMAL action will forward frames with * reserved (e.g. STP) destination Ethernet addresses. if forward_bpdu is false, * the NORMAL action will drop these frames. */ @@ -2201,7 +2193,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 +2210,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 +2236,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 +2245,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 +2255,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); } } @@ -2982,26 +2976,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 +3024,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); } @@ -3601,20 +3596,20 @@ 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); 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; @@ -3637,10 +3632,10 @@ 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); @@ -3751,9 +3746,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 +4051,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); @@ -4345,6 +4341,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 +4360,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); } @@ -6235,7 +6232,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 { @@ -6600,26 +6597,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 +6654,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 +6665,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); } }