Remove locking that is not needed. Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/tnl-ports.c | 102 ++++++++++++++++++++++--------------------------------- 1 file changed, 41 insertions(+), 61 deletions(-)
diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c index 4dbda7d..e46dc58 100644 --- a/lib/tnl-ports.c +++ b/lib/tnl-ports.c @@ -18,44 +18,43 @@ #include <stddef.h> #include <stdint.h> -#include "bitmap.h" #include "classifier.h" -#include "coverage.h" -#include "dpif-netdev.h" #include "fat-rwlock.h" #include "dynamic-string.h" #include "errno.h" -#include "flow.h" #include "hash.h" -#include "list.h" -#include "netdev.h" +#include "ofpbuf.h" #include "ovs-thread.h" #include "odp-util.h" -#include "packet-dpif.h" -#include "packets.h" -#include "poll-loop.h" -#include "timeval.h" #include "tnl-arp-cache.h" #include "tnl-ports.h" -#include "tnl-ports.h" -#include "unaligned.h" #include "unixctl.h" #include "util.h" -static struct classifier cls; -static struct ovs_mutex tunnel_mutex = OVS_MUTEX_INITIALIZER; +static struct classifier cls; /* Tunnel ports. */ -struct tunnel_ports { +struct tunnel_port { struct cls_rule cr; odp_port_t portno; struct ovs_refcount ref_cnt; char dev_name[IFNAMSIZ]; }; -static struct tunnel_ports * +static struct tunnel_port * tnl_port_cast(const struct cls_rule *cr) { - return cr ? CONTAINER_OF(cr, struct tunnel_ports, cr) : NULL; + if (offsetof(struct tunnel_port, cr) == 0) { + return CONTAINER_OF(cr, struct tunnel_port, cr); + } else { + return cr ? CONTAINER_OF(cr, struct tunnel_port, cr) : NULL; + } +} + +static void +tnl_port_free(struct tunnel_port *p) +{ + cls_rule_destroy(&p->cr); + free(p); } void @@ -63,58 +62,50 @@ tnl_port_insert_udp(odp_port_t port, ovs_be32 ip_dst, ovs_be16 udp_port, const char dev_name[]) { const struct cls_rule *cr; - struct tunnel_ports *p; - struct flow_wildcards wc; + struct tunnel_port *p; struct match match; - struct flow flow; - memset(&flow, 0, sizeof flow); + memset(&match, 0, sizeof match); - flow.dl_type = htons(ETH_TYPE_IP); - flow.nw_proto = IPPROTO_UDP; - flow.tp_dst = udp_port; - flow.nw_src = ip_dst; - - cr = classifier_lookup(&cls, &flow, NULL); - if (cr) { - struct tunnel_ports *p; + match.flow.dl_type = htons(ETH_TYPE_IP); + match.flow.nw_proto = IPPROTO_UDP; + match.flow.tp_dst = udp_port; + match.flow.nw_src = ip_dst; + 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)); - ovs_refcount_ref(&p->ref_cnt); - return; + if (p) { + return; /* Added refcount of an existing port. */ } p = xzalloc(sizeof *p); p->portno = port; - memset(&wc, 0, sizeof(wc)); - wc.masks.dl_type = 0xffff; - wc.masks.nw_proto = 0xff; - wc.masks.nw_frag = 0xff; - wc.masks.tp_dst = 0xffff; - wc.masks.nw_src = 0xffffffff; + 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; - /* Need to check IP address. */ - match_init(&match, &flow, &wc); - cls_rule_init(&p->cr, &match, 1); + cls_rule_init(&p->cr, &match, 0); /* Priority == 0. */ ovs_refcount_init(&p->ref_cnt); strncpy(p->dev_name, dev_name, IFNAMSIZ); - ovs_mutex_lock(&tunnel_mutex); classifier_insert(&cls, &p->cr); - ovs_mutex_unlock(&tunnel_mutex); } static void tnl_port_unref(struct cls_rule *cr) { - if (cr) { - struct tunnel_ports *p; + struct tunnel_port *p = tnl_port_cast(cr); - p = tnl_port_cast(cr); - if (ovs_refcount_unref_relaxed(&p->ref_cnt) == 1) { - classifier_remove(&cls, cr); + if (cr && ovs_refcount_unref_relaxed(&p->ref_cnt) == 1) { + if (classifier_remove(&cls, cr)) { + ovsrcu_postpone(tnl_port_free, p); } } } @@ -131,25 +122,16 @@ tnl_port_delete(ovs_be32 ip_dst, ovs_be16 udp_port) flow.tp_dst = udp_port; flow.nw_src = ip_dst; - ovs_mutex_lock(&tunnel_mutex); cr = classifier_lookup(&cls, &flow, NULL); tnl_port_unref(cr); - ovs_mutex_unlock(&tunnel_mutex); } odp_port_t tnl_port_lookup(const struct flow *flow, struct flow_wildcards *wc) { - const struct cls_rule *cr; - const struct tunnel_ports *p; + const struct cls_rule *cr = classifier_lookup(&cls, flow, wc); - /* Un wildcard protocol and stuff */ - cr = classifier_lookup(&cls, flow, wc); - if (!cr) { - return ODPP_NONE; - } - p = tnl_port_cast(cr); - return p->portno; + return (cr) ? tnl_port_cast(cr)->portno : ODPP_NONE; } static void @@ -157,9 +139,8 @@ tnl_port_show(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; - const struct tunnel_ports *p; + const struct tunnel_port *p; - ovs_mutex_lock(&tunnel_mutex); CLS_FOR_EACH(p, cr, &cls) { struct odputil_keybuf keybuf; struct odputil_keybuf maskbuf; @@ -190,7 +171,6 @@ tnl_port_show(struct unixctl_conn *conn, int argc OVS_UNUSED, /* build string. */ odp_flow_format(key, key_len, mask, mask_len, NULL, &ds, false); } - ovs_mutex_unlock(&tunnel_mutex); unixctl_command_reply(conn, ds_cstr(&ds)); ds_destroy(&ds); } -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev