* Re: [PATCH RFC] random: introduce get_random_bytes_busy_wait_initialized
From: Eric Dumazet @ 2013-09-25 12:06 UTC (permalink / raw)
To: Hannes Frederic Sowa
Cc: Tom Herbert, davem, netdev, jesse.brandeburg, tytso, linux-kernel
In-Reply-To: <20130925090034.GC4904@order.stressinduktion.org>
On Wed, 2013-09-25 at 11:00 +0200, Hannes Frederic Sowa wrote:
> /*
> + * Busy loop until the nonblocking_pool is intialized and return
> + * random data in buf of size nbytes.
> + *
> + * This is used by the network stack to defer the extraction of
> + * entropy from the nonblocking_pool until the pool is initialized.
> + *
> + * We need to busy loop here, because we could be called from an
> + * atomic section.
> + */
> +void get_random_bytes_busy_wait_initialized(void *buf, int nbytes)
> +{
> + while (!nonblocking_pool.initialized)
> + cpu_relax();
> + get_random_bytes(buf, nbytes);
> +}
No idea if this can work if called from IRQ context.
How is nonblocking_poll initialized if host has a single cpu ?
^ permalink raw reply
* Re: [PATCH net 1/2] ip_tunnel: Fix a memory corruption in ip_tunnel_xmit
From: Eric Dumazet @ 2013-09-25 11:56 UTC (permalink / raw)
To: Steffen Klassert; +Cc: David Miller, netdev
In-Reply-To: <20130925055418.GV7660@secunet.com>
On Wed, 2013-09-25 at 07:54 +0200, Steffen Klassert wrote:
> We might extend the used aera of a skb beyond the total
> headroom when we install the ipip header. Fix this by
> calling skb_cow_head() unconditionally.
>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
> ---
> net/ipv4/ip_tunnel.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
Do you know or can we find when was the bug introduced ?
(commit id and title in your changelog would be really nice)
Thanks !
^ permalink raw reply
* Re: [PATCH net-next v5 1/6] bonding: simplify and use RCU protection for 3ad xmit path
From: Veaceslav Falico @ 2013-09-25 10:50 UTC (permalink / raw)
To: Ding Tianhong
Cc: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Netdev
In-Reply-To: <5242B24F.5000309@huawei.com>
On Wed, Sep 25, 2013 at 05:52:15PM +0800, Ding Tianhong wrote:
>The commit 278b20837511776dc9d5f6ee1c7fabd5479838bb
>(bonding: initial RCU conversion) has convert the roundrobin, active-backup,
>broadcast and xor xmit path to rcu protection, the performance will be better
>for these mode, so this time, convert xmit path for 3ad mode.
>
>Suggested-by: Nikolay Aleksandrov <nikolay@redhat.com>
>Suggested-by: Veaceslav Falico <vfalico@redhat.com>
>Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>Signed-off-by: Wang Yufen <wangyufen@huawei.com>
>Cc: Nikolay Aleksandrov <nikolay@redhat.com>
>Cc: Veaceslav Falico <vfalico@redhat.com>
>---
> drivers/net/bonding/bond_3ad.c | 32 ++++++++++++++------------------
> drivers/net/bonding/bonding.h | 30 +++++++++++++++++++++++++++++-
> 2 files changed, 43 insertions(+), 19 deletions(-)
>
>diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
>index 0d8f427..13f1deb 100644
>--- a/drivers/net/bonding/bond_3ad.c
>+++ b/drivers/net/bonding/bond_3ad.c
>@@ -143,7 +143,7 @@ static inline struct bonding *__get_bond_by_port(struct port *port)
> */
> static inline struct port *__get_first_port(struct bonding *bond)
> {
>- struct slave *first_slave = bond_first_slave(bond);
>+ struct slave *first_slave = bond_first_slave_rcu(bond);
>
> return first_slave ? &(SLAVE_AD_INFO(first_slave).port) : NULL;
> }
>@@ -163,7 +163,7 @@ static inline struct port *__get_next_port(struct port *port)
> // If there's no bond for this port, or this is the last slave
> if (bond == NULL)
> return NULL;
>- slave_next = bond_next_slave(bond, slave);
>+ slave_next = bond_next_slave_rcu(bond, slave);
> if (!slave_next || bond_is_first_slave(bond, slave_next))
> return NULL;
>
>@@ -2417,16 +2417,14 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
>
> int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
> {
>- struct slave *slave, *start_at;
> struct bonding *bond = netdev_priv(dev);
>+ struct slave *slave;
> int slave_agg_no;
> int slaves_in_agg;
> int agg_id;
>- int i;
> struct ad_info ad_info;
> int res = 1;
>
>- read_lock(&bond->lock);
> if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
> pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
> dev->name);
>@@ -2444,13 +2442,17 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
>
> slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg);
>
>- bond_for_each_slave(bond, slave) {
>+ bond_for_each_slave_rcu(bond, slave) {
> struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
>
> if (agg && (agg->aggregator_identifier == agg_id)) {
>- slave_agg_no--;
>- if (slave_agg_no < 0)
>- break;
>+ if (--slave_agg_no < 0) {
>+ if (SLAVE_IS_OK(slave)) {
>+ res = bond_dev_queue_xmit(bond,
>+ skb, slave->dev);
>+ goto out;
>+ }
>+ }
> }
> }
>
>@@ -2460,23 +2462,17 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
> goto out;
> }
>
>- start_at = slave;
>-
>- bond_for_each_slave_from(bond, slave, i, start_at) {
>- int slave_agg_id = 0;
>+ bond_for_each_slave_rcu(bond, slave) {
> struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
>
>- if (agg)
>- slave_agg_id = agg->aggregator_identifier;
>-
>- if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
>+ if (SLAVE_IS_OK(slave) && agg &&
>+ agg->aggregator_identifier == agg_id) {
> res = bond_dev_queue_xmit(bond, skb, slave->dev);
> break;
> }
> }
>
> out:
>- read_unlock(&bond->lock);
> if (res) {
> /* no suitable interface, frame not sent */
> kfree_skb(skb);
>diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
>index 03cf3fd..eb36f57 100644
>--- a/drivers/net/bonding/bonding.h
>+++ b/drivers/net/bonding/bonding.h
>@@ -74,13 +74,31 @@
> /* slave list primitives */
> #define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
>
>+/* slave list primitives, Caller must hold rcu_read_lock */
>+#define bond_to_slave_rcu(ptr) list_entry_rcu(ptr, struct slave, list)
>+
>+/* bond_is_empty return NULL if slave list is empty*/
>+#define bond_is_empty(bond) \
>+ (list_empty(&(bond)->slave_list))
>+
>+/* bond_is_empty_rcu return NULL if slave list is empty*/
>+#define bond_is_empty_rcu(bond) \
>+ (!list_first_or_null_rcu(&(bond)->slave_list, struct slave, list))
Useless/dangerous function. It's not used in this patch and there can be no
constructs like:
1 if (!bond_is_empty_rcu(bond)) {
2 slave = bond_first_slave_rcu(bond);
3 do_something(slave);
because between 1) and 2) the slave can go away, and we'll end up with
slave == NULL.
>+
> /* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
> #define bond_first_slave(bond) \
> list_first_entry_or_null(&(bond)->slave_list, struct slave, list)
> #define bond_last_slave(bond) \
>- (list_empty(&(bond)->slave_list) ? NULL : \
>+ (bond_is_empty(bond) ? NULL : \
> bond_to_slave((bond)->slave_list.prev))
>
>+/**
>+ * IMPORTANT: bond_first/last_slave_rcu can return NULL in case of an empty list
>+ * Caller must hold rcu_read_lock
>+ */
>+#define bond_first_slave_rcu(bond) \
>+ list_first_or_null_rcu(&(bond)->slave_list, struct slave, list);
bond_first_slave_or_null_rcu() ?
>+
> #define bond_is_first_slave(bond, pos) ((pos)->list.prev == &(bond)->slave_list)
> #define bond_is_last_slave(bond, pos) ((pos)->list.next == &(bond)->slave_list)
>
>@@ -93,6 +111,16 @@
> (bond_is_first_slave(bond, pos) ? bond_last_slave(bond) : \
> bond_to_slave((pos)->list.prev))
>
>+/* Since bond_first/last_slave_rcu can return NULL, these can return NULL too */
>+#define bond_next_slave_rcu(bond, pos) \
>+ ({struct list_head *__slave_list = &(bond)->slave_list; \
>+ struct list_head __rcu *__next = list_next_rcu(__slave_list); \
>+ struct list_head __rcu *__pos_next = list_next_rcu(&(pos)->list); \
>+ likely(__pos_next != __slave_list) ? \
>+ container_of(__pos_next, struct slave, list) : \
>+ container_of(__next, struct slave, list); \
>+ })
And if bond has no slaves, whilst pos being the slave that has just
detached? Then bond->slave_list->next == pos->list->next ==
&bond->slave_list, and we'll return the container_of(bond->slave_list),
which is garbage, but not NULL.
>+
> /**
> * bond_for_each_slave_from - iterate the slaves list from a starting point
> * @bond: the bond holding this list.
>--
>1.8.0
>
>
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next v5 2/6] bonding: remove the no effect lock for bond_3ad_lacpdu_recv()
From: Veaceslav Falico @ 2013-09-25 10:33 UTC (permalink / raw)
To: Ding Tianhong
Cc: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Netdev
In-Reply-To: <5242B253.2070002@huawei.com>
On Wed, Sep 25, 2013 at 05:52:19PM +0800, Ding Tianhong wrote:
>There is no pointer needed read lock protection, remove the unnecessary lock
>and improve performance for the 3ad recv path.
I don't really understand it. Here's the code path:
rx_handler (holding rcu_read_lock()) -> bond_handle_frame() ->
bond->recv_probe -> bond_3ad_lacpdu_recv(). So we're holding only the
rcu_read_lock() there. What stops us from racing with
bond_3ad_unbind_slave(), for example?
As in:
CPU0 CPU1
-------- -----------
... bond_3ad_unbind_slave()
bond_3ad_rx_indication() ...
if (!port->slave) { ... //slave is ok
port->slave = NULL;
ad_marker_info_received() ...
ad_marker_send() ...
slave = port->slave; ...
skb->dev = slave->dev; ...
^^^ NULL pointer dereference.
I'm not saying that this approach is wrong, maybe I'm missing something,
but when removing locks it's usually a good thing to do - to comment it in
depth in the commit message why it's not already needed.
>
>Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>Cc: Nikolay Aleksandrov <nikolay@redhat.com>
>---
> drivers/net/bonding/bond_3ad.c | 2 --
> 1 file changed, 2 deletions(-)
>
>diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
>index 7a3860f..c134f43 100644
>--- a/drivers/net/bonding/bond_3ad.c
>+++ b/drivers/net/bonding/bond_3ad.c
>@@ -2494,9 +2494,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
> if (!lacpdu)
> return ret;
>
>- read_lock(&bond->lock);
> ret = bond_3ad_rx_indication(lacpdu, slave, skb->len);
>- read_unlock(&bond->lock);
> return ret;
> }
>
>--
>1.8.2.1
>
>
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next v5 5/6] bonding: remove the counter and simplify bond_for_each_slave_from()
From: Veaceslav Falico @ 2013-09-25 10:10 UTC (permalink / raw)
To: Ding Tianhong
Cc: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Netdev
In-Reply-To: <5242B25F.7020505@huawei.com>
On Wed, Sep 25, 2013 at 05:52:31PM +0800, Ding Tianhong wrote:
>Restructure the bond_for_each_slave_from(),
>remove the checking for bond->slave_cnt,
>make the new loop be more simple and racy.
The whole bond_for_each_slave_from() should be removed and replaced with a
standard bond_for_each_slave() - which is already in the process:
http://patchwork.ozlabs.org/patch/277701/
http://patchwork.ozlabs.org/patch/277717/
http://patchwork.ozlabs.org/patch/277716/
http://patchwork.ozlabs.org/patch/277702/
http://patchwork.ozlabs.org/patch/277703/
After that we're ready to use the standard and less painful
list_for_each_entry() analogue - bond_for_each_slave() - which can
afterwards be easily RCUified by just replacing bond_for_each_slave() with
bond_for_each_slave_rcu().
>
>Suggested-by: Nikolay Aleksandrov <nikolay@redhat.com>
>Suggested-by: Veaceslav Falico <vfalico@redhat.com>
>Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>Cc: Nikolay Aleksandrov <nikolay@redhat.com>
>Cc: Veaceslav Falico <vfalico@redhat.com>
>---
> drivers/net/bonding/bond_alb.c | 3 +--
> drivers/net/bonding/bond_main.c | 6 ++----
> drivers/net/bonding/bonding.h | 6 +++---
> 3 files changed, 6 insertions(+), 9 deletions(-)
>
>diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
>index f428ef57..4813dc6 100644
>--- a/drivers/net/bonding/bond_alb.c
>+++ b/drivers/net/bonding/bond_alb.c
>@@ -383,7 +383,6 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
> {
> struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> struct slave *rx_slave, *slave, *start_at;
>- int i = 0;
>
> if (bond_info->next_rx_slave)
> start_at = bond_info->next_rx_slave;
>@@ -392,7 +391,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
>
> rx_slave = NULL;
>
>- bond_for_each_slave_from(bond, slave, i, start_at) {
>+ bond_for_each_slave_from(bond, slave, start_at) {
> if (SLAVE_IS_OK(slave)) {
> if (!rx_slave) {
> rx_slave = slave;
>diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>index 55bbb8b..fbe25bc 100644
>--- a/drivers/net/bonding/bond_main.c
>+++ b/drivers/net/bonding/bond_main.c
>@@ -782,7 +782,6 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
> struct slave *new_active, *old_active;
> struct slave *bestslave = NULL;
> int mintime = bond->params.updelay;
>- int i;
>
> new_active = bond->curr_active_slave;
>
>@@ -801,7 +800,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
> /* remember where to stop iterating over the slaves */
> old_active = new_active;
>
>- bond_for_each_slave_from(bond, new_active, i, old_active) {
>+ bond_for_each_slave_from(bond, new_active, old_active) {
> if (new_active->link == BOND_LINK_UP) {
> return new_active;
> } else if (new_active->link == BOND_LINK_BACK &&
>@@ -2756,7 +2755,6 @@ do_failover:
> static void bond_ab_arp_probe(struct bonding *bond)
> {
> struct slave *slave, *next_slave;
>- int i;
>
> read_lock(&bond->curr_slave_lock);
>
>@@ -2788,7 +2786,7 @@ static void bond_ab_arp_probe(struct bonding *bond)
>
> /* search for next candidate */
> next_slave = bond_next_slave(bond, bond->current_arp_slave);
>- bond_for_each_slave_from(bond, slave, i, next_slave) {
>+ bond_for_each_slave_from(bond, slave, next_slave) {
> if (IS_UP(slave->dev)) {
> slave->link = BOND_LINK_BACK;
> bond_set_slave_active_flags(slave);
>diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
>index eb36f57..e5734ad 100644
>--- a/drivers/net/bonding/bonding.h
>+++ b/drivers/net/bonding/bonding.h
>@@ -130,9 +130,9 @@
> *
> * Caller must hold bond->lock
> */
>-#define bond_for_each_slave_from(bond, pos, cnt, start) \
>- for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \
>- cnt++, pos = bond_next_slave(bond, pos))
>+#define bond_for_each_slave_from(bond, pos, start) \
>+ for (pos = start; pos; (pos = bond_next_slave(bond, pos)) != start ? \
>+ (pos) : (pos = NULL))
>
> /**
> * bond_for_each_slave - iterate over all slaves
>--
>1.8.0
>
>
>
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH net-next v3 1/2] dev: update __dev_notify_flags() to send rtnl msg
From: Nicolas Dichtel @ 2013-09-25 10:02 UTC (permalink / raw)
To: stephen; +Cc: netdev, davem, Nicolas Dichtel
In-Reply-To: <20130924094707.41641042@nehalam.linuxnetplumber.net>
This patch only prepares the next one, there is no functional change.
Now, __dev_notify_flags() can also be used to notify flags changes via
rtnetlink.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
v3: add patch #1
use __dev_notify_flags() to notify rxflags (note that notifier chains are
not called when flags IFF_PROMISC and IFF_ALLMULTI are changed)
v2: rework the patch to avoid double notification
include/linux/netdevice.h | 4 +++-
net/core/dev.c | 11 ++++++-----
net/core/rtnetlink.c | 3 +--
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3de49aca4519..4466db0cb673 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2368,7 +2368,9 @@ extern int dev_ethtool(struct net *net, struct ifreq *);
extern unsigned int dev_get_flags(const struct net_device *);
extern int __dev_change_flags(struct net_device *, unsigned int flags);
extern int dev_change_flags(struct net_device *, unsigned int);
-extern void __dev_notify_flags(struct net_device *, unsigned int old_flags);
+void __dev_notify_flags(struct net_device *,
+ unsigned int old_flags,
+ unsigned int gchanges);
extern int dev_change_name(struct net_device *, const char *);
extern int dev_set_alias(struct net_device *, const char *, size_t);
extern int dev_change_net_namespace(struct net_device *,
diff --git a/net/core/dev.c b/net/core/dev.c
index 5c713f2239cc..1222309feeaa 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5069,10 +5069,14 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
return ret;
}
-void __dev_notify_flags(struct net_device *dev, unsigned int old_flags)
+void __dev_notify_flags(struct net_device *dev, unsigned int old_flags,
+ unsigned int gchanges)
{
unsigned int changes = dev->flags ^ old_flags;
+ if (gchanges)
+ rtmsg_ifinfo(RTM_NEWLINK, dev, gchanges);
+
if (changes & IFF_UP) {
if (dev->flags & IFF_UP)
call_netdevice_notifiers(NETDEV_UP, dev);
@@ -5108,10 +5112,7 @@ int dev_change_flags(struct net_device *dev, unsigned int flags)
return ret;
changes = old_flags ^ dev->flags;
- if (changes)
- rtmsg_ifinfo(RTM_NEWLINK, dev, changes);
-
- __dev_notify_flags(dev, old_flags);
+ __dev_notify_flags(dev, old_flags, changes);
return ret;
}
EXPORT_SYMBOL(dev_change_flags);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2a0e21de3060..4aedf03da052 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1647,9 +1647,8 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
}
dev->rtnl_link_state = RTNL_LINK_INITIALIZED;
- rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
- __dev_notify_flags(dev, old_flags);
+ __dev_notify_flags(dev, old_flags, ~0U);
return 0;
}
EXPORT_SYMBOL(rtnl_configure_link);
--
1.8.2.1
^ permalink raw reply related
* [PATCH net-next v3 2/2] dev: always advertise rx_flags changes via netlink
From: Nicolas Dichtel @ 2013-09-25 10:02 UTC (permalink / raw)
To: stephen; +Cc: netdev, davem, Nicolas Dichtel
In-Reply-To: <1380103365-5185-1-git-send-email-nicolas.dichtel@6wind.com>
When flags IFF_PROMISC and IFF_ALLMULTI are changed, netlink messages are not
consistent. For example, if a multicast daemon is running (flag IFF_ALLMULTI
set in dev->flags but not dev->gflags, ie not exported to userspace) and then a
user sets it via netlink (flag IFF_ALLMULTI set in dev->flags and dev->gflags, ie
exported to userspace), no netlink message is sent.
Same for IFF_PROMISC and because dev->promiscuity is exported via
IFLA_PROMISCUITY, we may send a netlink message after each change of this
counter.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
v3: add patch #1
use __dev_notify_flags() to notify rxflags (note that notifier chains are
not called when flags IFF_PROMISC and IFF_ALLMULTI are changed)
v2: rework the patch to avoid double notification
net/core/dev.c | 60 ++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 37 insertions(+), 23 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 1222309feeaa..b23aefcb3c42 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4822,7 +4822,7 @@ static void dev_change_rx_flags(struct net_device *dev, int flags)
ops->ndo_change_rx_flags(dev, flags);
}
-static int __dev_set_promiscuity(struct net_device *dev, int inc)
+static int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify)
{
unsigned int old_flags = dev->flags;
kuid_t uid;
@@ -4865,6 +4865,8 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc)
dev_change_rx_flags(dev, IFF_PROMISC);
}
+ if (notify)
+ __dev_notify_flags(dev, old_flags, IFF_PROMISC);
return 0;
}
@@ -4884,7 +4886,7 @@ int dev_set_promiscuity(struct net_device *dev, int inc)
unsigned int old_flags = dev->flags;
int err;
- err = __dev_set_promiscuity(dev, inc);
+ err = __dev_set_promiscuity(dev, inc, true);
if (err < 0)
return err;
if (dev->flags != old_flags)
@@ -4893,22 +4895,9 @@ int dev_set_promiscuity(struct net_device *dev, int inc)
}
EXPORT_SYMBOL(dev_set_promiscuity);
-/**
- * dev_set_allmulti - update allmulti count on a device
- * @dev: device
- * @inc: modifier
- *
- * Add or remove reception of all multicast frames to a device. While the
- * count in the device remains above zero the interface remains listening
- * to all interfaces. Once it hits zero the device reverts back to normal
- * filtering operation. A negative @inc value is used to drop the counter
- * when releasing a resource needing all multicasts.
- * Return 0 if successful or a negative errno code on error.
- */
-
-int dev_set_allmulti(struct net_device *dev, int inc)
+static int __dev_set_allmulti(struct net_device *dev, int inc, bool notify)
{
- unsigned int old_flags = dev->flags;
+ unsigned int old_flags = dev->flags, old_gflags = dev->gflags;
ASSERT_RTNL();
@@ -4931,9 +4920,30 @@ int dev_set_allmulti(struct net_device *dev, int inc)
if (dev->flags ^ old_flags) {
dev_change_rx_flags(dev, IFF_ALLMULTI);
dev_set_rx_mode(dev);
+ if (notify)
+ __dev_notify_flags(dev, old_flags,
+ dev->gflags ^ old_gflags);
}
return 0;
}
+
+/**
+ * dev_set_allmulti - update allmulti count on a device
+ * @dev: device
+ * @inc: modifier
+ *
+ * Add or remove reception of all multicast frames to a device. While the
+ * count in the device remains above zero the interface remains listening
+ * to all interfaces. Once it hits zero the device reverts back to normal
+ * filtering operation. A negative @inc value is used to drop the counter
+ * when releasing a resource needing all multicasts.
+ * Return 0 if successful or a negative errno code on error.
+ */
+
+int dev_set_allmulti(struct net_device *dev, int inc)
+{
+ return __dev_set_allmulti(dev, inc, true);
+}
EXPORT_SYMBOL(dev_set_allmulti);
/*
@@ -4958,10 +4968,10 @@ void __dev_set_rx_mode(struct net_device *dev)
* therefore calling __dev_set_promiscuity here is safe.
*/
if (!netdev_uc_empty(dev) && !dev->uc_promisc) {
- __dev_set_promiscuity(dev, 1);
+ __dev_set_promiscuity(dev, 1, false);
dev->uc_promisc = true;
} else if (netdev_uc_empty(dev) && dev->uc_promisc) {
- __dev_set_promiscuity(dev, -1);
+ __dev_set_promiscuity(dev, -1, false);
dev->uc_promisc = false;
}
}
@@ -5050,9 +5060,13 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
if ((flags ^ dev->gflags) & IFF_PROMISC) {
int inc = (flags & IFF_PROMISC) ? 1 : -1;
+ unsigned int old_flags = dev->flags;
dev->gflags ^= IFF_PROMISC;
- dev_set_promiscuity(dev, inc);
+
+ if (__dev_set_promiscuity(dev, inc, false) >= 0)
+ if (dev->flags != old_flags)
+ dev_set_rx_mode(dev);
}
/* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
@@ -5063,7 +5077,7 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
int inc = (flags & IFF_ALLMULTI) ? 1 : -1;
dev->gflags ^= IFF_ALLMULTI;
- dev_set_allmulti(dev, inc);
+ __dev_set_allmulti(dev, inc, false);
}
return ret;
@@ -5105,13 +5119,13 @@ void __dev_notify_flags(struct net_device *dev, unsigned int old_flags,
int dev_change_flags(struct net_device *dev, unsigned int flags)
{
int ret;
- unsigned int changes, old_flags = dev->flags;
+ unsigned int changes, old_flags = dev->flags, old_gflags = dev->gflags;
ret = __dev_change_flags(dev, flags);
if (ret < 0)
return ret;
- changes = old_flags ^ dev->flags;
+ changes = (old_flags ^ dev->flags) | (old_gflags ^ dev->gflags);
__dev_notify_flags(dev, old_flags, changes);
return ret;
}
--
1.8.2.1
^ permalink raw reply related
* [PATCH net v5 1/1] xen-netback: Handle backend state transitions in a more robust way
From: Paul Durrant @ 2013-09-25 9:59 UTC (permalink / raw)
To: xen-devel, netdev; +Cc: Paul Durrant, Ian Campbell, Wei Liu, David Vrabel
In-Reply-To: <1380103168-12067-1-git-send-email-paul.durrant@citrix.com>
When the frontend state changes netback now specifies its desired state to
a new function, set_backend_state(), which transitions through any
necessary intermediate states.
This fixes an issue observed with some old Windows frontend drivers where
they failed to transition through the Closing state and netback would not
behave correctly.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: David Vrabel <david.vrabel@citrix.com>
---
drivers/net/xen-netback/xenbus.c | 143 ++++++++++++++++++++++++++++++--------
1 file changed, 113 insertions(+), 30 deletions(-)
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index a53782e..01329b2 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -24,6 +24,7 @@
struct backend_info {
struct xenbus_device *dev;
struct xenvif *vif;
+ enum xenbus_state state;
enum xenbus_state frontend_state;
struct xenbus_watch hotplug_status_watch;
u8 have_hotplug_status_watch:1;
@@ -136,6 +137,8 @@ static int netback_probe(struct xenbus_device *dev,
if (err)
goto fail;
+ be->state = XenbusStateInitWait;
+
/* This kicks hotplug scripts, so do it immediately. */
backend_create_xenvif(be);
@@ -208,24 +211,113 @@ static void backend_create_xenvif(struct backend_info *be)
kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
}
-
-static void disconnect_backend(struct xenbus_device *dev)
+static void backend_disconnect(struct backend_info *be)
{
- struct backend_info *be = dev_get_drvdata(&dev->dev);
-
if (be->vif)
xenvif_disconnect(be->vif);
}
-static void destroy_backend(struct xenbus_device *dev)
+static void backend_connect(struct backend_info *be)
{
- struct backend_info *be = dev_get_drvdata(&dev->dev);
+ if (be->vif)
+ connect(be);
+}
- if (be->vif) {
- kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
- xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
- xenvif_free(be->vif);
- be->vif = NULL;
+static inline void backend_switch_state(struct backend_info *be,
+ enum xenbus_state state)
+{
+ struct xenbus_device *dev = be->dev;
+
+ pr_debug("%s -> %s\n", dev->nodename, xenbus_strstate(state));
+ be->state = state;
+
+ /* If we are waiting for a hotplug script then defer the
+ * actual xenbus state change.
+ */
+ if (!be->have_hotplug_status_watch)
+ xenbus_switch_state(dev, state);
+}
+
+/* Handle backend state transitions:
+ *
+ * The backend state starts in InitWait and the following transitions are
+ * allowed.
+ *
+ * InitWait -> Connected
+ *
+ * ^ \ |
+ * | \ |
+ * | \ |
+ * | \ |
+ * | \ |
+ * | \ |
+ * | V V
+ *
+ * Closed <-> Closing
+ *
+ * The state argument specifies the eventual state of the backend and the
+ * function transitions to that state via the shortest path.
+ */
+static void set_backend_state(struct backend_info *be,
+ enum xenbus_state state)
+{
+ while (be->state != state) {
+ switch (be->state) {
+ case XenbusStateClosed:
+ switch (state) {
+ case XenbusStateInitWait:
+ case XenbusStateConnected:
+ pr_info("%s: prepare for reconnect\n",
+ be->dev->nodename);
+ backend_switch_state(be, XenbusStateInitWait);
+ break;
+ case XenbusStateClosing:
+ backend_switch_state(be, XenbusStateClosing);
+ break;
+ default:
+ BUG();
+ }
+ break;
+ case XenbusStateInitWait:
+ switch (state) {
+ case XenbusStateConnected:
+ backend_connect(be);
+ backend_switch_state(be, XenbusStateConnected);
+ break;
+ case XenbusStateClosing:
+ case XenbusStateClosed:
+ backend_switch_state(be, XenbusStateClosing);
+ break;
+ default:
+ BUG();
+ }
+ break;
+ case XenbusStateConnected:
+ switch (state) {
+ case XenbusStateInitWait:
+ case XenbusStateClosing:
+ case XenbusStateClosed:
+ backend_disconnect(be);
+ backend_switch_state(be, XenbusStateClosing);
+ break;
+ default:
+ BUG();
+ }
+ break;
+ case XenbusStateClosing:
+ switch (state) {
+ case XenbusStateInitWait:
+ case XenbusStateConnected:
+ case XenbusStateClosed:
+ backend_switch_state(be, XenbusStateClosed);
+ break;
+ default:
+ BUG();
+ }
+ break;
+ default:
+ BUG();
+ }
}
}
@@ -237,40 +329,33 @@ static void frontend_changed(struct xenbus_device *dev,
{
struct backend_info *be = dev_get_drvdata(&dev->dev);
- pr_debug("frontend state %s\n", xenbus_strstate(frontend_state));
+ pr_debug("%s -> %s\n", dev->otherend, xenbus_strstate(frontend_state));
be->frontend_state = frontend_state;
switch (frontend_state) {
case XenbusStateInitialising:
- if (dev->state == XenbusStateClosed) {
- pr_info("%s: prepare for reconnect\n", dev->nodename);
- xenbus_switch_state(dev, XenbusStateInitWait);
- }
+ set_backend_state(be, XenbusStateInitWait);
break;
case XenbusStateInitialised:
break;
case XenbusStateConnected:
- if (dev->state == XenbusStateConnected)
- break;
- if (be->vif)
- connect(be);
+ set_backend_state(be, XenbusStateConnected);
break;
case XenbusStateClosing:
- disconnect_backend(dev);
- xenbus_switch_state(dev, XenbusStateClosing);
+ set_backend_state(be, XenbusStateClosing);
break;
case XenbusStateClosed:
- xenbus_switch_state(dev, XenbusStateClosed);
+ set_backend_state(be, XenbusStateClosed);
if (xenbus_dev_is_online(dev))
break;
- destroy_backend(dev);
/* fall through if not online */
case XenbusStateUnknown:
+ set_backend_state(be, XenbusStateClosed);
device_unregister(&dev->dev);
break;
@@ -363,7 +448,9 @@ static void hotplug_status_changed(struct xenbus_watch *watch,
if (IS_ERR(str))
return;
if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) {
- xenbus_switch_state(be->dev, XenbusStateConnected);
+ /* Complete any pending state change */
+ xenbus_switch_state(be->dev, be->state);
+
/* Not interested in this watch anymore. */
unregister_hotplug_status_watch(be);
}
@@ -393,12 +480,8 @@ static void connect(struct backend_info *be)
err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
hotplug_status_changed,
"%s/%s", dev->nodename, "hotplug-status");
- if (err) {
- /* Switch now, since we can't do a watch. */
- xenbus_switch_state(dev, XenbusStateConnected);
- } else {
+ if (!err)
be->have_hotplug_status_watch = 1;
- }
netif_wake_queue(be->vif->dev);
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH net v5 0/1] xen-netback: windows frontend compatibility fixes
From: Paul Durrant @ 2013-09-25 9:59 UTC (permalink / raw)
To: xen-devel, netdev
The following patches fix a couple more issues found when testing with
Windows frontends.
v5:
- Fix typos pointed out by Wei Liu
v4:
- Fix problem with hotplug failure noticed by Wei Liu
v3:
- Collapse both v2 patches into a single patch that introduces a new
function to handle backend state transtions. By doing this we ensure that
we always transition through intermediate states and that we don't attempt
repeated connects or disconnects.
v2:
- Add comment in 2/2 to note that state transitions from Connected to Closed
are incorrect.
^ permalink raw reply
* [PATCH net-next v5 5/6] bonding: remove the counter and simplify bond_for_each_slave_from()
From: Ding Tianhong @ 2013-09-25 9:52 UTC (permalink / raw)
To: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Veaceslav Falico, Netdev
Restructure the bond_for_each_slave_from(),
remove the checking for bond->slave_cnt,
make the new loop be more simple and racy.
Suggested-by: Nikolay Aleksandrov <nikolay@redhat.com>
Suggested-by: Veaceslav Falico <vfalico@redhat.com>
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Cc: Nikolay Aleksandrov <nikolay@redhat.com>
Cc: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_alb.c | 3 +--
drivers/net/bonding/bond_main.c | 6 ++----
drivers/net/bonding/bonding.h | 6 +++---
3 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f428ef57..4813dc6 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -383,7 +383,6 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct slave *rx_slave, *slave, *start_at;
- int i = 0;
if (bond_info->next_rx_slave)
start_at = bond_info->next_rx_slave;
@@ -392,7 +391,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
rx_slave = NULL;
- bond_for_each_slave_from(bond, slave, i, start_at) {
+ bond_for_each_slave_from(bond, slave, start_at) {
if (SLAVE_IS_OK(slave)) {
if (!rx_slave) {
rx_slave = slave;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 55bbb8b..fbe25bc 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -782,7 +782,6 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
struct slave *new_active, *old_active;
struct slave *bestslave = NULL;
int mintime = bond->params.updelay;
- int i;
new_active = bond->curr_active_slave;
@@ -801,7 +800,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
/* remember where to stop iterating over the slaves */
old_active = new_active;
- bond_for_each_slave_from(bond, new_active, i, old_active) {
+ bond_for_each_slave_from(bond, new_active, old_active) {
if (new_active->link == BOND_LINK_UP) {
return new_active;
} else if (new_active->link == BOND_LINK_BACK &&
@@ -2756,7 +2755,6 @@ do_failover:
static void bond_ab_arp_probe(struct bonding *bond)
{
struct slave *slave, *next_slave;
- int i;
read_lock(&bond->curr_slave_lock);
@@ -2788,7 +2786,7 @@ static void bond_ab_arp_probe(struct bonding *bond)
/* search for next candidate */
next_slave = bond_next_slave(bond, bond->current_arp_slave);
- bond_for_each_slave_from(bond, slave, i, next_slave) {
+ bond_for_each_slave_from(bond, slave, next_slave) {
if (IS_UP(slave->dev)) {
slave->link = BOND_LINK_BACK;
bond_set_slave_active_flags(slave);
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index eb36f57..e5734ad 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -130,9 +130,9 @@
*
* Caller must hold bond->lock
*/
-#define bond_for_each_slave_from(bond, pos, cnt, start) \
- for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \
- cnt++, pos = bond_next_slave(bond, pos))
+#define bond_for_each_slave_from(bond, pos, start) \
+ for (pos = start; pos; (pos = bond_next_slave(bond, pos)) != start ? \
+ (pos) : (pos = NULL))
/**
* bond_for_each_slave - iterate over all slaves
--
1.8.0
^ permalink raw reply related
* [PATCH net-next v5 6/6] bonding: use RCU protection for alb xmit path
From: Ding Tianhong @ 2013-09-25 9:52 UTC (permalink / raw)
To: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Veaceslav Falico, Netdev, Hideaki YOSHIFUJI
The commit 278b20837511776dc9d5f6ee1c7fabd5479838bb
(bonding: initial RCU conversion) has convert the roundrobin, active-backup,
broadcast and xor xmit path to rcu protection, the performance will be better
for these mode, so this time, convert xmit path for alb mode.
Suggested-by: Nikolay Aleksandrov <nikolay@redhat.com>
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Cc: Nikolay Aleksandrov <nikolay@redhat.com>
Cc: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_alb.c | 32 ++++++++++++++------------------
drivers/net/bonding/bonding.h | 2 +-
2 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 4813dc6..619a611 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -229,7 +229,7 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
max_gap = LLONG_MIN;
/* Find the slave with the largest gap */
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave_rcu(bond, slave) {
if (SLAVE_IS_OK(slave)) {
long long gap = compute_gap(slave);
@@ -382,16 +382,14 @@ out:
static struct slave *rlb_next_rx_slave(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- struct slave *rx_slave, *slave, *start_at;
+ struct slave *rx_slave, *slave;
if (bond_info->next_rx_slave)
- start_at = bond_info->next_rx_slave;
+ rx_slave = bond_info->next_rx_slave;
else
- start_at = bond_first_slave(bond);
-
- rx_slave = NULL;
+ rx_slave = bond_first_slave_rcu(bond);
- bond_for_each_slave_from(bond, slave, start_at) {
+ bond_for_each_slave_rcu(bond, slave) {
if (SLAVE_IS_OK(slave)) {
if (!rx_slave) {
rx_slave = slave;
@@ -402,7 +400,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
}
if (rx_slave) {
- slave = bond_next_slave(bond, rx_slave);
+ slave = bond_next_slave_rcu(bond, rx_slave);
bond_info->next_rx_slave = slave;
}
@@ -625,12 +623,14 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct arp_pkt *arp = arp_pkt(skb);
- struct slave *assigned_slave;
+ struct slave *assigned_slave, *curr_active_slave;
struct rlb_client_info *client_info;
u32 hash_index = 0;
_lock_rx_hashtbl(bond);
+ curr_active_slave = rcu_dereference(bond->curr_active_slave);
+
hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
client_info = &(bond_info->rx_hashtbl[hash_index]);
@@ -654,9 +654,9 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
* move the old client to primary (curr_active_slave) so
* that the new client can be assigned to this entry.
*/
- if (bond->curr_active_slave &&
- client_info->slave != bond->curr_active_slave) {
- client_info->slave = bond->curr_active_slave;
+ if (curr_active_slave &&
+ client_info->slave != curr_active_slave) {
+ client_info->slave = curr_active_slave;
rlb_update_client(client_info);
}
}
@@ -1338,8 +1338,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
/* make sure that the curr_active_slave do not change during tx
*/
- read_lock(&bond->lock);
- read_lock(&bond->curr_slave_lock);
switch (ntohs(skb->protocol)) {
case ETH_P_IP: {
@@ -1422,12 +1420,12 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
if (!tx_slave) {
/* unbalanced or unassigned, send through primary */
- tx_slave = bond->curr_active_slave;
+ tx_slave = rcu_dereference(bond->curr_active_slave);
bond_info->unbalanced_load += skb->len;
}
if (tx_slave && SLAVE_IS_OK(tx_slave)) {
- if (tx_slave != bond->curr_active_slave) {
+ if (tx_slave != rcu_dereference(bond->curr_active_slave)) {
memcpy(eth_data->h_source,
tx_slave->dev->dev_addr,
ETH_ALEN);
@@ -1442,8 +1440,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
}
}
- read_unlock(&bond->curr_slave_lock);
- read_unlock(&bond->lock);
if (res) {
/* no suitable interface, frame not sent */
kfree_skb(skb);
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index e5734ad..87782b4 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -522,7 +522,7 @@ static inline struct slave *bond_slave_has_mac(struct bonding *bond,
{
struct slave *tmp;
- bond_for_each_slave(bond, tmp)
+ bond_for_each_slave_rcu(bond, tmp)
if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
return tmp;
--
1.8.0
^ permalink raw reply related
* [PATCH net-next v5 1/6] bonding: simplify and use RCU protection for 3ad xmit path
From: Ding Tianhong @ 2013-09-25 9:52 UTC (permalink / raw)
To: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Veaceslav Falico, Netdev
The commit 278b20837511776dc9d5f6ee1c7fabd5479838bb
(bonding: initial RCU conversion) has convert the roundrobin, active-backup,
broadcast and xor xmit path to rcu protection, the performance will be better
for these mode, so this time, convert xmit path for 3ad mode.
Suggested-by: Nikolay Aleksandrov <nikolay@redhat.com>
Suggested-by: Veaceslav Falico <vfalico@redhat.com>
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Signed-off-by: Wang Yufen <wangyufen@huawei.com>
Cc: Nikolay Aleksandrov <nikolay@redhat.com>
Cc: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 32 ++++++++++++++------------------
drivers/net/bonding/bonding.h | 30 +++++++++++++++++++++++++++++-
2 files changed, 43 insertions(+), 19 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 0d8f427..13f1deb 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -143,7 +143,7 @@ static inline struct bonding *__get_bond_by_port(struct port *port)
*/
static inline struct port *__get_first_port(struct bonding *bond)
{
- struct slave *first_slave = bond_first_slave(bond);
+ struct slave *first_slave = bond_first_slave_rcu(bond);
return first_slave ? &(SLAVE_AD_INFO(first_slave).port) : NULL;
}
@@ -163,7 +163,7 @@ static inline struct port *__get_next_port(struct port *port)
// If there's no bond for this port, or this is the last slave
if (bond == NULL)
return NULL;
- slave_next = bond_next_slave(bond, slave);
+ slave_next = bond_next_slave_rcu(bond, slave);
if (!slave_next || bond_is_first_slave(bond, slave_next))
return NULL;
@@ -2417,16 +2417,14 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
{
- struct slave *slave, *start_at;
struct bonding *bond = netdev_priv(dev);
+ struct slave *slave;
int slave_agg_no;
int slaves_in_agg;
int agg_id;
- int i;
struct ad_info ad_info;
int res = 1;
- read_lock(&bond->lock);
if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
dev->name);
@@ -2444,13 +2442,17 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave_rcu(bond, slave) {
struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
if (agg && (agg->aggregator_identifier == agg_id)) {
- slave_agg_no--;
- if (slave_agg_no < 0)
- break;
+ if (--slave_agg_no < 0) {
+ if (SLAVE_IS_OK(slave)) {
+ res = bond_dev_queue_xmit(bond,
+ skb, slave->dev);
+ goto out;
+ }
+ }
}
}
@@ -2460,23 +2462,17 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
goto out;
}
- start_at = slave;
-
- bond_for_each_slave_from(bond, slave, i, start_at) {
- int slave_agg_id = 0;
+ bond_for_each_slave_rcu(bond, slave) {
struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
- if (agg)
- slave_agg_id = agg->aggregator_identifier;
-
- if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
+ if (SLAVE_IS_OK(slave) && agg &&
+ agg->aggregator_identifier == agg_id) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
break;
}
}
out:
- read_unlock(&bond->lock);
if (res) {
/* no suitable interface, frame not sent */
kfree_skb(skb);
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 03cf3fd..eb36f57 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -74,13 +74,31 @@
/* slave list primitives */
#define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
+/* slave list primitives, Caller must hold rcu_read_lock */
+#define bond_to_slave_rcu(ptr) list_entry_rcu(ptr, struct slave, list)
+
+/* bond_is_empty return NULL if slave list is empty*/
+#define bond_is_empty(bond) \
+ (list_empty(&(bond)->slave_list))
+
+/* bond_is_empty_rcu return NULL if slave list is empty*/
+#define bond_is_empty_rcu(bond) \
+ (!list_first_or_null_rcu(&(bond)->slave_list, struct slave, list))
+
/* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
#define bond_first_slave(bond) \
list_first_entry_or_null(&(bond)->slave_list, struct slave, list)
#define bond_last_slave(bond) \
- (list_empty(&(bond)->slave_list) ? NULL : \
+ (bond_is_empty(bond) ? NULL : \
bond_to_slave((bond)->slave_list.prev))
+/**
+ * IMPORTANT: bond_first/last_slave_rcu can return NULL in case of an empty list
+ * Caller must hold rcu_read_lock
+ */
+#define bond_first_slave_rcu(bond) \
+ list_first_or_null_rcu(&(bond)->slave_list, struct slave, list);
+
#define bond_is_first_slave(bond, pos) ((pos)->list.prev == &(bond)->slave_list)
#define bond_is_last_slave(bond, pos) ((pos)->list.next == &(bond)->slave_list)
@@ -93,6 +111,16 @@
(bond_is_first_slave(bond, pos) ? bond_last_slave(bond) : \
bond_to_slave((pos)->list.prev))
+/* Since bond_first/last_slave_rcu can return NULL, these can return NULL too */
+#define bond_next_slave_rcu(bond, pos) \
+ ({struct list_head *__slave_list = &(bond)->slave_list; \
+ struct list_head __rcu *__next = list_next_rcu(__slave_list); \
+ struct list_head __rcu *__pos_next = list_next_rcu(&(pos)->list); \
+ likely(__pos_next != __slave_list) ? \
+ container_of(__pos_next, struct slave, list) : \
+ container_of(__next, struct slave, list); \
+ })
+
/**
* bond_for_each_slave_from - iterate the slaves list from a starting point
* @bond: the bond holding this list.
--
1.8.0
^ permalink raw reply related
* [PATCH net-next v5 3/6] bonding: replace read_lock to rcu_read_lock for bond_3ad_get_active_agg_info()
From: Ding Tianhong @ 2013-09-25 9:52 UTC (permalink / raw)
To: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Veaceslav Falico, Netdev
the bond slave list will protected by rcu, so the read lock should replace by
rcu read lock.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Cc: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c134f43..b678502 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2408,9 +2408,9 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
{
int ret;
- read_lock(&bond->lock);
+ rcu_read_lock();
ret = __bond_3ad_get_active_agg_info(bond, ad_info);
- read_unlock(&bond->lock);
+ rcu_read_unlock();
return ret;
}
--
1.8.2.1
^ permalink raw reply related
* [PATCH net-next v5 2/6] bonding: remove the no effect lock for bond_3ad_lacpdu_recv()
From: Ding Tianhong @ 2013-09-25 9:52 UTC (permalink / raw)
To: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Veaceslav Falico, Netdev
There is no pointer needed read lock protection, remove the unnecessary lock
and improve performance for the 3ad recv path.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Cc: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_3ad.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7a3860f..c134f43 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2494,9 +2494,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
if (!lacpdu)
return ret;
- read_lock(&bond->lock);
ret = bond_3ad_rx_indication(lacpdu, slave, skb->len);
- read_unlock(&bond->lock);
return ret;
}
--
1.8.2.1
^ permalink raw reply related
* [PATCH net-next v5 4/6] bonding: add rtnl lock for bonding_store_xmit_hash
From: Ding Tianhong @ 2013-09-25 9:52 UTC (permalink / raw)
To: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Veaceslav Falico, Netdev
the bonding_store_xmit_hash() could update bond's xmit_policy, and
the xmit_policy is used in xmit path for xor mode, maybe it is hard
to occur any problem, but just follow the logic "don't change anything
slave-related without rtnl", so I think the rntl lock is fit here. :)
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Cc: Nikolay Aleksandrov <nikolay@redhat.com>
---
drivers/net/bonding/bond_sysfs.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 0f539de..deb1d8e 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -382,6 +382,9 @@ static ssize_t bonding_store_xmit_hash(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
+
new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
if (new_value < 0) {
pr_err("%s: Ignoring invalid xmit hash policy value %.*s.\n",
@@ -396,6 +399,7 @@ static ssize_t bonding_store_xmit_hash(struct device *d,
xmit_hashtype_tbl[new_value].modename, new_value);
}
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR,
--
1.8.2.1
^ permalink raw reply related
* [PATCH net-next v5 0/6] bonding: Patchset for rcu use in bonding
From: Ding Tianhong @ 2013-09-25 9:52 UTC (permalink / raw)
To: Jay Vosburgh, Andy Gospodarek, David S. Miller,
Nikolay Aleksandrov, Veaceslav Falico, Netdev
Hi:
The Patch Set convert the xmit of 3ad and alb mode to use rcu lock.
restructure and add more rcu list function.
add rtnl lock to protect bonding_store_xmit_hash().
remove read lock in bond_3ad_lacpdu_recv().
I test the patch well and no problems found till now.
v1: add 1 patch named remove the no effect lock for bond_3ad_lacpdu_recv().
get the advice from Nikolay Aleksandrov, and modify some mistake in the code.
v2: accept the Nikolay Aleksandrov's advise, modify the patch 05/06.
the new bond_for_each_slave_from will not use bond->slave_cnt and int cnt any more,
it test well.
move the rcu_dereference call of curr_active_slave after the lock avoid
a race condition with the slave removal.
v3: according to the advise of Veaceslav Falico and David S. Miller, modify the patch 01/06 and patch 05/06.
add rcu protect for read bond->slave_list.
simplify the bond_for_each_slave_from() and bond_for_each_slave_from_rcu()
v4: thanks for Veaceslav Falico's patient guidance, fix the problem of patch 01/06 and
patch 05/06.
restructure the bond_first_slave_rcu().
restructure the bond_for_each_slave() and bond_for_each_slave_rcu().
v5: modifty the patch 01/06,05/06,06/06
restructure the bond_first_slave_rcu().
remove the bond_for_each_slave_from_rcu(), it is no need to use till now, and the restructure is really
hard work, so miss it, and rebuild the logic for bond_for_each_slave_from in rcu protect.
Ding Tianhong (4):
Wang Yufen (1):
Yang Yingliang (1):
root (6):
bonding: simplify and use RCU protection for 3ad xmit path
bonding: remove the no effect lock for bond_3ad_lacpdu_recv()
bonding: replace read_lock to rcu_read_lock for
bond_3ad_get_active_agg_info()
bonding: add rtnl lock for bonding_store_xmit_hash
bonding: restructure and add rcu for bond_for_each_slave_next()
bonding: use RCU protection for alb xmit path
drivers/net/bonding/bond_3ad.c | 38 ++++++++++++---------------
drivers/net/bonding/bond_alb.c | 23 +++++++----------
drivers/net/bonding/bond_main.c | 6 ++---
drivers/net/bonding/bond_sysfs.c | 4 +++
drivers/net/bonding/bonding.h | 56 +++++++++++++++++++++++++++++++++++-----
5 files changed, 82 insertions(+), 45 deletions(-)
--
1.8.2.1
^ permalink raw reply
* Re: [PATCH] ipvs: improved SH fallback strategy
From: Alexander Frolkin @ 2013-09-25 9:26 UTC (permalink / raw)
To: Simon Horman
Cc: Sergei Shtylyov, Julian Anastasov, lvs-devel, Wensong Zhang,
netdev, linux-kernel
In-Reply-To: <20130925003033.GG26081@verge.net.au>
Improve the SH fallback realserver selection strategy.
With sh and sh-fallback, if a realserver is down, this attempts to
distribute the traffic that would have gone to that server evenly
among the remaining servers.
Signed-off-by: Alexander Frolkin <avf@eldamar.org.uk>
--
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 3588fae..3d5ab7c 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -115,27 +115,47 @@ ip_vs_sh_get(struct ip_vs_service *svc, struct ip_vs_sh_state *s,
}
-/* As ip_vs_sh_get, but with fallback if selected server is unavailable */
+/* As ip_vs_sh_get, but with fallback if selected server is unavailable
+ *
+ * The fallback strategy loops around the table starting from a "random"
+ * point (in fact, it is chosen to be the original hash value to make the
+ * algorithm deterministic) to find a new server.
+ */
static inline struct ip_vs_dest *
ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s,
const union nf_inet_addr *addr, __be16 port)
{
- unsigned int offset;
- unsigned int hash;
+ unsigned int offset, roffset;
+ unsigned int hash, ihash;
struct ip_vs_dest *dest;
- for (offset = 0; offset < IP_VS_SH_TAB_SIZE; offset++) {
- hash = ip_vs_sh_hashkey(svc->af, addr, port, offset);
- dest = rcu_dereference(s->buckets[hash].dest);
- if (!dest)
- break;
- if (is_unavailable(dest))
- IP_VS_DBG_BUF(6, "SH: selected unavailable server "
- "%s:%d (offset %d)",
+ /* first try the dest it's supposed to go to */
+ ihash = ip_vs_sh_hashkey(svc->af, addr, port, 0);
+ dest = rcu_dereference(s->buckets[ihash].dest);
+ if (!dest)
+ return NULL;
+ if (is_unavailable(dest)) {
+ IP_VS_DBG_BUF(6, "SH: selected unavailable server "
+ "%s:%d, reselecting",
+ IP_VS_DBG_ADDR(svc->af, &dest->addr),
+ ntohs(dest->port));
+ /* if the original dest is unavailable, loop around the table
+ * starting from ihash to find a new dest
+ */
+ for (offset = 0; offset < IP_VS_SH_TAB_SIZE; offset++) {
+ roffset = (offset + ihash) % IP_VS_SH_TAB_SIZE;
+ hash = ip_vs_sh_hashkey(svc->af, addr, port, roffset);
+ dest = rcu_dereference(s->buckets[hash].dest);
+ if (is_unavailable(dest))
+ IP_VS_DBG_BUF(6, "SH: selected unavailable "
+ "server %s:%d (offset %d), reselecting",
IP_VS_DBG_ADDR(svc->af, &dest->addr),
- ntohs(dest->port), offset);
- else
- return dest;
+ ntohs(dest->port), roffset);
+ else
+ return dest;
+ }
+ } else {
+ return dest;
}
return NULL;
^ permalink raw reply related
* [PATCH 2/2] net: qmi_wwan: fix checkpatch warnings
From: Fabio Porcedda @ 2013-09-25 9:21 UTC (permalink / raw)
To: netdev; +Cc: linux-usb, David S. Miller, Bjørn Mork, Dan Williams
In-Reply-To: <1380100886-16531-1-git-send-email-fabio.porcedda@gmail.com>
Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
---
drivers/net/usb/qmi_wwan.c | 56 +++++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 20 deletions(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 5f6b6fa..0e59f9e 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -143,16 +143,22 @@ static const struct net_device_ops qmi_wwan_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-/* using a counter to merge subdriver requests with our own into a combined state */
+/* using a counter to merge subdriver requests with our own into a
+ * combined state
+ */
static int qmi_wwan_manage_power(struct usbnet *dev, int on)
{
struct qmi_wwan_state *info = (void *)&dev->data;
int rv = 0;
- dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
+ dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__,
+ atomic_read(&info->pmcount), on);
- if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
- /* need autopm_get/put here to ensure the usbcore sees the new value */
+ if ((on && atomic_add_return(1, &info->pmcount) == 1) ||
+ (!on && atomic_dec_and_test(&info->pmcount))) {
+ /* need autopm_get/put here to ensure the usbcore sees
+ * the new value
+ */
rv = usb_autopm_get_interface(dev->intf);
if (rv < 0)
goto err;
@@ -199,7 +205,8 @@ static int qmi_wwan_register_subdriver(struct usbnet *dev)
atomic_set(&info->pmcount, 0);
/* register subdriver */
- subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc, 4096, &qmi_wwan_cdc_wdm_manage_power);
+ subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc,
+ 4096, &qmi_wwan_cdc_wdm_manage_power);
if (IS_ERR(subdriver)) {
dev_err(&info->control->dev, "subdriver registration failed\n");
rv = PTR_ERR(subdriver);
@@ -228,7 +235,8 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
struct usb_driver *driver = driver_of(intf);
struct qmi_wwan_state *info = (void *)&dev->data;
- BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
+ BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) <
+ sizeof(struct qmi_wwan_state)));
/* set up initial state */
info->control = intf;
@@ -250,7 +258,8 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
goto err;
}
if (h->bLength != sizeof(struct usb_cdc_header_desc)) {
- dev_dbg(&intf->dev, "CDC header len %u\n", h->bLength);
+ dev_dbg(&intf->dev, "CDC header len %u\n",
+ h->bLength);
goto err;
}
break;
@@ -260,7 +269,8 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
goto err;
}
if (h->bLength != sizeof(struct usb_cdc_union_desc)) {
- dev_dbg(&intf->dev, "CDC union len %u\n", h->bLength);
+ dev_dbg(&intf->dev, "CDC union len %u\n",
+ h->bLength);
goto err;
}
cdc_union = (struct usb_cdc_union_desc *)buf;
@@ -271,15 +281,15 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
goto err;
}
if (h->bLength != sizeof(struct usb_cdc_ether_desc)) {
- dev_dbg(&intf->dev, "CDC ether len %u\n", h->bLength);
+ dev_dbg(&intf->dev, "CDC ether len %u\n",
+ h->bLength);
goto err;
}
cdc_ether = (struct usb_cdc_ether_desc *)buf;
break;
}
- /*
- * Remember which CDC functional descriptors we've seen. Works
+ /* Remember which CDC functional descriptors we've seen. Works
* for all types we care about, of which USB_CDC_ETHERNET_TYPE
* (0x0f) is the highest numbered
*/
@@ -293,10 +303,14 @@ next_desc:
/* Use separate control and data interfaces if we found a CDC Union */
if (cdc_union) {
- info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
- if (desc->bInterfaceNumber != cdc_union->bMasterInterface0 || !info->data) {
- dev_err(&intf->dev, "bogus CDC Union: master=%u, slave=%u\n",
- cdc_union->bMasterInterface0, cdc_union->bSlaveInterface0);
+ info->data = usb_ifnum_to_if(dev->udev,
+ cdc_union->bSlaveInterface0);
+ if (desc->bInterfaceNumber != cdc_union->bMasterInterface0 ||
+ !info->data) {
+ dev_err(&intf->dev,
+ "bogus CDC Union: master=%u, slave=%u\n",
+ cdc_union->bMasterInterface0,
+ cdc_union->bSlaveInterface0);
goto err;
}
}
@@ -374,8 +388,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
struct qmi_wwan_state *info = (void *)&dev->data;
int ret;
- /*
- * Both usbnet_suspend() and subdriver->suspend() MUST return 0
+ /* Both usbnet_suspend() and subdriver->suspend() MUST return 0
* in system sleep context, otherwise, the resume callback has
* to recover device from previous suspend failure.
*/
@@ -383,7 +396,8 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
if (ret < 0)
goto err;
- if (intf == info->control && info->subdriver && info->subdriver->suspend)
+ if (intf == info->control && info->subdriver &&
+ info->subdriver->suspend)
ret = info->subdriver->suspend(intf, message);
if (ret < 0)
usbnet_resume(intf);
@@ -396,7 +410,8 @@ static int qmi_wwan_resume(struct usb_interface *intf)
struct usbnet *dev = usb_get_intfdata(intf);
struct qmi_wwan_state *info = (void *)&dev->data;
int ret = 0;
- bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume);
+ bool callsub = (intf == info->control && info->subdriver &&
+ info->subdriver->resume);
if (callsub)
ret = info->subdriver->resume(intf);
@@ -777,7 +792,8 @@ static const struct usb_device_id products[] = {
};
MODULE_DEVICE_TABLE(usb, products);
-static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id *prod)
+static int qmi_wwan_probe(struct usb_interface *intf,
+ const struct usb_device_id *prod)
{
struct usb_device_id *id = (struct usb_device_id *)prod;
--
1.8.4
^ permalink raw reply related
* [PATCH 1/2] net: qmi_wwan: add Telit LE920 newer firmware support
From: Fabio Porcedda @ 2013-09-25 9:21 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA, David S. Miller,
Bjørn Mork, Dan Williams
Newer firmware use a new pid and a different interface.
Signed-off-by: Fabio Porcedda <fabio.porcedda-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/net/usb/qmi_wwan.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 6312332..5f6b6fa 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -714,6 +714,7 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */
{QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
+ {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */
{QMI_FIXED_INTF(0x1e2d, 0x12d1, 4)}, /* Cinterion PLxx */
/* 4. Gobi 1000 devices */
--
1.8.4
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH] ipvs: improved SH fallback strategy
From: Alexander Frolkin @ 2013-09-25 9:01 UTC (permalink / raw)
To: Simon Horman
Cc: Sergei Shtylyov, Julian Anastasov, lvs-devel, Wensong Zhang,
netdev, linux-kernel
In-Reply-To: <20130925003033.GG26081@verge.net.au>
Hi,
> could you add some comments to the code or at least a description of the
> algorithm to the above the function. The intent of original code may not
> have been obvious to the eye but this version certainly isn't obvious to
> mine.
Sure. I have a bad habit of assuming that if I understand something,
then others automatically do too. :-)
The original code went through the table, starting at the same place as
the code without fallback and if that returned an unavailable
realserver, it offset the hash by one and repeated the lookup, then added
two, etc., up to IP_VS_SH_TAB_SIZE-1. So the hash offset was 0,
1, ..., IP_VS_SH_TAB_SIZE-1.
The result is that if a server is down, all traffic destined for it
would fall back onto the next server in the list.
The new code also starts at the same place as the old code (offset 0),
but if that fails, it uses the same fallback strategy as the old code,
but the hash offset is now ihash, ihash + 1, ..., IP_VS_SH_TAB_SIZE-1,
0, 1, ..., ihash - 1, i.e., it starts at ihash instead of 0 and loops
around the table. ihash could have been a random number, but choosing
it to be something based on the source IP and port (in which case it may
as well be the same hash [offset 0]) means that the behaviour will be
the same on different directors.
This spreads the load of an unavailable server across the remaining
servers instead of just moving it to the next one in the list.
Hope that makes sense...
I'll submit a patch with a comment shortly.
Alex
^ permalink raw reply
* [PATCH RFC] random: introduce get_random_bytes_busy_wait_initialized
From: Hannes Frederic Sowa @ 2013-09-25 9:00 UTC (permalink / raw)
To: Eric Dumazet
Cc: Tom Herbert, davem, netdev, jesse.brandeburg, tytso, linux-kernel
In-Reply-To: <1380028797.3165.65.camel@edumazet-glaptop>
On Tue, Sep 24, 2013 at 06:19:57AM -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> A host might need net_secret[] and never open a single socket.
>
> Problem added in commit aebda156a570782
> ("net: defer net_secret[] initialization")
>
> Based on prior patch from Hannes Frederic Sowa.
>
> Reported-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Perhaps we can even do a bit better? This patch is a RFC and I could split the
random and network parts if needed.
[PATCH RFC] random: introduce get_random_bytes_busy_wait_initialized
We want to use good entropy for initializing the secret keys used for
hashing in the core network stack. So busy wait before extracting random
data until the nonblocking_pool is initialized.
Further entropy is also gathered by interrupts, so we are guaranteed to
make progress here.
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
drivers/char/random.c | 18 ++++++++++++++++++
include/linux/random.h | 1 +
net/core/secure_seq.c | 3 ++-
net/ipv4/af_inet.c | 2 +-
4 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 7737b5b..50e8030 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1058,6 +1058,24 @@ void get_random_bytes(void *buf, int nbytes)
EXPORT_SYMBOL(get_random_bytes);
/*
+ * Busy loop until the nonblocking_pool is intialized and return
+ * random data in buf of size nbytes.
+ *
+ * This is used by the network stack to defer the extraction of
+ * entropy from the nonblocking_pool until the pool is initialized.
+ *
+ * We need to busy loop here, because we could be called from an
+ * atomic section.
+ */
+void get_random_bytes_busy_wait_initialized(void *buf, int nbytes)
+{
+ while (!nonblocking_pool.initialized)
+ cpu_relax();
+ get_random_bytes(buf, nbytes);
+}
+EXPORT_SYMBOL(get_random_bytes_busy_wait_initialized);
+
+/*
* This function will use the architecture-specific hardware random
* number generator if it is available. The arch-specific hw RNG will
* almost certainly be faster than what we can do in software, but it
diff --git a/include/linux/random.h b/include/linux/random.h
index 3b9377d..0b7e7dd 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -15,6 +15,7 @@ extern void add_input_randomness(unsigned int type, unsigned int code,
extern void add_interrupt_randomness(int irq, int irq_flags);
extern void get_random_bytes(void *buf, int nbytes);
+void get_random_bytes_busy_wait_initialized(void *buf, int nbbytes);
extern void get_random_bytes_arch(void *buf, int nbytes);
void generate_random_uuid(unsigned char uuid_out[16]);
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index 3f1ec15..ac55cb7 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -24,7 +24,8 @@ static void net_secret_init(void)
for (i = NET_SECRET_SIZE; i > 0;) {
do {
- get_random_bytes(&tmp, sizeof(tmp));
+ get_random_bytes_busy_wait_initialized(&tmp,
+ sizeof(tmp));
} while (!tmp);
cmpxchg(&net_secret[--i], 0, tmp);
}
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index cfeb85c..3edd277 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -260,7 +260,7 @@ void build_ehash_secret(void)
u32 rnd;
do {
- get_random_bytes(&rnd, sizeof(rnd));
+ get_random_bytes_busy_wait_initialized(&rnd, sizeof(rnd));
} while (rnd == 0);
if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0)
--
1.8.3.1
^ permalink raw reply related
* Re: BUG: MARK in OUTPUT + ip_tunnel causes kernel panic
From: Steffen Klassert @ 2013-09-25 8:59 UTC (permalink / raw)
To: Konstantin Kuzov; +Cc: netdev
In-Reply-To: <loom.20130925T095425-819@post.gmane.org>
On Wed, Sep 25, 2013 at 08:31:52AM +0000, Konstantin Kuzov wrote:
> Kristian Evensen <kristian.evensen <at> gmail.com> writes:
>
> > When trying to tunnel traffic originating from the same machine as the
> > tunnel endpoint, I am experiencing kernel panics for some types of
> > traffic (ICMP and UDP). TCP seems not to be affected by this, at least
> > I have not been able to trigger the panic.
> >
> > I have one tunnel (without an IP address) and use policy routing to
> > steer some traffic through the tunnels.
> [...]
> > An interesting thing is that I have seen different kernel panics being
> > triggered. The other one I have seen has RIP pointing to
> > e1000_xmit_frame() and the message "protocol 0800 is buggy". However,
> > the one I have posted is by far the most common.
> I'm experiencing the same issue on two different machines. It happens on any
> kernel starting from 3.10 when ip_tunnel/ip_tunnel_core were introduced.
>
Can you please try the patch below?
I've posted the same patch already to netdev in the morning.
Subject: [PATCH net 1/2] ip_tunnel: Fix a memory corruption in ip_tunnel_xmit
We might extend the used aera of a skb beyond the total
headroom when we install the ipip header. Fix this by
calling skb_cow_head() unconditionally.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_tunnel.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index ac9fabe..b8ce640 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -641,13 +641,13 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
+ rt->dst.header_len;
- if (max_headroom > dev->needed_headroom) {
+ if (max_headroom > dev->needed_headroom)
dev->needed_headroom = max_headroom;
- if (skb_cow_head(skb, dev->needed_headroom)) {
- dev->stats.tx_dropped++;
- dev_kfree_skb(skb);
- return;
- }
+
+ if (skb_cow_head(skb, dev->needed_headroom)) {
+ dev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ return;
}
err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol,
--
1.7.9.5
^ permalink raw reply related
* Re: BUG: MARK in OUTPUT + ip_tunnel causes kernel panic
From: Konstantin Kuzov @ 2013-09-25 8:31 UTC (permalink / raw)
To: netdev
In-Reply-To: <CAKfDRXgJwyhE6sg1Ej=S35A+-dnPiU9TBA69zb-n7hGXgG+Sxg@mail.gmail.com>
Kristian Evensen <kristian.evensen <at> gmail.com> writes:
> When trying to tunnel traffic originating from the same machine as the
> tunnel endpoint, I am experiencing kernel panics for some types of
> traffic (ICMP and UDP). TCP seems not to be affected by this, at least
> I have not been able to trigger the panic.
>
> I have one tunnel (without an IP address) and use policy routing to
> steer some traffic through the tunnels.
[...]
> An interesting thing is that I have seen different kernel panics being
> triggered. The other one I have seen has RIP pointing to
> e1000_xmit_frame() and the message "protocol 0800 is buggy". However,
> the one I have posted is by far the most common.
I'm experiencing the same issue on two different machines. It happens on any
kernel starting from 3.10 when ip_tunnel/ip_tunnel_core were introduced.
But in my configuration I have addresses on tunnel interfaces and only doing
masquerading on postrouting...
Same as you it triggers different kernel panics depends on which kernel
modules involved (nic, vbox, etc...) here are some samples:
http://nosferatu.g0x.ru/pub/kerneloops/
But most common one looks like that:
[ 81.797190] skbuff: skb_under_panic: text:ffffffff8170307f len:142 put:14
head:ffff88040cd12a00 data:ffff88040cd129ee tail:0x7c end:0xc0 dev:v33
[ 81.797240] ------------[ cut here ]------------
[ 81.797256] kernel BUG at net/core/skbuff.c:126!
[ 81.797272] invalid opcode: 0000 [#1] SMP
[ 81.797291] Modules linked in: ext2
[ 81.797309] CPU: 0 PID: 4654 Comm: ffmpeg Not tainted 3.11.1 #3
[ 81.797328] Hardware name: Gigabyte Technology Co., Ltd. Z68A-D3H-
B3/Z68A-D3H-B3, BIOS F13 03/20/2012
[ 81.797356] task: ffff88040cd5bc80 ti: ffff880407c38000 task.ti:
ffff880407c38000
[ 81.797380] RIP: 0010:[<ffffffff81881a55>] [<ffffffff81881a55>]
skb_panic+0x5e/0x60
[ 81.797411] RSP: 0000:ffff88041fa03898 EFLAGS: 00010296
[ 81.797428] RAX: 0000000000000084 RBX: ffff88040a2bd300 RCX:
0000000000000000
[ 81.797450] RDX: ffff88041fa0eb48 RSI: ffff88041fa0d258 RDI:
ffff88041fa0d258
[ 81.797472] RBP: ffff88041fa038b8 R08: 0000000000000000 R09:
00000000000003ca
[ 81.797494] R10: 0000000000000001 R11: 0000000000aaaaaa R12:
ffff88040b90aed8
[ 81.797516] R13: 000000000000000e R14: ffff88040b90aee8 R15:
0000000000000000
[ 81.797538] FS: 00007ff3002a0740(0000) GS:ffff88041fa00000(0000)
knlGS:0000000000000000
[ 81.797564] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 81.797582] CR2: 0000000008212000 CR3: 000000040a097000 CR4:
00000000000407f0
[ 81.797604] Stack:
[ 81.797613] ffff88040cd129ee 000000000000007c 00000000000000c0
ffff88040c71e000
[ 81.797643] ffff88041fa038c8 ffffffff816971d5 ffff88041fa03928
ffffffff8170307f
[ 81.797673] ffffffff81ee10a0 ffff88040c71e000 ffff88040d79dfc0
fe971fac81ee10a0
[ 81.797703] Call Trace:
[ 81.797713] <IRQ>
[ 81.797721]
[ 81.797730] [<ffffffff816971d5>] skb_push+0x35/0x40
[ 81.797745] [<ffffffff8170307f>] ip_finish_output+0x2af/0x3a0
[ 81.797765] [<ffffffff81703a98>] ip_output+0x88/0x90
[ 81.797782] [<ffffffff81703214>] ip_local_out+0x24/0x30
[ 81.797801] [<ffffffff8174291b>] iptunnel_xmit+0x17b/0x1b0
[ 81.797820] [<ffffffff81744560>] ip_tunnel_xmit+0x2e0/0x7d0
[ 81.797839] [<ffffffff8174a9ec>] ipip_tunnel_xmit+0x5c/0x70
[ 81.797859] [<ffffffff816a8240>] dev_hard_start_xmit+0x300/0x510
[ 81.798750] [<ffffffff81758668>] ? nf_nat_ipv4_out+0x58/0x100
[ 81.799648] [<ffffffff816a8718>] dev_queue_xmit+0x2c8/0x460
[ 81.800543] [<ffffffff816ae14c>] neigh_direct_output+0xc/0x10
[ 81.801434] [<ffffffff81702f7f>] ip_finish_output+0x1af/0x3a0
[ 81.802337] [<ffffffff81703a98>] ip_output+0x88/0x90
[ 81.803243] [<ffffffff81703214>] ip_local_out+0x24/0x30
[ 81.804143] [<ffffffff817044f4>] ip_send_skb+0x14/0x50
[ 81.805040] [<ffffffff81704562>] ip_push_pending_frames+0x32/0x40
[ 81.805950] [<ffffffff8172e1ae>] icmp_push_reply+0xee/0x120
[ 81.806851] [<ffffffff8172e969>] icmp_send+0x419/0x490
[ 81.807750] [<ffffffff816a6082>] ? __netif_receive_skb_core+0x622/0x7f0
[ 81.808651] [<ffffffff81077c00>] ? update_curr+0x10/0x160
[ 81.809552] [<ffffffff816b00e0>] ? neigh_invalidate+0x120/0x120
[ 81.810445] [<ffffffff816f933d>] ipv4_link_failure+0x1d/0x70
[ 81.811333] [<ffffffff8172c50d>] arp_error_report+0x2d/0x40
[ 81.812217] [<ffffffff816b004c>] neigh_invalidate+0x8c/0x120
[ 81.813102] [<ffffffff816b0316>] neigh_timer_handler+0x236/0x2a0
[ 81.813989] [<ffffffff8104fb3a>] call_timer_fn+0x3a/0x110
[ 81.814883] [<ffffffff816b00e0>] ? neigh_invalidate+0x120/0x120
[ 81.815787] [<ffffffff81050ea0>] run_timer_softirq+0x1c0/0x2a0
[ 81.816695] [<ffffffff81048ee9>] __do_softirq+0xe9/0x230
[ 81.817605] [<ffffffff81049185>] irq_exit+0x95/0xa0
[ 81.818513] [<ffffffff8102da75>] smp_apic_timer_interrupt+0x45/0x60
[ 81.819431] [<ffffffff8188feca>] apic_timer_interrupt+0x6a/0x70
[ 81.820355] <EOI>
[ 81.820363]
[ 81.821277] [<ffffffff8188f312>] ? system_call_fastpath+0x16/0x1b
[ 81.822208] Code: 00 00 48 89 44 24 10 8b 87 d0 00 00 00 48 89 44 24 08
48 8b 87 e0 00 00 00 48 c7 c7 80 fa c5 81 48 89 04 24 31 c0 e8 94 95 ff ff
<0f> 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55
[ 81.823365] RIP [<ffffffff81881a55>] skb_panic+0x5e/0x60
[ 81.824409] RSP <ffff88041fa03898>
I also can't trace why that happens and strangely I can't reproduce that
issue on virtualbox. Have you discovered anything more about this issue in
past month?
^ permalink raw reply
* Re: SMSC 9303 support
From: Florian Fainelli @ 2013-09-25 8:24 UTC (permalink / raw)
To: Gary Thomas; +Cc: Ben Hutchings, netdev
In-Reply-To: <5241E448.1060403@mlbassoc.com>
2013/9/24 Gary Thomas <gary@mlbassoc.com>:
> On 2013-09-24 12:29, Florian Fainelli wrote:
>>
>> Hello,
>>
>> 2013/9/24 Gary Thomas <gary@mlbassoc.com>:
>>>
>>> On 2013-09-24 10:51, Ben Hutchings wrote:
>>>>
>>>>
>>>> On Tue, 2013-09-24 at 06:21 -0600, Gary Thomas wrote:
>>>>>
>>>>>
>>>>> I need to support the SMSC9303 in an embedded system. I'm not
>>>>> finding any [explicit] support for this device in the latest
>>>>> mainline kernel. Did I miss something?
>>>>>
>>>>> To be clear, the SMSC9303 is a 3-port managed ethernet switch
>>>>> capable of supporting 802.1D/802.1Q directly. This switch is
>>>>> driven by a single MAC via MII/RMII and exposes the other two
>>>>> ports via physical PHYs. What I need it to do is behave like
>>>>> two external, separate devices. I was thinking that what I need
>>>>> to do is treat these as VLAN devices since the switch can manage
>>>>> the routing.
>>>>>
>>>>> Does this seem like a reasonable approach?
>>>>
>>>>
>>>>
>>>> Linux has 'DSA' (Distributed Switch Architecture) which supports tagging
>>>> of packets to indicate which switch port they are sent or received
>>>> through. This was originally added to support some Marvell switch chips
>>>> and I don't know whether it would be suitable or extensible for this
>>>> one.
>>>
>>>
>>>
>>> I've used the DSA stuff for years (worked directly with the Marvell folks
>>> when it was being developed). It might work for this device, I'll think
>>> some more about using it although I was hoping for a lighter weight
>>> solution.
>>
>>
>> I do not think DSA is suitable for pure 802.1q switches such as this
>> one. OpenWrt has an out of tree patch which adds some switch-specific
>> operations that can be controlled over netlink (currently trying to
>> get them in a shape where they can be submitted for mainline
>> inclusion) [1], which I think is much more suitable than DSA or any
>> other proprietary switch tagging mechanism.
>>
>> [1]:
>> https://dev.openwrt.org/browser/trunk/target/linux/generic/files/drivers/net/phy/swconfig.c
>>
>
> This looks interesting. Do you have any more information on how to
> integrate this and/or use it?
Here are a couple of drivers that implement these "switch ops", my
favorite being b53 because it shows nicely how SPI, MDIO or MMIO
switch can be supported within the same core:
https://dev.openwrt.org/browser/trunk/target/linux/generic/files/drivers/net/phy/b53
adm6996 is also pretty straight forward:
https://dev.openwrt.org/browser/trunk/target/linux/generic/files/drivers/net/phy/adm6996.c
and here is the user-space command line tool to query/control these
(needs libnl):
https://dev.openwrt.org/browser/trunk/package/network/config/swconfig/src
--
Florian
^ permalink raw reply
* [PATCH] iproute2: bridge: Close file with bridge monitor file
From: Petr Písař @ 2013-09-25 7:45 UTC (permalink / raw)
To: netdev; +Cc: Stephen Hemminger, Petr Písař
The `bridge monitor file FILENAME' reads dumped netlink messages from
a file. But it forgot to close the file after using it. This patch
fixes it.
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
bridge/monitor.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/bridge/monitor.c b/bridge/monitor.c
index e96fcaf..76e7d47 100644
--- a/bridge/monitor.c
+++ b/bridge/monitor.c
@@ -132,12 +132,15 @@ int do_monitor(int argc, char **argv)
if (file) {
FILE *fp;
+ int err;
fp = fopen(file, "r");
if (fp == NULL) {
perror("Cannot fopen");
exit(-1);
}
- return rtnl_from_file(fp, accept_msg, stdout);
+ err = rtnl_from_file(fp, accept_msg, stdout);
+ fclose(fp);
+ return err;
}
if (rtnl_open(&rth, groups) < 0)
--
1.8.3.1
^ 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