* [PATCH net-next v2 0/4] ipip/ip6tnl: allow to switch netns during encap/decap
From: Nicolas Dichtel @ 2013-08-13 15:51 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, bcrl, ravi.mlists, bhutchings, eric.dumazet
In-Reply-To: <20130704.145621.2060744817757546493.davem@davemloft.net>
This serie is a follow up of the previous serie witch adds this functionality
for sit tunnels.
The goal is to add x-netns support for the module ipip and ip6_tunnel, ie the
encapsulation addresses and the network device are not owned by the same
namespace.
Note that the two first patches are cleanup.
Example to configure an ipip tunnel:
modprobe ipip
ip netns add netns1
ip link add ipip1 type ipip remote 10.16.0.121 local 10.16.0.249
ip l s ipip1 netns netns1
ip netns exec netns1 ip l s lo up
ip netns exec netns1 ip l s ipip1 up
ip netns exec netns1 ip a a dev ipip1 192.168.2.123 remote 192.168.2.121
or an ip6_tunnel:
modprobe ip6_tunnel
ip netns add netns1
ip link add ip6tnl1 type ip6tnl remote 2001:660:3008:c1c3::121 local 2001:660:3008:c1c3::123
ip l s ip6tnl1 netns netns1
ip netns exec netns1 ip l s lo up
ip netns exec netns1 ip l s ip6tnl1 up
ip netns exec netns1 ip a a dev ip6tnl1 192.168.1.123 remote 192.168.1.121
ip netns exec netns1 ip -6 a a dev ip6tnl1 2001:1235::123 remote 2001:1235::121
v2: remove the patch 1/3 of the v1 serie (already included)
use net_eq()
add patch 1/4 and 2/4
include/net/ip6_tunnel.h | 1 +
include/net/ip_tunnels.h | 2 +-
net/core/dev.c | 6 +++---
net/ipv4/ip_gre.c | 4 ++--
net/ipv4/ip_tunnel.c | 52 ++++++++++++++++++++++++++++++------------------
net/ipv4/ip_vti.c | 2 +-
net/ipv4/ipip.c | 3 +--
net/ipv6/ip6_gre.c | 5 +++++
net/ipv6/ip6_tunnel.c | 41 ++++++++++++++++++++++++++++----------
net/ipv6/sit.c | 6 +++---
10 files changed, 81 insertions(+), 41 deletions(-)
Comments are welcome.
Regards,
Nicolas
^ permalink raw reply
* [PATCH net-next v2 1/4] dev: move skb_scrub_packet() after eth_type_trans()
From: Nicolas Dichtel @ 2013-08-13 15:51 UTC (permalink / raw)
To: netdev
Cc: davem, ebiederm, bcrl, ravi.mlists, bhutchings, eric.dumazet,
Nicolas Dichtel
In-Reply-To: <1376409072-6414-1-git-send-email-nicolas.dichtel@6wind.com>
skb_scrub_packet() was called before eth_type_trans() to let eth_type_trans()
set pkt_type.
In fact, we should force pkt_type to PACKET_HOST, so move the call after
eth_type_trans().
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/dev.c | 6 +++---
net/ipv4/ip_tunnel.c | 7 ++++---
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 58eb802584b9..1ed2b66a10a6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1691,13 +1691,13 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
kfree_skb(skb);
return NET_RX_DROP;
}
- skb_scrub_packet(skb);
skb->protocol = eth_type_trans(skb, dev);
/* eth_type_trans() can set pkt_type.
- * clear pkt_type _after_ calling eth_type_trans()
+ * call skb_scrub_packet() after it to clear pkt_type _after_ calling
+ * eth_type_trans().
*/
- skb->pkt_type = PACKET_HOST;
+ skb_scrub_packet(skb);
return netif_rx(skb);
}
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 9fdf8a6d95f3..fbc1094964bf 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -454,15 +454,16 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
tstats->rx_bytes += skb->len;
u64_stats_update_end(&tstats->syncp);
- if (tunnel->net != dev_net(tunnel->dev))
- skb_scrub_packet(skb);
-
if (tunnel->dev->type == ARPHRD_ETHER) {
skb->protocol = eth_type_trans(skb, tunnel->dev);
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
} else {
skb->dev = tunnel->dev;
}
+
+ if (tunnel->net != dev_net(tunnel->dev))
+ skb_scrub_packet(skb);
+
gro_cells_receive(&tunnel->gro_cells, skb);
return 0;
--
1.8.2.1
^ permalink raw reply related
* [PATCH net-next v2 4/4] ip6tnl: add x-netns support
From: Nicolas Dichtel @ 2013-08-13 15:51 UTC (permalink / raw)
To: netdev
Cc: davem, ebiederm, bcrl, ravi.mlists, bhutchings, eric.dumazet,
Nicolas Dichtel
In-Reply-To: <1376409072-6414-1-git-send-email-nicolas.dichtel@6wind.com>
This patch allows to switch the netns when packet is encapsulated or
decapsulated. In other word, the encapsulated packet is received in a netns,
where the lookup is done to find the tunnel. Once the tunnel is found, the
packet is decapsulated and injecting into the corresponding interface which
stands to another netns.
When one of the two netns is removed, the tunnel is destroyed.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/ip6_tunnel.h | 1 +
net/ipv6/ip6_gre.c | 5 +++++
net/ipv6/ip6_tunnel.c | 41 +++++++++++++++++++++++++++++++----------
3 files changed, 37 insertions(+), 10 deletions(-)
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index 4da5de10d1d4..2265b0bf97e5 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -36,6 +36,7 @@ struct __ip6_tnl_parm {
struct ip6_tnl {
struct ip6_tnl __rcu *next; /* next tunnel in list */
struct net_device *dev; /* virtual device associated with tunnel */
+ struct net *net; /* netns for packet i/o */
struct __ip6_tnl_parm parms; /* tunnel configuration parameters */
struct flowi fl; /* flowi template for xmit */
struct dst_entry *dst_cache; /* cached dst */
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index ecd60733e5e2..f2d0a42f8057 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -335,6 +335,7 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net,
dev->rtnl_link_ops = &ip6gre_link_ops;
nt->dev = dev;
+ nt->net = dev_net(dev);
ip6gre_tnl_link_config(nt, 1);
if (register_netdevice(dev) < 0)
@@ -1255,6 +1256,7 @@ static int ip6gre_tunnel_init(struct net_device *dev)
tunnel = netdev_priv(dev);
tunnel->dev = dev;
+ tunnel->net = dev_net(dev);
strcpy(tunnel->parms.name, dev->name);
memcpy(dev->dev_addr, &tunnel->parms.laddr, sizeof(struct in6_addr));
@@ -1275,6 +1277,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
struct ip6_tnl *tunnel = netdev_priv(dev);
tunnel->dev = dev;
+ tunnel->net = dev_net(dev);
strcpy(tunnel->parms.name, dev->name);
tunnel->hlen = sizeof(struct ipv6hdr) + 4;
@@ -1450,6 +1453,7 @@ static int ip6gre_tap_init(struct net_device *dev)
tunnel = netdev_priv(dev);
tunnel->dev = dev;
+ tunnel->net = dev_net(dev);
strcpy(tunnel->parms.name, dev->name);
ip6gre_tnl_link_config(tunnel, 1);
@@ -1501,6 +1505,7 @@ static int ip6gre_newlink(struct net *src_net, struct net_device *dev,
eth_hw_addr_random(dev);
nt->dev = dev;
+ nt->net = dev_net(dev);
ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]);
/* Can use a lockless transmit, unless we generate output sequences */
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 1e55866cead7..cc3bb201b8b0 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -315,6 +315,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
t = netdev_priv(dev);
t->parms = *p;
+ t->net = dev_net(dev);
err = ip6_tnl_create2(dev);
if (err < 0)
goto failed_free;
@@ -374,7 +375,7 @@ static void
ip6_tnl_dev_uninit(struct net_device *dev)
{
struct ip6_tnl *t = netdev_priv(dev);
- struct net *net = dev_net(dev);
+ struct net *net = t->net;
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
if (dev == ip6n->fb_tnl_dev)
@@ -741,7 +742,7 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t,
{
struct __ip6_tnl_parm *p = &t->parms;
int ret = 0;
- struct net *net = dev_net(t->dev);
+ struct net *net = t->net;
if ((p->flags & IP6_TNL_F_CAP_RCV) ||
((p->flags & IP6_TNL_F_CAP_PER_PACKET) &&
@@ -827,6 +828,9 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
tstats->rx_packets++;
tstats->rx_bytes += skb->len;
+ if (!net_eq(t->net, dev_net(t->dev)))
+ skb_scrub_packet(skb);
+
netif_rx(skb);
rcu_read_unlock();
@@ -895,7 +899,7 @@ int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
{
struct __ip6_tnl_parm *p = &t->parms;
int ret = 0;
- struct net *net = dev_net(t->dev);
+ struct net *net = t->net;
if (p->flags & IP6_TNL_F_CAP_XMIT) {
struct net_device *ldev = NULL;
@@ -945,8 +949,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
int encap_limit,
__u32 *pmtu)
{
- struct net *net = dev_net(dev);
struct ip6_tnl *t = netdev_priv(dev);
+ struct net *net = t->net;
struct net_device_stats *stats = &t->dev->stats;
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
struct ipv6_tel_txoption opt;
@@ -996,6 +1000,9 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
goto tx_err_dst_release;
}
+ if (!net_eq(t->net, dev_net(dev)))
+ skb_scrub_packet(skb);
+
/*
* Okay, now see if we can stuff it in the buffer as-is.
*/
@@ -1202,7 +1209,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
int strict = (ipv6_addr_type(&p->raddr) &
(IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL));
- struct rt6_info *rt = rt6_lookup(dev_net(dev),
+ struct rt6_info *rt = rt6_lookup(t->net,
&p->raddr, &p->laddr,
p->link, strict);
@@ -1251,7 +1258,7 @@ ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p)
static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p)
{
- struct net *net = dev_net(t->dev);
+ struct net *net = t->net;
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
int err;
@@ -1463,7 +1470,6 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
dev->mtu-=8;
dev->flags |= IFF_NOARP;
dev->addr_len = sizeof(struct in6_addr);
- dev->features |= NETIF_F_NETNS_LOCAL;
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
}
@@ -1479,6 +1485,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
struct ip6_tnl *t = netdev_priv(dev);
t->dev = dev;
+ t->net = dev_net(dev);
dev->tstats = alloc_percpu(struct pcpu_tstats);
if (!dev->tstats)
return -ENOMEM;
@@ -1596,9 +1603,9 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
struct nlattr *data[])
{
- struct ip6_tnl *t;
+ struct ip6_tnl *t = netdev_priv(dev);
struct __ip6_tnl_parm p;
- struct net *net = dev_net(dev);
+ struct net *net = t->net;
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
if (dev == ip6n->fb_tnl_dev)
@@ -1699,14 +1706,24 @@ static struct xfrm6_tunnel ip6ip6_handler __read_mostly = {
static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
{
+ struct net *net = dev_net(ip6n->fb_tnl_dev);
+ struct net_device *dev, *aux;
int h;
struct ip6_tnl *t;
LIST_HEAD(list);
+ for_each_netdev_safe(net, dev, aux)
+ if (dev->rtnl_link_ops == &ip6_link_ops)
+ unregister_netdevice_queue(dev, &list);
+
for (h = 0; h < HASH_SIZE; h++) {
t = rtnl_dereference(ip6n->tnls_r_l[h]);
while (t != NULL) {
- unregister_netdevice_queue(t->dev, &list);
+ /* If dev is in the same netns, it has already
+ * been added to the list by the previous loop.
+ */
+ if (!net_eq(dev_net(t->dev), net))
+ unregister_netdevice_queue(t->dev, &list);
t = rtnl_dereference(t->next);
}
}
@@ -1732,6 +1749,10 @@ static int __net_init ip6_tnl_init_net(struct net *net)
if (!ip6n->fb_tnl_dev)
goto err_alloc_dev;
dev_net_set(ip6n->fb_tnl_dev, net);
+ /* FB netdevice is special: we have one, and only one per netns.
+ * Allowing to move it to another netns is clearly unsafe.
+ */
+ ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL;
err = ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
if (err < 0)
--
1.8.2.1
^ permalink raw reply related
* [PATCH net-next v2 2/4] ipv4 tunnels: use net_eq() helper to check netns
From: Nicolas Dichtel @ 2013-08-13 15:51 UTC (permalink / raw)
To: netdev
Cc: davem, ebiederm, bcrl, ravi.mlists, bhutchings, eric.dumazet,
Nicolas Dichtel
In-Reply-To: <1376409072-6414-1-git-send-email-nicolas.dichtel@6wind.com>
It's better to use available helpers for these tests.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/ipv4/ip_tunnel.c | 4 ++--
net/ipv6/sit.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index fbc1094964bf..a351a003ee6b 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -461,7 +461,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
skb->dev = tunnel->dev;
}
- if (tunnel->net != dev_net(tunnel->dev))
+ if (!net_eq(tunnel->net, dev_net(tunnel->dev)))
skb_scrub_packet(skb);
gro_cells_receive(&tunnel->gro_cells, skb);
@@ -614,7 +614,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
goto tx_error;
}
- if (tunnel->net != dev_net(dev))
+ if (!net_eq(tunnel->net, dev_net(dev)))
skb_scrub_packet(skb);
if (tunnel->err_count > 0) {
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index a3437a4cd07e..f18f842ac893 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -621,7 +621,7 @@ static int ipip6_rcv(struct sk_buff *skb)
tstats->rx_packets++;
tstats->rx_bytes += skb->len;
- if (tunnel->net != dev_net(tunnel->dev))
+ if (!net_eq(tunnel->net, dev_net(tunnel->dev)))
skb_scrub_packet(skb);
netif_rx(skb);
@@ -860,7 +860,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
tunnel->err_count = 0;
}
- if (tunnel->net != dev_net(dev))
+ if (!net_eq(tunnel->net, dev_net(dev)))
skb_scrub_packet(skb);
/*
@@ -1589,7 +1589,7 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea
/* If dev is in the same netns, it has already
* been added to the list by the previous loop.
*/
- if (dev_net(t->dev) != net)
+ if (!net_eq(dev_net(t->dev), net))
unregister_netdevice_queue(t->dev,
head);
t = rtnl_dereference(t->next);
--
1.8.2.1
^ permalink raw reply related
* [PATCH net-next v2 3/4] ipip: add x-netns support
From: Nicolas Dichtel @ 2013-08-13 15:51 UTC (permalink / raw)
To: netdev
Cc: davem, ebiederm, bcrl, ravi.mlists, bhutchings, eric.dumazet,
Nicolas Dichtel
In-Reply-To: <1376409072-6414-1-git-send-email-nicolas.dichtel@6wind.com>
This patch allows to switch the netns when packet is encapsulated or
decapsulated. In other word, the encapsulated packet is received in a netns,
where the lookup is done to find the tunnel. Once the tunnel is found, the
packet is decapsulated and injecting into the corresponding interface which
stands to another netns.
When one of the two netns is removed, the tunnel is destroyed.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/ip_tunnels.h | 2 +-
net/ipv4/ip_gre.c | 4 ++--
net/ipv4/ip_tunnel.c | 43 ++++++++++++++++++++++++++++---------------
net/ipv4/ip_vti.c | 2 +-
net/ipv4/ipip.c | 3 +--
5 files changed, 33 insertions(+), 21 deletions(-)
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index c6acd9f8f877..5a76f2bef822 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -102,7 +102,7 @@ void ip_tunnel_dellink(struct net_device *dev, struct list_head *head);
int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname);
-void ip_tunnel_delete_net(struct ip_tunnel_net *itn);
+void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops);
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
const struct iphdr *tnl_params, const u8 protocol);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 1f6eab66f7ce..bc3a76521deb 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -534,7 +534,7 @@ static int __net_init ipgre_init_net(struct net *net)
static void __net_exit ipgre_exit_net(struct net *net)
{
struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id);
- ip_tunnel_delete_net(itn);
+ ip_tunnel_delete_net(itn, &ipgre_link_ops);
}
static struct pernet_operations ipgre_net_ops = {
@@ -767,7 +767,7 @@ static int __net_init ipgre_tap_init_net(struct net *net)
static void __net_exit ipgre_tap_exit_net(struct net *net)
{
struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id);
- ip_tunnel_delete_net(itn);
+ ip_tunnel_delete_net(itn, &ipgre_tap_ops);
}
static struct pernet_operations ipgre_tap_net_ops = {
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index a351a003ee6b..a4d9126c7b51 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -350,7 +350,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
struct flowi4 fl4;
struct rtable *rt;
- rt = ip_route_output_tunnel(dev_net(dev), &fl4,
+ rt = ip_route_output_tunnel(tunnel->net, &fl4,
tunnel->parms.iph.protocol,
iph->daddr, iph->saddr,
tunnel->parms.o_key,
@@ -365,7 +365,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
}
if (!tdev && tunnel->parms.link)
- tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+ tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
if (tdev) {
hlen = tdev->hard_header_len + tdev->needed_headroom;
@@ -654,7 +654,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
}
}
- err = iptunnel_xmit(dev_net(dev), rt, skb,
+ err = iptunnel_xmit(tunnel->net, rt, skb,
fl4.saddr, fl4.daddr, protocol,
ip_tunnel_ecn_encap(tos, inner_iph, skb), ttl, df);
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
@@ -821,11 +821,10 @@ static void ip_tunnel_dev_free(struct net_device *dev)
void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
{
- struct net *net = dev_net(dev);
struct ip_tunnel *tunnel = netdev_priv(dev);
struct ip_tunnel_net *itn;
- itn = net_generic(net, tunnel->ip_tnl_net_id);
+ itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
if (itn->fb_tunnel_dev != dev) {
ip_tunnel_del(netdev_priv(dev));
@@ -855,6 +854,10 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
rtnl_lock();
itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms);
+ /* FB netdevice is special: we have one, and only one per netns.
+ * Allowing to move it to another netns is clearly unsafe.
+ */
+ itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
rtnl_unlock();
if (IS_ERR(itn->fb_tunnel_dev))
@@ -864,28 +867,39 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
}
EXPORT_SYMBOL_GPL(ip_tunnel_init_net);
-static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head)
+static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head,
+ struct rtnl_link_ops *ops)
{
+ struct net *net = dev_net(itn->fb_tunnel_dev);
+ struct net_device *dev, *aux;
int h;
+ for_each_netdev_safe(net, dev, aux)
+ if (dev->rtnl_link_ops == ops)
+ unregister_netdevice_queue(dev, head);
+
for (h = 0; h < IP_TNL_HASH_SIZE; h++) {
struct ip_tunnel *t;
struct hlist_node *n;
struct hlist_head *thead = &itn->tunnels[h];
hlist_for_each_entry_safe(t, n, thead, hash_node)
- unregister_netdevice_queue(t->dev, head);
+ /* If dev is in the same netns, it has already
+ * been added to the list by the previous loop.
+ */
+ if (!net_eq(dev_net(t->dev), net))
+ unregister_netdevice_queue(t->dev, head);
}
if (itn->fb_tunnel_dev)
unregister_netdevice_queue(itn->fb_tunnel_dev, head);
}
-void ip_tunnel_delete_net(struct ip_tunnel_net *itn)
+void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops)
{
LIST_HEAD(list);
rtnl_lock();
- ip_tunnel_destroy(itn, &list);
+ ip_tunnel_destroy(itn, &list, ops);
unregister_netdevice_many(&list);
rtnl_unlock();
}
@@ -929,23 +943,21 @@ EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_parm *p)
{
- struct ip_tunnel *t, *nt;
- struct net *net = dev_net(dev);
+ struct ip_tunnel *t;
struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct net *net = tunnel->net;
struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
if (dev == itn->fb_tunnel_dev)
return -EINVAL;
- nt = netdev_priv(dev);
-
t = ip_tunnel_find(itn, p, dev->type);
if (t) {
if (t->dev != dev)
return -EEXIST;
} else {
- t = nt;
+ t = tunnel;
if (dev->type != ARPHRD_ETHER) {
unsigned int nflags = 0;
@@ -984,6 +996,7 @@ int ip_tunnel_init(struct net_device *dev)
}
tunnel->dev = dev;
+ tunnel->net = dev_net(dev);
strcpy(tunnel->parms.name, dev->name);
iph->version = 4;
iph->ihl = 5;
@@ -994,8 +1007,8 @@ EXPORT_SYMBOL_GPL(ip_tunnel_init);
void ip_tunnel_uninit(struct net_device *dev)
{
- struct net *net = dev_net(dev);
struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct net *net = tunnel->net;
struct ip_tunnel_net *itn;
itn = net_generic(net, tunnel->ip_tnl_net_id);
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 79b263da4168..e805e7b3030e 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -318,7 +318,7 @@ static int __net_init vti_init_net(struct net *net)
static void __net_exit vti_exit_net(struct net *net)
{
struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
- ip_tunnel_delete_net(itn);
+ ip_tunnel_delete_net(itn, &vti_link_ops);
}
static struct pernet_operations vti_net_ops = {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 51fc2a1dcdd3..87bd2952c733 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -286,7 +286,6 @@ static void ipip_tunnel_setup(struct net_device *dev)
dev->flags = IFF_NOARP;
dev->iflink = 0;
dev->addr_len = 4;
- dev->features |= NETIF_F_NETNS_LOCAL;
dev->features |= NETIF_F_LLTX;
dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
@@ -437,7 +436,7 @@ static int __net_init ipip_init_net(struct net *net)
static void __net_exit ipip_exit_net(struct net *net)
{
struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
- ip_tunnel_delete_net(itn);
+ ip_tunnel_delete_net(itn, &ipip_link_ops);
}
static struct pernet_operations ipip_net_ops = {
--
1.8.2.1
^ permalink raw reply related
* question about drivers/net/ethernet/jme.{c,h}
From: Julia Lawall @ 2013-08-13 16:33 UTC (permalink / raw)
To: cooldavid, netdev
I wonder what is the point of the macro NETIF_NAPI_SET? It has only one
definition, and it just transfers its arguments directly to the more
common function netif_napi_add. The fact that the definition of the macro
contains a semicolon also makes the use of NETIF_NAPI_SET not look like a
normal function call.
thanks,
julia
^ permalink raw reply
* [RFC] phy: micrel: Convert micrel PHY driver to use OF
From: dinguyen @ 2013-08-13 16:42 UTC (permalink / raw)
To: dinh.linux
Cc: Dinh Nguyen, netdev, Richard Cochran, Linus Walleij, Felipe Balbi,
David S. Miller, Giuseppe Cavallaro, Olof Johansson, Rob Herring
From: Dinh Nguyen <dinguyen@altera.com>
Convert the Micrel PHY driver to use OF. This initial patch is only
the beginning of an idea to convert the PHY driver to device tree.
Signed-of-by: Dinh Nguyen <dinguyen@altera.com>
Cc: netdev@vger.kernel.org
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Felipe Balbi <balbi@ti.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Rob Herring <rob.herring@calxeda.com>
---
Hello,
I would like to solicit comments on the need to convert the ethernet PHY
drivers to use OF/device trees? For the platform that I'm interested in,
SOCFPGA, it is using the stmicro ethernet driver. It has a Micrel PHY
on the board. The only way that I know of how to change the skew settings
for the phy is through a board level initialization.
One of the ARM maintainers suggested that perhaps refactoring the ethernet
driver to use device tree would be nice. But that would not help me with
configuring the PHY settings.
So a little investigation led me to believe that refactoring the /net/phy
drivers into a device tree implementation would help greatly. I was thinking
it could be done like the pinctrl or some of the usb/phy driver.
Since I am only familiar with the ARM SoC space, I want to make sure that
this idea is right approach. I can start with the micrel PHY driver
first, as that is the only HW I have access to.
Thanks for any comments,
Dinh
---
drivers/net/phy/micrel.c | 107 ++++++++++++++++------------------------------
1 file changed, 37 insertions(+), 70 deletions(-)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 2510435..6ee1e88 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -174,6 +174,15 @@ static int ksz8873mll_config_aneg(struct phy_device *phydev)
return 0;
}
+static const struct phy_driver ksphy_driver_data[] = {
+{
+ .config_init = kszphy_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = kszphy_ack_interrupt,
+ .config_intr = ks_config_intr,
+};
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -181,12 +190,6 @@ static struct phy_driver ksphy_driver[] = {
.name = "Micrel KS8737",
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = ks8737_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8021,
.phy_id_mask = 0x00ffffff,
@@ -194,12 +197,6 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = ksz8021_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = kszphy_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8031,
.phy_id_mask = 0x00ffffff,
@@ -207,12 +204,6 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = ksz8021_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = kszphy_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8041,
.phy_id_mask = 0x00fffff0,
@@ -220,12 +211,6 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = kszphy_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8051,
.phy_id_mask = 0x00fffff0,
@@ -233,60 +218,30 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = ks8051_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = kszphy_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8001,
.name = "Micrel KSZ8001 or KS8721",
.phy_id_mask = 0x00ffffff,
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = kszphy_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8081,
.name = "Micrel KSZ8081 or KSZ8091",
.phy_id_mask = 0x00fffff0,
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = kszphy_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8061,
.name = "Micrel KSZ8061",
.phy_id_mask = 0x00fffff0,
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = kszphy_config_intr,
- .driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ9021,
.phy_id_mask = 0x000ffffe,
.name = "Micrel KSZ9021 Gigabit PHY",
.features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = ksz9021_config_intr,
- .driver = { .owner = THIS_MODULE, },
}, {
.phy_id = PHY_ID_KSZ9031,
.phy_id_mask = 0x00fffff0,
@@ -294,32 +249,18 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_GBIT_FEATURES | SUPPORTED_Pause
| SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = kszphy_ack_interrupt,
- .config_intr = ksz9021_config_intr,
- .driver = { .owner = THIS_MODULE, },
}, {
.phy_id = PHY_ID_KSZ8873MLL,
.phy_id_mask = 0x00fffff0,
.name = "Micrel KSZ8873MLL Switch",
.features = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG,
- .config_init = kszphy_config_init,
- .config_aneg = ksz8873mll_config_aneg,
- .read_status = ksz8873mll_read_status,
- .driver = { .owner = THIS_MODULE, },
}, {
.phy_id = PHY_ID_KSZ886X,
.phy_id_mask = 0x00fffff0,
.name = "Micrel KSZ886X Switch",
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = kszphy_config_init,
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .driver = { .owner = THIS_MODULE, },
} };
static int __init ksphy_init(void)
@@ -334,8 +275,34 @@ static void __exit ksphy_exit(void)
ARRAY_SIZE(ksphy_driver));
}
-module_init(ksphy_init);
-module_exit(ksphy_exit);
+static const struct of_device_id phy_micrel_match[] = {
+ { .compatible = "micrel,ks8721", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ks8737", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8001", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8021", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8031", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8041", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8051", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8061", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8081", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8091", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8021-gigabit", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8031-gigabit", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz8873mll-switch", .data = &ksphy_driver_data },
+ { .compatible = "micrel,ksz886x-switch", .data = &ksphy_driver_data },
+ {},
+};
+MODULE_DEVICE_TABLE(of, phy_micrel_match);
+
+static struct platform_driver phy_micrel_driver = {
+ .probe = ksphy_init,
+ .remove = ksphy_exit,
+ .driver = {
+ .name = "phy_micrel",
+ .of_match_table = of_match_ptr(phy_micrel_match),
+ },
+};
+module_platform_driver(phy_micrel_driver);
MODULE_DESCRIPTION("Micrel PHY driver");
MODULE_AUTHOR("David J. Choi");
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH 2/3 v2] ipv6: rename ADBG() to pr_xxx()
From: Joe Perches @ 2013-08-13 16:48 UTC (permalink / raw)
To: Ding Tianhong
Cc: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Netdev, Patrick McHardy
In-Reply-To: <5209E6E8.1030702@huawei.com>
On Tue, 2013-08-13 at 15:57 +0800, Ding Tianhong wrote:
> According to Joe Perches opinions, the ADBG() was tedious and it is
> better to remove the KERN_<LEVEL>s and use the pr_xxx() instead of ADBG().
No, that's not really what I wrote.
I suggested it might be better to remove the KERN_<LEVELS>
from these ADBG uses and use pr_debug.
As is, you've changed logging messages which today
always compile away to nothing to now emit what I
think are pretty unnecessary messages.
^ permalink raw reply
* Re: question about drivers/net/ethernet/jme.{c,h}
From: Joe Perches @ 2013-08-13 17:26 UTC (permalink / raw)
To: Julia Lawall; +Cc: cooldavid, netdev
In-Reply-To: <alpine.DEB.2.02.1308131831250.2263@hadrien>
On Tue, 2013-08-13 at 18:33 +0200, Julia Lawall wrote:
> I wonder what is the point of the macro NETIF_NAPI_SET?
Today it seems pretty clear it's useless indirection.
It might have been useful sometime before the jme.c
file was first submitted, but now it should be removed.
In the jme.h file on JMicron's website, the driver
still supports linux versions less than 2.6.23 and
uses a form like this:
ftp://driver.jmicron.com.tw/Ethernet/Linux/jmebp-1.0.8.5.tar.bz
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
#define NETIF_NAPI_SET(dev, napis, pollfn, q) \
dev->poll = pollfn; \
dev->weight = q;
#else
#define NETIF_NAPI_SET(dev, napis, pollfn, q) \
netif_napi_add(dev, napis, pollfn, q);
^ permalink raw reply
* Re: tun always return NETDEV_TX_OK, why?
From: Stephen Hemminger @ 2013-08-13 17:33 UTC (permalink / raw)
To: Yannick Koehler; +Cc: netdev
In-Reply-To: <CAJ4BwwEbBQQ=S5pd=8rHAxnOm-P7yQPv9q2D7c1D9cVh5ArAPQ@mail.gmail.com>
On Tue, 13 Aug 2013 10:39:02 -0400
Yannick Koehler <yannick@koehler.name> wrote:
> Hello,
>
> I hit a problem recently with the tun interface, it looks like when
> this interface reach its txqueuelen it will then drop the packet and
> return NETDEV_TX_OK unconditionally.
>
> That, from my little understanding of the netdev framework, appears
> to be wrong and will simply eat up any pending buffer and discard them
> until the queue frees itself. That seems to be against the flow
> control design in the tx queue system of the kernel.
>
> So, is this a bug or a misunderstanding? Would it be ok for tun to
> return NETDEV_TX_BUSY when the txqueuelen is reach and call
> netif_stop_queue() so that the layer above stop sending frame to this
> interface until it can cope it's current queue content?
>
NETDEV_TX_BUSY won't work well for this because it basically
causes kernel to spin waiting for the transmit queue.
A better way is to figure out how to do proper flow control
with start/stop queue.
^ permalink raw reply
* Re: [PATCH net v5 0/5] bnx2x: fixes
From: Benjamin Poirier @ 2013-08-13 17:44 UTC (permalink / raw)
To: Dmitry Kravkov
Cc: Ariel Elior, davem@davemloft.net, netdev@vger.kernel.org,
Eilon Greenstein
In-Reply-To: <504C9EFCA2D0054393414C9CB605C37F20D708BF@SJEXCHMB06.corp.ad.broadcom.com>
On 2013/08/13 14:16, Dmitry Kravkov wrote:
[...]
> >
> > Let me rephrase my question:
> >
> > I'm confused. I thought that "[PATCH net v4 1/6] bnx2x: properly initialize
> > statistic counters" was meant to fix a race condition at driver startup which
> > causes a second statistics query to be sent before the first one completes,
> > resulting in a firmware assert and a stuck chip. Am I mistaken and there is no
> > such race condition, or is it addressed by the other patches in this series?
> >
> There is such condition, but it's not caused by wrongly initialized counted -
> the initialization done in a correct way. Patch "[PATCH net v5 1/5] bnx2x: protect
> different statistics flows" - prevents from two outstanding queries to be sent
> simultaneously.
Thank you for the clarification.
^ permalink raw reply
* Re: [PATCH 1/7] uio: add module owner to prevent inappropriate module unloading
From: Greg Kroah-Hartman @ 2013-08-13 17:48 UTC (permalink / raw)
To: Benedikt Spranger
Cc: netdev, Alexander Frank, Sebastian Andrzej Siewior, Hans J. Koch,
Holger Dengler
In-Reply-To: <1376384922-8519-3-git-send-email-b.spranger@linutronix.de>
On Tue, Aug 13, 2013 at 11:08:36AM +0200, Benedikt Spranger wrote:
> If an UIO device is created by another driver (MFD for instance) it has to be
> ensured that the MFD driver isn't removed while the UIO is still in use.
Shouldn't if the MFD driver is removed, the UIO device will be cleaned
up and also removed? You shouldn't need a module reference for this
type of thing.
And why did I only get 2 of the 7 patches here?
greg k-h
^ permalink raw reply
* Re: [PATCH net v5 1/5] bnx2x: protect different statistics flows
From: Neal Cardwell @ 2013-08-13 17:54 UTC (permalink / raw)
To: Dmitry Kravkov; +Cc: David Miller, Netdev, eilong, Ariel Elior
In-Reply-To: <1376349903-3461-2-git-send-email-dmitry@broadcom.com>
On Mon, Aug 12, 2013 at 7:24 PM, Dmitry Kravkov <dmitry@broadcom.com> wrote:
> Add locking to protect different statistics flows from
> running simultaneously.
> This in order to serialize statistics requests sent to FW,
> otherwise two outstanding queries may cause FW assert.
>
> Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
> Signed-off-by: Ariel Elior <ariele@broadcom.com>
> Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
> ---
> drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 +
> drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 1 +
> drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c | 66 ++++++++++++++++++-----
> 3 files changed, 57 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
> index d80e34b..98be67f 100644
Acked-by: Neal Cardwell <ncardwell@google.com>
Thanks!
neal
^ permalink raw reply
* Re: [PATCH 2/7] uio: Allow to create custom UIO attributes
From: Greg Kroah-Hartman @ 2013-08-13 17:54 UTC (permalink / raw)
To: Benedikt Spranger
Cc: netdev, Alexander Frank, Sebastian Andrzej Siewior, Hans J. Koch,
Holger Dengler
In-Reply-To: <1376384922-8519-4-git-send-email-b.spranger@linutronix.de>
On Tue, Aug 13, 2013 at 11:08:37AM +0200, Benedikt Spranger wrote:
> This patch the struct uio_attribute which represents a custom UIO
> attribute. The non-standard attributes are stored in a "attr" directory.
> This will be used by the flexcard driver which creates a UIO device that
> is using the "uio_pdrv" and requires one additional value to be read /
> written by the user.
>
> Cc: "Hans J. Koch" <hjk@hansjkoch.de>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
> Signed-off-by: Holger Dengler <dengler@linutronix.de>
> ---
> drivers/uio/uio.c | 106 ++++++++++++++++++++++++++++++++++++++++++++-
> include/linux/uio_driver.h | 36 +++++++++++----
> 2 files changed, 133 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
> index 9a95220..d66784a 100644
> --- a/drivers/uio/uio.c
> +++ b/drivers/uio/uio.c
> @@ -39,6 +39,7 @@ struct uio_device {
> struct uio_info *info;
> struct kobject *map_dir;
> struct kobject *portio_dir;
> + struct kobject attr_dir;
If you embed a kobject into a structure, it is now in charge of the
memory reference counting for that object.
Which you did not do correctly:
> +static struct kobj_type uio_attr_type = {
> + .sysfs_ops = &uio_sysfs_ops,
> +};
As per the documentation in the kernel, I now get to make fun of the
fact that you obviously didn't test this code (hint, the kernel would
have told you bad things happened if you did...)
But I don't understand your main goal of a new kobject for attributes,
why? What problem are you trying to solve here that a new kobject, and
new sysfs files attached to the UIO object are going to solve?
> /**
> + * uio_add_user_attributes - add an extra UIO attribute
> + * @info: UIO device capabilities
> + */
> +static int uio_add_user_attributes(struct uio_info *info)
> +{
> + struct uio_device *idev = info->uio_dev;
> + const struct uio_attribute **uio_attr;
> + int i;
> + int ret = 0;
> +
> + uio_attr = info->attributes;
> + if (!uio_attr)
> + return 0;
> +
> + for (i = 0; uio_attr[i]; i++) {
> +
> + ret = sysfs_create_file(&idev->attr_dir, &uio_attr[i]->attr);
> + if (ret)
> + break;
> + }
> + if (ret) {
> + while (--i >= 0)
> + sysfs_remove_file(&idev->attr_dir, &uio_attr[i]->attr);
> + }
> + return ret;
> +}
Ick, you just raced with userspace and blew up any tool that was wanting
to watch for your new kobject to be created with the attributes attached
to it :(
Sending code that doesn't work is fine, for review if you have questions
about things, but please, mark it with a big "I HAVEN'T TESTED THIS"
statement somewhere.
greg k-h
^ permalink raw reply
* [PATCH] macvtap: Correctly set tap features when IFF_VNET_HDR is disabled.
From: Vlad Yasevich @ 2013-08-13 17:55 UTC (permalink / raw)
To: netdev; +Cc: mst, Vlad Yasevich
When the user turns off IFF_VNET_HDR flag, attempts to change
offload features via TUNSETOFFLOAD do not work. This could cause
GSO packets to be delivered to the user when the user is
not prepared to handle them.
To solve, allow processing of TUNSETOFFLOAD when IFF_VNET_HDR is
disabled and make sure to turn off all offloads in this case.
Also, when IFF_VNET_HDR is disabled, run throught the offload change
as well to make sure that the functionality is not dependent on
the order of the ioclt() calls.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
drivers/net/macvtap.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index a98fb0e..076b9e7 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -1019,6 +1019,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
struct macvlan_dev *vlan;
netdev_features_t features;
netdev_features_t feature_mask = 0;
+ netdev_features_t tap_mask = TUN_OFFLOADS;
vlan = rtnl_dereference(q->vlan);
if (!vlan)
@@ -1026,7 +1027,12 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
features = vlan->dev->features;
- if (arg & TUN_F_CSUM) {
+ if (!(q->flags & IFF_VNET_HDR)) {
+ /* Turn off all checsum offloading also if user does
+ * not user vnet_hdr.
+ */
+ tap_mask |= NETIF_F_ALL_CSUM;
+ } else if (arg & TUN_F_CSUM) {
feature_mask = NETIF_F_HW_CSUM;
if (arg & (TUN_F_TSO4 | TUN_F_TSO6)) {
@@ -1058,8 +1064,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
/* tap_features are the same as features on tun/tap and
* reflect user expectations.
*/
- vlan->tap_features = vlan->dev->features &
- (feature_mask | ~TUN_OFFLOADS);
+ vlan->tap_features = vlan->dev->features & (feature_mask | ~tap_mask);
vlan->set_features = features;
netdev_update_features(vlan->dev);
@@ -1092,8 +1097,18 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
if ((u & ~(IFF_VNET_HDR | IFF_MULTI_QUEUE)) !=
(IFF_NO_PI | IFF_TAP))
ret = -EINVAL;
- else
+ else {
+ if ((q->flags ^ u) & IFF_VNET_HDR) {
+ /* vnet_hdr support impacts the offloads,
+ * so we need to run throught the offload
+ * change.
+ */
+ rtnl_lock();
+ ret = set_offload(q, 0);
+ rtnl_unlock();
+ }
q->flags = u;
+ }
return ret;
@@ -1155,10 +1170,6 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
TUN_F_TSO_ECN | TUN_F_UFO))
return -EINVAL;
- /* TODO: only accept frames with the features that
- got enabled for forwarded frames */
- if (!(q->flags & IFF_VNET_HDR))
- return -EINVAL;
rtnl_lock();
ret = set_offload(q, arg);
rtnl_unlock();
--
1.8.1.4
^ permalink raw reply related
* Re: [PATCH net v5 1/5] bnx2x: protect different statistics flows
From: Stephen Hemminger @ 2013-08-13 17:57 UTC (permalink / raw)
To: David Miller; +Cc: dmitry, netdev, eilong, ariele
In-Reply-To: <20130812.212402.138911128487906526.davem@davemloft.net>
On Mon, 12 Aug 2013 21:24:02 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:
> From: Stephen Hemminger <stephen@networkplumber.org>
> Date: Mon, 12 Aug 2013 17:12:08 -0700
>
> > On Tue, 13 Aug 2013 02:24:59 +0300
> > "Dmitry Kravkov" <dmitry@broadcom.com> wrote:
> >
> >> + bool stats_started;
> >> + struct semaphore stats_sema;
> >
> > Is there a reason to use a counting semaphore? Do you expect it to
> > be held across user process boundary? or want count > 1?
> >
> > Use of semaphores as a locking primitive is discouraged,
> > instead us a mutex.
>
> Would you please look at the feedback I gave these guys to the
> previous iteration of these changes?
>
> They were using custom locking primitives and semaphores gave
> the best approximation to the semantics they were looking for.
Your right in this case sempahore makes sense because it is
used to hold off process while hardware responds.
^ permalink raw reply
* Re: [PATCH net] bnx2x: guard stats_pending with stats_lock in all cases
From: Neal Cardwell @ 2013-08-13 17:57 UTC (permalink / raw)
To: Dmitry Kravkov
Cc: David Miller, netdev@vger.kernel.org, Eilon Greenstein,
Vladislav Zolotarov, Yaniv Rosner, Merav Sicron, Eric Dumazet,
Tom Herbert, Havard Skinnemoen, Sanjay Hortikar, Dmitry Kravkov
In-Reply-To: <CAM8tLiPUO2EHMM7AZJrj=LfZqCBnpKMbHT9wWomBAp6v_18YYg@mail.gmail.com>
On Mon, Aug 12, 2013 at 4:52 PM, Dmitry Kravkov <dkravkov@gmail.com> wrote:
> Neal, thanks for looking into this.
>
> There's another race, where two flows
> stats_update() and stats_start() may send two queries in parallel
> which will cause FW to assert.
>
> I'm preparing the set for net, which includes the fix for this race
> also(will be out in a couple of hours)
>
> I will be more than happy if you will take a look.
>
> Thanks
> Dmitry
Thanks! Your "bnx2x: protect different statistics flows" patch looks
like a superset of the synchronization I was proposing in this patch,
so we can drop mine.
Thanks,
neal
^ permalink raw reply
* Re: [PATCH] macvtap: Correctly set tap features when IFF_VNET_HDR is disabled.
From: Sergei Shtylyov @ 2013-08-13 18:05 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: netdev, mst
In-Reply-To: <1376416558-25015-1-git-send-email-vyasevic@redhat.com>
Hello.
On 08/13/2013 09:55 PM, Vlad Yasevich wrote:
> When the user turns off IFF_VNET_HDR flag, attempts to change
> offload features via TUNSETOFFLOAD do not work. This could cause
> GSO packets to be delivered to the user when the user is
> not prepared to handle them.
> To solve, allow processing of TUNSETOFFLOAD when IFF_VNET_HDR is
> disabled and make sure to turn off all offloads in this case.
> Also, when IFF_VNET_HDR is disabled, run throught the offload change
> as well to make sure that the functionality is not dependent on
> the order of the ioclt() calls.
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
> ---
> drivers/net/macvtap.c | 27 +++++++++++++++++++--------
> 1 file changed, 19 insertions(+), 8 deletions(-)
> diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
> index a98fb0e..076b9e7 100644
> --- a/drivers/net/macvtap.c
> +++ b/drivers/net/macvtap.c
[...]
> @@ -1092,8 +1097,18 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
> if ((u & ~(IFF_VNET_HDR | IFF_MULTI_QUEUE)) !=
> (IFF_NO_PI | IFF_TAP))
> ret = -EINVAL;
> - else
> + else {
> + if ((q->flags ^ u) & IFF_VNET_HDR) {
> + /* vnet_hdr support impacts the offloads,
> + * so we need to run throught the offload
> + * change.
> + */
> + rtnl_lock();
> + ret = set_offload(q, 0);
> + rtnl_unlock();
> + }
> q->flags = u;
> + }
According to Documentation/CodingStyle, both arms of the *if* statement
should have {} if one arm has it.
WBR, Sergei
^ permalink raw reply
* Re: [PATCH net-next] bonding: lacp_port_id setting for 802.3ad
From: Jay Vosburgh @ 2013-08-13 18:25 UTC (permalink / raw)
To: Krisztian Ivancso; +Cc: Ding Tianhong, netdev
In-Reply-To: <520A11CD.8060400@ivancso.net>
Krisztian Ivancso <github-ivan@ivancso.net> wrote:
>On 08/13/2013 11:39 AM, Ding Tianhong wrote:
>> On 2013/8/13 17:20, Krisztian Ivancso wrote:
>>> On 08/13/2013 03:07 AM, Ding Tianhong wrote:
>>>> On 2013/8/12 19:19, Krisztian Ivancso wrote:
>>>>> >From 472fffa5a8f170daed9e4cc677af8e2560b86be2 Mon Sep 17 00:00:00 2001
>>>>> From: Krisztian Ivancso <github-ivan@ivancso.net>
>>>>> Date: Sun, 11 Aug 2013 20:30:44 +0200
>>>>> Subject: [PATCH net-next] bonding: lacp_port_id setting for 802.3ad ports
>>
>> ok, for example: the bonding has four slave, slave1 and slave2 aggregation to 1 group,
>> and slave3 and slave4 aggregtion to 2 group, how you distinguish the 1 and 2 group by initialize id.
>
>this is not possible, because all slave have to be a member of the same
>aggregation group.
Just on the above point, bonding can group slaves into multiple
aggregators, but only one aggregator will be active at any given time.
To answer the question, the four slaves would each be given
unique port IDs that do not conflict.
>i think we misunderstood each other.
>
>here is a new example:
>- switch1 is a switch with a configured lag with two members ports
> (member1 and member2)
>- two linux (linux1 and linux2) box with a configured bonding device
> (bond0) with the same MAC set in both box and one
> slave on each
>- lacp_port_id is set to 10 in linux1 and 20 in linux2
>
>you can attach the slave from both linux boxes to the same
>lag on switch1. (slave from linux1 to port member1 and
>slave from linux2 to port member2 on switch1)
>
>port id must be unique within a system.
>bonding implementation set a unique system id for every bonding device
>which is derived from MAC of one of the slave interfaces.
>
>if we use the current bonding implementation second linux box can't be
>a member on switch1 because port id is 1 in both linux bonding device.
>
>if we can set different starting port id for bonding in different boxes
>the second box can be a member also.
I understand what you're trying to do here (permit multiple
instances of bonding on different systems to connect to a single
aggregator on a switch), and I don't really have a problem with it in
general.
I do have some comments:
First, altering the lacp_port_id (via sysfs) should only be
permitted when there are no slaves in the bond, otherwise the
/proc/net/bonding/bond0 output for the first port id will not match the
actual first port id value assigned to the slaves. As a practical
matter, altering lacp_port_id while slaves are present in the bond has
no effect until all slaves are released and the first new slave is
added, so this is not reducing functionality.
Second, the lacp_port_id is global across all bonds created
within the loaded module, and so multiple bonds will all use the same
starting value. Setting the lacp_port_id via sysfs has no effect, as it
alters a per-bond value, bond->params.lacp_port_id, that is never
actually used to set the port ID of a first slave in bond_enslave.
The global default value should only be used to initialize the
per-bond value when a bond is created, and that per-bond value should be
used when setting the port id in bond_enslave(). The per-bond value is
already displayed in /proc/net/bonding/bond0, and is the value modified
by the sysfs functions
Third, consider adding the port ID to the 803.2ad section in
bond_info_show_slave.
Lastly, I think this should be tested against systems other than
Cisco to insure that it really interoperates with, for example,
Juniper's methodology for spanning an aggregator across physical
chassis. I'm not sure why it wouldn't, but once new functionality
becomes part of the kernel, changing it in non-backwards compatible ways
is difficult.
-J
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply
* [PATCH net] net: tg3: fix NULL pointer dereference in tg3_io_error_detected and tg3_io_slot_reset
From: Nithin Nayak Sujir @ 2013-08-13 18:45 UTC (permalink / raw)
To: davem; +Cc: netdev, Daniel Borkmann, Gavin Shan, Michael Chan,
Nithin Nayak Sujir
From: Daniel Borkmann <dborkman@redhat.com>
Commit d8af4dfd8 ("net/tg3: Fix kernel crash") introduced a possible
NULL pointer dereference in tg3 driver when !netdev || !netif_running(netdev)
condition is met and netdev is NULL. Then, the jump to the 'done' label
calls dev_close() with a netdevice that is NULL. Therefore, only call
dev_close() when we have a netdevice, but one that is not running.
[ Add the same checks in tg3_io_slot_reset() per Gavin Shan - by Nithin
Nayak Sujir ]
Reported-by: Dave Jones <davej@redhat.com>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Cc: Gavin Shan <shangw@linux.vnet.ibm.com>
Cc: Michael Chan <mchan@broadcom.com>
Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
---
drivers/net/ethernet/broadcom/tg3.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ddebc7a..0da2214 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -17796,8 +17796,10 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
done:
if (state == pci_channel_io_perm_failure) {
- tg3_napi_enable(tp);
- dev_close(netdev);
+ if (netdev) {
+ tg3_napi_enable(tp);
+ dev_close(netdev);
+ }
err = PCI_ERS_RESULT_DISCONNECT;
} else {
pci_disable_device(pdev);
@@ -17827,7 +17829,8 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
rtnl_lock();
if (pci_enable_device(pdev)) {
- netdev_err(netdev, "Cannot re-enable PCI device after reset.\n");
+ dev_err(&pdev->dev,
+ "Cannot re-enable PCI device after reset.\n");
goto done;
}
@@ -17835,7 +17838,7 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
pci_restore_state(pdev);
pci_save_state(pdev);
- if (!netif_running(netdev)) {
+ if (!netdev || !netif_running(netdev)) {
rc = PCI_ERS_RESULT_RECOVERED;
goto done;
}
@@ -17847,7 +17850,7 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
rc = PCI_ERS_RESULT_RECOVERED;
done:
- if (rc != PCI_ERS_RESULT_RECOVERED && netif_running(netdev)) {
+ if (rc != PCI_ERS_RESULT_RECOVERED && netdev && netif_running(netdev)) {
tg3_napi_enable(tp);
dev_close(netdev);
}
--
1.8.1.4
^ permalink raw reply related
* [PATCH] r8169: remember WOL preferences on driver load
From: Peter Wu @ 2013-08-13 20:19 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, nic_swsd, lekensteyn
Do not clear Broadcast/Multicast/Unicast Wake Flag or LanWake in
Config5. This is necessary to preserve WOL state when the driver is
loaded. The r8168 vendor driver used to write to both Config1 and
Config5, but in recent versions, this is commented out. Here we keep
writing PMEnable to Config1 because there may be older chips where
PMEnable is not sticky.
Signed-off-by: Peter Wu <lekensteyn@gmail.com>
---
drivers/net/ethernet/realtek/r8169.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 28af01c..7bdf322 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -7093,7 +7093,6 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
- RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
tp->features |= RTL_FEATURE_WOL;
if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
--
1.8.3.4
^ permalink raw reply related
* [PATCH] r8169: fix invalid register dump
From: Peter Wu @ 2013-08-13 20:37 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, nic_swsd, lekensteyn
From: Peter Wu <lekensteyn@gmail.com>
For some reason, my PCIe RTL8111E onboard NIC on a GA-Z68X-UD3H-B3
motherboard reads as FFs when reading from MMIO with a block size
larger than 7. Therefore change to reading blocks of four bytes.
Signed-off-by: Peter Wu <lekensteyn@gmail.com>
---
Hi,
Personally I dislike the repetition of this patch, a hypothetical
`memcpy_fromio_block(bytes, tp->mmio_addr, 4)` would look cleaner, but
perhaps I am doing something wrong because apparantly nobody had a need
for reading multiple blocks from IO?
Anyway, this patch (with patched ethtool) allows `ethtool -d` to be more
useful for the mentioned chip.
Regards,
Peter
---
drivers/net/ethernet/realtek/r8169.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index b5eb419..28af01c 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -1897,12 +1897,17 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
{
struct rtl8169_private *tp = netdev_priv(dev);
+ char *bytes = p;
+ int i;
if (regs->len > R8169_REGS_SIZE)
regs->len = R8169_REGS_SIZE;
rtl_lock_work(tp);
- memcpy_fromio(p, tp->mmio_addr, regs->len);
+ for (i = 0; i < regs->len - 4; i += 4)
+ memcpy_fromio(bytes + i, tp->mmio_addr + i, 4);
+ if (i < regs->len)
+ memcpy_fromio(bytes + i, tp->mmio_addr + i, regs->len - i);
rtl_unlock_work(tp);
}
--
1.8.3.4
^ permalink raw reply related
* Re: question about netif_rx
From: Francois Romieu @ 2013-08-13 20:41 UTC (permalink / raw)
To: David Shwatrz
Cc: Julia Lawall, grant.likely, rob.herring, netdev, linux-kernel,
devicetree
In-Reply-To: <CAJJAcocQ59Kc9a1b=jrNSc1akLLN_74yKANMEmLVmvxoRjX4hw@mail.gmail.com>
(no top-post nor lazy quote please)
David Shwatrz <dshwatrz@gmail.com> :
[...]
> In the napi_gro_receive() we check that the device supports
> NETIF_F_GRO, but I don't see that we inspect checksum or that
> NETIF_F_GRO is depends on checksum.
napi_gro_receive is irrelevant. Let aside tunnel, the real work happens
in the protocol specific gro_receive handlers.
However I am an happy retard and I missed that tcp gro stopped depending
on Rx checksum since commit 861b650101eb0c627d171eb18de81dddb93d395e. :o/
So, yes, napi_gro_receive could be used.
--
Ueimor
^ permalink raw reply
* Find vlanid with non-root user
From: Amador Pahim @ 2013-08-13 20:46 UTC (permalink / raw)
To: netdev
Hello,
Is there a way to get vlanid from a vlan interface as a regular user?
Default permissions to /proc/net/vlan/ is 600.
-rw-------. 1 root root 0 Aug 13 17:23 /proc/net/vlan/eth1.10-fcoe
Not sure if deducting vlanid from vlan name is a reasonable way to do so.
Thank you in advance,.
Best Regards,
--
Pahim
^ permalink raw reply
* Re: [PATCH 1/2] net: asix: Staticise non-exported symbols
From: David Miller @ 2013-08-13 21:14 UTC (permalink / raw)
To: broonie; +Cc: linux-usb, netdev, linaro-kernel, broonie
In-Reply-To: <1376069482-16951-1-git-send-email-broonie@kernel.org>
From: Mark Brown <broonie@kernel.org>
Date: Fri, 9 Aug 2013 18:31:21 +0100
> From: Mark Brown <broonie@linaro.org>
>
> Make functions that are only referenced from ops structures static, they
> do not need to be in the global namespace and sparse complains about this.
>
> Signed-off-by: Mark Brown <broonie@linaro.org>
Applied.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox