X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=datapath%2Ftunnel.c;h=46f966b8649dbe26cc9ce0d24131214fd3f3fb6f;hb=7f9bd4e8db2b307813c44bce0c5c5e2e69331c25;hp=548b99dc105de7f37e8f2557c74d9dc4abc21866;hpb=dd851cbbcc5a1b3c8ad5c10a47ddca1c510c1879;p=openvswitch diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 548b99dc..46f966b8 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Nicira Networks. + * Copyright (c) 2010, 2011 Nicira Networks. * Distributed under the terms of the GNU GPL version 2. * * Significant portions of this file may be copied from parts of the Linux @@ -1323,9 +1323,9 @@ out: return sent_len; } -static int set_config(const void *config, const struct tnl_ops *tnl_ops, - const struct vport *cur_vport, - struct tnl_mutable_config *mutable) +static int tnl_set_config(const void *config, const struct tnl_ops *tnl_ops, + const struct vport *cur_vport, + struct tnl_mutable_config *mutable) { const struct vport *old_vport; const struct tnl_mutable_config *old_mutable; @@ -1372,6 +1372,7 @@ struct vport *tnl_create(const struct vport_parms *parms, { struct vport *vport; struct tnl_vport *tnl_vport; + struct tnl_mutable_config *mutable; int initial_frag_id; int err; @@ -1386,19 +1387,19 @@ struct vport *tnl_create(const struct vport_parms *parms, strcpy(tnl_vport->name, parms->name); tnl_vport->tnl_ops = tnl_ops; - tnl_vport->mutable = kzalloc(sizeof(struct tnl_mutable_config), GFP_KERNEL); - if (!tnl_vport->mutable) { + mutable = kzalloc(sizeof(struct tnl_mutable_config), GFP_KERNEL); + if (!mutable) { err = -ENOMEM; goto error_free_vport; } - vport_gen_rand_ether_addr(tnl_vport->mutable->eth_addr); - tnl_vport->mutable->mtu = ETH_DATA_LEN; + vport_gen_rand_ether_addr(mutable->eth_addr); + mutable->mtu = ETH_DATA_LEN; get_random_bytes(&initial_frag_id, sizeof(int)); atomic_set(&tnl_vport->frag_id, initial_frag_id); - err = set_config(parms->config, tnl_ops, NULL, tnl_vport->mutable); + err = tnl_set_config(parms->config, tnl_ops, NULL, mutable); if (err) goto error_free_mutable; @@ -1406,9 +1407,11 @@ struct vport *tnl_create(const struct vport_parms *parms, #ifdef NEED_CACHE_TIMEOUT tnl_vport->cache_exp_interval = MAX_CACHE_EXP - - (net_random() % (MAX_CACHE_EXP / 2)); + (net_random() % (MAX_CACHE_EXP / 2)); #endif + rcu_assign_pointer(tnl_vport->mutable, mutable); + err = add_port(vport); if (err) goto error_free_mutable; @@ -1416,7 +1419,7 @@ struct vport *tnl_create(const struct vport_parms *parms, return vport; error_free_mutable: - kfree(tnl_vport->mutable); + kfree(mutable); error_free_vport: vport_free(vport); error: @@ -1429,13 +1432,14 @@ int tnl_modify(struct vport *vport, struct odp_port *port) struct tnl_mutable_config *mutable; int err; - mutable = kmemdup(tnl_vport->mutable, sizeof(struct tnl_mutable_config), GFP_KERNEL); + mutable = kmemdup(rtnl_dereference(tnl_vport->mutable), + sizeof(struct tnl_mutable_config), GFP_KERNEL); if (!mutable) { err = -ENOMEM; goto error; } - err = set_config(port->config, tnl_vport->tnl_ops, vport, mutable); + err = tnl_set_config(port->config, tnl_vport->tnl_ops, vport, mutable); if (err) goto error_free; @@ -1455,26 +1459,24 @@ error: static void free_port_rcu(struct rcu_head *rcu) { - struct tnl_vport *tnl_vport = container_of(rcu, struct tnl_vport, rcu); + struct tnl_vport *tnl_vport = container_of(rcu, + struct tnl_vport, rcu); - spin_lock_bh(&tnl_vport->cache_lock); - free_cache(tnl_vport->cache); - spin_unlock_bh(&tnl_vport->cache_lock); - - kfree(tnl_vport->mutable); + free_cache((struct tnl_cache __force *)tnl_vport->cache); + kfree((struct tnl_mutable __force *)tnl_vport->mutable); vport_free(tnl_vport_to_vport(tnl_vport)); } int tnl_destroy(struct vport *vport) { struct tnl_vport *tnl_vport = tnl_vport_priv(vport); - const struct tnl_mutable_config *old_mutable; + const struct tnl_mutable_config *mutable, *old_mutable; + + mutable = rtnl_dereference(tnl_vport->mutable); - if (vport == tnl_find_port(tnl_vport->mutable->port_config.saddr, - tnl_vport->mutable->port_config.daddr, - tnl_vport->mutable->port_config.in_key, - tnl_vport->mutable->tunnel_type, - &old_mutable)) + if (vport == tnl_find_port(mutable->port_config.saddr, + mutable->port_config.daddr, mutable->port_config.in_key, + mutable->tunnel_type, &old_mutable)) del_port(vport); call_rcu(&tnl_vport->rcu, free_port_rcu); @@ -1487,7 +1489,8 @@ int tnl_set_mtu(struct vport *vport, int mtu) struct tnl_vport *tnl_vport = tnl_vport_priv(vport); struct tnl_mutable_config *mutable; - mutable = kmemdup(tnl_vport->mutable, sizeof(struct tnl_mutable_config), GFP_KERNEL); + mutable = kmemdup(rtnl_dereference(tnl_vport->mutable), + sizeof(struct tnl_mutable_config), GFP_KERNEL); if (!mutable) return -ENOMEM; @@ -1502,7 +1505,8 @@ int tnl_set_addr(struct vport *vport, const unsigned char *addr) struct tnl_vport *tnl_vport = tnl_vport_priv(vport); struct tnl_mutable_config *mutable; - mutable = kmemdup(tnl_vport->mutable, sizeof(struct tnl_mutable_config), GFP_KERNEL); + mutable = kmemdup(rtnl_dereference(tnl_vport->mutable), + sizeof(struct tnl_mutable_config), GFP_KERNEL); if (!mutable) return -ENOMEM;