X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=b2cdb108418343f8b35c2af4d161925cc70d56ea;hb=1e827902be9194d71ea851c9ce2676f65eeed33a;hp=ef444a24aba5468e5482a9fd4e40fc4916bf79c2;hpb=67761761a4a49f8af7d04b0e3dd9ae9b0534540c;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index ef444a24a..b2cdb1084 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * Copyright (c) 2010 Jean Tourrilhes - HP-Labs. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -306,10 +306,10 @@ static size_t allocated_ofproto_classes; /* Global lock that protects all flow table operations. */ struct ovs_mutex ofproto_mutex = OVS_MUTEX_INITIALIZER; -unsigned flow_eviction_threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT; +unsigned ofproto_flow_limit = OFPROTO_FLOW_LIMIT_DEFAULT; enum ofproto_flow_miss_model flow_miss_model = OFPROTO_HANDLE_MISS_AUTO; -size_t n_handlers; +size_t n_handlers, n_revalidators; /* Map from datapath name to struct ofproto, for use by unixctl commands. */ static struct hmap all_ofprotos = HMAP_INITIALIZER(&all_ofprotos); @@ -693,10 +693,9 @@ ofproto_set_in_band_queue(struct ofproto *ofproto, int queue_id) /* Sets the number of flows at which eviction from the kernel flow table * will occur. */ void -ofproto_set_flow_eviction_threshold(unsigned threshold) +ofproto_set_flow_limit(unsigned limit) { - flow_eviction_threshold = MAX(OFPROTO_FLOW_EVICTION_THRESHOLD_MIN, - threshold); + ofproto_flow_limit = limit; } /* Sets the path for handling flow misses. */ @@ -734,13 +733,23 @@ ofproto_set_mac_table_config(struct ofproto *ofproto, unsigned idle_time, } } -/* Sets number of upcall handler threads. The default is - * (number of online cores - 2). */ void -ofproto_set_threads(size_t n_handlers_) +ofproto_set_threads(size_t n_handlers_, size_t n_revalidators_) { - int threads = MAX(count_cpu_cores() - 2, 1); - n_handlers = n_handlers_ ? n_handlers_ : threads; + int threads = MAX(count_cpu_cores(), 2); + + n_revalidators = n_revalidators_; + n_handlers = n_handlers_; + + if (!n_revalidators) { + n_revalidators = n_handlers + ? MAX(threads - (int) n_handlers, 1) + : threads / 4 + 1; + } + + if (!n_handlers) { + n_handlers = MAX(threads - (int) n_revalidators, 1); + } } void @@ -1159,7 +1168,7 @@ ofproto_configure_table(struct ofproto *ofproto, int table_id, } table->max_flows = s->max_flows; - ovs_rwlock_wrlock(&table->cls.rwlock); + fat_rwlock_wrlock(&table->cls.rwlock); if (classifier_count(&table->cls) > table->max_flows && table->eviction_fields) { /* 'table' contains more flows than allowed. We might not be able to @@ -1179,7 +1188,7 @@ ofproto_configure_table(struct ofproto *ofproto, int table_id, classifier_set_prefix_fields(&table->cls, s->prefix_fields, s->n_prefix_fields); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); } bool @@ -1254,9 +1263,9 @@ ofproto_flush__(struct ofproto *ofproto) continue; } - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, NULL); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, cr, &cursor) { if (!rule->pending) { ofproto_rule_delete__(ofproto, rule, OFPRR_DELETE); @@ -1445,7 +1454,7 @@ ofproto_run(struct ofproto *p) heap_rebuild(&evg->rules); } - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, NULL); CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { if (!rule->eviction_group @@ -1453,7 +1462,7 @@ ofproto_run(struct ofproto *p) eviction_group_add_rule(rule); } } - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); ovs_mutex_unlock(&ofproto_mutex); } } @@ -1603,9 +1612,9 @@ ofproto_get_memory_usage(const struct ofproto *ofproto, struct simap *usage) n_rules = 0; OFPROTO_FOR_EACH_TABLE (table, ofproto) { - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); n_rules += classifier_count(&table->cls); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); } simap_increase(usage, "rules", n_rules); @@ -1892,7 +1901,7 @@ ofproto_add_flow(struct ofproto *ofproto, const struct match *match, /* First do a cheap check whether the rule we're looking for already exists * with the actions that we want. If it does, then we're done. */ - ovs_rwlock_rdlock(&ofproto->tables[0].cls.rwlock); + fat_rwlock_rdlock(&ofproto->tables[0].cls.rwlock); rule = rule_from_cls_rule(classifier_find_match_exactly( &ofproto->tables[0].cls, match, priority)); if (rule) { @@ -1904,7 +1913,7 @@ ofproto_add_flow(struct ofproto *ofproto, const struct match *match, } else { must_add = true; } - ovs_rwlock_unlock(&ofproto->tables[0].cls.rwlock); + fat_rwlock_unlock(&ofproto->tables[0].cls.rwlock); /* If there's no such rule or the rule doesn't have the actions we want, * fall back to a executing a full flow mod. We can't optimize this at @@ -1943,10 +1952,10 @@ ofproto_delete_flow(struct ofproto *ofproto, /* First do a cheap check whether the rule we're looking for has already * been deleted. If so, then we're done. */ - ovs_rwlock_rdlock(&cls->rwlock); + fat_rwlock_rdlock(&cls->rwlock); rule = rule_from_cls_rule(classifier_find_match_exactly(cls, target, priority)); - ovs_rwlock_unlock(&cls->rwlock); + fat_rwlock_unlock(&cls->rwlock); if (!rule) { return true; } @@ -2518,26 +2527,16 @@ void ofproto_rule_ref(struct rule *rule) { if (rule) { - unsigned int orig; - - atomic_add(&rule->ref_count, 1, &orig); - ovs_assert(orig != 0); + ovs_refcount_ref(&rule->ref_count); } } void ofproto_rule_unref(struct rule *rule) { - if (rule) { - unsigned int orig; - - atomic_sub(&rule->ref_count, 1, &orig); - if (orig == 1) { - rule->ofproto->ofproto_class->rule_destruct(rule); - ofproto_rule_destroy__(rule); - } else { - ovs_assert(orig != 0); - } + if (rule && ovs_refcount_unref(&rule->ref_count) == 1) { + rule->ofproto->ofproto_class->rule_destruct(rule); + ofproto_rule_destroy__(rule); } } @@ -2569,6 +2568,7 @@ ofproto_rule_destroy__(struct rule *rule) cls_rule_destroy(CONST_CAST(struct cls_rule *, &rule->cr)); rule_actions_unref(rule->actions); ovs_mutex_destroy(&rule->mutex); + ovs_refcount_destroy(&rule->ref_count); rule->ofproto->ofproto_class->rule_dealloc(rule); } @@ -2584,7 +2584,7 @@ rule_actions_create(const struct ofproto *ofproto, struct rule_actions *actions; actions = xmalloc(sizeof *actions); - atomic_init(&actions->ref_count, 1); + ovs_refcount_init(&actions->ref_count); actions->ofpacts = xmemdup(ofpacts, ofpacts_len); actions->ofpacts_len = ofpacts_len; actions->provider_meter_id @@ -2599,10 +2599,7 @@ void rule_actions_ref(struct rule_actions *actions) { if (actions) { - unsigned int orig; - - atomic_add(&actions->ref_count, 1, &orig); - ovs_assert(orig != 0); + ovs_refcount_ref(&actions->ref_count); } } @@ -2611,16 +2608,10 @@ rule_actions_ref(struct rule_actions *actions) void rule_actions_unref(struct rule_actions *actions) { - if (actions) { - unsigned int orig; - - atomic_sub(&actions->ref_count, 1, &orig); - if (orig == 1) { - free(actions->ofpacts); - free(actions); - } else { - ovs_assert(orig != 0); - } + if (actions && ovs_refcount_unref(&actions->ref_count) == 1) { + ovs_refcount_destroy(&actions->ref_count); + free(actions->ofpacts); + free(actions); } } @@ -3069,9 +3060,9 @@ handle_table_stats_request(struct ofconn *ofconn, ots[i].instructions = htonl(OFPIT11_ALL); ots[i].config = htonl(OFPTC11_TABLE_MISS_MASK); ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */ - ovs_rwlock_rdlock(&p->tables[i].cls.rwlock); + fat_rwlock_rdlock(&p->tables[i].cls.rwlock); ots[i].active_count = htonl(classifier_count(&p->tables[i].cls)); - ovs_rwlock_unlock(&p->tables[i].cls.rwlock); + fat_rwlock_unlock(&p->tables[i].cls.rwlock); } p->ofproto_class->get_tables(p, ots); @@ -3218,14 +3209,11 @@ calc_duration(long long int start, long long int now, } /* Checks whether 'table_id' is 0xff or a valid table ID in 'ofproto'. Returns - * 0 if 'table_id' is OK, otherwise an OpenFlow error code. */ -static enum ofperr + * true if 'table_id' is OK, false otherwise. */ +static bool check_table_id(const struct ofproto *ofproto, uint8_t table_id) { - return (table_id == 0xff || table_id < ofproto->n_tables - ? 0 - : OFPERR_OFPBRC_BAD_TABLE_ID); - + return table_id == OFPTT_ALL || table_id < ofproto->n_tables; } static struct oftable * @@ -3409,12 +3397,12 @@ collect_rules_loose(struct ofproto *ofproto, OVS_REQUIRES(ofproto_mutex) { struct oftable *table; - enum ofperr error; + enum ofperr error = 0; rule_collection_init(rules); - error = check_table_id(ofproto, criteria->table_id); - if (error) { + if (!check_table_id(ofproto, criteria->table_id)) { + error = OFPERR_OFPBRC_BAD_TABLE_ID; goto exit; } @@ -3436,7 +3424,7 @@ collect_rules_loose(struct ofproto *ofproto, struct cls_cursor cursor; struct rule *rule; - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, &criteria->cr); CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { error = collect_rule(rule, criteria, rules); @@ -3444,7 +3432,7 @@ collect_rules_loose(struct ofproto *ofproto, break; } } - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); } } @@ -3470,12 +3458,12 @@ collect_rules_strict(struct ofproto *ofproto, OVS_REQUIRES(ofproto_mutex) { struct oftable *table; - int error; + int error = 0; rule_collection_init(rules); - error = check_table_id(ofproto, criteria->table_id); - if (error) { + if (!check_table_id(ofproto, criteria->table_id)) { + error = OFPERR_OFPBRC_BAD_TABLE_ID; goto exit; } @@ -3496,10 +3484,10 @@ collect_rules_strict(struct ofproto *ofproto, FOR_EACH_MATCHING_TABLE (table, criteria->table_id, ofproto) { struct rule *rule; - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); rule = rule_from_cls_rule(classifier_find_rule_exactly( &table->cls, &criteria->cr)); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); if (rule) { error = collect_rule(rule, criteria, rules); if (error) { @@ -3647,12 +3635,12 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results) struct cls_cursor cursor; struct rule *rule; - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, NULL); CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { flow_stats_ds(rule, results); } - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); } } @@ -3928,10 +3916,10 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, struct cls_rule cr; struct rule *rule; uint8_t table_id; - int error; + int error = 0; - error = check_table_id(ofproto, fm->table_id); - if (error) { + if (!check_table_id(ofproto, fm->table_id)) { + error = OFPERR_OFPBRC_BAD_TABLE_ID; return error; } @@ -3963,9 +3951,9 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, cls_rule_init(&cr, &fm->match, fm->priority); /* Transform "add" into "modify" if there's an existing identical flow. */ - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls, &cr)); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); if (rule) { cls_rule_destroy(&cr); if (!rule_is_modifiable(rule)) { @@ -3995,9 +3983,9 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, if (fm->flags & OFPUTIL_FF_CHECK_OVERLAP) { bool overlaps; - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); overlaps = classifier_rule_overlaps(&table->cls, &cr); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); if (overlaps) { cls_rule_destroy(&cr); @@ -4024,7 +4012,7 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, /* Initialize base state. */ *CONST_CAST(struct ofproto **, &rule->ofproto) = ofproto; cls_rule_move(CONST_CAST(struct cls_rule *, &rule->cr), &cr); - atomic_init(&rule->ref_count, 1); + ovs_refcount_init(&rule->ref_count); rule->pending = NULL; rule->flow_cookie = fm->new_cookie; rule->created = rule->modified = rule->used = time_msec(); @@ -4818,13 +4806,13 @@ ofproto_collect_ofmonitor_refresh_rules(const struct ofmonitor *m, struct cls_cursor cursor; struct rule *rule; - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, &target); CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { ovs_assert(!rule->pending); /* XXX */ ofproto_collect_ofmonitor_refresh_rule(m, rule, seqno, rules); } - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); } HMAP_FOR_EACH (op, hmap_node, &ofproto->deletions) { @@ -6653,12 +6641,13 @@ oftable_init(struct oftable *table) static void oftable_destroy(struct oftable *table) { - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); ovs_assert(classifier_is_empty(&table->cls)); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); 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 @@ -6737,12 +6726,12 @@ oftable_enable_eviction(struct oftable *table, hmap_init(&table->eviction_groups_by_id); heap_init(&table->eviction_groups_by_size); - ovs_rwlock_rdlock(&table->cls.rwlock); + fat_rwlock_rdlock(&table->cls.rwlock); cls_cursor_init(&cursor, &table->cls, NULL); CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { eviction_group_add_rule(rule); } - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); } /* Removes 'rule' from the oftable that contains it. */ @@ -6752,9 +6741,9 @@ oftable_remove_rule__(struct ofproto *ofproto, struct rule *rule) { struct classifier *cls = &ofproto->tables[rule->table_id].cls; - ovs_rwlock_wrlock(&cls->rwlock); + fat_rwlock_wrlock(&cls->rwlock); classifier_remove(cls, CONST_CAST(struct cls_rule *, &rule->cr)); - ovs_rwlock_unlock(&cls->rwlock); + fat_rwlock_unlock(&cls->rwlock); cookies_remove(ofproto, rule); @@ -6801,9 +6790,9 @@ oftable_insert_rule(struct rule *rule) struct meter *meter = ofproto->meters[meter_id]; list_insert(&meter->rules, &rule->meter_list_node); } - ovs_rwlock_wrlock(&table->cls.rwlock); + fat_rwlock_wrlock(&table->cls.rwlock); classifier_insert(&table->cls, CONST_CAST(struct cls_rule *, &rule->cr)); - ovs_rwlock_unlock(&table->cls.rwlock); + fat_rwlock_unlock(&table->cls.rwlock); eviction_group_add_rule(rule); } @@ -6872,7 +6861,7 @@ ofproto_get_vlan_usage(struct ofproto *ofproto, unsigned long int *vlan_bitmap) OFPROTO_FOR_EACH_TABLE (oftable, ofproto) { const struct cls_subtable *table; - ovs_rwlock_rdlock(&oftable->cls.rwlock); + fat_rwlock_rdlock(&oftable->cls.rwlock); HMAP_FOR_EACH (table, hmap_node, &oftable->cls.subtables) { if (minimask_get_vid_mask(&table->mask) == VLAN_VID_MASK) { const struct cls_rule *rule; @@ -6884,7 +6873,7 @@ ofproto_get_vlan_usage(struct ofproto *ofproto, unsigned long int *vlan_bitmap) } } } - ovs_rwlock_unlock(&oftable->cls.rwlock); + fat_rwlock_unlock(&oftable->cls.rwlock); } }