projects
/
openvswitch
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
gre: Network namespace upon device creation.
[openvswitch]
/
datapath
/
linux-2.6
/
compat-2.6
/
ip_gre.c
diff --git
a/datapath/linux-2.6/compat-2.6/ip_gre.c
b/datapath/linux-2.6/compat-2.6/ip_gre.c
index 4c47b92530af17f600dca771efce05e4e0dc61ac..2f1a9adbeb78f201dc25d2611fde59e906b97da5 100644
(file)
--- a/
datapath/linux-2.6/compat-2.6/ip_gre.c
+++ b/
datapath/linux-2.6/compat-2.6/ip_gre.c
@@
-178,8
+178,13
@@
struct ipgre_net {
#define tunnels_r tunnels[2]
#define tunnels_l tunnels[1]
#define tunnels_wc tunnels[0]
#define tunnels_r tunnels[2]
#define tunnels_l tunnels[1]
#define tunnels_wc tunnels[0]
+/*
+ * Locking : hash tables are protected by RCU and a spinlock
+ */
+static DEFINE_SPINLOCK(ipgre_lock);
-static DEFINE_RWLOCK(ipgre_lock);
+#define for_each_ip_tunnel_rcu(start) \
+ for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
/* Given src, dst and key, find appropriate for input tunnel. */
/* Given src, dst and key, find appropriate for input tunnel. */
@@
-197,7
+202,7
@@
static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
ARPHRD_ETHER : ARPHRD_IPGRE;
int score, cand_score = 4;
ARPHRD_ETHER : ARPHRD_IPGRE;
int score, cand_score = 4;
- for
(t = ign->tunnels_r_l[h0^h1]; t; t = t->next
) {
+ for
_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]
) {
if (local != t->parms.iph.saddr ||
remote != t->parms.iph.daddr ||
key != t->parms.i_key ||
if (local != t->parms.iph.saddr ||
remote != t->parms.iph.daddr ||
key != t->parms.i_key ||
@@
-222,7
+227,7
@@
static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
}
}
}
}
- for
(t = ign->tunnels_r[h0^h1]; t; t = t->next
) {
+ for
_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]
) {
if (remote != t->parms.iph.daddr ||
key != t->parms.i_key ||
!(t->dev->flags & IFF_UP))
if (remote != t->parms.iph.daddr ||
key != t->parms.i_key ||
!(t->dev->flags & IFF_UP))
@@
-246,7
+251,7
@@
static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
}
}
}
}
- for
(t = ign->tunnels_l[h1]; t; t = t->next
) {
+ for
_each_ip_tunnel_rcu(ign->tunnels_l[h1]
) {
if ((local != t->parms.iph.saddr &&
(local != t->parms.iph.daddr ||
!ipv4_is_multicast(local))) ||
if ((local != t->parms.iph.saddr &&
(local != t->parms.iph.daddr ||
!ipv4_is_multicast(local))) ||
@@
-272,7
+277,7
@@
static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
}
}
}
}
- for
(t = ign->tunnels_wc[h1]; t; t = t->next
) {
+ for
_each_ip_tunnel_rcu(ign->tunnels_wc[h1]
) {
if (t->parms.i_key != key ||
!(t->dev->flags & IFF_UP))
continue;
if (t->parms.i_key != key ||
!(t->dev->flags & IFF_UP))
continue;
@@
-298,8
+303,9
@@
static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
if (cand != NULL)
return cand;
if (cand != NULL)
return cand;
- if (ign->fb_tunnel_dev->flags & IFF_UP)
- return netdev_priv(ign->fb_tunnel_dev);
+ dev = ign->fb_tunnel_dev;
+ if (dev->flags & IFF_UP)
+ return netdev_priv(dev);
return NULL;
}
return NULL;
}
@@
-333,10
+339,10
@@
static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
{
struct ip_tunnel **tp = ipgre_bucket(ign, t);
{
struct ip_tunnel **tp = ipgre_bucket(ign, t);
+ spin_lock_bh(&ipgre_lock);
t->next = *tp;
t->next = *tp;
- write_lock_bh(&ipgre_lock);
- *tp = t;
- write_unlock_bh(&ipgre_lock);
+ rcu_assign_pointer(*tp, t);
+ spin_unlock_bh(&ipgre_lock);
}
static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
}
static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
@@
-345,9
+351,9
@@
static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) {
if (t == *tp) {
for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) {
if (t == *tp) {
-
write
_lock_bh(&ipgre_lock);
+
spin
_lock_bh(&ipgre_lock);
*tp = t->next;
*tp = t->next;
-
write
_unlock_bh(&ipgre_lock);
+
spin
_unlock_bh(&ipgre_lock);
break;
}
}
break;
}
}
@@
-504,7
+510,7
@@
static void ipgre_err(struct sk_buff *skb, u32 info)
break;
}
break;
}
- r
ead_lock(&ipgre_lock
);
+ r
cu_read_lock(
);
t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
flags & GRE_KEY ?
*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
flags & GRE_KEY ?
*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
@@
-522,7
+528,7
@@
static void ipgre_err(struct sk_buff *skb, u32 info)
t->err_count = 1;
t->err_time = jiffies;
out:
t->err_count = 1;
t->err_time = jiffies;
out:
- r
ead_unlock(&ipgre_lock
);
+ r
cu_read_unlock(
);
return;
}
return;
}
@@
-601,7
+607,7
@@
static int ipgre_rcv(struct sk_buff *skb)
gre_proto = *(__be16 *)(h + 2);
gre_proto = *(__be16 *)(h + 2);
- r
ead_lock(&ipgre_lock
);
+ r
cu_read_lock(
);
if ((tunnel = ipgre_tunnel_lookup(skb->dev,
iph->saddr, iph->daddr, key,
gre_proto))) {
if ((tunnel = ipgre_tunnel_lookup(skb->dev,
iph->saddr, iph->daddr, key,
gre_proto))) {
@@
-680,13
+686,13
@@
static int ipgre_rcv(struct sk_buff *skb)
ipgre_ecn_decapsulate(iph, skb);
netif_rx(skb);
ipgre_ecn_decapsulate(iph, skb);
netif_rx(skb);
- r
ead_unlock(&ipgre_lock
);
+ r
cu_read_unlock(
);
return(0);
}
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
return(0);
}
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
- r
ead_unlock(&ipgre_lock
);
+ r
cu_read_unlock(
);
drop_nolock:
kfree_skb(skb);
return(0);
drop_nolock:
kfree_skb(skb);
return(0);
@@
-1440,16
+1446,19
@@
static const struct net_protocol ipgre_protocol = {
#endif
};
#endif
};
-static void ipgre_destroy_tunnels(struct ipgre_net *ign)
+static void ipgre_destroy_tunnels(struct ipgre_net *ign
, struct list_head *head
)
{
int prio;
for (prio = 0; prio < 4; prio++) {
int h;
for (h = 0; h < HASH_SIZE; h++) {
{
int prio;
for (prio = 0; prio < 4; prio++) {
int h;
for (h = 0; h < HASH_SIZE; h++) {
- struct ip_tunnel *t;
- while ((t = ign->tunnels[prio][h]) != NULL)
- unregister_netdevice(t->dev);
+ struct ip_tunnel *t = ign->tunnels[prio][h];
+
+ while (t != NULL) {
+ unregister_netdevice_queue(t->dev, head);
+ t = t->next;
+ }
}
}
}
}
}
}
@@
-1503,10
+1512,12
@@
err_alloc:
static void ipgre_exit_net(struct net *net)
{
struct ipgre_net *ign;
static void ipgre_exit_net(struct net *net)
{
struct ipgre_net *ign;
+ LIST_HEAD(list);
ign = net_generic(net, ipgre_net_id);
rtnl_lock();
ign = net_generic(net, ipgre_net_id);
rtnl_lock();
- ipgre_destroy_tunnels(ign);
+ ipgre_destroy_tunnels(ign, &list);
+ unregister_netdevice_many(&list);
rtnl_unlock();
kfree(ign);
}
rtnl_unlock();
kfree(ign);
}
@@
-1650,8
+1661,13
@@
static void ipgre_netlink_parms(struct nlattr *data[],
parms->iph.frag_off = htons(IP_DF);
}
parms->iph.frag_off = htons(IP_DF);
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
+static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[],
+ struct nlattr *data[])
+#else
static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[])
static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[])
+#endif
{
struct ip_tunnel *nt;
struct net *net = dev_net(dev);
{
struct ip_tunnel *nt;
struct net *net = dev_net(dev);