* Re: [PATCH net-next] team: add ethtool support
From: Flavio Leitner @ 2012-12-30 1:44 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, Jiri Pirko
In-Reply-To: <20121229172945.25a09fc8@nehalam.linuxnetplumber.net>
On Sat, Dec 29, 2012 at 05:29:45PM -0800, Stephen Hemminger wrote:
> On Sat, 29 Dec 2012 23:19:26 -0200
> Flavio Leitner <fbl@redhat.com> wrote:
>
> > This patch adds few ethtool operations to team driver.
> >
> > Signed-off-by: Flavio Leitner <fbl@redhat.com>
>
> What is the motivation for this? Is there an application that depends
> on ethtool (versus netlink, or /proc)?
Speaking as a support engineer, it's a lot easier to grab ethtool -S and
see everything than grab two or more outputs.
> Sorry, I see no point in providing ethtool statistics for generic data that is already
> reported by existing netlink and other infrastructure. The purpose of ethtool
> statistics is to report device specific that is not available through the normal
> generic statistics.
Right, but those statistics can be device specific as well. The tg3 and bnx2, for
instance, do the same reporting [rx|tx]_bytes|octets.
I see no harm, and it is helpful.
--
fbl
^ permalink raw reply
* Re: [PATCHv2 net-next] bridge: respect RFC2863 operational state
From: Flavio Leitner @ 2012-12-30 2:01 UTC (permalink / raw)
To: netdev
In-Reply-To: <20121228201522.62a48370@nehalam.linuxnetplumber.net>
On Fri, Dec 28, 2012 at 08:15:22PM -0800, Stephen Hemminger wrote:
> The bridge link detection should follow the operational state
> of the lower device, rather than the carrier bit. This allows devices
> like tunnels that are controlled by userspace control plane to work
> with bridge STP link management.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
> ---
Although I can't test this right now, it does look good to me.
Reviewed-by: Flavio Leitner <fbl@redhat.com>
^ permalink raw reply
* [PATCH net-next] veth: reduce stat overhead
From: Eric Dumazet @ 2012-12-30 2:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
veth stats are a bit bloated. There is no need to account transmit
and receive stats, since they are absolutely symmetric.
Also use a per device atomic64_t for the dropped counter, as it
should never be used in fast path.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
drivers/net/veth.c | 115 ++++++++++++++----------------------
include/linux/netdevice.h | 1
2 files changed, 48 insertions(+), 68 deletions(-)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 95814d9..c048f8d 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -25,18 +25,15 @@
#define MIN_MTU 68 /* Min L3 MTU */
#define MAX_MTU 65535 /* Max L3 MTU (arbitrary) */
-struct veth_net_stats {
- u64 rx_packets;
- u64 rx_bytes;
- u64 tx_packets;
- u64 tx_bytes;
- u64 rx_dropped;
+struct pcpu_vstats {
+ u64 packets;
+ u64 bytes;
struct u64_stats_sync syncp;
};
struct veth_priv {
- struct net_device *peer;
- struct veth_net_stats __percpu *stats;
+ struct net_device *peer;
+ atomic64_t dropped;
};
/*
@@ -107,50 +104,30 @@ static const struct ethtool_ops veth_ethtool_ops = {
.get_ethtool_stats = veth_get_ethtool_stats,
};
-/*
- * xmit
- */
-
static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct net_device *rcv = NULL;
- struct veth_priv *priv, *rcv_priv;
- struct veth_net_stats *stats, *rcv_stats;
- int length;
-
- priv = netdev_priv(dev);
- rcv = priv->peer;
- rcv_priv = netdev_priv(rcv);
-
- stats = this_cpu_ptr(priv->stats);
- rcv_stats = this_cpu_ptr(rcv_priv->stats);
+ struct veth_priv *priv = netdev_priv(dev);
+ struct net_device *rcv = priv->peer;
+ int length = skb->len;
/* don't change ip_summed == CHECKSUM_PARTIAL, as that
- will cause bad checksum on forwarded packets */
+ * will cause bad checksum on forwarded packets
+ */
if (skb->ip_summed == CHECKSUM_NONE &&
rcv->features & NETIF_F_RXCSUM)
skb->ip_summed = CHECKSUM_UNNECESSARY;
- length = skb->len;
- if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
- goto rx_drop;
-
- u64_stats_update_begin(&stats->syncp);
- stats->tx_bytes += length;
- stats->tx_packets++;
- u64_stats_update_end(&stats->syncp);
+ if (likely(dev_forward_skb(rcv, skb) == NET_RX_SUCCESS)) {
+ struct pcpu_vstats *stats = this_cpu_ptr(dev->vstats);
- u64_stats_update_begin(&rcv_stats->syncp);
- rcv_stats->rx_bytes += length;
- rcv_stats->rx_packets++;
- u64_stats_update_end(&rcv_stats->syncp);
-
- return NETDEV_TX_OK;
+ u64_stats_update_begin(&stats->syncp);
+ stats->bytes += length;
+ stats->packets++;
+ u64_stats_update_end(&stats->syncp);
+ } else {
+ atomic64_inc(&priv->dropped);
+ }
-rx_drop:
- u64_stats_update_begin(&rcv_stats->syncp);
- rcv_stats->rx_dropped++;
- u64_stats_update_end(&rcv_stats->syncp);
return NETDEV_TX_OK;
}
@@ -158,32 +135,42 @@ rx_drop:
* general routines
*/
-static struct rtnl_link_stats64 *veth_get_stats64(struct net_device *dev,
- struct rtnl_link_stats64 *tot)
+static u64 veth_stats_one(struct pcpu_vstats *result, struct net_device *dev)
{
struct veth_priv *priv = netdev_priv(dev);
int cpu;
+ result->packets = 0;
+ result->bytes = 0;
for_each_possible_cpu(cpu) {
- struct veth_net_stats *stats = per_cpu_ptr(priv->stats, cpu);
- u64 rx_packets, rx_bytes, rx_dropped;
- u64 tx_packets, tx_bytes;
+ struct pcpu_vstats *stats = per_cpu_ptr(dev->vstats, cpu);
+ u64 packets, bytes;
unsigned int start;
do {
start = u64_stats_fetch_begin_bh(&stats->syncp);
- rx_packets = stats->rx_packets;
- tx_packets = stats->tx_packets;
- rx_bytes = stats->rx_bytes;
- tx_bytes = stats->tx_bytes;
- rx_dropped = stats->rx_dropped;
+ packets = stats->packets;
+ bytes = stats->bytes;
} while (u64_stats_fetch_retry_bh(&stats->syncp, start));
- tot->rx_packets += rx_packets;
- tot->tx_packets += tx_packets;
- tot->rx_bytes += rx_bytes;
- tot->tx_bytes += tx_bytes;
- tot->rx_dropped += rx_dropped;
+ result->packets += packets;
+ result->bytes += bytes;
}
+ return atomic64_read(&priv->dropped);
+}
+
+static struct rtnl_link_stats64 *veth_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *tot)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+ struct pcpu_vstats one;
+
+ tot->tx_dropped = veth_stats_one(&one, dev);
+ tot->tx_bytes = one.bytes;
+ tot->tx_packets = one.packets;
+
+ tot->rx_dropped = veth_stats_one(&one, priv->peer);
+ tot->rx_bytes = one.bytes;
+ tot->rx_packets = one.packets;
return tot;
}
@@ -228,24 +215,16 @@ static int veth_change_mtu(struct net_device *dev, int new_mtu)
static int veth_dev_init(struct net_device *dev)
{
- struct veth_net_stats __percpu *stats;
- struct veth_priv *priv;
-
- stats = alloc_percpu(struct veth_net_stats);
- if (stats == NULL)
+ dev->vstats = alloc_percpu(struct pcpu_vstats);
+ if (!dev->vstats)
return -ENOMEM;
- priv = netdev_priv(dev);
- priv->stats = stats;
return 0;
}
static void veth_dev_free(struct net_device *dev)
{
- struct veth_priv *priv;
-
- priv = netdev_priv(dev);
- free_percpu(priv->stats);
+ free_percpu(dev->vstats);
free_netdev(dev);
}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c599e47..e3f5755 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1274,6 +1274,7 @@ struct net_device {
struct pcpu_lstats __percpu *lstats; /* loopback stats */
struct pcpu_tstats __percpu *tstats; /* tunnel stats */
struct pcpu_dstats __percpu *dstats; /* dummy stats */
+ struct pcpu_vstats __percpu *vstats; /* veth stats */
};
/* GARP */
struct garp_port __rcu *garp_port;
^ permalink raw reply related
* Re: [PATCH net-next] team: add ethtool support
From: David Miller @ 2012-12-30 2:09 UTC (permalink / raw)
To: fbl; +Cc: shemminger, netdev, jiri
In-Reply-To: <20121230014403.GA2077@obelix.rh>
From: Flavio Leitner <fbl@redhat.com>
Date: Sat, 29 Dec 2012 23:44:03 -0200
> Right, but those statistics can be device specific as well. The tg3 and bnx2, for
> instance, do the same reporting [rx|tx]_bytes|octets.
Because those ARE PER QUEUE in multiqueue configurations, and thus
device specific.
There is no reason to report the bare single-queue generic
netdevice stats via ethtool.
^ permalink raw reply
* [PATCH] veth: extend device features
From: Eric Dumazet @ 2012-12-30 2:26 UTC (permalink / raw)
To: Michał Mirosław, David Miller
Cc: Andrew Vagin, netdev, vvs, Michał Mirosław
In-Reply-To: <CAHXqBFL+Ycw4-_LRcOCT0bjhALE3HfVMB7YfcoCruu=zW5PN-g@mail.gmail.com>
From: Eric Dumazet <edumazet@google.com>
veth is lacking most modern facilities, like SG, checksums, TSO.
It makes sense to extend dev->features to get them, or GRO aggregation
is defeated by a forced segmentation.
Reported-by: Andrew Vagin <avagin@parallels.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
drivers/net/veth.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 95814d9..ccf211f 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -259,6 +259,10 @@ static const struct net_device_ops veth_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
};
+#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
+ NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_HIGHDMA | \
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX)
+
static void veth_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -269,9 +273,10 @@ static void veth_setup(struct net_device *dev)
dev->netdev_ops = &veth_netdev_ops;
dev->ethtool_ops = &veth_ethtool_ops;
dev->features |= NETIF_F_LLTX;
+ dev->features |= VETH_FEATURES;
dev->destructor = veth_dev_free;
- dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_RXCSUM;
+ dev->hw_features = VETH_FEATURES;
}
/*
^ permalink raw reply related
* Re: [PATCH net-next] team: add ethtool support
From: Flavio Leitner @ 2012-12-30 2:30 UTC (permalink / raw)
To: David Miller; +Cc: shemminger, netdev, jiri
In-Reply-To: <20121229.180930.2054437059250829691.davem@davemloft.net>
On Sat, Dec 29, 2012 at 06:09:30PM -0800, David Miller wrote:
> From: Flavio Leitner <fbl@redhat.com>
> Date: Sat, 29 Dec 2012 23:44:03 -0200
>
> > Right, but those statistics can be device specific as well. The tg3 and bnx2, for
> > instance, do the same reporting [rx|tx]_bytes|octets.
>
> Because those ARE PER QUEUE in multiqueue configurations, and thus
> device specific.
>
> There is no reason to report the bare single-queue generic
> netdevice stats via ethtool.
Alright, I will post another version without the statistics.
please, drop this one.
thanks,
--
fbl
^ permalink raw reply
* Re: [PATCH net-next] team: add ethtool support
From: Eric Dumazet @ 2012-12-30 2:31 UTC (permalink / raw)
To: Flavio Leitner; +Cc: Stephen Hemminger, netdev, Jiri Pirko
In-Reply-To: <20121230014403.GA2077@obelix.rh>
On Sat, 2012-12-29 at 23:44 -0200, Flavio Leitner wrote:
> Speaking as a support engineer, it's a lot easier to grab ethtool -S and
> see everything than grab two or more outputs.
>
I agree its very convenient.
I have a patch to add GRO statistics at the core layer, in the ethtool
-S stats.
I was about to ask netdev guys what they think of this idea ?
net-gro: Add GRO counters to ethtool -S
In order to get an idea of how effective is GRO aggregation on a machine,
we need appropriate counters. Preferably use "ethtool -S" to display them
on a per device basis, or even per RX queue.
In this implementation, I chose to not change NIC drivers.
Core network stack adds the gro counters at the end of the counters
each NIC driver provides for ethtool -S
There are 5 counters per RX queue :
gro_complete: number of time the NAPI handler did not consume its budget
(This force a flush of all GRO packets in the GRO queue)
gro_overflows: number of time a segment could not be stored in GRO queue
because current number or messages is too high
gro_nogro: number of time a segment was not stored in GRO queue.
(Because its not a TCP packet, or it includes a
SYN/FIN/RST/PSH flag)
gro_msgs: number of GRO messages (might contain 1 to 17 segments)
gro_segs: number of GRO segments
Example:
On receiver machine, with 8 RX queues :
ethtool -S eth4 | tail -n 10
gro_complete[7]: 56635
gro_overflows[7]: 0
gro_nogro[7]: 212
gro_msgs[7]: 129410
gro_segs[7]: 1434925
gro_complete: 699479
gro_overflows: 0
gro_nogro: 2455
gro_msgs: 1626470
gro_segs: 17876794
In this example, we can compute average number of segments per GRO message :
17876794/17876794 = 10.99
Or more precisely : 17876794/(17876794+2455) = 10.97
^ permalink raw reply
* [PATCH v2 net-next] team: add ethtool support
From: Flavio Leitner @ 2012-12-30 2:37 UTC (permalink / raw)
To: netdev; +Cc: Jiri Pirko, Flavio Leitner
This patch adds few ethtool operations to team driver.
Signed-off-by: Flavio Leitner <fbl@redhat.com>
---
v2 - removed generic statistics from ethtool
drivers/net/team/team.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index ad86660..7665a088 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -28,6 +28,7 @@
#include <net/genetlink.h>
#include <net/netlink.h>
#include <net/sch_generic.h>
+#include <generated/utsrelease.h>
#include <linux/if_team.h>
#define DRV_NAME "team"
@@ -1731,6 +1732,21 @@ static const struct net_device_ops team_netdev_ops = {
.ndo_fix_features = team_fix_features,
};
+/***********************
+ * ethtool interface
+ ***********************/
+
+static void team_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strncpy(drvinfo->driver, DRV_NAME, 32);
+ strncpy(drvinfo->version, UTS_RELEASE, 32);
+}
+
+static const struct ethtool_ops team_ethtool_ops = {
+ .get_drvinfo = team_ethtool_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+};
/***********************
* rt netlink interface
@@ -1780,6 +1796,7 @@ static void team_setup(struct net_device *dev)
ether_setup(dev);
dev->netdev_ops = &team_netdev_ops;
+ dev->ethtool_ops = &team_ethtool_ops;
dev->destructor = team_destructor;
dev->tx_queue_len = 0;
dev->flags |= IFF_MULTICAST;
--
1.8.0.1
^ permalink raw reply related
* [PATCH] net: fix checking boundary of valid vlan id
From: akong @ 2012-12-30 6:28 UTC (permalink / raw)
To: netdev; +Cc: davem
From: Amos Kong <akong@redhat.com>
4096 is not a valid vlan id.
Signed-off-by: Amos Kong <akong@redhat.com>
---
net/bridge/netfilter/ebt_vlan.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index eae67bf..b279ec0 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -121,8 +121,8 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par)
* if_vlan.h: VLAN_N_VID 4096. */
if (GET_BITMASK(EBT_VLAN_ID)) {
if (!!info->id) { /* if id!=0 => check vid range */
- if (info->id > VLAN_N_VID) {
- pr_debug("id %d is out of range (1-4096)\n",
+ if (info->id >= VLAN_N_VID) {
+ pr_debug("id %d is out of range (1-4095)\n",
info->id);
return -EINVAL;
}
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH] net: fix checking boundary of valid vlan id
From: Amos Kong @ 2012-12-30 6:39 UTC (permalink / raw)
To: netdev; +Cc: davem
In-Reply-To: <1356848931-22193-1-git-send-email-akong@redhat.com>
On Sun, Dec 30, 2012 at 02:28:51PM +0800, akong@redhat.com wrote:
> From: Amos Kong <akong@redhat.com>
>
> 4096 is not a valid vlan id.
>
> Signed-off-by: Amos Kong <akong@redhat.com>
> ---
> net/bridge/netfilter/ebt_vlan.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
> index eae67bf..b279ec0 100644
> --- a/net/bridge/netfilter/ebt_vlan.c
> +++ b/net/bridge/netfilter/ebt_vlan.c
> @@ -121,8 +121,8 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par)
> * if_vlan.h: VLAN_N_VID 4096. */
> if (GET_BITMASK(EBT_VLAN_ID)) {
> if (!!info->id) { /* if id!=0 => check vid range */
> - if (info->id > VLAN_N_VID) {
> - pr_debug("id %d is out of range (1-4096)\n",
> + if (info->id >= VLAN_N_VID) {
> + pr_debug("id %d is out of range (1-4095)\n",
Hi David,
4095 is reserved, treat it as invalid here?
if (info->id >= VLAN_N_VID - 1) {
pr_debug("id %d is out of range (1-4094)\n",
> info->id);
> return -EINVAL;
> }
> --
> 1.7.11.7
^ permalink raw reply
* Re: [PATCH] net: fix checking boundary of valid vlan id
From: David Miller @ 2012-12-30 7:40 UTC (permalink / raw)
To: akong; +Cc: netdev
In-Reply-To: <1356848931-22193-1-git-send-email-akong@redhat.com>
Please send netfilter patches to the netfilter developers
at netfilter-devel@vger.kernel.org
Thanks.
^ permalink raw reply
* Re: [PATCH net-next] team: implement carrier change
From: Jiri Pirko @ 2012-12-30 8:50 UTC (permalink / raw)
To: Flavio Leitner; +Cc: netdev
In-Reply-To: <1356831061-1483-1-git-send-email-fbl@redhat.com>
Sun, Dec 30, 2012 at 02:31:01AM CET, fbl@redhat.com wrote:
>The user space teamd daemon may need to control the
>master's carrier state depending on the selected mode.
>
>Signed-off-by: Flavio Leitner <fbl@redhat.com>
>---
> drivers/net/team/team.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
>diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
>index f711039..14cb843 100644
>--- a/drivers/net/team/team.c
>+++ b/drivers/net/team/team.c
>@@ -1708,6 +1708,15 @@ static netdev_features_t team_fix_features(struct net_device *dev,
> return features;
> }
>
>+static int team_change_carrier(struct net_device *dev, bool new_carrier)
>+{
>+ if (new_carrier)
>+ netif_carrier_on(dev);
>+ else
>+ netif_carrier_off(dev);
>+ return 0;
>+}
>+
> static const struct net_device_ops team_netdev_ops = {
> .ndo_init = team_init,
> .ndo_uninit = team_uninit,
>@@ -1730,6 +1739,7 @@ static const struct net_device_ops team_netdev_ops = {
> .ndo_add_slave = team_add_slave,
> .ndo_del_slave = team_del_slave,
> .ndo_fix_features = team_fix_features,
>+ .ndo_change_carrier = team_change_carrier,
> };
>
> /***********************
>--
>1.8.0.1
Acked-by: Jiri Pirko <jiri@resnulli.us>
>
^ permalink raw reply
* Re: [PATCH v2 net-next] team: add ethtool support
From: Jiri Pirko @ 2012-12-30 8:51 UTC (permalink / raw)
To: Flavio Leitner; +Cc: netdev
In-Reply-To: <1356835053-25602-1-git-send-email-fbl@redhat.com>
Sun, Dec 30, 2012 at 03:37:33AM CET, fbl@redhat.com wrote:
>This patch adds few ethtool operations to team driver.
>
>Signed-off-by: Flavio Leitner <fbl@redhat.com>
>---
>v2 - removed generic statistics from ethtool
>
> drivers/net/team/team.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
>diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
>index ad86660..7665a088 100644
>--- a/drivers/net/team/team.c
>+++ b/drivers/net/team/team.c
>@@ -28,6 +28,7 @@
> #include <net/genetlink.h>
> #include <net/netlink.h>
> #include <net/sch_generic.h>
>+#include <generated/utsrelease.h>
> #include <linux/if_team.h>
>
> #define DRV_NAME "team"
>@@ -1731,6 +1732,21 @@ static const struct net_device_ops team_netdev_ops = {
> .ndo_fix_features = team_fix_features,
> };
>
>+/***********************
>+ * ethtool interface
>+ ***********************/
>+
>+static void team_ethtool_get_drvinfo(struct net_device *dev,
>+ struct ethtool_drvinfo *drvinfo)
>+{
>+ strncpy(drvinfo->driver, DRV_NAME, 32);
>+ strncpy(drvinfo->version, UTS_RELEASE, 32);
>+}
>+
>+static const struct ethtool_ops team_ethtool_ops = {
>+ .get_drvinfo = team_ethtool_get_drvinfo,
>+ .get_link = ethtool_op_get_link,
>+};
>
> /***********************
> * rt netlink interface
>@@ -1780,6 +1796,7 @@ static void team_setup(struct net_device *dev)
> ether_setup(dev);
>
> dev->netdev_ops = &team_netdev_ops;
>+ dev->ethtool_ops = &team_ethtool_ops;
> dev->destructor = team_destructor;
> dev->tx_queue_len = 0;
> dev->flags |= IFF_MULTICAST;
>--
>1.8.0.1
>
Acked-by: Jiri Pirko <jiri@resnulli.us>
^ permalink raw reply
* Re: [patch net-next 01/15] net: introduce upper device lists
From: Jiri Pirko @ 2012-12-30 9:53 UTC (permalink / raw)
To: David Miller
Cc: netdev, edumazet, bhutchings, faisal.latif, shemminger, fbl,
roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
nhorman, john.r.fastabend, pablo
In-Reply-To: <20121229.153101.676681277388952344.davem@davemloft.net>
Sun, Dec 30, 2012 at 12:31:01AM CET, davem@davemloft.net wrote:
>From: Jiri Pirko <jiri@resnulli.us>
>Date: Sat, 29 Dec 2012 11:38:28 +0100
>
>> + /*
>> + * To prevent loops, check if dev is not upper device to upper_dev.
>> + */
>
>Please use:
>
> /* To prevent loops, check if dev is not upper device to upper_dev. */
fixed
>
>> +/**
>> + * netdev_upper_free_rcu - Frees a upper device list item via the RCU pointer
>> + * @entry: the entry's RCU field
>> + *
>> + * This function is designed to be used as a callback to the call_rcu()
>> + * function so that the memory allocated to the netdev upper device list item
>> + * can be released safely.
>> + */
>> +static void netdev_upper_free_rcu(struct rcu_head *entry)
>> +{
>> + struct netdev_upper *upper;
>> +
>> + upper = container_of(entry, struct netdev_upper, rcu);
>> + kfree(upper);
>> +}
>
>Please use kfree_rcu().
fixed
>
>Also, since __netdev_has_upper_dev() modifies &search_list inside
>of the list traversal loop, I think you really need to use
>list_for_each_entry_safe() even though you always append to the
>tail of &search_list.
Hmm, I do not believe that list_for_each_entry_safe() would work correctly
here. In case that the current iterator is at the very end of
the list and now other items are added, list_for_each_entry_safe() would
remember that next is head and the newly added items would not be
processed. list_for_each_entry() works just fine in any case I can
imagine. Note that no items are removed during the iteration.
Am I missing something?
Thanks!
Jiri
^ permalink raw reply
* Re: [PATCH net-next] net: filter: return -EINVAL if BPF_S_ANC* operation is not supported
From: David Miller @ 2012-12-30 10:30 UTC (permalink / raw)
To: dborkman; +Cc: ani, netdev, eric.dumazet
In-Reply-To: <1356727817-10649-1-git-send-email-dborkman@redhat.com>
From: Daniel Borkmann <dborkman@redhat.com>
Date: Fri, 28 Dec 2012 21:50:17 +0100
> Currently, we return -EINVAL for malformed or wrong BPF filters.
> However, this is not done for BPF_S_ANC* operations, which makes it
> more difficult to detect if it's actually supported or not by the
> BPF machine. Therefore, we should also return -EINVAL if K is within
> the SKF_AD_OFF universe and the ancillary operation did not match.
...
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> Reported-by: Ani Sinha <ani@aristanetworks.com>
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCHv2 net-next] bridge: respect RFC2863 operational state
From: David Miller @ 2012-12-30 10:32 UTC (permalink / raw)
To: shemminger; +Cc: netdev
In-Reply-To: <20121228201522.62a48370@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Fri, 28 Dec 2012 20:15:22 -0800
> The bridge link detection should follow the operational state
> of the lower device, rather than the carrier bit. This allows devices
> like tunnels that are controlled by userspace control plane to work
> with bridge STP link management.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] team: implement carrier change
From: David Miller @ 2012-12-30 10:32 UTC (permalink / raw)
To: fbl; +Cc: netdev, jiri
In-Reply-To: <1356831061-1483-1-git-send-email-fbl@redhat.com>
From: Flavio Leitner <fbl@redhat.com>
Date: Sat, 29 Dec 2012 23:31:01 -0200
> The user space teamd daemon may need to control the
> master's carrier state depending on the selected mode.
>
> Signed-off-by: Flavio Leitner <fbl@redhat.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] veth: reduce stat overhead
From: David Miller @ 2012-12-30 10:32 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1356832963.21409.6156.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sat, 29 Dec 2012 18:02:43 -0800
> From: Eric Dumazet <edumazet@google.com>
>
> veth stats are a bit bloated. There is no need to account transmit
> and receive stats, since they are absolutely symmetric.
>
> Also use a per device atomic64_t for the dropped counter, as it
> should never be used in fast path.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Applied.
^ permalink raw reply
* Re: [PATCH] veth: extend device features
From: David Miller @ 2012-12-30 10:32 UTC (permalink / raw)
To: erdnetdev; +Cc: mirqus, avagin, netdev, vvs, mirq-linux
In-Reply-To: <1356834370.21409.6234.camel@edumazet-glaptop>
From: Eric Dumazet <erdnetdev@gmail.com>
Date: Sat, 29 Dec 2012 18:26:10 -0800
> From: Eric Dumazet <edumazet@google.com>
>
> veth is lacking most modern facilities, like SG, checksums, TSO.
>
> It makes sense to extend dev->features to get them, or GRO aggregation
> is defeated by a forced segmentation.
>
> Reported-by: Andrew Vagin <avagin@parallels.com>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Applied.
^ permalink raw reply
* Re: [PATCH v2 net-next] team: add ethtool support
From: David Miller @ 2012-12-30 10:33 UTC (permalink / raw)
To: fbl; +Cc: netdev, jiri
In-Reply-To: <1356835053-25602-1-git-send-email-fbl@redhat.com>
From: Flavio Leitner <fbl@redhat.com>
Date: Sun, 30 Dec 2012 00:37:33 -0200
> This patch adds few ethtool operations to team driver.
>
> Signed-off-by: Flavio Leitner <fbl@redhat.com>
Applied.
^ permalink raw reply
* [patch net-next V4 00/15] net: introduce upper device lists and remove dev->master
From: Jiri Pirko @ 2012-12-30 11:58 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
nhorman, john.r.fastabend, pablo
This is a V4 of a repost of my previous patchset:
"[patch net-next v2 00/15] net: introduce upper device lists and remove dev->master" from Aug 14
The discussion around
"[net-next] bonding: don't allow the master to become its slave"
forced me to think about upper<->lower device connections.
This patchset adds a possibility to record upper device linkage.
All upper<->lower devices are converted to use this mechanism right after.
That leads to dev->master removal because this info becomes redundant since
"master links" have the same value.
After all changes, there is no longer possible to do things as:
"bond->someotherdevice->samebond"
Also I think that drivers like cxgb3, qlcnic, qeth would benefit by this
in future by being able to get more appropriate info about l3 addresses.
v3->v4:
- comments in __netdev_upper_dev_link() squashed into one line
- kfree_rcu used instead of call_rcu in netdev_upper_dev_unlink()
v2->v3:
- removed recursion in __netdev_has_upper_dev()
- refreshed bits to be applicable on current net-next
v1->v2:
- s/unique/master/ better naming + stays closer to the past
- fixed vlan err goto
- original patch 15 (WARN_ON change) is squashed into the first patch
Jiri Pirko (15):
net: introduce upper device lists
macvlan: add link to upper device
vlan: add link to upper device
rtnetlink: remove usage of dev->master
team: remove usage of netdev_set_master()
bridge: remove usage of netdev_set_master()
netpoll: remove usage of dev->master
cxgb3: remove usage of dev->master
qlcnic: guard __vlan_find_dev_deep() by rcu_read_lock
qeth: ensure that __vlan_find_dev_deep() is called with rcu_read_lock
vlan: remove usage of dev->master in __vlan_find_dev_deep()
nes: remove usage of dev->master
bonding: remove usage of dev->master
net: remove no longer used netdev_set_bond_master() and
netdev_set_master()
net: kill dev->master
drivers/infiniband/hw/nes/nes.c | 8 +-
drivers/infiniband/hw/nes/nes_cm.c | 2 +-
drivers/net/bonding/bond_3ad.c | 30 +--
drivers/net/bonding/bond_alb.c | 6 +-
drivers/net/bonding/bond_main.c | 94 ++++----
drivers/net/bonding/bonding.h | 14 +-
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c | 11 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 +
drivers/net/macvlan.c | 9 +-
drivers/net/team/team.c | 13 +-
drivers/s390/net/qeth_l3_main.c | 21 +-
include/linux/netdevice.h | 22 +-
net/8021q/vlan.c | 10 +-
net/8021q/vlan_core.c | 18 +-
net/bridge/br_if.c | 6 +-
net/core/dev.c | 244 +++++++++++++++++----
net/core/netpoll.c | 9 +-
net/core/rtnetlink.c | 70 +++---
18 files changed, 407 insertions(+), 182 deletions(-)
--
1.8.0
^ permalink raw reply
* [patch net-next 01/15] net: introduce upper device lists
From: Jiri Pirko @ 2012-12-30 11:58 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
nhorman, john.r.fastabend, pablo
In-Reply-To: <1356868702-8144-1-git-send-email-jiri@resnulli.us>
This lists are supposed to serve for storing pointers to all upper devices.
Eventually it will replace dev->master pointer which is used for
bonding, bridge, team but it cannot be used for vlan, macvlan where
there might be multiple upper present. In case the upper link is
replacement for dev->master, it is marked with "master" flag.
New upper device list resolves this limitation. Also, the information
stored in lists is used for preventing looping setups like
"bond->somethingelse->samebond"
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
include/linux/netdevice.h | 14 +++
net/core/dev.c | 237 +++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 247 insertions(+), 4 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6835b58..52d1146 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1172,6 +1172,8 @@ struct net_device {
* which this device is member of.
*/
+ struct list_head upper_dev_list; /* List of upper devices */
+
/* Interface address info used in eth_type_trans() */
unsigned char *dev_addr; /* hw address, (before bcast
because most packets are
@@ -2634,6 +2636,18 @@ extern int netdev_max_backlog;
extern int netdev_tstamp_prequeue;
extern int weight_p;
extern int bpf_jit_enable;
+
+extern bool netdev_has_upper_dev(struct net_device *dev,
+ struct net_device *upper_dev);
+extern bool netdev_has_any_upper_dev(struct net_device *dev);
+extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
+extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
+extern int netdev_upper_dev_link(struct net_device *dev,
+ struct net_device *upper_dev);
+extern int netdev_master_upper_dev_link(struct net_device *dev,
+ struct net_device *upper_dev);
+extern void netdev_upper_dev_unlink(struct net_device *dev,
+ struct net_device *upper_dev);
extern int netdev_set_master(struct net_device *dev, struct net_device *master);
extern int netdev_set_bond_master(struct net_device *dev,
struct net_device *master);
diff --git a/net/core/dev.c b/net/core/dev.c
index 21c5b97..1af3141 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4600,6 +4600,230 @@ static int __init dev_proc_init(void)
#endif /* CONFIG_PROC_FS */
+struct netdev_upper {
+ struct net_device *dev;
+ bool master;
+ struct list_head list;
+ struct rcu_head rcu;
+ struct list_head search_list;
+};
+
+static void __append_search_uppers(struct list_head *search_list,
+ struct net_device *dev)
+{
+ struct netdev_upper *upper;
+
+ list_for_each_entry(upper, &dev->upper_dev_list, list) {
+ /* check if this upper is not already in search list */
+ if (list_empty(&upper->search_list))
+ list_add_tail(&upper->search_list, search_list);
+ }
+}
+
+static bool __netdev_has_upper_dev(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ LIST_HEAD(search_list);
+ struct netdev_upper *upper;
+ struct netdev_upper *tmp;
+ bool ret = false;
+
+ __append_search_uppers(&search_list, dev);
+ list_for_each_entry(upper, &search_list, search_list) {
+ if (upper->dev == upper_dev) {
+ ret = true;
+ break;
+ }
+ __append_search_uppers(&search_list, upper->dev);
+ }
+ list_for_each_entry_safe(upper, tmp, &search_list, search_list)
+ INIT_LIST_HEAD(&upper->search_list);
+ return ret;
+}
+
+static struct netdev_upper *__netdev_find_upper(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ struct netdev_upper *upper;
+
+ list_for_each_entry(upper, &dev->upper_dev_list, list) {
+ if (upper->dev == upper_dev)
+ return upper;
+ }
+ return NULL;
+}
+
+/**
+ * netdev_has_upper_dev - Check if device is linked to an upper device
+ * @dev: device
+ * @upper_dev: upper device to check
+ *
+ * Find out if a device is linked to specified upper device and return true
+ * in case it is. The caller must hold the RTNL semaphore.
+ */
+bool netdev_has_upper_dev(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ ASSERT_RTNL();
+
+ return __netdev_find_upper(dev, upper_dev);
+}
+EXPORT_SYMBOL(netdev_has_upper_dev);
+
+/**
+ * netdev_has_any_upper_dev - Check if device is linked to some device
+ * @dev: device
+ *
+ * Find out if a device is linked to an upper device and return true in case
+ * it is. The caller must hold the RTNL semaphore.
+ */
+bool netdev_has_any_upper_dev(struct net_device *dev)
+{
+ ASSERT_RTNL();
+
+ return !list_empty(&dev->upper_dev_list);
+}
+EXPORT_SYMBOL(netdev_has_any_upper_dev);
+
+/**
+ * netdev_master_upper_dev_get - Get master upper device
+ * @dev: device
+ *
+ * Find a master upper device and return pointer to it or NULL in case
+ * it's not there. The caller must hold the RTNL semaphore.
+ */
+struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
+{
+ struct netdev_upper *upper;
+
+ ASSERT_RTNL();
+
+ if (list_empty(&dev->upper_dev_list))
+ return NULL;
+
+ upper = list_first_entry(&dev->upper_dev_list,
+ struct netdev_upper, list);
+ if (likely(upper->master))
+ return upper->dev;
+ return NULL;
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_get);
+
+/**
+ * netdev_master_upper_dev_get_rcu - Get master upper device
+ * @dev: device
+ *
+ * Find a master upper device and return pointer to it or NULL in case
+ * it's not there. The caller must hold the RCU read lock.
+ */
+struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
+{
+ struct netdev_upper *upper;
+
+ upper = list_first_or_null_rcu(&dev->upper_dev_list,
+ struct netdev_upper, list);
+ if (upper && likely(upper->master))
+ return upper->dev;
+ return NULL;
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
+
+static int __netdev_upper_dev_link(struct net_device *dev,
+ struct net_device *upper_dev, bool master)
+{
+ struct netdev_upper *upper;
+
+ ASSERT_RTNL();
+
+ if (dev == upper_dev)
+ return -EBUSY;
+
+ /* To prevent loops, check if dev is not upper device to upper_dev. */
+ if (__netdev_has_upper_dev(upper_dev, dev))
+ return -EBUSY;
+
+ if (__netdev_find_upper(dev, upper_dev))
+ return -EEXIST;
+
+ if (master && netdev_master_upper_dev_get(dev))
+ return -EBUSY;
+
+ upper = kmalloc(sizeof(*upper), GFP_KERNEL);
+ if (!upper)
+ return -ENOMEM;
+
+ upper->dev = upper_dev;
+ upper->master = master;
+ INIT_LIST_HEAD(&upper->search_list);
+
+ /* Ensure that master upper link is always the first item in list. */
+ if (master)
+ list_add_rcu(&upper->list, &dev->upper_dev_list);
+ else
+ list_add_tail_rcu(&upper->list, &dev->upper_dev_list);
+ dev_hold(upper_dev);
+
+ return 0;
+}
+/**
+ * netdev_upper_dev_link - Add a link to the upper device
+ * @dev: device
+ * @upper_dev: new upper device
+ *
+ * Adds a link to device which is upper to this one. The caller must hold
+ * the RTNL semaphore. On a failure a negative errno code is returned.
+ * On success the reference counts are adjusted and the function
+ * returns zero.
+ */
+int netdev_upper_dev_link(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ return __netdev_upper_dev_link(dev, upper_dev, false);
+}
+EXPORT_SYMBOL(netdev_upper_dev_link);
+
+/**
+ * netdev_master_upper_dev_link - Add a master link to the upper device
+ * @dev: device
+ * @upper_dev: new upper device
+ *
+ * Adds a link to device which is upper to this one. In this case, only
+ * one master upper device can be linked, although other non-master devices
+ * might be linked as well. The caller must hold the RTNL semaphore.
+ * On a failure a negative errno code is returned. On success the reference
+ * counts are adjusted and the function returns zero.
+ */
+int netdev_master_upper_dev_link(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ return __netdev_upper_dev_link(dev, upper_dev, true);
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_link);
+
+/**
+ * netdev_upper_dev_unlink - Removes a link to upper device
+ * @dev: device
+ * @upper_dev: new upper device
+ *
+ * Removes a link to device which is upper to this one. The caller must hold
+ * the RTNL semaphore.
+ */
+void netdev_upper_dev_unlink(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ struct netdev_upper *upper;
+
+ ASSERT_RTNL();
+
+ upper = __netdev_find_upper(dev, upper_dev);
+ if (!upper)
+ return;
+ list_del_rcu(&upper->list);
+ dev_put(upper_dev);
+ kfree_rcu(upper, rcu);
+}
+EXPORT_SYMBOL(netdev_upper_dev_unlink);
+
/**
* netdev_set_master - set up master pointer
* @slave: slave device
@@ -4613,19 +4837,23 @@ static int __init dev_proc_init(void)
int netdev_set_master(struct net_device *slave, struct net_device *master)
{
struct net_device *old = slave->master;
+ int err;
ASSERT_RTNL();
if (master) {
if (old)
return -EBUSY;
- dev_hold(master);
+ err = netdev_master_upper_dev_link(slave, master);
+ if (err)
+ return err;
}
slave->master = master;
if (old)
- dev_put(old);
+ netdev_upper_dev_unlink(slave, master);
+
return 0;
}
EXPORT_SYMBOL(netdev_set_master);
@@ -5501,8 +5729,8 @@ static void rollback_registered_many(struct list_head *head)
if (dev->netdev_ops->ndo_uninit)
dev->netdev_ops->ndo_uninit(dev);
- /* Notifier chain MUST detach us from master device. */
- WARN_ON(dev->master);
+ /* Notifier chain MUST detach us all upper devices. */
+ WARN_ON(netdev_has_any_upper_dev(dev));
/* Remove entries from kobject tree */
netdev_unregister_kobject(dev);
@@ -6210,6 +6438,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->link_watch_list);
+ INIT_LIST_HEAD(&dev->upper_dev_list);
dev->priv_flags = IFF_XMIT_DST_RELEASE;
setup(dev);
--
1.8.0
^ permalink raw reply related
* [patch net-next 02/15] macvlan: add link to upper device
From: Jiri Pirko @ 2012-12-30 11:58 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
nhorman, john.r.fastabend, pablo
In-Reply-To: <1356868702-8144-1-git-send-email-jiri@resnulli.us>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/macvlan.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 68a43fe..b7b614f 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -765,16 +765,22 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN);
}
+ err = netdev_upper_dev_link(lowerdev, dev);
+ if (err)
+ goto destroy_port;
+
port->count += 1;
err = register_netdevice(dev);
if (err < 0)
- goto destroy_port;
+ goto upper_dev_unlink;
list_add_tail(&vlan->list, &port->vlans);
netif_stacked_transfer_operstate(lowerdev, dev);
return 0;
+upper_dev_unlink:
+ netdev_upper_dev_unlink(lowerdev, dev);
destroy_port:
port->count -= 1;
if (!port->count)
@@ -798,6 +804,7 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head)
list_del(&vlan->list);
unregister_netdevice_queue(dev, head);
+ netdev_upper_dev_unlink(vlan->lowerdev, dev);
}
EXPORT_SYMBOL_GPL(macvlan_dellink);
--
1.8.0
^ permalink raw reply related
* [patch net-next 03/15] vlan: add link to upper device
From: Jiri Pirko @ 2012-12-30 11:58 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
nhorman, john.r.fastabend, pablo
In-Reply-To: <1356868702-8144-1-git-send-email-jiri@resnulli.us>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
net/8021q/vlan.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index a292e80..babfde9 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -105,6 +105,8 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
*/
unregister_netdevice_queue(dev, head);
+ netdev_upper_dev_unlink(real_dev, dev);
+
if (grp->nr_vlan_devs == 0)
vlan_gvrp_uninit_applicant(real_dev);
@@ -162,9 +164,13 @@ int register_vlan_dev(struct net_device *dev)
if (err < 0)
goto out_uninit_applicant;
+ err = netdev_upper_dev_link(real_dev, dev);
+ if (err)
+ goto out_uninit_applicant;
+
err = register_netdevice(dev);
if (err < 0)
- goto out_uninit_applicant;
+ goto out_upper_dev_unlink;
/* Account for reference in struct vlan_dev_priv */
dev_hold(real_dev);
@@ -180,6 +186,8 @@ int register_vlan_dev(struct net_device *dev)
return 0;
+out_upper_dev_unlink:
+ netdev_upper_dev_unlink(real_dev, dev);
out_uninit_applicant:
if (grp->nr_vlan_devs == 0)
vlan_gvrp_uninit_applicant(real_dev);
--
1.8.0
^ permalink raw reply related
* [patch net-next 04/15] rtnetlink: remove usage of dev->master
From: Jiri Pirko @ 2012-12-30 11:58 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, bhutchings, faisal.latif, shemminger, fbl,
roland, sean.hefty, hal.rosenstock, fubar, andy, divy,
jitendra.kalsaria, sony.chacko, linux-driver, kaber, ursula.braun,
blaschka, schwidefsky, heiko.carstens, ebiederm, joe, amwang,
nhorman, john.r.fastabend, pablo
In-Reply-To: <1356868702-8144-1-git-send-email-jiri@resnulli.us>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
net/core/rtnetlink.c | 69 ++++++++++++++++++++++++++++------------------------
1 file changed, 37 insertions(+), 32 deletions(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2ef7a56..ae612f4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -880,6 +880,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
const struct rtnl_link_stats64 *stats;
struct nlattr *attr, *af_spec;
struct rtnl_af_ops *af_ops;
+ struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
ASSERT_RTNL();
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
@@ -908,8 +909,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
#endif
(dev->ifindex != dev->iflink &&
nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
- (dev->master &&
- nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
+ (upper_dev &&
+ nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
(dev->qdisc &&
nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
@@ -1273,16 +1274,16 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
static int do_set_master(struct net_device *dev, int ifindex)
{
- struct net_device *master_dev;
+ struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
const struct net_device_ops *ops;
int err;
- if (dev->master) {
- if (dev->master->ifindex == ifindex)
+ if (upper_dev) {
+ if (upper_dev->ifindex == ifindex)
return 0;
- ops = dev->master->netdev_ops;
+ ops = upper_dev->netdev_ops;
if (ops->ndo_del_slave) {
- err = ops->ndo_del_slave(dev->master, dev);
+ err = ops->ndo_del_slave(upper_dev, dev);
if (err)
return err;
} else {
@@ -1291,12 +1292,12 @@ static int do_set_master(struct net_device *dev, int ifindex)
}
if (ifindex) {
- master_dev = __dev_get_by_index(dev_net(dev), ifindex);
- if (!master_dev)
+ upper_dev = __dev_get_by_index(dev_net(dev), ifindex);
+ if (!upper_dev)
return -EINVAL;
- ops = master_dev->netdev_ops;
+ ops = upper_dev->netdev_ops;
if (ops->ndo_add_slave) {
- err = ops->ndo_add_slave(master_dev, dev);
+ err = ops->ndo_add_slave(upper_dev, dev);
if (err)
return err;
} else {
@@ -2064,7 +2065,6 @@ errout:
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct net *net = sock_net(skb->sk);
- struct net_device *master = NULL;
struct ndmsg *ndm;
struct nlattr *tb[NDA_MAX+1];
struct net_device *dev;
@@ -2106,10 +2106,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
/* Support fdb on master device the net/bridge default case */
if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
(dev->priv_flags & IFF_BRIDGE_PORT)) {
- master = dev->master;
- err = master->netdev_ops->ndo_fdb_add(ndm, tb,
- dev, addr,
- nlh->nlmsg_flags);
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
+ const struct net_device_ops *ops = br_dev->netdev_ops;
+
+ err = ops->ndo_fdb_add(ndm, tb, dev, addr, nlh->nlmsg_flags);
if (err)
goto out;
else
@@ -2170,10 +2170,11 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
/* Support fdb on master device the net/bridge default case */
if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
(dev->priv_flags & IFF_BRIDGE_PORT)) {
- struct net_device *master = dev->master;
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
+ const struct net_device_ops *ops = br_dev->netdev_ops;
- if (master->netdev_ops->ndo_fdb_del)
- err = master->netdev_ops->ndo_fdb_del(ndm, dev, addr);
+ if (ops->ndo_fdb_del)
+ err = ops->ndo_fdb_del(ndm, dev, addr);
if (err)
goto out;
@@ -2257,9 +2258,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
for_each_netdev_rcu(net, dev) {
if (dev->priv_flags & IFF_BRIDGE_PORT) {
- struct net_device *master = dev->master;
- const struct net_device_ops *ops = master->netdev_ops;
+ struct net_device *br_dev;
+ const struct net_device_ops *ops;
+ br_dev = netdev_master_upper_dev_get(dev);
+ ops = br_dev->netdev_ops;
if (ops->ndo_fdb_dump)
idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
}
@@ -2280,6 +2283,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct ifinfomsg *ifm;
struct nlattr *br_afspec;
u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
if (nlh == NULL)
@@ -2297,8 +2301,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
- (dev->master &&
- nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
+ (br_dev &&
+ nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) ||
(dev->addr_len &&
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
(dev->ifindex != dev->iflink &&
@@ -2334,11 +2338,11 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
for_each_netdev_rcu(net, dev) {
const struct net_device_ops *ops = dev->netdev_ops;
- struct net_device *master = dev->master;
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
- if (master && master->netdev_ops->ndo_bridge_getlink) {
+ if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
if (idx >= cb->args[0] &&
- master->netdev_ops->ndo_bridge_getlink(
+ br_dev->netdev_ops->ndo_bridge_getlink(
skb, portid, seq, dev) < 0)
break;
idx++;
@@ -2375,7 +2379,7 @@ static inline size_t bridge_nlmsg_size(void)
static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
{
struct net *net = dev_net(dev);
- struct net_device *master = dev->master;
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
struct sk_buff *skb;
int err = -EOPNOTSUPP;
@@ -2386,8 +2390,8 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
}
if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) &&
- master && master->netdev_ops->ndo_bridge_getlink) {
- err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
+ br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
+ err = br_dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
if (err < 0)
goto errout;
}
@@ -2446,13 +2450,14 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
oflags = flags;
if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
- if (!dev->master ||
- !dev->master->netdev_ops->ndo_bridge_setlink) {
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
+
+ if (!br_dev || !br_dev->netdev_ops->ndo_bridge_setlink) {
err = -EOPNOTSUPP;
goto out;
}
- err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
+ err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
if (err)
goto out;
--
1.8.0
^ permalink raw reply related
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