* [PATCH net-next v4 08/13] bonding: convert bond_has_this_ip() to use upper devices
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
Currently, bond_has_this_ip() is aware only of vlan upper devices, and thus
will return false if the address is associated with the upper bridge or any
other device, and thus will break the arp logic.
Fix this by using the upper device list. For every upper device we verify
if the address associated with it is our address, and if yes - return true.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v1: use netdev_for_each_upper_dev()
v2: use netdev_for_each_upper_dev_rcu()
v3: no change
v4: no change
drivers/net/bonding/bond_main.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 28f4ad0..f38d590 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2392,24 +2392,25 @@ re_arm:
}
}
-static int bond_has_this_ip(struct bonding *bond, __be32 ip)
+static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
{
- struct vlan_entry *vlan;
- struct net_device *vlan_dev;
+ struct net_device *upper;
+ struct list_head *iter;
+ bool ret = false;
if (ip == bond_confirm_addr(bond->dev, 0, ip))
- return 1;
+ return true;
- list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- rcu_read_lock();
- vlan_dev = __vlan_find_dev_deep(bond->dev, htons(ETH_P_8021Q),
- vlan->vlan_id);
- rcu_read_unlock();
- if (vlan_dev && ip == bond_confirm_addr(vlan_dev, 0, ip))
- return 1;
+ rcu_read_lock();
+ netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ if (ip == bond_confirm_addr(upper, 0, ip)) {
+ ret = true;
+ break;
+ }
}
+ rcu_read_unlock();
- return 0;
+ return ret;
}
/*
--
1.8.4
^ permalink raw reply related
* [PATCH net-next v4 09/13] bonding: use vlan_uses_dev() in __bond_release_one()
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
We always hold the rtnl_lock() in __bond_release_one(), so use
vlan_uses_dev() instead of bond_vlan_used().
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v1: no change
v2: no change
v3: no change
v4: no change
drivers/net/bonding/bond_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index f38d590..55a48d3 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1954,7 +1954,7 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_set_carrier(bond);
eth_hw_addr_random(bond_dev);
- if (bond_vlan_used(bond)) {
+ if (vlan_uses_dev(bond_dev)) {
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
bond_dev->name, bond_dev->name);
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
--
1.8.4
^ permalink raw reply related
* [PATCH net-next v4 07/13] bonding: make bond_arp_send_all use upper device list
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev; +Cc: Veaceslav Falico, Vlad Yasevich, Jay Vosburgh, Andy Gospodarek
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
Currently, bond_arp_send_all() is aware only of vlans, which breaks
configurations like bond <- bridge (or any other 'upper' device) with IP
(which is quite a common scenario for virt setups).
To fix this we convert the bond_arp_send_all() to first verify if the rt
device is the bond itself, and if not - to go through its list of upper
vlans and their respectiv upper devices (if the vlan's upper device matches
- tag the packet), if still not found - go through all of our upper list
devices to see if any of them match the route device for the target. If the
match is a vlan device - we also save its vlan_id and tag it in
bond_arp_send().
Also, clean the function a bit to be more readable.
CC: Vlad Yasevich <vyasevic@redhat.com>
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v1: use netdev_for_each_upper_dev()
v2: use netdev_for_each_upper_dev_rcu()
v3: no change
v4: first search for any device that's on top of our upper vlans, to spot a
config like "bond <- vlan <- bridge (ip address)", and only after that
go through all devices.
drivers/net/bonding/bond_main.c | 102 ++++++++++++++++++++--------------------
1 file changed, 51 insertions(+), 51 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 7407e65..28f4ad0 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2444,30 +2444,16 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_
static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
{
- int i, vlan_id;
- __be32 *targets = bond->params.arp_targets;
- struct vlan_entry *vlan;
- struct net_device *vlan_dev = NULL;
+ struct net_device *upper, *vlan_upper;
+ struct list_head *iter, *vlan_iter;
struct rtable *rt;
+ __be32 *targets = bond->params.arp_targets, addr;
+ int i, vlan_id;
- for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
- __be32 addr;
- if (!targets[i])
- break;
+ for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) {
pr_debug("basa: target %pI4\n", &targets[i]);
- if (!bond_vlan_used(bond)) {
- pr_debug("basa: empty vlan: arp_send\n");
- addr = bond_confirm_addr(bond->dev, targets[i], 0);
- bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- addr, 0);
- continue;
- }
- /*
- * If VLANs are configured, we do a route lookup to
- * determine which VLAN interface would be used, so we
- * can tag the ARP with the proper VLAN tag.
- */
+ /* Find out through which dev should the packet go */
rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
RTO_ONLINK, 0);
if (IS_ERR(rt)) {
@@ -2478,47 +2464,61 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
continue;
}
- /*
- * This target is not on a VLAN
- */
- if (rt->dst.dev == bond->dev) {
- ip_rt_put(rt);
- pr_debug("basa: rtdev == bond->dev: arp_send\n");
- addr = bond_confirm_addr(bond->dev, targets[i], 0);
- bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- addr, 0);
- continue;
- }
-
vlan_id = 0;
- list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- rcu_read_lock();
- vlan_dev = __vlan_find_dev_deep(bond->dev,
- htons(ETH_P_8021Q),
- vlan->vlan_id);
- rcu_read_unlock();
- if (vlan_dev == rt->dst.dev) {
- vlan_id = vlan->vlan_id;
- pr_debug("basa: vlan match on %s %d\n",
- vlan_dev->name, vlan_id);
- break;
+
+ /* bond device itself */
+ if (rt->dst.dev == bond->dev)
+ goto found;
+
+ rcu_read_lock();
+ /* first we search only for vlan devices. for every vlan
+ * found we verify its upper dev list, searching for the
+ * rt->dst.dev. If found we save the tag of the vlan and
+ * proceed to send the packet.
+ *
+ * TODO: QinQ?
+ */
+ netdev_for_each_upper_dev_rcu(bond->dev, vlan_upper, vlan_iter) {
+ if (!is_vlan_dev(vlan_upper))
+ continue;
+ netdev_for_each_upper_dev_rcu(vlan_upper, upper, iter) {
+ if (upper == rt->dst.dev) {
+ vlan_id = vlan_dev_vlan_id(vlan_upper);
+ rcu_read_unlock();
+ goto found;
+ }
}
}
- if (vlan_id && vlan_dev) {
- ip_rt_put(rt);
- addr = bond_confirm_addr(vlan_dev, targets[i], 0);
- bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- addr, vlan_id);
- continue;
+ /* if the device we're looking for is not on top of any of
+ * our upper vlans, then just search for any dev that
+ * matches, and in case it's a vlan - save the id
+ */
+ netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ if (upper == rt->dst.dev) {
+ /* if it's a vlan - get its VID */
+ if (is_vlan_dev(upper))
+ vlan_id = vlan_dev_vlan_id(upper);
+
+ rcu_read_unlock();
+ goto found;
+ }
}
+ rcu_read_unlock();
- if (net_ratelimit()) {
+ /* Not our device - skip */
+ if (net_ratelimit())
pr_warning("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
bond->dev->name, &targets[i],
rt->dst.dev ? rt->dst.dev->name : "NULL");
- }
ip_rt_put(rt);
+ continue;
+
+found:
+ addr = bond_confirm_addr(rt->dst.dev, targets[i], 0);
+ ip_rt_put(rt);
+ bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
+ addr, vlan_id);
}
}
--
1.8.4
^ permalink raw reply related
* [PATCH net-next v4 04/13] net: add netdev_upper_get_next_dev_rcu(dev, iter)
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck, Cong Wang
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
This function returns the next dev in the dev->upper_dev_list after the
struct list_head **iter position, and updates *iter accordingly. Returns
NULL if there are no devices left.
Caller must hold RCU read lock.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v1: new patch
v2: rename netdev_upper_get_next_dev{,_rcu} to reflect the RCU, and rename
the netdev_upper to netdev_adjacent
v3: no change
v4: no change
net/core/dev.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/net/core/dev.c b/net/core/dev.c
index 749925a..6fbb0c9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4468,6 +4468,31 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
+/* netdev_upper_get_next_dev_rcu - Get the next dev from upper list
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next device from the dev's upper list, starting from iter
+ * position. The caller must hold RCU read lock.
+ */
+struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
+ struct list_head **iter)
+{
+ struct netdev_adjacent *upper;
+
+ WARN_ON_ONCE(!rcu_read_lock_held());
+
+ upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
+
+ if (&upper->list == &dev->upper_dev_list)
+ return NULL;
+
+ *iter = &upper->list;
+
+ return upper->dev;
+}
+EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+
/**
* netdev_master_upper_dev_get_rcu - Get master upper device
* @dev: device
--
1.8.4
^ permalink raw reply related
* [PATCH net-next v4 05/13] net: add netdev_for_each_upper_dev_rcu()
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck, Cong Wang
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
The new macro netdev_for_each_upper_dev_rcu(dev, upper, iter) iterates
through the dev->upper_dev_list starting from the first element, using
the netdev_upper_get_next_dev_rcu(dev, &iter).
Must be called under RCU read lock.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v1: new patch
v2: rename netdev_for_each_upper_dev{,_rcu} and use/export the renamed
netdev_upper_get_next_dev_rcu().
v3: no change
v4: no change
include/linux/netdevice.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5ccf5b7..3ad49b8 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2768,6 +2768,16 @@ 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_upper_get_next_dev_rcu(struct net_device *dev,
+ struct list_head **iter);
+
+/* iterate through upper list, must be called under RCU read lock */
+#define netdev_for_each_upper_dev_rcu(dev, upper, iter) \
+ for (iter = &(dev)->upper_dev_list, \
+ upper = netdev_upper_get_next_dev_rcu(dev, &(iter)); \
+ upper; \
+ upper = netdev_upper_get_next_dev_rcu(dev, &(iter)))
+
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,
--
1.8.4
^ permalink raw reply related
* [PATCH net-next v4 03/13] net: remove search_list from netdev_adjacent
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck, Cong Wang
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
We already don't need it cause we see every upper/lower device in the list
already.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v2: new patch
v3: no change
v4: no change
net/core/dev.c | 37 +------------------------------------
1 file changed, 1 insertion(+), 36 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 2aa914e..749925a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4381,42 +4381,8 @@ struct netdev_adjacent {
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_adjacent *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_search_upper_dev(struct net_device *dev,
- struct net_device *upper_dev)
-{
- LIST_HEAD(search_list);
- struct netdev_adjacent *upper;
- struct netdev_adjacent *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_adjacent *__netdev_find_adj(struct net_device *dev,
struct net_device *adj_dev,
bool upper)
@@ -4544,7 +4510,6 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->master = master;
adj->neighbour = neighbour;
adj->ref_nr = 1;
- INIT_LIST_HEAD(&adj->search_list);
dev_hold(adj_dev);
pr_debug("dev_hold for %s, because of %s link added from %s to %s\n",
@@ -4671,7 +4636,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return -EBUSY;
/* To prevent loops, check if dev is not upper device to upper_dev. */
- if (__netdev_search_upper_dev(upper_dev, dev))
+ if (__netdev_find_upper(upper_dev, dev))
return -EBUSY;
if (__netdev_find_upper(dev, upper_dev))
--
1.8.4
^ permalink raw reply related
* [PATCH net-next v4 02/13] net: add lower_dev_list to net_device and make a full mesh
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck, Cong Wang
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
This patch adds lower_dev_list list_head to net_device, which is the same
as upper_dev_list, only for lower devices, and begins to use it in the same
way as the upper list.
It also changes the way the whole adjacent device lists work - now they
contain *all* of upper/lower devices, not only the first level. The first
level devices are distinguished by the bool neighbour field in
netdev_adjacent, also added by this patch.
There are cases when a device can be added several times to the adjacent
list, the simplest would be:
/---- eth0.10 ---\
eth0- --- bond0
\---- eth0.20 ---/
where both bond0 and eth0 'see' each other in the adjacent lists two times.
To avoid duplication of netdev_adjacent structures ref_nr is being kept as
the number of times the device was added to the list.
The 'full view' is achieved by adding, on link creation, all of the
upper_dev's upper_dev_list devices as upper devices to all of the
lower_dev's lower_dev_list devices (and to the lower_dev itself), and vice
versa. On unlink they are removed using the same logic.
I've tested it with thousands vlans/bonds/bridges, everything works ok and
no observable lags even on a huge number of interfaces.
Memory footprint for 128 devices interconnected with each other via both
upper and lower (which is impossible, but for the comparison) lists would be:
128*128*2*sizeof(netdev_adjacent) = 1.5MB
but in the real world we usualy have at most several devices with slaves
and a lot of vlans, so the footprint will be much lower.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v2: new patch
v3: move the renaming part back to the first patch, where it belongs, and
correct style/comment issues.
v4: no change
include/linux/netdevice.h | 1 +
net/core/dev.c | 285 +++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 259 insertions(+), 27 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 077363d..5ccf5b7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1125,6 +1125,7 @@ struct net_device {
struct list_head napi_list;
struct list_head unreg_list;
struct list_head upper_dev_list; /* List of upper devices */
+ struct list_head lower_dev_list;
/* currently active device features */
diff --git a/net/core/dev.c b/net/core/dev.c
index 5072e2c..2aa914e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4369,7 +4369,16 @@ softnet_break:
struct netdev_adjacent {
struct net_device *dev;
+
+ /* upper master flag, there can only be one master device per list */
bool master;
+
+ /* indicates that this dev is our first-level lower/upper device */
+ bool neighbour;
+
+ /* counter for the number of times this device was added to us */
+ u16 ref_nr;
+
struct list_head list;
struct rcu_head rcu;
struct list_head search_list;
@@ -4408,18 +4417,34 @@ static bool __netdev_search_upper_dev(struct net_device *dev,
return ret;
}
-static struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
- struct net_device *upper_dev)
+static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
+ struct net_device *adj_dev,
+ bool upper)
{
- struct netdev_adjacent *upper;
+ struct netdev_adjacent *adj;
+ struct list_head *dev_list;
- list_for_each_entry(upper, &dev->upper_dev_list, list) {
- if (upper->dev == upper_dev)
- return upper;
+ dev_list = upper ? &dev->upper_dev_list : &dev->lower_dev_list;
+
+ list_for_each_entry(adj, dev_list, list) {
+ if (adj->dev == adj_dev)
+ return adj;
}
return NULL;
}
+static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
+ struct net_device *udev)
+{
+ return __netdev_find_adj(dev, udev, true);
+}
+
+static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev,
+ struct net_device *ldev)
+{
+ return __netdev_find_adj(dev, ldev, false);
+}
+
/**
* netdev_has_upper_dev - Check if device is linked to an upper device
* @dev: device
@@ -4496,10 +4521,149 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
+static int __netdev_adjacent_dev_insert(struct net_device *dev,
+ struct net_device *adj_dev,
+ bool neighbour, bool master,
+ bool upper)
+{
+ struct netdev_adjacent *adj;
+
+ adj = __netdev_find_adj(dev, adj_dev, upper);
+
+ if (adj) {
+ BUG_ON(neighbour);
+ adj->ref_nr++;
+ return 0;
+ }
+
+ adj = kmalloc(sizeof(*adj), GFP_KERNEL);
+ if (!adj)
+ return -ENOMEM;
+
+ adj->dev = adj_dev;
+ adj->master = master;
+ adj->neighbour = neighbour;
+ adj->ref_nr = 1;
+ INIT_LIST_HEAD(&adj->search_list);
+
+ dev_hold(adj_dev);
+ pr_debug("dev_hold for %s, because of %s link added from %s to %s\n",
+ adj_dev->name, upper ? "upper" : "lower", dev->name,
+ adj_dev->name);
+
+ if (!upper) {
+ list_add_tail_rcu(&adj->list, &dev->lower_dev_list);
+ return 0;
+ }
+
+ /* Ensure that master upper link is always the first item in list. */
+ if (master)
+ list_add_rcu(&adj->list, &dev->upper_dev_list);
+ else
+ list_add_tail_rcu(&adj->list, &dev->upper_dev_list);
+
+ return 0;
+}
+
+static inline int __netdev_upper_dev_insert(struct net_device *dev,
+ struct net_device *udev,
+ bool master, bool neighbour)
+{
+ return __netdev_adjacent_dev_insert(dev, udev, neighbour, master,
+ true);
+}
+
+static inline int __netdev_lower_dev_insert(struct net_device *dev,
+ struct net_device *ldev,
+ bool neighbour)
+{
+ return __netdev_adjacent_dev_insert(dev, ldev, neighbour, false,
+ false);
+}
+
+void __netdev_adjacent_dev_remove(struct net_device *dev,
+ struct net_device *adj_dev, bool upper)
+{
+ struct netdev_adjacent *adj;
+
+ if (upper)
+ adj = __netdev_find_upper(dev, adj_dev);
+ else
+ adj = __netdev_find_lower(dev, adj_dev);
+
+ if (!adj)
+ BUG();
+
+ if (adj->ref_nr > 1) {
+ adj->ref_nr--;
+ return;
+ }
+
+ list_del_rcu(&adj->list);
+ pr_debug("dev_put for %s, because of %s link removed from %s to %s\n",
+ adj_dev->name, upper ? "upper" : "lower", dev->name,
+ adj_dev->name);
+ dev_put(adj_dev);
+ kfree_rcu(adj, rcu);
+}
+
+static inline void __netdev_upper_dev_remove(struct net_device *dev,
+ struct net_device *udev)
+{
+ return __netdev_adjacent_dev_remove(dev, udev, true);
+}
+
+static inline void __netdev_lower_dev_remove(struct net_device *dev,
+ struct net_device *ldev)
+{
+ return __netdev_adjacent_dev_remove(dev, ldev, false);
+}
+
+int __netdev_adjacent_dev_insert_link(struct net_device *dev,
+ struct net_device *upper_dev,
+ bool master, bool neighbour)
+{
+ int ret;
+
+ ret = __netdev_upper_dev_insert(dev, upper_dev, master, neighbour);
+ if (ret)
+ return ret;
+
+ ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour);
+ if (ret) {
+ __netdev_upper_dev_remove(dev, upper_dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline int __netdev_adjacent_dev_link(struct net_device *dev,
+ struct net_device *udev)
+{
+ return __netdev_adjacent_dev_insert_link(dev, udev, false, false);
+}
+
+static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
+ struct net_device *udev,
+ bool master)
+{
+ return __netdev_adjacent_dev_insert_link(dev, udev, master, true);
+}
+
+void __netdev_adjacent_dev_unlink(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ __netdev_upper_dev_remove(dev, upper_dev);
+ __netdev_lower_dev_remove(upper_dev, dev);
+}
+
+
static int __netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev, bool master)
{
- struct netdev_adjacent *upper;
+ struct netdev_adjacent *i, *j, *to_i, *to_j;
+ int ret = 0;
ASSERT_RTNL();
@@ -4516,22 +4680,76 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (master && netdev_master_upper_dev_get(dev))
return -EBUSY;
- upper = kmalloc(sizeof(*upper), GFP_KERNEL);
- if (!upper)
- return -ENOMEM;
+ ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master);
+ if (ret)
+ return ret;
- upper->dev = upper_dev;
- upper->master = master;
- INIT_LIST_HEAD(&upper->search_list);
+ /* Now that we linked these devs, make all the upper_dev's
+ * upper_dev_list visible to every dev's lower_dev_list and vice
+ * versa, and don't forget the devices itself. All of these
+ * links are non-neighbours.
+ */
+ list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(j, &dev->lower_dev_list, list) {
+ ret = __netdev_adjacent_dev_link(i->dev, j->dev);
+ if (ret)
+ goto rollback_mesh;
+ }
+ }
+
+ /* add dev to every upper_dev's upper device */
+ list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ ret = __netdev_adjacent_dev_link(dev, i->dev);
+ if (ret)
+ goto rollback_upper_mesh;
+ }
+
+ /* add upper_dev to every dev's lower device */
+ list_for_each_entry(i, &dev->lower_dev_list, list) {
+ ret = __netdev_adjacent_dev_link(i->dev, upper_dev);
+ if (ret)
+ goto rollback_lower_mesh;
+ }
- /* 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);
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
return 0;
+
+rollback_lower_mesh:
+ to_i = i;
+ list_for_each_entry(i, &dev->lower_dev_list, list) {
+ if (i == to_i)
+ break;
+ __netdev_adjacent_dev_unlink(i->dev, upper_dev);
+ }
+
+ i = NULL;
+
+rollback_upper_mesh:
+ to_i = i;
+ list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ if (i == to_i)
+ break;
+ __netdev_adjacent_dev_unlink(dev, i->dev);
+ }
+
+ i = j = NULL;
+
+rollback_mesh:
+ to_i = i;
+ to_j = j;
+ list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
+ if (i == to_i && j == to_j)
+ break;
+ __netdev_adjacent_dev_unlink(i->dev, j->dev);
+ }
+ if (i == to_i)
+ break;
+ }
+
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
+
+ return ret;
}
/**
@@ -4580,16 +4798,28 @@ EXPORT_SYMBOL(netdev_master_upper_dev_link);
void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
- struct netdev_adjacent *upper;
-
+ struct netdev_adjacent *i, *j;
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);
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
+
+ /* Here is the tricky part. We must remove all dev's lower
+ * devices from all upper_dev's upper devices and vice
+ * versa, to maintain the graph relationship.
+ */
+ list_for_each_entry(i, &dev->lower_dev_list, list)
+ list_for_each_entry(j, &upper_dev->upper_dev_list, list)
+ __netdev_adjacent_dev_unlink(i->dev, j->dev);
+
+ /* remove also the devices itself from lower/upper device
+ * list
+ */
+ list_for_each_entry(i, &dev->lower_dev_list, list)
+ __netdev_adjacent_dev_unlink(i->dev, upper_dev);
+
+ list_for_each_entry(i, &upper_dev->upper_dev_list, list)
+ __netdev_adjacent_dev_unlink(dev, i->dev);
+
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
@@ -5850,6 +6080,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->link_watch_list);
INIT_LIST_HEAD(&dev->upper_dev_list);
+ INIT_LIST_HEAD(&dev->lower_dev_list);
dev->priv_flags = IFF_XMIT_DST_RELEASE;
setup(dev);
--
1.8.4
^ permalink raw reply related
* [PATCH net-next v4 0/13] bonding: remove vlan special handling
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev
Cc: Vlad Yasevich, Jay Vosburgh, Andy Gospodarek, David S. Miller,
Eric Dumazet, Jiri Pirko, Alexander Duyck, Cong Wang,
Veaceslav Falico
v1: Per Jiri's advice, remove the exported netdev_upper struct to keep it
inside dev.c only, and instead implement a macro to iterate over the
list and return only net_device *.
v2: Jiri noted that we need to see every upper device, but not only the
first level. Modify the netdev_upper logic to include a list of lower
devices and for both upper/lower lists every device would see both its
first-level devices and every other devices that is lower/upper of it.
Also, convert some annoying spamming warnings to pr_debug in
bond_arp_send_all.
v3: move renaming part completely to patch 1 (did I forget to git add
before commiting?) and address Jiri's input about comments/style of
patch 2.
v4: as Vlad found spotted, bond_arp_send_all() won't work in a config where
we have a device with ip on top of our upper vlan. It fails to send
packets because we don't tag the packet, while the device on top of
vlan will emit tagged packets through this vlan. Fix this by first
searching for all upper vlans, and for each vlan - for the devs on top
of it. If we find the dev - then tag the packet with the underling's
vlan_id, otherwise just search the old way - for all devices on top of
bonding. Also, move the version changes under "---" so they won't get
into the commit message, if/when applied.
The aim of this patchset is to remove bondings' own vlan handling as much
as possible and replace it with the netdev upper device functionality.
The upper device functionality is extended to include also lower devices
and to have, for each device, a full view of every lower and upper device,
but not only the first-level ones. This might permit in the future to
avoid, for any grouping/teaming/upper/lower devices, to maintain its own
lists of slaves/vlans/etc.
This is achieved by adding a helper function to upper dev list handling -
netdev_upper_get_next_dev(dev, iter), which returns the next device after
the list_head **iter, and sets *iter to the next list_head *. This patchset
also adds netdev_for_each_upper_dev(dev, upper, iter), which iterates
through the whole dev->upper_dev_list, setting upper to the net_device.
The only special treatment of vlans remains in rlb code.
This patchset solves several issues with bonding, simplifies it overall,
RCUify further and exports upper list functions for any other users which
might also want to get rid of its own vlan_lists or slaves.
I'm testing it continuously currently, no issues found, will update on
anything.
CC: Vlad Yasevich <vyasevic@redhat.com>
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
drivers/net/bonding/bond_alb.c | 75 +++++----
drivers/net/bonding/bond_alb.h | 2 -
drivers/net/bonding/bond_main.c | 272 +++++++++----------------------
drivers/net/bonding/bonding.h | 21 ++-
include/linux/netdevice.h | 11 ++
net/core/dev.c | 345 ++++++++++++++++++++++++++++++++--------
6 files changed, 416 insertions(+), 310 deletions(-)
^ permalink raw reply
* [PATCH net-next v4 01/13] net: rename netdev_upper to netdev_adjacent
From: Veaceslav Falico @ 2013-08-28 21:25 UTC (permalink / raw)
To: netdev
Cc: Veaceslav Falico, David S. Miller, Eric Dumazet, Jiri Pirko,
Alexander Duyck, Cong Wang
In-Reply-To: <1377725116-31126-1-git-send-email-vfalico@redhat.com>
Rename the structure to reflect the upcoming addition of lower_dev_list.
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
Notes:
v2: new patch
v3: actually rename everything
v4: no change
net/core/dev.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 1ed2b66..5072e2c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4367,7 +4367,7 @@ softnet_break:
goto out;
}
-struct netdev_upper {
+struct netdev_adjacent {
struct net_device *dev;
bool master;
struct list_head list;
@@ -4378,7 +4378,7 @@ struct netdev_upper {
static void __append_search_uppers(struct list_head *search_list,
struct net_device *dev)
{
- struct netdev_upper *upper;
+ struct netdev_adjacent *upper;
list_for_each_entry(upper, &dev->upper_dev_list, list) {
/* check if this upper is not already in search list */
@@ -4391,8 +4391,8 @@ static bool __netdev_search_upper_dev(struct net_device *dev,
struct net_device *upper_dev)
{
LIST_HEAD(search_list);
- struct netdev_upper *upper;
- struct netdev_upper *tmp;
+ struct netdev_adjacent *upper;
+ struct netdev_adjacent *tmp;
bool ret = false;
__append_search_uppers(&search_list, dev);
@@ -4408,10 +4408,10 @@ static bool __netdev_search_upper_dev(struct net_device *dev,
return ret;
}
-static struct netdev_upper *__netdev_find_upper(struct net_device *dev,
+static struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
struct net_device *upper_dev)
{
- struct netdev_upper *upper;
+ struct netdev_adjacent *upper;
list_for_each_entry(upper, &dev->upper_dev_list, list) {
if (upper->dev == upper_dev)
@@ -4462,7 +4462,7 @@ EXPORT_SYMBOL(netdev_has_any_upper_dev);
*/
struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
{
- struct netdev_upper *upper;
+ struct netdev_adjacent *upper;
ASSERT_RTNL();
@@ -4470,7 +4470,7 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
return NULL;
upper = list_first_entry(&dev->upper_dev_list,
- struct netdev_upper, list);
+ struct netdev_adjacent, list);
if (likely(upper->master))
return upper->dev;
return NULL;
@@ -4486,10 +4486,10 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get);
*/
struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
{
- struct netdev_upper *upper;
+ struct netdev_adjacent *upper;
upper = list_first_or_null_rcu(&dev->upper_dev_list,
- struct netdev_upper, list);
+ struct netdev_adjacent, list);
if (upper && likely(upper->master))
return upper->dev;
return NULL;
@@ -4499,7 +4499,7 @@ 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;
+ struct netdev_adjacent *upper;
ASSERT_RTNL();
@@ -4580,7 +4580,7 @@ EXPORT_SYMBOL(netdev_master_upper_dev_link);
void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
- struct netdev_upper *upper;
+ struct netdev_adjacent *upper;
ASSERT_RTNL();
--
1.8.4
^ permalink raw reply related
* Re: [PATCH v3 2/2] genl: Hold reference on correct module while netlink-dump.
From: David Miller @ 2013-08-28 21:19 UTC (permalink / raw)
To: pshelar; +Cc: netdev, jesse, johannes.berg
In-Reply-To: <1377287104-13297-1-git-send-email-pshelar@nicira.com>
From: Pravin B Shelar <pshelar@nicira.com>
Date: Fri, 23 Aug 2013 12:45:04 -0700
> netlink dump operations take module as parameter to hold
> reference for entire netlink dump duration.
> Currently it holds ref only on genl module which is not correct
> when we use ops registered to genl from another module.
> Following patch adds module pointer to genl_ops so that netlink
> can hold ref count on it.
>
> CC: Jesse Gross <jesse@nicira.com>
> CC: Johannes Berg <johannes.berg@intel.com>
> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH v3 1/2] genl: Fix genl dumpit() locking.
From: David Miller @ 2013-08-28 21:19 UTC (permalink / raw)
To: pshelar; +Cc: netdev, jesse, johannes.berg
In-Reply-To: <1377287095-13245-1-git-send-email-pshelar@nicira.com>
From: Pravin B Shelar <pshelar@nicira.com>
Date: Fri, 23 Aug 2013 12:44:55 -0700
> In case of genl-family with parallel ops off, dumpif() callback
> is expected to run under genl_lock, But commit def3117493eafd9df
> (genl: Allow concurrent genl callbacks.) changed this behaviour
> where only first dumpit() op was called under genl-lock.
> For subsequent dump, only nlk->cb_lock was taken.
> Following patch fixes it by defining locked dumpit() and done()
> callback which takes care of genl-locking.
>
> CC: Jesse Gross <jesse@nicira.com>
> CC: Johannes Berg <johannes.berg@intel.com>
> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Applied, and queued up for -stable.
^ permalink raw reply
* Re: [net-next 04/10] ixgbe: fix link test when connected to 1Gbps link partner
From: Sergei Shtylyov @ 2013-08-28 20:38 UTC (permalink / raw)
To: Tantilov, Emil S
Cc: Kirsher, Jeffrey T, davem@davemloft.net, netdev@vger.kernel.org,
gospo@redhat.com, sassmann@redhat.com
In-Reply-To: <87618083B2453E4A8714035B62D679924FDF9934@FMSMSX105.amr.corp.intel.com>
On 08/29/2013 12:24 AM, Tantilov, Emil S wrote:
>>> From: Emil Tantilov <emil.s.tantilov@intel.com>
>>> This patch is a partial reverse of:
>>> commit dfcc4615f09c33454bc553567f7c7506cae60cb9
>> Please also specify that commit's summary line in
>> parens.
> commit dfcc4615f09c33454bc553567f7c7506cae60cb9
> Author: Jacob Keller <jacob.e.keller@intel.com>
> Date: Thu Nov 8 07:07:08 2012 +0000
> ixgbe: ethtool ixgbe_diag_test cleanup
>>> Specifically forcing the laser before the link check can
>> lead to
>>> inconsistent results because it does not guarantee that
>> the link will be
>>> negotiated correctly. Such is the case when dual speed
>> SFP+ module is
>>> connected to a gigabit link partner.
>>> Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
>>> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
>>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>>> ---
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 26
>>> ++++++++----------------
>>> 1 file changed, 9 insertions(+), 17 deletions(-)
>>> diff --git
>>> a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>>> b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>>> index db0dbf6..57465d8 100644
>>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>>> @@ -1885,11 +1885,11 @@ static void ixgbe_diag_test(struct
>> net_device *netdev,
>>> struct ethtool_test
>> *eth_test, u64 *data)
>>> {
>>> struct ixgbe_adapter *adapter = netdev_priv(netdev);
>>> - struct ixgbe_hw *hw = &adapter->hw;
>>> bool if_running = netif_running(netdev);
>>>
>>> set_bit(__IXGBE_TESTING, &adapter->state);
>>> if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
>>> + struct ixgbe_hw *hw = &adapter->hw;
>>
>> Empty line wouldn't here, after declaration. At least in
Missed the verb "hurt" before "here".
>> the code above you have it.
> It's probably a good idea to make it more readable. Assuming you meant adding an empty line after the declaration.
Yes.
>>
>>> if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
>>> int i;
>>> for (i = 0; i < adapter->num_vfs; i++) {
>>
>> WBR, Sergei
> If the lack of commit description and the empty line after the *hw declaration is too big of a concern I can resubmit the patch.
The earlier is certainly a requirement (coming originally from Linus).
It's the only way to uniquely identify the commit and it's the only way to
easily know what the commit was about without a git tree or with 'cgit'
currently used by http://git.kernel.org (it doesn't follow the commit SHA1 as
the 'gitweb' used to do).
> Thanks,
> Emil
WBR, Sergei
^ permalink raw reply
* Re: [net-next 1/2] vxlan: Notify drivers for listening UDP port changes
From: Joseph Gasparakis @ 2013-08-28 20:41 UTC (permalink / raw)
To: John Fastabend
Cc: Kirsher, Jeffrey T, davem@davemloft.net, Gasparakis, Joseph,
netdev@vger.kernel.org, gospo@redhat.com, sassmann@redhat.com,
Stephen Hemminger
In-Reply-To: <521E50B1.4010102@intel.com>
On Wed, 28 Aug 2013, John Fastabend wrote:
> On 8/27/2013 9:46 PM, Jeff Kirsher wrote:
> > From: Joseph Gasparakis <joseph.gasparakis@intel.com>
> >
> > This patch adds two more ndo ops: ndo_add_rx_vxlan_port() and
> > ndo_del_rx_vxlan_port().
> >
> > Drivers can get notifications through the above functions about changes
> > of the UDP listening port of VXLAN. Also, when physical ports come up,
> > now they can call vxlan_get_rx_port() in order to obtain the port number(s)
> > of the existing VXLAN interface in case they already up before them.
> >
> > This information about the listening UDP port would be used for VXLAN
> > related offloads.
>
> [...]
>
> > /* Add new entry to forwarding table -- assumes lock held */
> > static int vxlan_fdb_create(struct vxlan_dev *vxlan,
> > const u8 *mac, __be32 ip,
> > @@ -797,13 +823,15 @@ static void vxlan_sock_hold(struct vxlan_sock *vs)
> >
> > void vxlan_sock_release(struct vxlan_sock *vs)
> > {
> > - struct vxlan_net *vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id);
> > + struct net *net = sock_net(vs->sock->sk);
> > + struct vxlan_net *vn = net_generic(net, vxlan_net_id);
> >
> > if (!atomic_dec_and_test(&vs->refcnt))
> > return;
> >
> > spin_lock(&vn->sock_lock);
> > hlist_del_rcu(&vs->hlist);
> > + vxlan_notify_del_rx_port(net, inet_sk(vs->sock->sk)->inet_sport);
> > spin_unlock(&vn->sock_lock);
>
> Both the del and add port are protected by sock_lock serializing the
> operations.
>
> >
> > queue_work(vxlan_wq, &vs->del_work);
> > @@ -1543,6 +1571,28 @@ static struct device_type vxlan_type = {
> > .name = "vxlan",
> > };
> >
> > +/* Calls the ndo_add_vxlan_port of the caller in order to
> > + * supply the listening VXLAN udp ports.
> > + */
> > +void vxlan_get_rx_port(struct net_device *dev)
> > +{
> > + struct vxlan_sock *vs;
> > + struct net *net = dev_net(dev);
> > + u16 port;
> > + int i;
> > +
> > + if (!dev || !dev->netdev_ops || !dev->netdev_ops->ndo_add_vxlan_port)
> > + return;
> > +
> > + for (i = 0; i < PORT_HASH_SIZE; ++i) {
> > + hlist_for_each_entry_rcu(vs, vs_head(net, i), hlist) {
> > + port = htons(inet_sk(vs->sock->sk)->inet_sport);
> > + dev->netdev_ops->ndo_add_vxlan_port(dev, port);
>
> However this list walk occurs without the sock_lock. Looks like you
> could delete a port and then subsequently add it here if you had really
> "good" timing.
>
> Then it would be deleted from the vxlan list but pushed into hardware.
> Probably not a terrible scenario but it would waste hardware resources.
>
> I suspect you want to lock this list traversal with the sock_lock as
> well.
>
Yes, you are right. I will wait a little bit more to gather more comments
and will push a v2 fixing this issue.
> > + }
> > + }
> > +}
> > +EXPORT_SYMBOL_GPL(vxlan_get_rx_port);
>
> --
> 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: [net-next 04/10] ixgbe: fix link test when connected to 1Gbps link partner
From: Tantilov, Emil S @ 2013-08-28 20:24 UTC (permalink / raw)
To: Sergei Shtylyov, Kirsher, Jeffrey T
Cc: davem@davemloft.net, netdev@vger.kernel.org, gospo@redhat.com,
sassmann@redhat.com
In-Reply-To: <521E4148.3030402@cogentembedded.com>
>-----Original Message-----
>From: Sergei Shtylyov
>[mailto:sergei.shtylyov@cogentembedded.com]
>Sent: Wednesday, August 28, 2013 11:28 AM
>To: Kirsher, Jeffrey T
>Cc: davem@davemloft.net; Tantilov, Emil S;
>netdev@vger.kernel.org; gospo@redhat.com;
>sassmann@redhat.com
>Subject: Re: [net-next 04/10] ixgbe: fix link test when
>connected to 1Gbps link partner
>
>Hello.
>
>On 08/28/2013 02:33 PM, Jeff Kirsher wrote:
>
>> From: Emil Tantilov <emil.s.tantilov@intel.com>
>
>> This patch is a partial reverse of:
>> commit dfcc4615f09c33454bc553567f7c7506cae60cb9
>
> Please also specify that commit's summary line in
>parens.
commit dfcc4615f09c33454bc553567f7c7506cae60cb9
Author: Jacob Keller <jacob.e.keller@intel.com>
Date: Thu Nov 8 07:07:08 2012 +0000
ixgbe: ethtool ixgbe_diag_test cleanup
>
>> Specifically forcing the laser before the link check can
>lead to
>> inconsistent results because it does not guarantee that
>the link will be
>> negotiated correctly. Such is the case when dual speed
>SFP+ module is
>> connected to a gigabit link partner.
>
>> Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
>> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>> ---
>> drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 26
>++++++++----------------
>> 1 file changed, 9 insertions(+), 17 deletions(-)
>
>> diff --git
>a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>> index db0dbf6..57465d8 100644
>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
>> @@ -1885,11 +1885,11 @@ static void ixgbe_diag_test(struct
>net_device *netdev,
>> struct ethtool_test
>*eth_test, u64 *data)
>> {
>> struct ixgbe_adapter *adapter = netdev_priv(netdev);
>> - struct ixgbe_hw *hw = &adapter->hw;
>> bool if_running = netif_running(netdev);
>>
>> set_bit(__IXGBE_TESTING, &adapter->state);
>> if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
>> + struct ixgbe_hw *hw = &adapter->hw;
>
> Empty line wouldn't here, after declaration. At least in
>the code above you have it.
It's probably a good idea to make it more readable. Assuming you meant adding an empty line after the declaration.
>
>> if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
>> int i;
>> for (i = 0; i < adapter->num_vfs; i++) {
>
>WBR, Sergei
If the lack of commit description and the empty line after the *hw declaration is too big of a concern I can resubmit the patch.
Thanks,
Emil
^ permalink raw reply
* [PATCH net-next 3/3] net: packet: document available fanout policies
From: Daniel Borkmann @ 2013-08-28 20:13 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1377720791-15844-1-git-send-email-dborkman@redhat.com>
Update documentation to add fanout policies that are available.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
Documentation/networking/packet_mmap.txt | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 8572796..c012236 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -543,6 +543,14 @@ TPACKET_V2 --> TPACKET_V3:
In the AF_PACKET fanout mode, packet reception can be load balanced among
processes. This also works in combination with mmap(2) on packet sockets.
+Currently implemented fanout policies are:
+
+ - PACKET_FANOUT_HASH: schedule to socket by skb's rxhash
+ - PACKET_FANOUT_LB: schedule to socket by round-robin
+ - PACKET_FANOUT_CPU: schedule to socket by CPU packet arrives on
+ - PACKET_FANOUT_RND: schedule to socket by random selection
+ - PACKET_FANOUT_ROLLOVER: if one socket is full, rollover to another
+
Minimal example code by David S. Miller (try things like "./test eth0 hash",
"./test eth0 lb", etc.):
--
1.7.11.7
^ permalink raw reply related
* [PATCH net-next 2/3] net: packet: use reciprocal_divide in fanout_demux_hash
From: Daniel Borkmann @ 2013-08-28 20:13 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1377720791-15844-1-git-send-email-dborkman@redhat.com>
Instead of hard-coding reciprocal_divide function, use the inline
function from reciprocal_div.h.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
net/packet/af_packet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 91596f5..130e2ea 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1135,7 +1135,7 @@ static unsigned int fanout_demux_hash(struct packet_fanout *f,
struct sk_buff *skb,
unsigned int num)
{
- return (((u64)skb->rxhash) * num) >> 32;
+ return reciprocal_divide(skb->rxhash, num);
}
static unsigned int fanout_demux_lb(struct packet_fanout *f,
--
1.7.11.7
^ permalink raw reply related
* [PATCH net-next 1/3] net: packet: add randomized fanout scheduler
From: Daniel Borkmann @ 2013-08-28 20:13 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1377720791-15844-1-git-send-email-dborkman@redhat.com>
We currently allow for different fanout scheduling policies in pf_packet
such as scheduling by skb's rxhash, round-robin, by cpu, and rollover.
Also allow for a random, equidistributed selection of the socket from the
fanout process group.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
include/uapi/linux/if_packet.h | 1 +
net/packet/af_packet.c | 13 ++++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index b950c02..dbf0666 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -56,6 +56,7 @@ struct sockaddr_ll {
#define PACKET_FANOUT_LB 1
#define PACKET_FANOUT_CPU 2
#define PACKET_FANOUT_ROLLOVER 3
+#define PACKET_FANOUT_RND 4
#define PACKET_FANOUT_FLAG_ROLLOVER 0x1000
#define PACKET_FANOUT_FLAG_DEFRAG 0x8000
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 6c53dd9..91596f5 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -88,7 +88,7 @@
#include <linux/virtio_net.h>
#include <linux/errqueue.h>
#include <linux/net_tstamp.h>
-
+#include <linux/reciprocal_div.h>
#ifdef CONFIG_INET
#include <net/inet_common.h>
#endif
@@ -1158,6 +1158,13 @@ static unsigned int fanout_demux_cpu(struct packet_fanout *f,
return smp_processor_id() % num;
}
+static unsigned int fanout_demux_rnd(struct packet_fanout *f,
+ struct sk_buff *skb,
+ unsigned int num)
+{
+ return reciprocal_divide(prandom_u32(), num);
+}
+
static unsigned int fanout_demux_rollover(struct packet_fanout *f,
struct sk_buff *skb,
unsigned int idx, unsigned int skip,
@@ -1215,6 +1222,9 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
case PACKET_FANOUT_CPU:
idx = fanout_demux_cpu(f, skb, num);
break;
+ case PACKET_FANOUT_RND:
+ idx = fanout_demux_rnd(f, skb, num);
+ break;
case PACKET_FANOUT_ROLLOVER:
idx = fanout_demux_rollover(f, skb, 0, (unsigned int) -1, num);
break;
@@ -1284,6 +1294,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
case PACKET_FANOUT_HASH:
case PACKET_FANOUT_LB:
case PACKET_FANOUT_CPU:
+ case PACKET_FANOUT_RND:
break;
default:
return -EINVAL;
--
1.7.11.7
^ permalink raw reply related
* [PATCH net-next 0/3] pf_packet updates
From: Daniel Borkmann @ 2013-08-28 20:13 UTC (permalink / raw)
To: davem; +Cc: netdev
Daniel Borkmann (3):
net: packet: add random fanout scheduler
net: packet: use reciprocal_divide in fanout_demux_hash
net: packet: document available fanout policies
Documentation/networking/packet_mmap.txt | 8 ++++++++
include/uapi/linux/if_packet.h | 1 +
net/packet/af_packet.c | 15 +++++++++++++--
3 files changed, 22 insertions(+), 2 deletions(-)
--
1.7.11.7
^ permalink raw reply
* [gcv v3 04/35] net: Replace __get_cpu_var uses
From: Christoph Lameter @ 2013-08-28 19:48 UTC (permalink / raw)
To: Tejun Heo
Cc: akpm, David S. Miller, netdev, linux-arch, Steven Rostedt,
linux-kernel
In-Reply-To: <20130828193457.140443630@linux.com>
__get_cpu_var() is used for multiple purposes in the kernel source. One of them is
address calculation via the form &__get_cpu_var(x). This calculates the address for
the instance of the percpu variable of the current processor based on an offset.
Other use cases are for storing and retrieving data from the current processors percpu area.
__get_cpu_var() can be used as an lvalue when writing data or on the right side of an assignment.
__get_cpu_var() is defined as :
#define __get_cpu_var(var) (*this_cpu_ptr(&(var)))
__get_cpu_var() always only does an address determination. However, store and retrieve operations
could use a segment prefix (or global register on other platforms) to avoid the address calculation.
this_cpu_write() and this_cpu_read() can directly take an offset into a percpu area and use
optimized assembly code to read and write per cpu variables.
This patch converts __get_cpu_var into either an explicit address calculation using this_cpu_ptr()
or into a use of this_cpu operations that use the offset. Thereby address calcualtions are avoided
and less registers are used when code is generated.
At the end of the patchset all uses of __get_cpu_var have been removed so the macro is removed too.
The patchset includes passes over all arches as well. Once these operations are used throughout then
specialized macros can be defined in non -x86 arches as well in order to optimize per cpu access by
f.e. using a global register that may be set to the per cpu base.
Transformations done to __get_cpu_var()
1. Determine the address of the percpu instance of the current processor.
DEFINE_PER_CPU(int, y);
int *x = &__get_cpu_var(y);
Converts to
int *x = this_cpu_ptr(&y);
2. Same as #1 but this time an array structure is involved.
DEFINE_PER_CPU(int, y[20]);
int *x = __get_cpu_var(y);
Converts to
int *x = this_cpu_ptr(y);
3. Retrieve the content of the current processors instance of a per cpu variable.
DEFINE_PER_CPU(int, u);
int x = __get_cpu_var(y)
Converts to
int x = __this_cpu_read(y);
4. Retrieve the content of a percpu struct
DEFINE_PER_CPU(struct mystruct, y);
struct mystruct x = __get_cpu_var(y);
Converts to
memcpy(this_cpu_ptr(&x), y, sizeof(x));
5. Assignment to a per cpu variable
DEFINE_PER_CPU(int, y)
__get_cpu_var(y) = x;
Converts to
this_cpu_write(y, x);
6. Increment/Decrement etc of a per cpu variable
DEFINE_PER_CPU(int, y);
__get_cpu_var(y)++
Converts to
this_cpu_inc(y)
Signed-off-by: Christoph Lameter <cl@linux.com>
Index: linux/net/core/dev.c
===================================================================
--- linux.orig/net/core/dev.c 2013-08-26 14:16:59.000000000 -0500
+++ linux/net/core/dev.c 2013-08-26 14:18:37.214005168 -0500
@@ -2129,7 +2129,7 @@ static inline void __netif_reschedule(st
unsigned long flags;
local_irq_save(flags);
- sd = &__get_cpu_var(softnet_data);
+ sd = this_cpu_ptr(&softnet_data);
q->next_sched = NULL;
*sd->output_queue_tailp = q;
sd->output_queue_tailp = &q->next_sched;
@@ -2151,7 +2151,7 @@ void dev_kfree_skb_irq(struct sk_buff *s
unsigned long flags;
local_irq_save(flags);
- sd = &__get_cpu_var(softnet_data);
+ sd = this_cpu_ptr(&softnet_data);
skb->next = sd->completion_queue;
sd->completion_queue = skb;
raise_softirq_irqoff(NET_TX_SOFTIRQ);
@@ -3111,7 +3111,7 @@ static void rps_trigger_softirq(void *da
static int rps_ipi_queued(struct softnet_data *sd)
{
#ifdef CONFIG_RPS
- struct softnet_data *mysd = &__get_cpu_var(softnet_data);
+ struct softnet_data *mysd = this_cpu_ptr(&softnet_data);
if (sd != mysd) {
sd->rps_ipi_next = mysd->rps_ipi_list;
@@ -3138,7 +3138,7 @@ static bool skb_flow_limit(struct sk_buf
if (qlen < (netdev_max_backlog >> 1))
return false;
- sd = &__get_cpu_var(softnet_data);
+ sd = this_cpu_ptr(&softnet_data);
rcu_read_lock();
fl = rcu_dereference(sd->flow_limit);
@@ -3280,7 +3280,7 @@ EXPORT_SYMBOL(netif_rx_ni);
static void net_tx_action(struct softirq_action *h)
{
- struct softnet_data *sd = &__get_cpu_var(softnet_data);
+ struct softnet_data *sd = this_cpu_ptr(&softnet_data);
if (sd->completion_queue) {
struct sk_buff *clist;
@@ -3700,7 +3700,7 @@ EXPORT_SYMBOL(netif_receive_skb);
static void flush_backlog(void *arg)
{
struct net_device *dev = arg;
- struct softnet_data *sd = &__get_cpu_var(softnet_data);
+ struct softnet_data *sd = this_cpu_ptr(&softnet_data);
struct sk_buff *skb, *tmp;
rps_lock(sd);
@@ -4146,7 +4146,7 @@ void __napi_schedule(struct napi_struct
unsigned long flags;
local_irq_save(flags);
- ____napi_schedule(&__get_cpu_var(softnet_data), n);
+ ____napi_schedule(this_cpu_ptr(&softnet_data), n);
local_irq_restore(flags);
}
EXPORT_SYMBOL(__napi_schedule);
@@ -4274,7 +4274,7 @@ EXPORT_SYMBOL(netif_napi_del);
static void net_rx_action(struct softirq_action *h)
{
- struct softnet_data *sd = &__get_cpu_var(softnet_data);
+ struct softnet_data *sd = this_cpu_ptr(&softnet_data);
unsigned long time_limit = jiffies + 2;
int budget = netdev_budget;
void *have;
Index: linux/net/core/drop_monitor.c
===================================================================
--- linux.orig/net/core/drop_monitor.c 2013-08-26 14:16:59.000000000 -0500
+++ linux/net/core/drop_monitor.c 2013-08-26 14:18:37.218005126 -0500
@@ -142,7 +142,7 @@ static void trace_drop_common(struct sk_
unsigned long flags;
local_irq_save(flags);
- data = &__get_cpu_var(dm_cpu_data);
+ data = this_cpu_ptr(&dm_cpu_data);
spin_lock(&data->lock);
dskb = data->skb;
Index: linux/net/core/skbuff.c
===================================================================
--- linux.orig/net/core/skbuff.c 2013-08-26 14:16:59.000000000 -0500
+++ linux/net/core/skbuff.c 2013-08-26 14:18:37.218005126 -0500
@@ -371,7 +371,7 @@ static void *__netdev_alloc_frag(unsigne
unsigned long flags;
local_irq_save(flags);
- nc = &__get_cpu_var(netdev_alloc_cache);
+ nc = this_cpu_ptr(&netdev_alloc_cache);
if (unlikely(!nc->frag.page)) {
refill:
for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) {
Index: linux/net/ipv4/syncookies.c
===================================================================
--- linux.orig/net/ipv4/syncookies.c 2013-08-26 14:16:59.000000000 -0500
+++ linux/net/ipv4/syncookies.c 2013-08-26 14:18:37.210005210 -0500
@@ -44,7 +44,7 @@ static DEFINE_PER_CPU(__u32 [16 + 5 + SH
static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
u32 count, int c)
{
- __u32 *tmp = __get_cpu_var(ipv4_cookie_scratch);
+ __u32 *tmp = this_cpu_ptr(ipv4_cookie_scratch);
memcpy(tmp + 4, syncookie_secret[c], sizeof(syncookie_secret[c]));
tmp[0] = (__force u32)saddr;
Index: linux/net/ipv4/tcp_output.c
===================================================================
--- linux.orig/net/ipv4/tcp_output.c 2013-08-26 14:16:59.000000000 -0500
+++ linux/net/ipv4/tcp_output.c 2013-08-26 14:18:37.218005126 -0500
@@ -810,7 +810,7 @@ void tcp_wfree(struct sk_buff *skb)
/* queue this socket to tasklet queue */
local_irq_save(flags);
- tsq = &__get_cpu_var(tsq_tasklet);
+ tsq = this_cpu_ptr(&tsq_tasklet);
list_add(&tp->tsq_node, &tsq->head);
tasklet_schedule(&tsq->tasklet);
local_irq_restore(flags);
Index: linux/net/ipv6/syncookies.c
===================================================================
--- linux.orig/net/ipv6/syncookies.c 2013-08-26 14:16:59.000000000 -0500
+++ linux/net/ipv6/syncookies.c 2013-08-26 14:18:37.214005168 -0500
@@ -66,7 +66,7 @@ static DEFINE_PER_CPU(__u32 [16 + 5 + SH
static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr,
__be16 sport, __be16 dport, u32 count, int c)
{
- __u32 *tmp = __get_cpu_var(ipv6_cookie_scratch);
+ __u32 *tmp = this_cpu_ptr(ipv6_cookie_scratch);
/*
* we have 320 bits of information to hash, copy in the remaining
Index: linux/net/rds/ib_rdma.c
===================================================================
--- linux.orig/net/rds/ib_rdma.c 2013-08-26 14:16:59.000000000 -0500
+++ linux/net/rds/ib_rdma.c 2013-08-26 14:18:37.218005126 -0500
@@ -267,7 +267,7 @@ static inline struct rds_ib_mr *rds_ib_r
unsigned long *flag;
preempt_disable();
- flag = &__get_cpu_var(clean_list_grace);
+ flag = this_cpu_ptr(&clean_list_grace);
set_bit(CLEAN_LIST_BUSY_BIT, flag);
ret = llist_del_first(&pool->clean_list);
if (ret)
Index: linux/include/net/netfilter/nf_conntrack.h
===================================================================
--- linux.orig/include/net/netfilter/nf_conntrack.h 2013-08-26 14:23:46.000000000 -0500
+++ linux/include/net/netfilter/nf_conntrack.h 2013-08-26 14:24:17.190395755 -0500
@@ -243,7 +243,7 @@ extern s16 (*nf_ct_nat_offset)(const str
DECLARE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
static inline struct nf_conn *nf_ct_untracked_get(void)
{
- return &__raw_get_cpu_var(nf_conntrack_untracked);
+ return __this_cpu_ptr(&nf_conntrack_untracked);
}
extern void nf_ct_untracked_status_or(unsigned long bits);
^ permalink raw reply
* Re: [net-next 1/2] vxlan: Notify drivers for listening UDP port changes
From: John Fastabend @ 2013-08-28 19:34 UTC (permalink / raw)
To: Jeff Kirsher
Cc: davem, Joseph Gasparakis, netdev, gospo, sassmann,
Stephen Hemminger
In-Reply-To: <1377665218-6760-1-git-send-email-jeffrey.t.kirsher@intel.com>
On 8/27/2013 9:46 PM, Jeff Kirsher wrote:
> From: Joseph Gasparakis <joseph.gasparakis@intel.com>
>
> This patch adds two more ndo ops: ndo_add_rx_vxlan_port() and
> ndo_del_rx_vxlan_port().
>
> Drivers can get notifications through the above functions about changes
> of the UDP listening port of VXLAN. Also, when physical ports come up,
> now they can call vxlan_get_rx_port() in order to obtain the port number(s)
> of the existing VXLAN interface in case they already up before them.
>
> This information about the listening UDP port would be used for VXLAN
> related offloads.
[...]
> /* Add new entry to forwarding table -- assumes lock held */
> static int vxlan_fdb_create(struct vxlan_dev *vxlan,
> const u8 *mac, __be32 ip,
> @@ -797,13 +823,15 @@ static void vxlan_sock_hold(struct vxlan_sock *vs)
>
> void vxlan_sock_release(struct vxlan_sock *vs)
> {
> - struct vxlan_net *vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id);
> + struct net *net = sock_net(vs->sock->sk);
> + struct vxlan_net *vn = net_generic(net, vxlan_net_id);
>
> if (!atomic_dec_and_test(&vs->refcnt))
> return;
>
> spin_lock(&vn->sock_lock);
> hlist_del_rcu(&vs->hlist);
> + vxlan_notify_del_rx_port(net, inet_sk(vs->sock->sk)->inet_sport);
> spin_unlock(&vn->sock_lock);
Both the del and add port are protected by sock_lock serializing the
operations.
>
> queue_work(vxlan_wq, &vs->del_work);
> @@ -1543,6 +1571,28 @@ static struct device_type vxlan_type = {
> .name = "vxlan",
> };
>
> +/* Calls the ndo_add_vxlan_port of the caller in order to
> + * supply the listening VXLAN udp ports.
> + */
> +void vxlan_get_rx_port(struct net_device *dev)
> +{
> + struct vxlan_sock *vs;
> + struct net *net = dev_net(dev);
> + u16 port;
> + int i;
> +
> + if (!dev || !dev->netdev_ops || !dev->netdev_ops->ndo_add_vxlan_port)
> + return;
> +
> + for (i = 0; i < PORT_HASH_SIZE; ++i) {
> + hlist_for_each_entry_rcu(vs, vs_head(net, i), hlist) {
> + port = htons(inet_sk(vs->sock->sk)->inet_sport);
> + dev->netdev_ops->ndo_add_vxlan_port(dev, port);
However this list walk occurs without the sock_lock. Looks like you
could delete a port and then subsequently add it here if you had really
"good" timing.
Then it would be deleted from the vxlan list but pushed into hardware.
Probably not a terrible scenario but it would waste hardware resources.
I suspect you want to lock this list traversal with the sock_lock as
well.
> + }
> + }
> +}
> +EXPORT_SYMBOL_GPL(vxlan_get_rx_port);
^ permalink raw reply
* Re: [PATCH net-next 1/1] net: neighbour: Simplify ifdefs around neigh_app_ns()
From: Tim Gardner @ 2013-08-28 19:09 UTC (permalink / raw)
To: Joe Perches
Cc: netdev, linux-kernel, David S. Miller, Alexey Kuznetsov,
James Morris, Hideaki YOSHIFUJI, Patrick McHardy,
Eric W. Biederman, Gao feng
In-Reply-To: <1377715873.1928.47.camel@joe-AO722>
On 08/28/2013 12:51 PM, Joe Perches wrote:
> On Wed, 2013-08-28 at 12:24 -0600, Tim Gardner wrote:
>> Drop a couple of ifdef/endif pairs by moving the ifdef
>> surrounding neigh_app_ns() to the interior of neigh_app_ns().
> []
>> This is an admittedly trivial change. I stumbled on it while trying to figure
>> out why Ubuntu doesn't have CONFIG_ARPD enabled.
>
> I'd be more inclined to make neigh_app_ns static inline
> in the .h file and remove the EXPORT_SYMBOL
>
I thought about that as well, but then you'd have to extern
__neigh_notify(), which is currently a static function and large enough
to not really be suitable for inlining. Seems like unnecessary churn to me.
rtg
--
Tim Gardner tim.gardner@canonical.com
^ permalink raw reply
* RE: [patch net-next v6 4/4] igb/igbvf: implement ndo_get_phys_port_id
From: Brown, Aaron F @ 2013-08-28 19:06 UTC (permalink / raw)
To: Jiri Pirko
Cc: Kirsher, Jeffrey T, netdev@vger.kernel.org, davem@davemloft.net,
stephen@networkplumber.org, Narendra_K@Dell.com,
bhutchings@solarflare.com, or.gerlitz@gmail.com, Wyborny, Carolyn,
Rose, Gregory V, vyasevic@redhat.com, amwang@redhat.com,
johannes@sipsolutions.net
In-Reply-To: <20130828060558.GA1589@minipsycho.orion>
[-- Attachment #1: Type: text/plain, Size: 6383 bytes --]
> -----Original Message-----
> From: Jiri Pirko [mailto:jiri@resnulli.us]
> Sent: Tuesday, August 27, 2013 11:06 PM
> To: Brown, Aaron F
> Cc: Kirsher, Jeffrey T; netdev@vger.kernel.org; davem@davemloft.net;
> stephen@networkplumber.org; Narendra_K@Dell.com;
> bhutchings@solarflare.com; or.gerlitz@gmail.com; Wyborny, Carolyn; Rose,
> Gregory V; vyasevic@redhat.com; amwang@redhat.com;
> johannes@sipsolutions.net
> Subject: Re: [patch net-next v6 4/4] igb/igbvf: implement
> ndo_get_phys_port_id
>
> Wed, Aug 28, 2013 at 04:26:28AM CEST, aaron.f.brown@intel.com wrote:
> >Sorry, I was out sick towards the end of last week and playing catch up
> for the last few days... Info inline.
> >
> >> From: Jiri Pirko [mailto:jiri@resnulli.us]
> >> Sent: Thursday, August 22, 2013 6:10 AM
> >> To: Kirsher, Jeffrey T
> >> Cc: Brown, Aaron F; netdev@vger.kernel.org; davem@davemloft.net;
> >> stephen@networkplumber.org; Narendra_K@Dell.com;
> >> bhutchings@solarflare.com; or.gerlitz@gmail.com; Wyborny, Carolyn;
> >> Rose, Gregory V; vyasevic@redhat.com; amwang@redhat.com;
> >> johannes@sipsolutions.net
> >> Subject: Re: [patch net-next v6 4/4] igb/igbvf: implement
> >> ndo_get_phys_port_id
> >>
> >> Thu, Aug 22, 2013 at 12:39:10PM CEST, jeffrey.t.kirsher@intel.com
> wrote:
> >> >On Mon, 2013-07-29 at 18:16 +0200, Jiri Pirko wrote:
> >> >> igb driver generated random number which will identify physical
> port.
> >> >> This id is available via ndo_get_phys_port_id directly on igb
> netdev.
> >> >> Also, id is passed to igbvf using mailbox. After that, it is
> >> >> available via ndo_get_phys_port_id on igbvf netdev as well.
> >> >>
> >> >> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> >> >> ---
> >> >> drivers/net/ethernet/intel/igb/e1000_mbx.h | 1 +
> >> >> drivers/net/ethernet/intel/igb/igb.h | 3 +++
> >> >> drivers/net/ethernet/intel/igb/igb_main.c | 37
> >> >> ++++++++++++++++++++++++++++-
> >> >> drivers/net/ethernet/intel/igbvf/igbvf.h | 4 ++++
> >> >> drivers/net/ethernet/intel/igbvf/mbx.h | 1 +
> >> >> drivers/net/ethernet/intel/igbvf/netdev.c | 38
> >> >> ++++++++++++++++++++++++++++++
> >> >> drivers/net/ethernet/intel/igbvf/vf.c | 34
> >> >> ++++++++++++++++++++++++++
> >> >> drivers/net/ethernet/intel/igbvf/vf.h | 1 +
> >> >> 8 files changed, 118 insertions(+), 1 deletion(-)
> >> >
> >> >Jiri-
> >> >
> >> >Validation ran into a couple of issues with this patch. Here is
> >> >what Aaron found when testing this patch...
> >>
> >> Interesting. So since igbvf_refresh_ppid() is called from
> >> igbvf_reset() and igbvf_probe(), I believed that is enough. Looks
> >> like perm_addr getting works in similar way. Can you please check if
> >> perm_addr is set correctly in the same time reading phys_port_id gives
> -EOPNOTSUPP?
> >
> >By perm_addr do you mean the MAC Address of the vf? Yes, it is set up
> >(and I can view it vi ip link or sysconfig) when I see the op not
> >supported message (after I fi vfs via sysfs, before bringing the vf
> >interface up or reloading igbvf.)
>
> Can you please send me dmesg log from the system you are testing this?
Attached, dmesg dump from a fresh boot to the eopnosupp. I've been using a .config with a whole bunch of debug junk in it and this is putting out tons of kobject messages, I can re-build and send something with less junk if it's pushing anything relevant off the top.
>
> Looking at the code, it looks like whenever mac.ops.reset_hw() (which sets
> up mac) is called, igbvf_refresh_ppid() is called as well.
>
> Thanks
>
> >
> >>
> >>
> >> >
> >> >Aaron Brown wrote:
> >> >I think I have to fail this, it seems to have an issue with
> >> >initialization. When I first create a vf via sysfs the pys_port_id
> >> >file is created along with the other sysfs files for the vf, however
> >> >an attempt to cat out the value returns " Operation not supported".
> >> >At this point the vf is still down, if I bring it up (or simply
> >> >unload / reload the igbvf driver) I can then cat the file
> >> >successfully and the vf interface phys_port_id matches the
> >> >phys_port_id of the pf. This is testing from bare metal, a console
> >> >session showing this behavior
> >> >follows:
> >> >
> >> >u1304:[0]/sys> find . -iname phys_port_id
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:00.0/net/eth0/phys_port_id
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:00.1/net/eth1/phys_port_id
> >> >./devices/virtual/net/sit0/phys_port_id
> >> >./devices/virtual/net/lo/phys_port_id
> >> >u1304:[0]/sys> cat
> >> >devices/pci0000:00/0000:00:01.0/0000:07:00.0/net/eth0/phys_port_id
> >> >5ece9fbd9cd51546982e15c1f2c11e25
> >> >u1304:[0]/sys>
> >> >
> >> >So far so good, now make a few vfs and check for new phys_port_id
> >> >sysfs
> >> files.
> >> >
> >> >u1304:[0]/sys> find . -iname sriov_numvfs
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:00.0/sriov_numvfs
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:00.1/sriov_numvfs
> >> >u1304:[0]/sys> echo 2 >
> >> devices/pci0000:00/0000:00:01.0/0000:07:00.0/sriov_numvfs
> >> >u1304:[0]/sys> find . -iname phys_port_id
> >> ./devices/pci0000:00/0000:00:01.0/0000:07:00.0/net/eth0/phys_port_id
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:00.1/net/eth1/phys_port_id
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:10.0/net/eth2/phys_port_id
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:10.2/net/eth3/phys_port_id
> >> >./devices/virtual/net/sit0/phys_port_id
> >> >./devices/virtual/net/lo/phys_port_id
> >> >u1304:[0]/sys>
> >> >
> >> >The first vf is eth2, attempt to cat out it's phys_port_id
> >> >
> >> >u1304:[0]/sys> cat
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:10.0/net/eth2/phys_port_id
> >> >cat:
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:10.0/net/eth2/phys_port_id:
> >> >Operation not supported u1304:[0]/sys>
> >> >
> >> >But, if I bring the interface up (or unload / load the igbvf driver)
> >> >I
> >> then am able to cat the phys_port_id of the vf and it matches the
> >> phys_port_id of the physical interface.
> >> >
> >> >u1304:[0]/sys> ifconfig eth2 u1304-2 u1304:[0]/sys> cat
> >> >./devices/pci0000:00/0000:00:01.0/0000:07:10.0/net/eth2/phys_port_id
> >> >5ece9fbd9cd51546982e15c1f2c11e25
> >> >u1304:[0]/sys>
> >>
> >
[-- Attachment #2: phys_port_id_eopnosupp_dmesg_from_boot.tgz --]
[-- Type: application/x-compressed, Size: 29823 bytes --]
^ permalink raw reply
* Re: [PATCH net-next 1/1] net: neighbour: Simplify ifdefs around neigh_app_ns()
From: Joe Perches @ 2013-08-28 18:51 UTC (permalink / raw)
To: Tim Gardner
Cc: netdev, linux-kernel, David S. Miller, Alexey Kuznetsov,
James Morris, Hideaki YOSHIFUJI, Patrick McHardy,
Eric W. Biederman, Gao feng
In-Reply-To: <1377714286-51816-1-git-send-email-tim.gardner@canonical.com>
On Wed, 2013-08-28 at 12:24 -0600, Tim Gardner wrote:
> Drop a couple of ifdef/endif pairs by moving the ifdef
> surrounding neigh_app_ns() to the interior of neigh_app_ns().
[]
> This is an admittedly trivial change. I stumbled on it while trying to figure
> out why Ubuntu doesn't have CONFIG_ARPD enabled.
I'd be more inclined to make neigh_app_ns static inline
in the .h file and remove the EXPORT_SYMBOL
> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index 60533db..049dd9e 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -2759,13 +2759,13 @@ errout:
> rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
> }
>
> -#ifdef CONFIG_ARPD
> void neigh_app_ns(struct neighbour *n)
> {
> +#ifdef CONFIG_ARPD
> __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
> +#endif /* CONFIG_ARPD */
> }
> EXPORT_SYMBOL(neigh_app_ns);
> -#endif /* CONFIG_ARPD */
>
> #ifdef CONFIG_SYSCTL
> static int zero;
> diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
> index 4429b01..7808093 100644
> --- a/net/ipv4/arp.c
> +++ b/net/ipv4/arp.c
> @@ -368,9 +368,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
> } else {
> probes -= neigh->parms->app_probes;
> if (probes < 0) {
> -#ifdef CONFIG_ARPD
> neigh_app_ns(neigh);
> -#endif
> return;
> }
> }
> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index 04d31c2..d5693ad 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -663,9 +663,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
> }
> ndisc_send_ns(dev, neigh, target, target, saddr);
> } else if ((probes -= neigh->parms->app_probes) < 0) {
> -#ifdef CONFIG_ARPD
> neigh_app_ns(neigh);
> -#endif
> } else {
> addrconf_addr_solict_mult(target, &mcaddr);
> ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
^ permalink raw reply
* Re: [net-next 04/10] ixgbe: fix link test when connected to 1Gbps link partner
From: Sergei Shtylyov @ 2013-08-28 18:28 UTC (permalink / raw)
To: Jeff Kirsher; +Cc: davem, Emil Tantilov, netdev, gospo, sassmann
In-Reply-To: <1377686028-30747-5-git-send-email-jeffrey.t.kirsher@intel.com>
Hello.
On 08/28/2013 02:33 PM, Jeff Kirsher wrote:
> From: Emil Tantilov <emil.s.tantilov@intel.com>
> This patch is a partial reverse of:
> commit dfcc4615f09c33454bc553567f7c7506cae60cb9
Please also specify that commit's summary line in parens.
> Specifically forcing the laser before the link check can lead to
> inconsistent results because it does not guarantee that the link will be
> negotiated correctly. Such is the case when dual speed SFP+ module is
> connected to a gigabit link partner.
> Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
> drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 26 ++++++++----------------
> 1 file changed, 9 insertions(+), 17 deletions(-)
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
> index db0dbf6..57465d8 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
> @@ -1885,11 +1885,11 @@ static void ixgbe_diag_test(struct net_device *netdev,
> struct ethtool_test *eth_test, u64 *data)
> {
> struct ixgbe_adapter *adapter = netdev_priv(netdev);
> - struct ixgbe_hw *hw = &adapter->hw;
> bool if_running = netif_running(netdev);
>
> set_bit(__IXGBE_TESTING, &adapter->state);
> if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
> + struct ixgbe_hw *hw = &adapter->hw;
Empty line wouldn't here, after declaration. At least in the code above
you have it.
> if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
> int i;
> for (i = 0; i < adapter->num_vfs; i++) {
WBR, Sergei
^ permalink raw reply
* [PATCH net-next 1/1] net: neighbour: Simplify ifdefs around neigh_app_ns()
From: Tim Gardner @ 2013-08-28 18:24 UTC (permalink / raw)
To: netdev, linux-kernel
Cc: Tim Gardner, David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, Eric W. Biederman, Gao feng,
Joe Perches
Drop a couple of ifdef/endif pairs by moving the ifdef
surrounding neigh_app_ns() to the interior of neigh_app_ns().
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Gao feng <gaofeng@cn.fujitsu.com>
Cc: Joe Perches <joe@perches.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
---
This is an admittedly trivial change. I stumbled on it while trying to figure
out why Ubuntu doesn't have CONFIG_ARPD enabled.
net/core/neighbour.c | 4 ++--
net/ipv4/arp.c | 2 --
net/ipv6/ndisc.c | 2 --
3 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 60533db..049dd9e 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2759,13 +2759,13 @@ errout:
rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
}
-#ifdef CONFIG_ARPD
void neigh_app_ns(struct neighbour *n)
{
+#ifdef CONFIG_ARPD
__neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
+#endif /* CONFIG_ARPD */
}
EXPORT_SYMBOL(neigh_app_ns);
-#endif /* CONFIG_ARPD */
#ifdef CONFIG_SYSCTL
static int zero;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 4429b01..7808093 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -368,9 +368,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
} else {
probes -= neigh->parms->app_probes;
if (probes < 0) {
-#ifdef CONFIG_ARPD
neigh_app_ns(neigh);
-#endif
return;
}
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 04d31c2..d5693ad 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -663,9 +663,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
}
ndisc_send_ns(dev, neigh, target, target, saddr);
} else if ((probes -= neigh->parms->app_probes) < 0) {
-#ifdef CONFIG_ARPD
neigh_app_ns(neigh);
-#endif
} else {
addrconf_addr_solict_mult(target, &mcaddr);
ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
--
1.7.9.5
^ 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