diff options
author | Jarno Rajahalme <jrajahalme@nicira.com> | 2014-11-14 15:58:09 -0800 |
---|---|---|
committer | Jarno Rajahalme <jrajahalme@nicira.com> | 2014-11-14 15:58:09 -0800 |
commit | fccd7c092e09ce9767d34436bf9c70302c87c5f5 (patch) | |
tree | c8f4b214dcc276199be878ce9c4b1c603cec0a8f /lib/tnl-ports.c | |
parent | de4ad4a21569fa63912be87c1b2e858d888dc1b0 (diff) | |
download | openvswitch-fccd7c092e09ce9767d34436bf9c70302c87c5f5.tar.gz |
classifier: Remove internal mutex.
Almost all classifier users already exclude concurrent modifications,
or are single-threaded, hence the classifier internal mutex can be
removed. Due to this change, ovs-router.c and tnl-ports.c need new
mutexes, which are added.
As noted by Ben in review, ovs_router_flush() should also free the
entries it removes from the classifier. It now calls
ovsrcu_postpone() to that effect.
Suggested-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/tnl-ports.c')
-rw-r--r-- | lib/tnl-ports.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index bcf055ba2..9832ef46d 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -26,9 +26,11 @@ #include "odp-util.h" #include "tnl-arp-cache.h" #include "tnl-ports.h" +#include "ovs-thread.h" #include "unixctl.h" #include "util.h" +static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; static struct classifier cls; /* Tunnel ports. */ struct tnl_port_in { @@ -80,30 +82,30 @@ tnl_port_map_insert(odp_port_t port, ovs_be32 ip_dst, ovs_be16 udp_port, memset(&match, 0, sizeof match); tnl_port_init_flow(&match.flow, ip_dst, udp_port); + ovs_mutex_lock(&mutex); do { cr = classifier_lookup(&cls, &match.flow, NULL); p = tnl_port_cast(cr); /* Try again if the rule was released before we get the reference. */ } while (p && !ovs_refcount_try_ref_rcu(&p->ref_cnt)); - if (p) { - return; /* Added refcount of an existing port. */ - } - - p = xzalloc(sizeof *p); - p->portno = port; + if (!p) { + p = xzalloc(sizeof *p); + p->portno = port; - match.wc.masks.dl_type = OVS_BE16_MAX; - match.wc.masks.nw_proto = 0xff; - match.wc.masks.nw_frag = 0xff; /* XXX: No fragments support. */ - match.wc.masks.tp_dst = OVS_BE16_MAX; - match.wc.masks.nw_src = OVS_BE32_MAX; + match.wc.masks.dl_type = OVS_BE16_MAX; + match.wc.masks.nw_proto = 0xff; + match.wc.masks.nw_frag = 0xff; /* XXX: No fragments support. */ + match.wc.masks.tp_dst = OVS_BE16_MAX; + match.wc.masks.nw_src = OVS_BE32_MAX; - cls_rule_init(&p->cr, &match, 0); /* Priority == 0. */ - ovs_refcount_init(&p->ref_cnt); - strncpy(p->dev_name, dev_name, IFNAMSIZ); + cls_rule_init(&p->cr, &match, 0); /* Priority == 0. */ + ovs_refcount_init(&p->ref_cnt); + strncpy(p->dev_name, dev_name, IFNAMSIZ); - classifier_insert(&cls, &p->cr); + classifier_insert(&cls, &p->cr); + } + ovs_mutex_unlock(&mutex); } static void @@ -112,9 +114,11 @@ tnl_port_unref(const struct cls_rule *cr) struct tnl_port_in *p = tnl_port_cast(cr); if (cr && ovs_refcount_unref_relaxed(&p->ref_cnt) == 1) { + ovs_mutex_lock(&mutex); if (classifier_remove(&cls, cr)) { ovsrcu_postpone(tnl_port_free, p); } + ovs_mutex_unlock(&mutex); } } |