Netdev List
 help / color / mirror / Atom feed
* [PATCH V2 09/12] net/eipoib: Add main driver functionality
From: Or Gerlitz @ 2012-08-01 17:09 UTC (permalink / raw)
  To: davem; +Cc: roland, netdev, ali, sean.hefty, Erez Shitrit, Or Gerlitz
In-Reply-To: <1343840975-3252-1-git-send-email-ogerlitz@mellanox.com>

From: Erez Shitrit <erezsh@mellanox.co.il>

The eipoib driver provides a standard Ethernet netdevice over
the InfiniBand IPoIB interface .

Some services can run only on top of Ethernet L2 interfaces, and cannot be
bound to an IPoIB interface. With this new driver, these services can run
seamlessly.

Main use case of the driver is the Ethernet Virtual Switching used in
virtualized environments, where an eipoib netdevice can be used as a
Physical Interface (PIF) in the hypervisor domain, and allow other
guests Virtual Interfaces (VIF) connected to the same Virtual Switch
to run over the InfiniBand fabric.

This driver supports L2 Switching (Direct Bridging) as well as other L3
Switching modes (e.g. NAT).

Whenever an IPoIB interface is created, one eIPoIB PIF netdevice
will be created. The default naming scheme is as in other Ethernet
interfaces: ethX, for example, on a system with two IPoIB interfaces,
ib0 and ib1, two interfaces will be created ethX and ethX+1 When "X"
is the next free Ethernet number in the system.

Using "ethtool -i " over the new interface can tell on which IPoIB
PIF interface that interface is above.  For example: driver: eth_ipoib:ib0
indicates that eth3 is the Ethernet interface over the ib0 IPoIB interface.

The driver can be used as independent interface or to serve in
virtualization environment as the physical layer for the virtual
interfaces on the virtual guest.

The driver interface (eipoib interface or which is also referred to as parent)
uses slave interfaces, IPoIB clones, which are the VIFs described above.

VIFs interfaces are enslaved/released from the eipoib driver on demand, according
to the management interface provided to user space.

Note: Each ethX interface has at least one ibX.Y slave to serve the PIF
itself, in the VIFs list of ethX you'll notice that ibX.1 is always created
to serve applications running from the Hypervisor on top of ethX interface directly.

For IB applications that require native IPoIB interfaces (e.g. RDMA-CM), the
original ipoib interfaces ibX can still be used.  For example, RDMA-CM and
eth_ipoib drivers can co-exist and make use of IPoIB

Support for Live migration:

The driver expose sysfs interface through which the manager can notify on
migrated out guests ("detached VIF"). The abandoned eIPoIB driver instance
sends ARP requests (defined number) to the network in order to triger the migrated
guest to publish its mac address of the new VIF that hosts it. When the guest
responds to that ARP, the eIPoIB driver on the host that owns that guest, sends
Gratuitous ARP in behalf of that guest such that all the peers on the network
which communicate with this VM are noticed on the new VIF address which is
used by the guest.

Signed-off-by: Erez Shitrit <erezsh@mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 drivers/net/eipoib/eth_ipoib_main.c | 1953 +++++++++++++++++++++++++++++++++++
 1 files changed, 1953 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/eipoib/eth_ipoib_main.c

diff --git a/drivers/net/eipoib/eth_ipoib_main.c b/drivers/net/eipoib/eth_ipoib_main.c
new file mode 100644
index 0000000..0a8e7f4
--- /dev/null
+++ b/drivers/net/eipoib/eth_ipoib_main.c
@@ -0,0 +1,1953 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. All rights reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * openfabric.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "eth_ipoib.h"
+#include <net/ip.h>
+#include <linux/if_link.h>
+
+#define EMAC_IP_GC_TIME (10 * HZ)
+
+#define MIG_OUT_ARP_REQ_ISSUE_TIME (0.5 * HZ)
+
+#define MIG_OUT_MAX_ARP_RETRIES 5
+
+#define LIVE_MIG_PACKET 1
+
+#define PARENT_MAC_MASK 0xe7
+
+/* forward declaration */
+static rx_handler_result_t eipoib_handle_frame(struct sk_buff **pskb);
+static int eipoib_device_event(struct notifier_block *unused,
+			       unsigned long event, void *ptr);
+static void free_ip_mem_in_rec(struct guest_emac_info *emac_info);
+
+static const char * const version =
+	DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
+
+LIST_HEAD(parent_dev_list);
+
+/* name space sys/fs functions */
+int eipoib_net_id __read_mostly;
+
+static int __net_init eipoib_net_init(struct net *net)
+{
+	int rc;
+	struct eipoib_net *eipoib_n = net_generic(net, eipoib_net_id);
+
+	eipoib_n->net = net;
+	rc = mod_create_sysfs(eipoib_n);
+
+	return rc;
+}
+
+static void __net_exit eipoib_net_exit(struct net *net)
+{
+	struct eipoib_net *eipoib_n = net_generic(net, eipoib_net_id);
+
+	mod_destroy_sysfs(eipoib_n);
+}
+
+static struct pernet_operations eipoib_net_ops = {
+	.init = eipoib_net_init,
+	.exit = eipoib_net_exit,
+	.id   = &eipoib_net_id,
+	.size = sizeof(struct eipoib_net),
+};
+
+/* set mac fields emac=<qpn><lid> */
+static inline
+void build_neigh_mac(u8 *_mac, u32 _qpn, u16 _lid)
+{
+	/* _qpn: 3B _lid: 2B */
+	*((__be32 *)(_mac)) = cpu_to_be32(_qpn);
+	*(u8 *)(_mac) = 0x2; /* set LG bit */
+	*(__be16 *)(_mac + sizeof(_qpn)) = cpu_to_be16(_lid);
+}
+
+static inline
+struct slave *get_slave_by_dev(struct parent *parent,
+			       struct net_device *slave_dev)
+{
+	struct slave *slave, *slave_tmp;
+	int found = 0;
+
+	parent_for_each_slave(parent, slave_tmp) {
+		if (slave_tmp->dev == slave_dev) {
+			found = 1;
+			slave = slave_tmp;
+			break;
+		}
+	}
+
+	return found ? slave : NULL;
+}
+
+static inline
+struct slave *get_slave_by_mac_and_vlan(struct parent *parent, u8 *mac,
+					u16 vlan)
+{
+	struct slave *slave, *slave_tmp;
+	int found = 0;
+
+	parent_for_each_slave(parent, slave_tmp) {
+		if ((!memcmp(slave_tmp->emac, mac, ETH_ALEN)) &&
+		    (slave_tmp->vlan == vlan)) {
+			found = 1;
+			slave = slave_tmp;
+			break;
+		}
+	}
+
+	return found ? slave : NULL;
+}
+
+
+static inline
+struct guest_emac_info *get_mac_ip_info_by_mac_and_vlan(struct parent *parent,
+							u8 *mac, u16 vlan)
+{
+	struct guest_emac_info *emac_info, *emac_info_ret;
+	int found = 0;
+
+	list_for_each_entry(emac_info, &parent->emac_ip_list, list) {
+		if ((!memcmp(emac_info->emac, mac, ETH_ALEN)) &&
+		    vlan == emac_info->vlan) {
+			found = 1;
+			emac_info_ret = emac_info;
+			break;
+		}
+	}
+
+	return found ? emac_info_ret : NULL;
+}
+
+/*
+ * searches for the relevant guest_emac_info in the parent.
+ * if found it, check if it contains the required ip
+ * if no such guest_emac_info object or no ip return 0,
+ * otherwise return 1 and if exist set the guest_emac_info obj.
+ */
+static inline
+int is_mac_info_contain_ip(struct parent *parent, u8 *mac, __be32 ip,
+			  struct guest_emac_info *emac_info, u16 vlan)
+{
+	struct ip_member *ipm;
+	int found = 0;
+
+	emac_info = get_mac_ip_info_by_mac_and_vlan(parent, mac, vlan);
+	if (!emac_info)
+		return 0;
+
+	list_for_each_entry(ipm, &emac_info->ip_list, list) {
+		if (ipm->ip == ip) {
+			found = 1;
+			break;
+		}
+	}
+
+	return found;
+}
+
+static inline int netdev_set_parent_master(struct net_device *slave,
+					   struct net_device *master)
+{
+	int err;
+
+	ASSERT_RTNL();
+
+	err = netdev_set_master(slave, master);
+	if (err)
+		return err;
+	if (master) {
+			slave->priv_flags |= IFF_EIPOIB_VIF;
+			/* deny bonding from enslaving it. */;
+			slave->flags |= IFF_SLAVE;
+	} else {
+		slave->priv_flags &= ~(IFF_EIPOIB_VIF);
+		slave->flags &= ~(IFF_SLAVE);
+	}
+
+	return 0;
+}
+
+static inline int is_driver_owner(struct net_device *dev, char *name)
+{
+	struct ethtool_drvinfo drvinfo;
+
+	if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
+		if (!strstr(drvinfo.driver, name))
+			return 0;
+	} else
+		return 0;
+
+	return 1;
+}
+
+static inline int is_parent(struct net_device *dev)
+{
+	return (dev->priv_flags & IFF_EIPOIB_PIF) &&
+		is_driver_owner(dev, DRV_NAME);
+}
+
+static inline int is_parent_mac(struct net_device *dev, u8 *mac)
+{
+	return is_parent(dev) && !memcmp(mac, dev->dev_addr, dev->addr_len);
+}
+
+static inline int __is_slave(struct net_device *dev)
+{
+	return dev->master && is_parent(dev->master);
+}
+
+static inline int is_slave(struct net_device *dev)
+{
+	return (dev->priv_flags & IFF_EIPOIB_VIF) &&
+		is_driver_owner(dev, SDRV_NAME) && __is_slave(dev);
+}
+
+/*
+ * ------------------------------- Link status ------------------
+ * set parent carrier:
+ * link is up if at least one slave has link up
+ * otherwise, bring link down
+ * return 1 if parent carrier changed, zero otherwise
+ */
+static int parent_set_carrier(struct parent *parent)
+{
+	struct slave *slave;
+
+	if (parent->slave_cnt == 0)
+		goto down;
+
+	/* bring parent link up if one slave (at least) is up */
+	parent_for_each_slave(parent, slave) {
+		if (netif_carrier_ok(slave->dev)) {
+			if (!netif_carrier_ok(parent->dev)) {
+				netif_carrier_on(parent->dev);
+				return 1;
+			}
+			return 0;
+		}
+	}
+
+down:
+	if (netif_carrier_ok(parent->dev)) {
+		pr_info("bring down carrier\n");
+		netif_carrier_off(parent->dev);
+		return 1;
+	}
+	return 0;
+}
+
+static int parent_set_mtu(struct parent *parent)
+{
+	struct slave *slave, *f_slave;
+	unsigned int mtu;
+
+	if (parent->slave_cnt == 0)
+		return 0;
+
+	/* find min mtu */
+	f_slave = list_first_entry(&parent->slave_list, struct slave, list);
+	mtu = f_slave->dev->mtu;
+
+	parent_for_each_slave(parent, slave)
+		mtu = min(slave->dev->mtu, mtu);
+
+	if (parent->dev->mtu != mtu) {
+		dev_set_mtu(parent->dev, mtu);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ *--------------------------- slave list handling ------
+ *
+ * This function attaches the slave to the end of list.
+ * pay attention, the caller should held paren->lock
+ */
+static void parent_attach_slave(struct parent *parent,
+				struct slave *new_slave)
+{
+	list_add_tail(&new_slave->list, &parent->slave_list);
+	parent->slave_cnt++;
+}
+
+static void parent_detach_slave(struct parent *parent, struct slave *slave)
+{
+	list_del(&slave->list);
+	parent->slave_cnt--;
+}
+
+static netdev_features_t parent_fix_features(struct net_device *dev,
+					     netdev_features_t features)
+{
+	struct slave *slave;
+	struct parent *parent = netdev_priv(dev);
+	netdev_features_t mask;
+
+	read_lock_bh(&parent->lock);
+
+	mask = features;
+	features &= ~NETIF_F_ONE_FOR_ALL;
+	features |= NETIF_F_ALL_FOR_ALL;
+
+	parent_for_each_slave(parent, slave)
+		features = netdev_increment_features(features,
+						     slave->dev->features,
+						     mask);
+
+	features &= ~NETIF_F_VLAN_CHALLENGED;
+	read_unlock_bh(&parent->lock);
+	return features;
+}
+
+static int parent_compute_features(struct parent *parent)
+{
+	struct net_device *parent_dev = parent->dev;
+	u64 hw_features, features;
+	struct slave *slave;
+
+	if (list_empty(&parent->slave_list))
+		goto done;
+
+	/* starts with the max set of features mask */
+	hw_features = features = ~0LL;
+
+	/* gets the common features from all slaves */
+	parent_for_each_slave(parent, slave) {
+		features &= slave->dev->features;
+		hw_features &= slave->dev->hw_features;
+	}
+
+	features = features | PARENT_VLAN_FEATURES;
+	hw_features = hw_features | PARENT_VLAN_FEATURES;
+
+	hw_features &= ~NETIF_F_VLAN_CHALLENGED;
+	features &= hw_features;
+
+	parent_dev->hw_features = hw_features;
+	parent_dev->features = features;
+	parent_dev->vlan_features = parent_dev->features & ~PARENT_VLAN_FEATURES;
+done:
+	pr_info("%s: %s: Features: 0x%llx\n",
+		__func__, parent_dev->name, parent_dev->features);
+
+	return 0;
+}
+
+static inline u16 slave_get_pkey(struct net_device *dev)
+{
+	u16 pkey = (dev->broadcast[8] << 8) + dev->broadcast[9];
+
+	return pkey;
+}
+
+static void parent_setup_by_slave(struct net_device *parent_dev,
+				  struct net_device *slave_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
+
+	parent_dev->mtu = slave_dev->mtu;
+	parent_dev->hard_header_len = slave_dev->hard_header_len;
+
+	slave_ops->ndo_neigh_setup(slave_dev, &parent->nparms);
+
+}
+
+/* enslave device <slave> to parent device <master> */
+int parent_enslave(struct net_device *parent_dev, struct net_device *slave_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+	struct slave *new_slave = NULL;
+	int old_features = parent_dev->features;
+	int res = 0;
+	/* slave must be claimed by ipoib */
+	if (!is_driver_owner(slave_dev, SDRV_NAME))
+		return -EOPNOTSUPP;
+
+	/* parent must be initialized by parent_open() before enslaving */
+	if (!(parent_dev->flags & IFF_UP)) {
+		pr_warn("%s parent is not up in "
+			"parent_enslave\n",
+			parent_dev->name);
+		return -EPERM;
+	}
+
+	/* already enslaved */
+	if ((slave_dev->flags & IFF_SLAVE) ||
+		(slave_dev->priv_flags & IFF_EIPOIB_VIF)) {
+		pr_err("%s was already enslaved!!!\n", slave_dev->name);
+		return -EBUSY;
+	}
+
+	/* mark it as ipoib clone vif */
+	slave_dev->priv_flags |= IFF_EIPOIB_VIF;
+
+	/* set parent netdev attributes */
+	if (parent->slave_cnt == 0)
+		parent_setup_by_slave(parent_dev, slave_dev);
+	else {
+		/* check netdev attr match */
+		if (slave_dev->hard_header_len != parent_dev->hard_header_len) {
+			pr_err("%s slave %s has different HDR len %d != %d\n",
+			       parent_dev->name, slave_dev->name,
+			       slave_dev->hard_header_len,
+			       parent_dev->hard_header_len);
+			res = -EINVAL;
+			goto err_undo_flags;
+		}
+
+		if (slave_dev->type != ARPHRD_INFINIBAND ||
+		    slave_dev->addr_len != INFINIBAND_ALEN) {
+			pr_err("%s slave type/addr_len is invalid (%d/%d)\n",
+			       parent_dev->name, slave_dev->type,
+			       slave_dev->addr_len);
+			res = -EINVAL;
+			goto err_undo_flags;
+		}
+	}
+	/*
+	 * verfiy that this (slave) device belongs to the relevant PIF
+	 * abort if the name of the slave is not as the regular way in ipoib
+	 */
+	if (!strstr(slave_dev->name, parent->ipoib_main_interface)) {
+		pr_err("%s slave name (%s) doesn't contain parent name (%s) ",
+		       parent_dev->name, slave_dev->name,
+		       parent->ipoib_main_interface);
+		res = -EINVAL;
+		goto err_undo_flags;
+	}
+
+	new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
+	if (!new_slave) {
+		res = -ENOMEM;
+		goto err_undo_flags;
+	}
+
+	INIT_LIST_HEAD(&new_slave->neigh_list);
+
+	/* save slave's vlan */
+	new_slave->pkey = slave_get_pkey(slave_dev);
+
+	res = netdev_set_parent_master(slave_dev, parent_dev);
+	if (res) {
+		pr_err("%s %d calling netdev_set_master\n",
+		       slave_dev->name, res);
+		goto err_free;
+	}
+
+	res = dev_open(slave_dev);
+	if (res) {
+		pr_info("open failed %s\n",
+			slave_dev->name);
+		goto err_unset_master;
+	}
+
+	new_slave->dev = slave_dev;
+
+	write_lock_bh(&parent->lock);
+
+	parent_attach_slave(parent, new_slave);
+
+	parent_compute_features(parent);
+
+	write_unlock_bh(&parent->lock);
+
+	read_lock_bh(&parent->lock);
+
+	parent_set_carrier(parent);
+
+	read_unlock_bh(&parent->lock);
+
+	res = create_slave_symlinks(parent_dev, slave_dev);
+	if (res)
+		goto err_close;
+
+	/* register handler */
+	res = netdev_rx_handler_register(slave_dev, eipoib_handle_frame,
+					 new_slave);
+	if (res) {
+		pr_warn("%s %d calling netdev_rx_handler_register\n",
+			parent_dev->name, res);
+		goto err_close;
+	}
+
+	pr_info("%s: enslaving %s\n", parent_dev->name, slave_dev->name);
+
+	/* enslave is successful */
+	return 0;
+
+/* Undo stages on error */
+err_close:
+	dev_close(slave_dev);
+
+err_unset_master:
+	netdev_set_parent_master(slave_dev, NULL);
+
+err_free:
+	kfree(new_slave);
+
+err_undo_flags:
+	parent_dev->features = old_features;
+
+	return res;
+}
+
+static void slave_free(struct parent *parent, struct slave *slave)
+{
+	struct neigh *neigh, *neigh_tmp;
+
+	list_for_each_entry_safe(neigh, neigh_tmp, &slave->neigh_list, list) {
+		list_del(&neigh->list);
+		kfree(neigh);
+	}
+
+	netdev_rx_handler_unregister(slave->dev);
+
+	kfree(slave);
+}
+
+int parent_release_slave(struct net_device *parent_dev,
+			 struct net_device *slave_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+	struct slave *slave;
+	struct guest_emac_info *emac_info;
+
+	/* slave is not a slave or master is not master of this slave */
+	if (!(slave_dev->flags & IFF_SLAVE) ||
+	    (slave_dev->master != parent_dev)) {
+		pr_err("%s cannot release %s.\n",
+		       parent_dev->name, slave_dev->name);
+		return -EINVAL;
+	}
+
+	write_lock_bh(&parent->lock);
+
+	slave = get_slave_by_dev(parent, slave_dev);
+	if (!slave) {
+		/* not a slave of this parent */
+		pr_warn("%s not enslaved %s\n",
+			parent_dev->name, slave_dev->name);
+		write_unlock_bh(&parent->lock);
+		return -EINVAL;
+	}
+
+	pr_info("%s: releasing interface %s\n", parent_dev->name,
+		slave_dev->name);
+
+	/* for live migration, mark its mac_ip record as invalid */
+	emac_info = get_mac_ip_info_by_mac_and_vlan(parent, slave->emac, slave->vlan);
+	if (!emac_info)
+		pr_warn("%s %s didn't find emac: %pM\n",
+			parent_dev->name, slave_dev->name, slave->emac);
+	else {
+		emac_info->rec_state = MIGRATED_OUT;
+		/* start GC work */
+		pr_info("%s: sending clean task for slave mac: %pM\n",
+			__func__, slave->emac);
+		queue_delayed_work(parent->wq, &parent->migrate_out_work, 0);
+		queue_delayed_work(parent->wq, &parent->emac_ip_work,
+				   EMAC_IP_GC_TIME);
+	}
+
+	/* release the slave from its parent */
+	parent_detach_slave(parent, slave);
+
+	parent_compute_features(parent);
+
+	if (parent->slave_cnt == 0)
+		parent_set_carrier(parent);
+
+	write_unlock_bh(&parent->lock);
+
+	/* must do this from outside any spinlocks */
+	destroy_slave_symlinks(parent_dev, slave_dev);
+
+	netdev_set_parent_master(slave_dev, NULL);
+
+	dev_close(slave_dev);
+
+	slave_free(parent, slave);
+
+	return 0;  /* deletion OK */
+}
+
+static int parent_release_all(struct net_device *parent_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+	struct slave *slave, *slave_tmp;
+	struct net_device *slave_dev;
+	struct neigh *neigh_cmd, *neigh_cmd_tmp;
+	struct guest_emac_info *emac_info, *emac_info_tmp;
+	struct slave;
+
+	write_lock_bh(&parent->lock);
+
+	netif_carrier_off(parent_dev);
+
+	if (parent->slave_cnt == 0)
+		goto out;
+
+	list_for_each_entry_safe(slave, slave_tmp, &parent->slave_list, list) {
+		slave_dev = slave->dev;
+
+		/* remove slave from parent's slave-list */
+		parent_detach_slave(parent, slave);
+
+		parent_compute_features(parent);
+
+		write_unlock_bh(&parent->lock);
+
+		destroy_slave_symlinks(parent_dev, slave_dev);
+
+		netdev_set_parent_master(slave_dev, NULL);
+
+		dev_close(slave_dev);
+
+		slave_free(parent, slave);
+
+		write_lock_bh(&parent->lock);
+	}
+
+	list_for_each_entry_safe(neigh_cmd, neigh_cmd_tmp,
+				 &parent->neigh_add_list, list) {
+		list_del(&neigh_cmd->list);
+			kfree(neigh_cmd);
+		}
+
+	list_for_each_entry_safe(emac_info, emac_info_tmp,
+				 &parent->emac_ip_list, list) {
+		free_ip_mem_in_rec(emac_info);
+		list_del(&emac_info->list);
+		kfree(emac_info);
+	}
+
+	pr_info("%s: released all slaves\n", parent_dev->name);
+
+out:
+	write_unlock_bh(&parent->lock);
+
+	return 0;
+}
+
+/* -------------------------- Device entry points --------------------------- */
+static struct rtnl_link_stats64 *parent_get_stats(struct net_device *parent_dev,
+						  struct rtnl_link_stats64 *stats)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+	struct slave *slave;
+	struct rtnl_link_stats64 temp;
+
+	memset(stats, 0, sizeof(*stats));
+
+	read_lock_bh(&parent->lock);
+
+	parent_for_each_slave(parent, slave) {
+		const struct rtnl_link_stats64 *sstats =
+			dev_get_stats(slave->dev, &temp);
+
+		stats->rx_packets += sstats->rx_packets;
+		stats->rx_bytes += sstats->rx_bytes;
+		stats->rx_errors += sstats->rx_errors;
+		stats->rx_dropped += sstats->rx_dropped;
+
+		stats->tx_packets += sstats->tx_packets;
+		stats->tx_bytes += sstats->tx_bytes;
+		stats->tx_errors += sstats->tx_errors;
+		stats->tx_dropped += sstats->tx_dropped;
+
+		stats->multicast += sstats->multicast;
+		stats->collisions += sstats->collisions;
+
+		stats->rx_length_errors += sstats->rx_length_errors;
+		stats->rx_over_errors += sstats->rx_over_errors;
+		stats->rx_crc_errors += sstats->rx_crc_errors;
+		stats->rx_frame_errors += sstats->rx_frame_errors;
+		stats->rx_fifo_errors += sstats->rx_fifo_errors;
+		stats->rx_missed_errors += sstats->rx_missed_errors;
+
+		stats->tx_aborted_errors += sstats->tx_aborted_errors;
+		stats->tx_carrier_errors += sstats->tx_carrier_errors;
+		stats->tx_fifo_errors += sstats->tx_fifo_errors;
+		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+		stats->tx_window_errors += sstats->tx_window_errors;
+	}
+
+	read_unlock_bh(&parent->lock);
+
+	return stats;
+}
+
+/* ---------------------------- Main funcs ---------------------------------- */
+static struct neigh *neigh_cmd_find_by_mac(struct slave *slave, u8 *mac)
+{
+	struct net_device *dev = slave->dev;
+	struct net_device *parent_dev = dev->master;
+	struct parent *parent = netdev_priv(parent_dev);
+	struct neigh *neigh;
+	int found = 0;
+
+	list_for_each_entry(neigh, &parent->neigh_add_list, list) {
+		if (!memcmp(neigh->emac, mac, ETH_ALEN)) {
+			found = 1;
+			break;
+		}
+	}
+
+	return found ? neigh : NULL;
+}
+
+static struct neigh *neigh_find_by_mac(struct slave *slave, u8 *mac)
+{
+	struct neigh *neigh;
+	int found = 0;
+
+	list_for_each_entry(neigh, &slave->neigh_list, list) {
+		if (!memcmp(neigh->emac, mac, ETH_ALEN)) {
+			found = 1;
+			break;
+		}
+	}
+
+	return found ? neigh : NULL;
+}
+
+static int neigh_learn(struct slave *slave, struct sk_buff *skb, u8 *remac)
+{
+	struct net_device *dev = slave->dev;
+	struct net_device *parent_dev = dev->master;
+	struct parent *parent = netdev_priv(parent_dev);
+	struct neigh *neigh_cmd;
+	u8 *rimac;
+	int rc;
+
+	/* linearize to easy on reading the arp payload */
+	rc = skb_linearize(skb);
+	if (rc) {
+		pr_err("%s: skb_linearize failed rc %d\n", dev->name, rc);
+		goto out;
+	} else
+		rimac = skb->data + sizeof(struct arphdr);
+
+	/* check if entry is being processed or already exists */
+	if (neigh_find_by_mac(slave, remac))
+		goto out;
+
+	if (neigh_cmd_find_by_mac(slave, remac))
+		goto out;
+
+	neigh_cmd = parent_get_neigh_cmd('+', slave->dev->name, remac, rimac);
+	if (!neigh_cmd) {
+		pr_err("%s cannot build neigh cmd\n", slave->dev->name);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	list_add_tail(&neigh_cmd->list, &parent->neigh_add_list);
+
+	/* calls neigh_learn_task() */
+	queue_delayed_work(parent->wq, &parent->neigh_learn_work, 0);
+
+out:
+	return rc;
+}
+
+static void neigh_learn_task(struct work_struct *work)
+{
+	struct parent *parent = container_of(work, struct parent,
+					     neigh_learn_work.work);
+	struct neigh *neigh_cmd, *neigh_cmd_tmp;
+
+	write_lock_bh(&parent->lock);
+
+	if (parent->kill_timers)
+		goto out;
+
+	list_for_each_entry_safe(neigh_cmd, neigh_cmd_tmp,
+				 &parent->neigh_add_list, list) {
+		__parent_store_neighs(&parent->dev->dev, NULL,
+				      neigh_cmd->cmd, PAGE_SIZE);
+		list_del(&neigh_cmd->list);
+		kfree(neigh_cmd);
+	}
+
+out:
+	write_unlock_bh(&parent->lock);
+	return;
+}
+
+static void parent_work_cancel_all(struct parent *parent)
+{
+	write_lock_bh(&parent->lock);
+	parent->kill_timers = 1;
+	write_unlock_bh(&parent->lock);
+
+	if (delayed_work_pending(&parent->neigh_learn_work))
+		cancel_delayed_work(&parent->neigh_learn_work);
+
+	if (delayed_work_pending(&parent->emac_ip_work))
+		cancel_delayed_work(&parent->emac_ip_work);
+
+	if (delayed_work_pending(&parent->migrate_out_work))
+		cancel_delayed_work(&parent->migrate_out_work);
+}
+
+static struct parent *get_parent_by_pif_name(char *pif_name)
+{
+	struct parent *parent, *nxt;
+
+	list_for_each_entry_safe(parent, nxt, &parent_dev_list, parent_list) {
+		if (!strcmp(parent->ipoib_main_interface, pif_name))
+			return parent;
+	}
+	return NULL;
+}
+
+static void free_ip_mem_in_rec(struct guest_emac_info *emac_info)
+{
+	struct ip_member *ipm, *tmp_ipm;
+	list_for_each_entry_safe(ipm, tmp_ipm, &emac_info->ip_list, list) {
+		list_del(&ipm->list);
+		kfree(ipm);
+	}
+}
+
+static inline void free_invalid_emac_ip_det(struct parent *parent)
+{
+	struct guest_emac_info *emac_info, *emac_info_tmp;
+
+	list_for_each_entry_safe(emac_info, emac_info_tmp,
+				 &parent->emac_ip_list, list) {
+		if (emac_info->rec_state == INVALID) {
+			free_ip_mem_in_rec(emac_info);
+			list_del(&emac_info->list);
+			kfree(emac_info);
+		}
+	}
+}
+
+static void emac_info_clean_task(struct work_struct *work)
+{
+	struct parent *parent = container_of(work, struct parent,
+					     emac_ip_work.work);
+
+	write_lock_bh(&parent->lock);
+
+	if (parent->kill_timers)
+		goto out;
+
+	free_invalid_emac_ip_det(parent);
+
+out:
+	write_unlock_bh(&parent->lock);
+	return;
+}
+
+static int migrate_out_gen_arp_req(struct parent *parent, u8 *emac,
+				   u16 vlan)
+{
+	struct guest_emac_info *emac_info;
+	struct ip_member *ipm;
+	struct slave *slave;
+	struct sk_buff *nskb;
+	int ret = 0;
+
+	slave = get_slave_by_mac_and_vlan(parent, parent->dev->dev_addr, vlan);
+	if (unlikely(!slave)) {
+		pr_info("%s: Failed to find parent slave !!! %pM\n",
+			__func__, parent->dev->dev_addr);
+		return -ENODEV;
+	}
+
+	emac_info = get_mac_ip_info_by_mac_and_vlan(parent, emac, vlan);
+
+	if (!emac_info)
+		return 0;
+
+	/* go over all ip's attached to that mac */
+	list_for_each_entry(ipm, &emac_info->ip_list, list) {
+		/* create and send arp request to that ip.*/
+		pr_info("%s: Sending arp For migrate_out event, to %pI4 "
+			"from 0.0.0.0\n", parent->dev->name, &(ipm->ip));
+
+		nskb = arp_create(ARPOP_REQUEST,
+				  ETH_P_ARP,
+				  ipm->ip,
+				  slave->dev,
+				  0,
+				  slave->dev->broadcast,
+				  slave->dev->broadcast,
+				  slave->dev->broadcast);
+		if (nskb)
+			arp_xmit(nskb);
+		else {
+			pr_err("%s: %s failed creating skb\n",
+			       __func__, slave->dev->name);
+			ret = -ENOMEM;
+		}
+	}
+	return ret;
+}
+
+static void migrate_out_work_task(struct work_struct *work)
+{
+	struct parent *parent = container_of(work, struct parent,
+					     migrate_out_work.work);
+	struct guest_emac_info *emac_info;
+	int is_reschedule = 0;
+	int ret;
+
+	write_lock_bh(&parent->lock);
+
+	if (parent->kill_timers)
+		goto out;
+
+	list_for_each_entry(emac_info, &parent->emac_ip_list, list) {
+		if (emac_info->rec_state == MIGRATED_OUT) {
+			if (emac_info->num_of_retries <
+			    MIG_OUT_MAX_ARP_RETRIES) {
+				ret = migrate_out_gen_arp_req(parent, emac_info->emac,
+							      emac_info->vlan);
+				if (ret)
+					pr_err("%s: migrate_out_gen_arp failed: %d\n",
+					       __func__, ret);
+
+				emac_info->num_of_retries =
+					emac_info->num_of_retries + 1;
+				is_reschedule = 1;
+			} else
+				emac_info->rec_state = INVALID;
+		}
+	}
+	/* issue arp request till the device removed that entry from list */
+	if (is_reschedule)
+		queue_delayed_work(parent->wq, &parent->migrate_out_work,
+				   MIG_OUT_ARP_REQ_ISSUE_TIME);
+out:
+	write_unlock_bh(&parent->lock);
+	return;
+}
+
+static inline int add_emac_ip_info(struct net_device *slave_dev, __be32 ip,
+				   u8 *mac, u16 vlan)
+{
+	struct net_device *parent_dev = slave_dev->master;
+	struct parent *parent = netdev_priv(parent_dev);
+	struct guest_emac_info *emac_info = NULL;
+	struct ip_member *ipm;
+	int ret;
+	int is_just_alloc_emac_info = 0;
+
+	ret = is_mac_info_contain_ip(parent, mac, ip, emac_info, vlan);
+	if (ret)
+		return 0;
+
+	/* new ip add it to the emc_ip obj */
+	if (!emac_info) {
+		emac_info = kzalloc(sizeof *emac_info, GFP_ATOMIC);
+		if (!emac_info) {
+			pr_err("%s: Failed allocating emac_info\n",
+			       parent_dev->name);
+			return -ENOMEM;
+		}
+		memcpy(emac_info->emac, mac, ETH_ALEN);
+		INIT_LIST_HEAD(&emac_info->ip_list);
+		emac_info->rec_state = VALID;
+		emac_info->vlan = vlan;
+		emac_info->num_of_retries = 0;
+		list_add_tail(&emac_info->list, &parent->emac_ip_list);
+		is_just_alloc_emac_info = 1;
+	}
+
+	ipm = kzalloc(sizeof *ipm, GFP_ATOMIC);
+	if (!ipm) {
+		pr_err(" %s Failed allocating emac_info (ipm)\n",
+		       parent_dev->name);
+		if (is_just_alloc_emac_info)
+			kfree(emac_info);
+		return -ENOMEM;
+	}
+
+	ipm->ip = ip;
+	list_add_tail(&ipm->list, &emac_info->ip_list);
+
+	return 0;
+}
+
+/* build ipoib arp/rarp request/reply packet */
+static struct sk_buff *get_slave_skb_arp(struct slave *slave,
+					 struct sk_buff *skb,
+					 u8 *rimac, int *ret)
+{
+	struct sk_buff *nskb;
+	struct arphdr *arphdr = (struct arphdr *)
+				(skb->data + sizeof(struct ethhdr));
+	struct eth_arp_data *arp_data = (struct eth_arp_data *)
+					(skb->data + sizeof(struct ethhdr) +
+					 sizeof(struct arphdr));
+	u8 t_addr[ETH_ALEN] = {0};
+	int err = 0;
+	/* mark regular packet handling */
+	*ret = 0;
+
+	/*
+	 * live-migration support: keeps the new mac/ip address:
+	 * In that way each driver knows which mac/vlan - IP's where on the
+	 * guests above, whenever migrate_out event comes it will send
+	 * arp request for all these IP's.
+	 */
+	if (skb->protocol == htons(ETH_P_ARP))
+		err = add_emac_ip_info(slave->dev, arp_data->arp_sip,
+				       arp_data->arp_sha, slave->vlan);
+	if (err)
+		pr_warn("%s: Failed creating: emac_ip_info for ip: %pI4",
+			__func__, &arp_data->arp_sip);
+	/*
+	 * live migration support:
+	 * 1.checck if we are in live migration process
+	 * 2.check if the arp response is for the parent
+	 * 3.ignore local-administrated bit, which was set to make sure
+	 *   that the bridge will not drop it.
+	 */
+	arp_data->arp_dha[0] = arp_data->arp_dha[0] & 0xFD;
+	if (htons(ARPOP_REPLY) == (arphdr->ar_op) &&
+	    !memcmp(arp_data->arp_dha, slave->dev->master->dev_addr, ETH_ALEN)) {
+		/*
+		 * when the source is the parent interface, assumes
+		 * that we are in the middle of live migration process,
+		 * so, we will send gratuitous arp.
+		 */
+		pr_info("%s: Arp packet for parent: %s",
+			__func__, slave->dev->master->name);
+		/* create gratuitous ARP on behalf of the guest */
+		nskb = arp_create(ARPOP_REQUEST,
+				  be16_to_cpu(skb->protocol),
+				  arp_data->arp_sip,
+				  slave->dev,
+				  arp_data->arp_sip,
+				  NULL,
+				  slave->dev->dev_addr,
+				  t_addr);
+		if (unlikely(!nskb))
+			pr_err("%s: %s live migration: failed creating skb\n",
+			       __func__, slave->dev->name);
+	} else {
+		nskb = arp_create(be16_to_cpu(arphdr->ar_op),
+				  be16_to_cpu(skb->protocol),
+				  arp_data->arp_dip,
+				  slave->dev,
+				  arp_data->arp_sip,
+				  rimac,
+				  slave->dev->dev_addr,
+				  NULL);
+	}
+
+	return nskb;
+}
+
+/*
+ * build ipoib arp request packet according to ip header.
+ * uses for live-migration, or missing neigh for new vif.
+ */
+static void get_slave_skb_arp_by_ip(struct slave *slave,
+				    struct sk_buff *skb)
+{
+	struct sk_buff *nskb = NULL;
+	struct iphdr *iph = ip_hdr(skb);
+
+	pr_info("Sending arp on behalf of slave %s, from %pI4"
+		" to %pI4" , slave->dev->name, &(iph->saddr),
+		&(iph->daddr));
+
+	nskb = arp_create(ARPOP_REQUEST,
+			  ETH_P_ARP,
+			  iph->daddr,
+			  slave->dev,
+			  iph->saddr,
+			  slave->dev->broadcast,
+			  slave->dev->dev_addr,
+			  NULL);
+	if (nskb)
+		arp_xmit(nskb);
+	else
+		pr_err("%s: %s failed creating skb\n",
+		       __func__, slave->dev->name);
+}
+
+/* build ipoib ipv4/ipv6 packet */
+static struct sk_buff *get_slave_skb_ip(struct slave *slave,
+					struct sk_buff *skb)
+{
+
+	skb_pull(skb, ETH_HLEN);
+	skb_reset_network_header(skb);
+
+	return skb;
+}
+
+/*
+ * get_slave_skb -- called in TX flow
+ * get skb that can be sent thru slave xmit func,
+ * if skb was adjusted (cloned, pulled, etc..) successfully
+ * the old skb (if any) is freed here.
+ */
+static struct sk_buff *get_slave_skb(struct slave *slave, struct sk_buff *skb)
+{
+	struct net_device *dev = slave->dev;
+	struct net_device *parent_dev = dev->master;
+	struct parent *parent = netdev_priv(parent_dev);
+	struct sk_buff *nskb = NULL;
+	struct ethhdr *ethh = (struct ethhdr *)(skb->data);
+	struct neigh *neigh = NULL;
+	u8 rimac[INFINIBAND_ALEN];
+	int ret = 0;
+
+	/* set neigh mac */
+	if (is_multicast_ether_addr(ethh->h_dest)) {
+		memcpy(rimac, dev->broadcast, INFINIBAND_ALEN);
+	} else {
+		neigh = neigh_find_by_mac(slave, ethh->h_dest);
+		if (neigh) {
+			memcpy(rimac, neigh->imac, INFINIBAND_ALEN);
+		} else {
+			++parent->port_stats.tx_neigh_miss;
+			/*
+			 * assume VIF migration, tries to get the neigh by
+			 * issue arp request on behalf of the vif.
+			 */
+			if (skb->protocol == htons(ETH_P_IP)) {
+				pr_info("Missed neigh for slave: %s,"
+					"issue ARP request\n",
+					slave->dev->name);
+				get_slave_skb_arp_by_ip(slave, skb);
+				goto out_arp_sent_instead;
+			}
+		}
+	}
+
+	if (skb->protocol == htons(ETH_P_ARP) ||
+	    skb->protocol == htons(ETH_P_RARP)) {
+		nskb = get_slave_skb_arp(slave, skb, rimac, &ret);
+		if (!nskb && LIVE_MIG_PACKET == ret) {
+			pr_info("%s: live migration packets\n", __func__);
+			goto err;
+		}
+	} else {
+		if (!neigh)
+			goto err;
+		/* pull ethernet header here */
+		nskb = get_slave_skb_ip(slave, skb);
+	}
+
+	/* if new skb could not be adjusted/allocated, abort */
+	if (!nskb) {
+		pr_err("%s get_slave_skb_ip/arp failed 0x%x\n",
+		       dev->name, skb->protocol);
+		goto err;
+	}
+
+	if (neigh && nskb == skb) { /* ucast & non-arp/rarp */
+		/* dev_hard_header only for ucast, for arp done already.*/
+		if (dev_hard_header(nskb, dev, ntohs(skb->protocol), rimac,
+				    dev->dev_addr, nskb->len) < 0) {
+			pr_warn("%s: dev_hard_header failed\n",
+				dev->name);
+			goto err;
+		}
+	}
+
+	/*
+	 * new skb is ready to be sent, clean old skb if we hold a clone
+	 * (old skb is not shared, already checked that.)
+	 */
+	if ((nskb != skb))
+		dev_kfree_skb(skb);
+
+	nskb->dev = slave->dev;
+	return nskb;
+
+out_arp_sent_instead:/* whenever sent arp instead of ip packet */
+err:
+	/* got error after nskb was adjusted/allocated */
+	if (nskb && (nskb != skb))
+		dev_kfree_skb(nskb);
+
+	return NULL;
+}
+
+static struct sk_buff *get_parent_skb_arp(struct slave *slave,
+					  struct sk_buff *skb,
+					  u8 *remac)
+{
+	struct net_device *dev = slave->dev->master;
+	struct sk_buff *nskb;
+	struct arphdr *arphdr = (struct arphdr *)(skb->data);
+	struct ipoib_arp_data *arp_data = (struct ipoib_arp_data *)
+					(skb->data + sizeof(struct arphdr));
+	u8 *target_hw = slave->emac;
+	u8 *dst_hw = slave->emac;
+	u8 local_eth_addr[ETH_ALEN];
+
+	/* live migration: gets arp with broadcast src and dst */
+	if (!memcmp(arp_data->arp_sha, slave->dev->broadcast, INFINIBAND_ALEN) &&
+	    !memcmp(arp_data->arp_dha, slave->dev->broadcast, INFINIBAND_ALEN)) {
+		pr_info("%s: ARP with bcast src and dest send from src_hw: %pM\n",
+			__func__, slave->dev->master->dev_addr);
+		/* replace the src with the parent src: */
+		memcpy(local_eth_addr, slave->dev->master->dev_addr, ETH_ALEN);
+		/*
+		 * set local administrated bit,
+		 * that way the bridge will not throws it
+		 */
+		local_eth_addr[0] = local_eth_addr[0] | 0x2;
+		memcpy(remac, local_eth_addr, ETH_ALEN);
+		target_hw = NULL;
+		dst_hw = NULL;
+	}
+
+	nskb = arp_create(be16_to_cpu(arphdr->ar_op),
+			  be16_to_cpu(skb->protocol),
+			  arp_data->arp_dip,
+			  dev,
+			  arp_data->arp_sip,
+			  dst_hw,
+			  remac,
+			  target_hw);
+
+	/* prepare place for the headers. */
+	if (nskb)
+		skb_reserve(nskb, ETH_HLEN);
+
+	return nskb;
+}
+
+static struct sk_buff *get_parent_skb_ip(struct slave *slave,
+					 struct sk_buff *skb)
+{
+	/* nop */
+	return skb;
+}
+
+/* get_parent_skb -- called in RX flow */
+static struct sk_buff *get_parent_skb(struct slave *slave,
+				      struct sk_buff *skb, u8 *remac)
+{
+	struct net_device *dev = slave->dev->master;
+	struct sk_buff *nskb = NULL;
+	struct ethhdr *ethh;
+
+	if (skb->protocol == htons(ETH_P_ARP) ||
+	    skb->protocol == htons(ETH_P_RARP))
+		nskb = get_parent_skb_arp(slave, skb, remac);
+	else
+		nskb = get_parent_skb_ip(slave, skb);
+
+	/* if new skb could not be adjusted/allocated, abort */
+	if (!nskb)
+		goto err;
+
+	/* at this point, we can free old skb if it was cloned */
+	if (nskb && (nskb != skb))
+		dev_kfree_skb(skb);
+
+	skb = nskb;
+
+	/* build ethernet header */
+	ethh = (struct ethhdr *)skb_push(skb, ETH_HLEN);
+	ethh->h_proto = skb->protocol;
+	memcpy(ethh->h_source, remac, ETH_ALEN);
+	memcpy(ethh->h_dest, slave->emac, ETH_ALEN);
+
+	/* zero padding whenever is needed (arp for example).to ETH_ZLEN size */
+	if (unlikely((skb->len < ETH_ZLEN))) {
+		if ((skb->tail + (ETH_ZLEN - skb->len) > skb->end) ||
+		    skb_is_nonlinear(skb))
+			/* nothing */;
+		else
+			memset(skb_put(skb, ETH_ZLEN - skb->len), 0,
+			       ETH_ZLEN - skb->len);
+	}
+
+	/* set new skb fields */
+	skb->pkt_type = PACKET_HOST;
+	/*
+	 * use master dev, to allow netpoll_receive_skb()
+	 * in netif_receive_skb()
+	 */
+	skb->dev = dev;
+
+	/* pull the Ethernet header and update other fields */
+	skb->protocol = eth_type_trans(skb, skb->dev);
+
+	return skb;
+
+err:
+	/* got error after nskb was adjusted/allocated */
+	if (nskb && (nskb != skb))
+		dev_kfree_skb(nskb);
+
+	return NULL;
+}
+
+static int parent_rx(struct sk_buff *skb, struct slave *slave)
+{
+	struct net_device *slave_dev = skb->dev;
+	struct net_device *parent_dev = slave_dev->master;
+	struct parent *parent = netdev_priv(parent_dev);
+	struct eipoib_cb_data *data = IPOIB_HANDLER_CB(skb);
+	struct napi_struct *napi =  data->rx.napi;
+	struct sk_buff *nskb;
+	int rc = 0;
+	u8 remac[ETH_ALEN];
+	int vlan_tag;
+
+	build_neigh_mac(remac, data->rx.sqpn, data->rx.slid);
+
+	read_lock_bh(&parent->lock);
+
+	if (unlikely(skb_headroom(skb) < ETH_HLEN)) {
+		pr_warn("%s: small headroom %d < %d\n",
+			skb->dev->name, skb_headroom(skb), ETH_HLEN);
+		++parent->port_stats.rx_skb_errors;
+		goto drop;
+	}
+
+	/* learn neighs based on ARP snooping */
+	if (unlikely(ntohs(skb->protocol) == ETH_P_ARP)) {
+		read_unlock_bh(&parent->lock);
+		write_lock_bh(&parent->lock);
+		neigh_learn(slave, skb, remac);
+		write_unlock_bh(&parent->lock);
+		read_lock_bh(&parent->lock);
+	}
+
+	nskb = get_parent_skb(slave, skb, remac);
+	if (unlikely(!nskb)) {
+		++parent->port_stats.rx_skb_errors;
+		pr_warn("%s: failed to create parent_skb\n",
+			skb->dev->name);
+		goto drop;
+	} else
+		skb = nskb;
+
+	vlan_tag = slave->vlan & 0xfff;
+	if (vlan_tag) {
+		skb = __vlan_hwaccel_put_tag(skb, vlan_tag);
+		if (!skb) {
+			pr_err("%s failed to insert VLAN tag\n",
+			       skb->dev->name);
+			goto drop;
+		}
+		++parent->port_stats.rx_vlan;
+	}
+
+	if (napi)
+		rc = napi_gro_receive(napi, skb);
+	else
+		rc = netif_receive_skb(skb);
+
+	read_unlock_bh(&parent->lock);
+
+	return rc;
+
+drop:
+	dev_kfree_skb_any(skb);
+	read_unlock_bh(&parent->lock);
+
+	return NET_RX_DROP;
+}
+
+static rx_handler_result_t eipoib_handle_frame(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct slave *slave;
+
+	slave = eipoib_slave_get_rcu(skb->dev);
+
+	parent_rx(skb, slave);
+
+	return RX_HANDLER_CONSUMED;
+}
+
+static netdev_tx_t parent_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct parent *parent = netdev_priv(dev);
+	struct slave *slave = NULL;
+	struct ethhdr *ethh = (struct ethhdr *)(skb->data);
+	struct sk_buff *nskb;
+	int rc;
+	u16 vlan;
+	u8 mac_no_admin_bit[ETH_ALEN];
+
+	read_lock_bh(&parent->lock);
+
+	if (unlikely(!IS_E_IPOIB_PROTO(ethh->h_proto))) {
+		++parent->port_stats.tx_proto_errors;
+		goto drop;
+	}
+	/* assume: only orphan skb's */
+	if (unlikely(skb_shared(skb))) {
+		++parent->port_stats.tx_shared;
+		goto drop;
+	}
+
+	/* obtain VLAN information if present */
+	if (vlan_tx_tag_present(skb)) {
+		vlan = vlan_tx_tag_get(skb) & 0xfff;
+		++parent->port_stats.tx_vlan;
+	} else {
+		vlan = VLAN_N_VID;
+	}
+
+	/*
+	 * for live migration: mask the admin bit if exists.
+	 * only in ARP packets that came from parent's VIF interface.
+	 */
+	if (unlikely((htons(ETH_P_ARP) == ethh->h_proto) &&
+	    !memcmp(parent->dev->dev_addr + 1, ethh->h_source + 1, ETH_ALEN - 1))) {
+		/* parent's VIF: */
+		memcpy(mac_no_admin_bit, ethh->h_source, ETH_ALEN);
+		mac_no_admin_bit[0] = mac_no_admin_bit[0] & 0xFD;
+		/* get slave, and queue packet */
+		slave = get_slave_by_mac_and_vlan(parent, mac_no_admin_bit, vlan);
+	}
+	/* get slave, and queue packet */
+	if (!slave)
+		slave = get_slave_by_mac_and_vlan(parent, ethh->h_source, vlan);
+	if (unlikely(!slave)) {
+		pr_info("vif: %pM with vlan: %d miss for parent: %s\n",
+			ethh->h_source, vlan, parent->ipoib_main_interface);
+		++parent->port_stats.tx_vif_miss;
+		goto drop;
+	}
+
+	nskb = get_slave_skb(slave, skb);
+	if (unlikely(!nskb)) {
+		++parent->port_stats.tx_skb_errors;
+		goto drop;
+	} else
+		skb = nskb;
+
+	/*
+	 * VST mode: removes the vlan tag in the tx (will add it in the rx)
+	 * the slave is from IPoIB and it is NETIF_F_VLAN_CHALLENGED,
+	 * so must remove the vlan tag.
+	 */
+	if (vlan != VLAN_N_VID)
+		skb->vlan_tci = 0;
+
+	/* arp packets: */
+	if (skb->protocol == htons(ETH_P_ARP) ||
+	    skb->protocol == htons(ETH_P_RARP)) {
+		arp_xmit(skb);
+		goto out;
+	}
+
+	/* ip packets */
+	skb_record_rx_queue(skb, skb_get_queue_mapping(skb));
+
+	rc = dev_queue_xmit(skb);
+	if (unlikely(rc)) {
+		pr_err("slave tx method failed %d\n", rc);
+		++parent->port_stats.tx_slave_err;
+		dev_kfree_skb(skb);
+	}
+
+	goto out;
+
+drop:
+	++parent->port_stats.tx_parent_dropped;
+	dev_kfree_skb(skb);
+
+out:
+	read_unlock_bh(&parent->lock);
+	return NETDEV_TX_OK;
+}
+
+static int parent_open(struct net_device *parent_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+
+	parent->kill_timers = 0;
+	INIT_DELAYED_WORK(&parent->neigh_learn_work, neigh_learn_task);
+	INIT_DELAYED_WORK(&parent->emac_ip_work, emac_info_clean_task);
+	INIT_DELAYED_WORK(&parent->migrate_out_work, migrate_out_work_task);
+	return 0;
+}
+
+static int parent_close(struct net_device *parent_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+
+	write_lock_bh(&parent->lock);
+	parent->kill_timers = 1;
+	write_unlock_bh(&parent->lock);
+
+	cancel_delayed_work(&parent->neigh_learn_work);
+	cancel_delayed_work(&parent->emac_ip_work);
+	cancel_delayed_work(&parent->migrate_out_work);
+
+	return 0;
+}
+
+
+static void parent_deinit(struct net_device *parent_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+
+	list_del(&parent->parent_list);
+
+	parent_work_cancel_all(parent);
+}
+
+static void parent_uninit(struct net_device *parent_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+
+	parent_deinit(parent_dev);
+	parent_destroy_sysfs_entry(parent);
+
+	if (parent->wq)
+		destroy_workqueue(parent->wq);
+}
+
+static struct lock_class_key parent_netdev_xmit_lock_key;
+static struct lock_class_key parent_netdev_addr_lock_key;
+
+static void parent_set_lockdep_class_one(struct net_device *dev,
+					 struct netdev_queue *txq,
+					 void *_unused)
+{
+	lockdep_set_class(&txq->_xmit_lock,
+			  &parent_netdev_xmit_lock_key);
+}
+
+static void parent_set_lockdep_class(struct net_device *dev)
+{
+	lockdep_set_class(&dev->addr_list_lock,
+			  &parent_netdev_addr_lock_key);
+	netdev_for_each_tx_queue(dev, parent_set_lockdep_class_one, NULL);
+}
+
+static int parent_init(struct net_device *parent_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+
+	parent->wq = create_singlethread_workqueue(parent_dev->name);
+	if (!parent->wq)
+		return -ENOMEM;
+
+	parent_set_lockdep_class(parent_dev);
+
+	list_add_tail(&parent->parent_list, &parent_dev_list);
+
+	return 0;
+}
+
+static u16 parent_select_q(struct net_device *dev, struct sk_buff *skb)
+{
+	return skb_tx_hash(dev, skb);
+}
+
+static int parent_add_vif_param(struct net_device *parent_dev,
+				struct net_device *new_vif_dev,
+				u16 vlan, u8 *mac)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+	struct slave *new_slave, *slave_tmp;
+	int ret = 0;
+
+	if (!is_valid_ether_addr(mac)) {
+		pr_err("Invalid mac input for slave:%pM \n", mac);
+		return -EINVAL;
+	}
+
+	write_lock_bh(&parent->lock);
+
+	new_slave = get_slave_by_dev(parent, new_vif_dev);
+	if (!new_slave) {
+		pr_err("%s: ERROR no slave:%s.!!!! \n",
+		       __func__, new_vif_dev->name);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (!is_zero_ether_addr(new_slave->emac)) {
+		pr_err("slave %s mac already set to %pM\n",
+		       new_slave->dev->name, new_slave->emac);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* check another slave has this mac/vlan */
+	parent_for_each_slave(parent, slave_tmp) {
+		if (!memcmp(slave_tmp->emac, mac, ETH_ALEN) &&
+		    slave_tmp->vlan == new_slave->vlan) {
+			pr_err("cannot update %s, slave %s already has"
+			       " vlan 0x%x mac %pM\n",
+			       parent->dev->name, new_slave->dev->name,
+			       slave_tmp->vlan,
+			       mac);
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	/* ready to go */
+	pr_info("slave %s mac is set to %pM, vlan set to: %d\n",
+		new_slave->dev->name, mac, vlan);
+
+	memcpy(new_slave->emac, mac, ETH_ALEN);
+
+	new_slave->vlan = vlan;
+
+out:
+	write_unlock_bh(&parent->lock);
+
+	return ret;
+}
+
+static const struct net_device_ops parent_netdev_ops = {
+	.ndo_init		= parent_init,
+	.ndo_uninit		= parent_uninit,
+	.ndo_open		= parent_open,
+	.ndo_stop		= parent_close,
+	.ndo_start_xmit		= parent_tx,
+	.ndo_select_queue	= parent_select_q,
+	/* parnt mtu is min(slaves_mtus) */
+	.ndo_change_mtu		= NULL,
+	.ndo_fix_features	= parent_fix_features,
+	/*
+	 * initial mac address is randomized, can be changed
+	 * thru this func later
+	 */
+	.ndo_set_mac_address = eth_mac_addr,
+	.ndo_get_stats64 = parent_get_stats,
+	.ndo_add_slave = parent_enslave,
+	.ndo_del_slave = parent_release_slave,
+	.ndo_set_vif_param = parent_add_vif_param,
+};
+
+static void parent_setup(struct net_device *parent_dev)
+{
+	struct parent *parent = netdev_priv(parent_dev);
+
+	/* initialize rwlocks */
+	rwlock_init(&parent->lock);
+
+	/* Initialize pointers */
+	parent->dev = parent_dev;
+	INIT_LIST_HEAD(&parent->neigh_add_list);
+	INIT_LIST_HEAD(&parent->slave_list);
+	INIT_LIST_HEAD(&parent->emac_ip_list);
+	/* Initialize the device entry points */
+	ether_setup(parent_dev);
+	/* parent_dev->hard_header_len is adjusted later */
+	parent_dev->netdev_ops = &parent_netdev_ops;
+	parent_set_ethtool_ops(parent_dev);
+
+	/* Initialize the device options */
+	parent_dev->tx_queue_len = 0;
+	/* mark the parent intf as pif (master of other vifs.) */
+	parent_dev->priv_flags = IFF_EIPOIB_PIF;
+
+	parent_dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
+		NETIF_F_RXCSUM | NETIF_F_GRO | NETIF_F_TSO;
+
+	parent_dev->features = parent_dev->hw_features;
+	parent_dev->vlan_features = parent_dev->hw_features;
+
+	parent_dev->features |= PARENT_VLAN_FEATURES;
+}
+
+/*
+ * Create a new parent based on the specified name and parent parameters.
+ * Caller must NOT hold rtnl_lock; we need to release it here before we
+ * set up our sysfs entries.
+ */
+static struct parent *parent_create(struct net_device *ibd)
+{
+	struct net_device *parent_dev;
+	u32 num_queues;
+	int rc;
+	union ib_gid gid;
+	struct parent *parent = NULL;
+	int i, j;
+
+	memcpy(&gid, ibd->dev_addr + 4, sizeof(union ib_gid));
+	num_queues = num_online_cpus();
+	num_queues = roundup_pow_of_two(num_queues);
+
+	parent_dev = alloc_netdev_mq(sizeof(struct parent), "",
+				     parent_setup, num_queues);
+	if (!parent_dev) {
+		pr_err("%s failed to alloc netdev!\n", ibd->name);
+		rc = -ENOMEM;
+		goto out_rtnl;
+	}
+
+	rc = dev_alloc_name(parent_dev, "eth%d");
+	if (rc < 0)
+		goto out_netdev;
+
+	/* eIPoIB interface mac format. */
+	for (i = 0, j = 0; i < 8; i++) {
+		if ((PARENT_MAC_MASK >> i) & 0x1) {
+			if (j < 6) /* only 6 bytes eth address */
+				parent_dev->dev_addr[j] =
+					gid.raw[GUID_LEN + i];
+			j++;
+		}
+	}
+
+	/* assuming that the ibd->dev.parent was alreadey been set. */
+	SET_NETDEV_DEV(parent_dev, ibd->dev.parent);
+
+	rc = register_netdevice(parent_dev);
+	if (rc < 0)
+		goto out_parent;
+
+	dev_net_set(parent_dev, &init_net);
+
+	rc = parent_create_sysfs_entry(netdev_priv(parent_dev));
+	if (rc < 0)
+		goto out_unreg;
+
+	parent = netdev_priv(parent_dev);
+	memcpy(parent->gid.raw, gid.raw, GID_LEN);
+	strncpy(parent->ipoib_main_interface, ibd->name, IFNAMSIZ);
+	parent_dev->dev_id = ibd->dev_id;
+
+	return parent;
+
+out_unreg:
+	unregister_netdevice(parent_dev);
+out_parent:
+	parent_deinit(parent_dev);
+out_netdev:
+	free_netdev(parent_dev);
+out_rtnl:
+	return ERR_PTR(rc);
+}
+
+
+static void parent_free(struct parent *parent)
+{
+	struct net_device *parent_dev = parent->dev;
+
+	parent_work_cancel_all(parent);
+
+	parent_release_all(parent_dev);
+
+	unregister_netdevice(parent_dev);
+}
+
+static void parent_free_all(void)
+{
+	struct parent *parent, *nxt;
+
+	list_for_each_entry_safe(parent, nxt, &parent_dev_list, parent_list)
+		parent_free(parent);
+}
+
+/* netdev events handlers */
+static inline int is_ipoib_pif_intf(struct net_device *dev)
+{
+	if (ARPHRD_INFINIBAND == dev->type && dev->priv_flags & IFF_EIPOIB_PIF)
+		return 1;
+	return 0;
+}
+
+static int parent_event_changename(struct parent *parent)
+{
+	parent_destroy_sysfs_entry(parent);
+
+	parent_create_sysfs_entry(parent);
+
+	return NOTIFY_DONE;
+}
+
+static int parent_master_netdev_event(unsigned long event,
+				      struct net_device *parent_dev)
+{
+	struct parent *event_parent = netdev_priv(parent_dev);
+
+	switch (event) {
+	case NETDEV_CHANGENAME:
+		pr_info("%s: got NETDEV_CHANGENAME event", parent_dev->name);
+		return parent_event_changename(event_parent);
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int parent_slave_netdev_event(unsigned long event,
+				     struct net_device *slave_dev)
+{
+	struct net_device *parent_dev = slave_dev->master;
+	struct parent *parent = netdev_priv(parent_dev);
+
+	if (!parent_dev) {
+		pr_err("slave:%s has no parent.\n", slave_dev->name);
+		return NOTIFY_DONE;
+	}
+
+	switch (event) {
+	case NETDEV_UNREGISTER:
+		parent_release_slave(parent_dev, slave_dev);
+		break;
+	case NETDEV_CHANGE:
+	case NETDEV_UP:
+	case NETDEV_DOWN:
+		parent_set_carrier(parent);
+		break;
+	case NETDEV_CHANGEMTU:
+		parent_set_mtu(parent);
+		break;
+	case NETDEV_CHANGENAME:
+		break;
+	case NETDEV_FEAT_CHANGE:
+		parent_compute_features(parent);
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int eipoib_netdev_event(struct notifier_block *this,
+			       unsigned long event, void *ptr)
+{
+	struct net_device *event_dev = (struct net_device *)ptr;
+
+	if (dev_net(event_dev) != &init_net)
+		return NOTIFY_DONE;
+
+	if (is_parent(event_dev))
+		return parent_master_netdev_event(event, event_dev);
+
+	if (is_slave(event_dev))
+		return parent_slave_netdev_event(event, event_dev);
+	/*
+	 * general network device triggers event, check if it is new
+	 * ib interface that we want to enslave.
+	 */
+	return eipoib_device_event(this, event, ptr);
+}
+
+static struct notifier_block parent_netdev_notifier = {
+	.notifier_call = eipoib_netdev_event,
+};
+
+static int eipoib_device_event(struct notifier_block *unused,
+			       unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+	struct parent *parent;
+
+	if (!is_ipoib_pif_intf(dev))
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_REGISTER:
+		parent = parent_create(dev);
+		if (IS_ERR(parent)) {
+			pr_warn("failed to create parent for %s\n",
+				dev->name);
+			break;
+		}
+		break;
+	case NETDEV_UNREGISTER:
+		parent = get_parent_by_pif_name(dev->name);
+		if (parent)
+			parent_free(parent);
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int __init mod_init(void)
+{
+	int rc;
+
+	pr_info(DRV_NAME": %s", version);
+
+	rc = register_pernet_subsys(&eipoib_net_ops);
+	if (rc)
+		goto out;
+
+	rc = register_netdevice_notifier(&parent_netdev_notifier);
+	if (rc) {
+		pr_err("%s failed to register_netdevice_notifier, rc: 0x%x\n",
+		       __func__, rc);
+		goto unreg_subsys;
+	}
+
+	goto out;
+
+unreg_subsys:
+	unregister_pernet_subsys(&eipoib_net_ops);
+out:
+	return rc;
+
+}
+
+static void __exit mod_exit(void)
+{
+	unregister_netdevice_notifier(&parent_netdev_notifier);
+
+	unregister_pernet_subsys(&eipoib_net_ops);
+
+	rtnl_lock();
+	parent_free_all();
+	rtnl_unlock();
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
+MODULE_AUTHOR("Ali Ayoub && Erez Shitrit");
-- 
1.7.1

^ permalink raw reply related

* Re: assert_cfg80211_lock warning with Linux v3.5-8833-g2d53492
From: Johannes Berg @ 2012-08-01 17:14 UTC (permalink / raw)
  To: Seth Forshee
  Cc: Arend van Spriel, John W. Linville, Josh Boyer, Brett Rudley,
	Roland Vossen, linux-wireless, netdev
In-Reply-To: <20120801161959.GC22963@thinkpad-t410>

On Wed, 2012-08-01 at 11:19 -0500, Seth Forshee wrote:
> On Wed, Aug 01, 2012 at 05:53:58PM +0200, Johannes Berg wrote:
> > On Wed, 2012-08-01 at 17:51 +0200, Arend van Spriel wrote:
> > > On 08/01/2012 05:38 PM, Arend van Spriel wrote:
> > > >> brcmsmac needs to hold cfg80211_mutex before calling freq_reg_info...
> > > >> > 
> > > >> > It looks like those calls were added in mid-June.
> > > >> > 
> > > > I think mid-june sounds about right. We never observed the warning when
> > > > changes to use regulatory infrastructure were tested/reviewed. Should
> > > > this precondition be mentioned in cfg80211.h?
> > > > 
> > > > Gr. AvS
> > > 
> > > Diving in further it seems brcmsmac can not grab the cfg80211_mutex. So
> > > another solution is needed.
> > 
> > Yeah I was going to say -- how can it possibly access that? It seems
> > that in some patch the API got broken, it should be taking the lock or
> > whatever ... I'll leave it to Luis to sort out though :-P
> 
> In other drivers freq_reg_info only seems to get used by the regulatory
> notifiers, which get called with the lock held. brcmsmac is wanting to
> know whether or not OFDM is allowed when setting the channel though, and
> I didn't find that information anywhere outside the regulatory
> information. If there's another way then calling freq_reg_info() could
> be avoided. Or maybe we could add an OFDM flag to the channel
> information?

Seems reasonable to add the flags (or some of them) to the channel
flags, yeah.

johannes

^ permalink raw reply

* [PATCH V2 10/12] net/eipoib: Add sysfs support
From: Or Gerlitz @ 2012-08-01 17:09 UTC (permalink / raw)
  To: davem; +Cc: roland, netdev, ali, sean.hefty, Erez Shitrit, Or Gerlitz
In-Reply-To: <1343840975-3252-1-git-send-email-ogerlitz@mellanox.com>

From: Erez Shitrit <erezsh@mellanox.co.il>

The management interface for the driver was using sysfs. 

While most of this usage (all the "set" operations) was ported to use 
rtnetlink, still some sysfs "show" entries were left in this posting, 
till its clear if/how they can be implemented otherwise.

Here are few sysfs commands that are used in order to get 
information from the driver,

1. get parent's slaves:

	$ cat /sys/class/net/ethZ/eth/slaves

where ethZ is the driver interface

2. see the list of ipoib interfaces enslaved under eipoib interface,

	$ cat /sys/class/net/ethX/eth/vifs

for example:

	$ cat /sys/class/net/eth4/eth/vifs

	SLAVE=ib0.1      MAC=9a:c2:1f:d7:3b:63 VLAN=N/A
	SLAVE=ib0.2      MAC=52:54:00:60:55:88 VLAN=N/A
	SLAVE=ib0.3      MAC=52:54:00:60:55:89 VLAN=N/A

Signed-off-by: Erez Shitrit <erezsh@mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 drivers/net/eipoib/eth_ipoib_sysfs.c |  435 ++++++++++++++++++++++++++++++++++
 1 files changed, 435 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/eipoib/eth_ipoib_sysfs.c

diff --git a/drivers/net/eipoib/eth_ipoib_sysfs.c b/drivers/net/eipoib/eth_ipoib_sysfs.c
new file mode 100644
index 0000000..8217e32
--- /dev/null
+++ b/drivers/net/eipoib/eth_ipoib_sysfs.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. All rights reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * openfabric.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
+#include <linux/sysfs.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
+#include <linux/rtnetlink.h>
+#include <linux/etherdevice.h>
+#include <net/net_namespace.h>
+
+#include "eth_ipoib.h"
+
+#define to_dev(obj)	container_of(obj, struct device, kobj)
+#define to_parent(cd)	((struct parent *)(netdev_priv(to_net_dev(cd))))
+#define MOD_NA_STRING		"N/A"
+
+#define _sprintf(p, buf, format, arg...)				\
+((PAGE_SIZE - (int)(p - buf)) <= 0 ? 0 :				\
+	scnprintf(p, PAGE_SIZE - (int)(p - buf), format, ## arg))\
+
+#define _end_of_line(_p, _buf)					\
+do { if (_p - _buf) /* eat the leftover space */			\
+		buf[_p - _buf - 1] = '\n';				\
+} while (0)
+
+/* helper functions */
+static int get_emac(u8 *mac, char *s)
+{
+	if (sscanf(s, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+		   mac + 0, mac + 1, mac + 2, mac + 3, mac + 4,
+		   mac + 5) != 6)
+		return -1;
+
+	return 0;
+}
+
+static int get_imac(u8 *mac, char *s)
+{
+	if (sscanf(s, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:"
+		   "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:"
+		   "%hhx:%hhx:%hhx:%hhx",
+		   mac + 0, mac + 1, mac + 2, mac + 3, mac + 4,
+		   mac + 5, mac + 6, mac + 7, mac + 8, mac + 9,
+		   mac + 10, mac + 11, mac + 12, mac + 13,
+		   mac + 14, mac + 15, mac + 16, mac + 17,
+		   mac + 18, mac + 19) != 20)
+		return -1;
+
+	return 0;
+}
+
+/* show/store functions per module (CLASS_ATTR) */
+static ssize_t show_parents(struct class *cls, struct class_attribute *attr,
+			    char *buf)
+{
+	char *p = buf;
+	struct parent *parent;
+
+	rtnl_lock(); /* because of parent_dev_list */
+
+	list_for_each_entry(parent, &parent_dev_list, parent_list) {
+		p += _sprintf(p, buf, "%s over IB port: %s\n",
+			      parent->dev->name,
+			      parent->ipoib_main_interface);
+	}
+	_end_of_line(p, buf);
+
+	rtnl_unlock();
+	return (ssize_t)(p - buf);
+}
+
+/* show/store functions per parent (DEVICE_ATTR) */
+static ssize_t parent_show_neighs(struct device *d,
+				  struct device_attribute *attr, char *buf)
+{
+	struct slave *slave;
+	struct neigh *neigh;
+	struct parent *parent = to_parent(d);
+	char *p = buf;
+
+	read_lock_bh(&parent->lock);
+	parent_for_each_slave(parent, slave) {
+		list_for_each_entry(neigh, &slave->neigh_list, list) {
+			p += _sprintf(p, buf, "SLAVE=%-10s EMAC=%pM IMAC=%pM:%pM:%pM:%.2x:%.2x\n",
+				      slave->dev->name,
+				      neigh->emac,
+				      neigh->imac, neigh->imac + 6, neigh->imac + 12,
+				      neigh->imac[18], neigh->imac[19]);
+		}
+	}
+
+	read_unlock_bh(&parent->lock);
+
+	_end_of_line(p, buf);
+
+	return (ssize_t)(p - buf);
+}
+
+struct neigh *parent_get_neigh_cmd(char op,
+				   char *ifname, u8 *remac, u8 *rimac)
+{
+	struct neigh *neigh_cmd;
+
+	neigh_cmd = kzalloc(sizeof *neigh_cmd, GFP_ATOMIC);
+	if (!neigh_cmd) {
+		pr_err("%s cannot allocate neigh struct\n", ifname);
+		goto out;
+	}
+
+	/*
+	 * populate emac field so it can be used easily
+	 * in neigh_cmd_find_by_mac()
+	 */
+	memcpy(neigh_cmd->emac, remac, ETH_ALEN);
+	memcpy(neigh_cmd->imac, rimac, INFINIBAND_ALEN);
+
+	/* prepare the command as a string */
+	sprintf(neigh_cmd->cmd, "%c%s %pM %pM:%pM:%pM:%.2x:%.2x",
+		op, ifname, remac, rimac, rimac + 6, rimac + 12, rimac[18], rimac[19]);
+out:
+	return neigh_cmd;
+}
+
+/* write_lock_bh(&parent->lock) must be held */
+ssize_t __parent_store_neighs(struct device *d,
+			      struct device_attribute *attr,
+			      const char *buffer, size_t count)
+{
+	char command[IFNAMSIZ + 1] = { 0, };
+	char emac_str[ETH_ALEN * 3] = { 0, };
+	u8 emac[ETH_ALEN];
+	char imac_str[INFINIBAND_ALEN * 3] = { 0, };
+	u8 imac[INFINIBAND_ALEN];
+	char *ifname;
+	int found = 0, ret = count;
+	struct slave *slave = NULL, *slave_tmp;
+	struct neigh *neigh;
+	struct parent *parent = to_parent(d);
+
+	sscanf(buffer, "%s %s %s", command, emac_str, imac_str);
+
+	/* check ifname */
+	ifname = command + 1;
+	if ((strlen(command) <= 1) || !dev_valid_name(ifname) ||
+	    (command[0] != '+' && command[0] != '-'))
+		goto err_no_cmd;
+
+	/* check if ifname exist */
+	parent_for_each_slave(parent, slave_tmp) {
+		if (!strcmp(slave_tmp->dev->name, ifname)) {
+			found = 1;
+			slave = slave_tmp;
+		}
+	}
+
+	if (!found) {
+		pr_err("%s could not find slave\n", ifname);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (get_emac(emac, emac_str)) {
+		pr_err("%s bad emac %s\n", ifname, emac_str);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (get_imac(imac, imac_str)) {
+		pr_err("%s bad imac %s\n", ifname, imac_str);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* process command */
+	if (command[0] == '+') {
+		found = 0;
+		list_for_each_entry(neigh, &slave->neigh_list, list) {
+			if (!memcmp(neigh->emac, emac, ETH_ALEN))
+				found = 1;
+		}
+
+		if (found) {
+			pr_err("%s: cannot update neigh, slave already has "
+			       "this neigh mac %pM\n",
+			       slave->dev->name, emac);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		neigh = kzalloc(sizeof *neigh, GFP_ATOMIC);
+		if (!neigh) {
+			pr_err("%s cannot allocate neigh struct\n",
+			       slave->dev->name);
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		/* ready to go */
+		pr_info("%s: slave %s neigh mac is set to %pM\n",
+			ifname, parent->dev->name, emac);
+		memcpy(neigh->emac, emac, ETH_ALEN);
+		memcpy(neigh->imac, imac, INFINIBAND_ALEN);
+
+		list_add_tail(&neigh->list, &slave->neigh_list);
+
+		goto out;
+	}
+
+	if (command[0] == '-') {
+		found = 0;
+		list_for_each_entry(neigh, &slave->neigh_list, list) {
+			if (!memcmp(neigh->emac, emac, ETH_ALEN))
+				found = 1;
+		}
+
+		if (!found) {
+			pr_err("%s cannot delete neigh mac %pM\n",
+			       ifname, emac);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		list_del(&neigh->list);
+		kfree(neigh);
+
+		goto out;
+	}
+
+err_no_cmd:
+	pr_err("%s USAGE: (-|+)ifname emac imac\n", DRV_NAME);
+	ret = -EPERM;
+
+out:
+	return ret;
+}
+
+static DEVICE_ATTR(neighs, S_IRUGO, parent_show_neighs,
+		   NULL);
+
+static ssize_t parent_show_vifs(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct slave *slave;
+	struct parent *parent = to_parent(d);
+	char *p = buf;
+
+	read_lock_bh(&parent->lock);
+	parent_for_each_slave(parent, slave) {
+		if (is_zero_ether_addr(slave->emac)) {
+			p += _sprintf(p, buf, "SLAVE=%-10s MAC=%-17s "
+				      "VLAN=%s\n", slave->dev->name,
+				      MOD_NA_STRING, MOD_NA_STRING);
+		} else if (slave->vlan == VLAN_N_VID) {
+			p += _sprintf(p, buf, "SLAVE=%-10s MAC=%pM VLAN=%s\n",
+				      slave->dev->name,
+				      slave->emac,
+				      MOD_NA_STRING);
+		} else {
+			p += _sprintf(p, buf, "SLAVE=%-10s MAC=%pM VLAN=%d\n",
+				      slave->dev->name,
+				      slave->emac,
+				      slave->vlan);
+		}
+	}
+	read_unlock_bh(&parent->lock);
+
+	_end_of_line(p, buf);
+
+	return (ssize_t)(p - buf);
+}
+
+static DEVICE_ATTR(vifs, S_IRUGO, parent_show_vifs,
+		   NULL);
+
+static ssize_t parent_show_slaves(struct device *d,
+				  struct device_attribute *attr, char *buf)
+{
+	struct slave *slave;
+	struct parent *parent = to_parent(d);
+	char *p = buf;
+
+	read_lock_bh(&parent->lock);
+	parent_for_each_slave(parent, slave)
+		p += _sprintf(p, buf, "%s\n", slave->dev->name);
+	read_unlock_bh(&parent->lock);
+
+	_end_of_line(p, buf);
+
+	return (ssize_t)(p - buf);
+}
+
+static DEVICE_ATTR(slaves, S_IRUGO, parent_show_slaves,
+		   NULL);
+
+/* sysfs create/destroy functions */
+static struct attribute *per_parent_attrs[] = {
+	&dev_attr_slaves.attr, /* DEVICE_ATTR(slaves..) */
+	&dev_attr_vifs.attr,
+	&dev_attr_neighs.attr,
+	NULL,
+};
+
+/* name spcase  support */
+static const void *eipoib_namespace(struct class *cls,
+				    const struct class_attribute *attr)
+{
+	const struct eipoib_net *eipoib_n =
+		container_of(attr,
+			     struct eipoib_net, class_attr_eipoib_interfaces);
+	return eipoib_n->net;
+}
+
+static struct attribute_group parent_group = {
+	/* per parent sysfs files under: /sys/class/net/<IF>/eth/.. */
+	.name = "eth",
+	.attrs = per_parent_attrs
+};
+
+int create_slave_symlinks(struct net_device *master,
+			  struct net_device *slave)
+{
+	char linkname[IFNAMSIZ+7];
+	int ret = 0;
+
+	ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj),
+				"eth_parent");
+	if (ret)
+		return ret;
+
+	sprintf(linkname, "slave_%s", slave->name);
+	ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
+				linkname);
+	return ret;
+
+}
+
+void destroy_slave_symlinks(struct net_device *master,
+			    struct net_device *slave)
+{
+	char linkname[IFNAMSIZ+7];
+
+	sysfs_remove_link(&(slave->dev.kobj), "eth_parent");
+	sprintf(linkname, "slave_%s", slave->name);
+	sysfs_remove_link(&(master->dev.kobj), linkname);
+}
+
+static struct class_attribute class_attr_eth_ipoib_interfaces = {
+	.attr = {
+		.name = "eth_ipoib_interfaces",
+		.mode = S_IWUSR | S_IRUGO,
+	},
+	.show = show_parents,
+	.namespace = eipoib_namespace,
+};
+
+/* per module sysfs file under: /sys/class/net/eth_ipoib_interfaces */
+int mod_create_sysfs(struct eipoib_net *eipoib_n)
+{
+	int rc;
+	/* defined in CLASS_ATTR(eth_ipoib_interfaces..) */
+	eipoib_n->class_attr_eipoib_interfaces =
+		class_attr_eth_ipoib_interfaces;
+
+	sysfs_attr_init(&eipoib_n->class_attr_eipoib_interfaces.attr);
+
+	rc = netdev_class_create_file(&eipoib_n->class_attr_eipoib_interfaces);
+	if (rc)
+		pr_err("%s failed to create sysfs (rc %d)\n",
+		       eipoib_n->class_attr_eipoib_interfaces.attr.name, rc);
+
+	return rc;
+}
+
+void mod_destroy_sysfs(struct eipoib_net *eipoib_n)
+{
+	netdev_class_remove_file(&eipoib_n->class_attr_eipoib_interfaces);
+}
+
+int parent_create_sysfs_entry(struct parent *parent)
+{
+	struct net_device *dev = parent->dev;
+	int rc;
+
+	rc = sysfs_create_group(&(dev->dev.kobj), &parent_group);
+	if (rc)
+		pr_info("failed to create sysfs group\n");
+
+	return rc;
+}
+
+void parent_destroy_sysfs_entry(struct parent *parent)
+{
+	struct net_device *dev = parent->dev;
+
+	sysfs_remove_group(&(dev->dev.kobj), &parent_group);
+}
-- 
1.7.1

^ permalink raw reply related

* Re: assert_cfg80211_lock warning with Linux v3.5-8833-g2d53492
From: Arend van Spriel @ 2012-08-01 17:24 UTC (permalink / raw)
  To: Johannes Berg
  Cc: John W. Linville, Josh Boyer, Brett Rudley, Roland Vossen,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, Seth Forshee, Luis R. Rodriguez
In-Reply-To: <1343836438.4638.5.camel-8upI4CBIZJIJvtFkdXX2HixXY32XiHfO@public.gmane.org>

+ Luis

On 08/01/2012 05:53 PM, Johannes Berg wrote:
> On Wed, 2012-08-01 at 17:51 +0200, Arend van Spriel wrote:
>> On 08/01/2012 05:38 PM, Arend van Spriel wrote:
>>>> brcmsmac needs to hold cfg80211_mutex before calling freq_reg_info...
>>>>>
>>>>> It looks like those calls were added in mid-June.
>>>>>
>>> I think mid-june sounds about right. We never observed the warning when
>>> changes to use regulatory infrastructure were tested/reviewed. Should
>>> this precondition be mentioned in cfg80211.h?
>>>
>>> Gr. AvS
>>
>> Diving in further it seems brcmsmac can not grab the cfg80211_mutex. So
>> another solution is needed.
> 
> Yeah I was going to say -- how can it possibly access that? It seems
> that in some patch the API got broken, it should be taking the lock or
> whatever ... I'll leave it to Luis to sort out though :-P
> 
> johannes
> 

The assert was added by following commit:

commit ac46d48e00349c63650b3cc6f9460fcc183da6a6
Author: Luis R. Rodriguez <lrodriguez-DlyHzToyqoxBDgjK7y7TUQ@public.gmane.org>
Date:   Fri May 1 18:44:50 2009 -0400

    cfg80211: fix race condition with wiphy_apply_custom_regulatory()

    We forgot to lock using the cfg80211_mutex in
    wiphy_apply_custom_regulatory(). Without the lock
    there is possible race between processing a reply from CRDA
    and a driver calling wiphy_apply_custom_regulatory(). During
    the processing of the reply from CRDA we free last_request and
    wiphy_apply_custom_regulatory() eventually accesses an
    element from last_request in the through freq_reg_info_regd().

    This is very difficult to reproduce (I haven't), it takes us
    3 hours and you need to be banging hard, but the race is obvious
    by looking at the code.

    This should only affect those who use this caller, which currently
    is ath5k, ath9k, and ar9170.

    EIP: 0060:[<f8ebec50>] EFLAGS: 00210282 CPU: 1
    EIP is at freq_reg_info_regd+0x24/0x121 [cfg80211]

It seems the API was as it currently is when adding regulatory framework
changes in brcmsmac so we should have seen this assert flying by. The
problem is that freq_reg_info() is exposed in cfg80211.h, but as it is
now it can only be used under the cfg80211_mutex lock, ie. in regulatory
notify callback (as Seth indicated).

Gr. AvS

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" 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

* Re: assert_cfg80211_lock warning with Linux v3.5-8833-g2d53492
From: Seth Forshee @ 2012-08-01 17:56 UTC (permalink / raw)
  To: Johannes Berg, John W. Linville
  Cc: Arend van Spriel, Josh Boyer, Brett Rudley, Roland Vossen,
	linux-wireless, netdev
In-Reply-To: <1343841285.4638.10.camel@jlt3.sipsolutions.net>

On Wed, Aug 01, 2012 at 07:14:45PM +0200, Johannes Berg wrote:
> On Wed, 2012-08-01 at 11:19 -0500, Seth Forshee wrote:
> > On Wed, Aug 01, 2012 at 05:53:58PM +0200, Johannes Berg wrote:
> > > On Wed, 2012-08-01 at 17:51 +0200, Arend van Spriel wrote:
> > > > On 08/01/2012 05:38 PM, Arend van Spriel wrote:
> > > > >> brcmsmac needs to hold cfg80211_mutex before calling freq_reg_info...
> > > > >> > 
> > > > >> > It looks like those calls were added in mid-June.
> > > > >> > 
> > > > > I think mid-june sounds about right. We never observed the warning when
> > > > > changes to use regulatory infrastructure were tested/reviewed. Should
> > > > > this precondition be mentioned in cfg80211.h?
> > > > > 
> > > > > Gr. AvS
> > > > 
> > > > Diving in further it seems brcmsmac can not grab the cfg80211_mutex. So
> > > > another solution is needed.
> > > 
> > > Yeah I was going to say -- how can it possibly access that? It seems
> > > that in some patch the API got broken, it should be taking the lock or
> > > whatever ... I'll leave it to Luis to sort out though :-P
> > 
> > In other drivers freq_reg_info only seems to get used by the regulatory
> > notifiers, which get called with the lock held. brcmsmac is wanting to
> > know whether or not OFDM is allowed when setting the channel though, and
> > I didn't find that information anywhere outside the regulatory
> > information. If there's another way then calling freq_reg_info() could
> > be avoided. Or maybe we could add an OFDM flag to the channel
> > information?
> 
> Seems reasonable to add the flags (or some of them) to the channel
> flags, yeah.

Great, I'll work something up.

Seth

^ permalink raw reply

* Re: binding UDP port 0 with SO_REUSEADDR
From: Eric Dumazet @ 2012-08-01 19:02 UTC (permalink / raw)
  To: Tobias S. Josefowitz; +Cc: netdev
In-Reply-To: <CAEZM=bNdyZoTiGYwNM_3v+ro7dEn0q9aTo4040tBDqDSH3HOXg@mail.gmail.com>

On Wed, 2012-08-01 at 13:36 +0200, Tobias S. Josefowitz wrote:
> Hey all,
> 
> I recently noticed that binding UDP port 0 with SO_REUSEADDR yields
> unexpected results for me - the kernel occasionally gives out UDP
> ports used by other processes, if they were bound with SO_REUSEADDR,
> too.
> 
> I did some digging, it seems that
> f24d43c07e208372aa3d3bff419afbf43ba87698 introduced this behaviour.
> I'm not at all sure if this could/should be called a bug, but I need
> to say, it was severly unexpected at my side, and that probably goes
> for others, too.
> 
> Just bringing this to your attention, I have no suggestions on it whatsoever.

And why are you using SO_REUSEADDR on UDP unicast sockets ?

I mean, this is exactly saying " By using this REUSEADDR, I am allowing
this port being used by another process, even from another user"

^ permalink raw reply

* [PATCH] firmware: Remove obsolete Chelsio cxgb3 firmware
From: Tim Gardner @ 2012-08-01 19:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Tim Gardner, Paul Gortmaker, Ben Hutchings, James Bottomley,
	Dan Williams, Divy Le Ray, netdev

The current firmware version used by the device driver
is 7.12.0

Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Ben Hutchings <ben@decadent.org.uk>
Cc: James Bottomley <JBottomley@Parallels.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Divy Le Ray <divy@chelsio.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
---
 firmware/Makefile                   |    1 -
 firmware/cxgb3/t3fw-7.10.0.bin.ihex | 1935 -----------------------------------
 2 files changed, 1936 deletions(-)
 delete mode 100644 firmware/cxgb3/t3fw-7.10.0.bin.ihex

diff --git a/firmware/Makefile b/firmware/Makefile
index 344713b..76628e3 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -43,7 +43,6 @@ fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
 fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin
 fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \
 				   cxgb3/t3c_psram-1.1.0.bin \
-				   cxgb3/t3fw-7.10.0.bin \
 				   cxgb3/ael2005_opt_edc.bin \
 				   cxgb3/ael2005_twx_edc.bin \
 				   cxgb3/ael2020_twx_edc.bin
diff --git a/firmware/cxgb3/t3fw-7.10.0.bin.ihex b/firmware/cxgb3/t3fw-7.10.0.bin.ihex
deleted file mode 100644
index 96399d8..0000000
-- 
1.7.9.5

^ permalink raw reply related

* Re: assert_cfg80211_lock warning with Linux v3.5-8833-g2d53492
From: Arend van Spriel @ 2012-08-01 19:28 UTC (permalink / raw)
  To: Johannes Berg
  Cc: John W. Linville, Josh Boyer, Brett Rudley, Roland Vossen,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, Seth Forshee, Luis R. Rodriguez
In-Reply-To: <50196660.8090001-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

On 08/01/2012 07:24 PM, Arend van Spriel wrote:
> It seems the API was as it currently is when adding regulatory framework
> changes in brcmsmac so we should have seen this assert flying by. The
> problem is that freq_reg_info() is exposed in cfg80211.h, but as it is
> now it can only be used under the cfg80211_mutex lock, ie. in regulatory
> notify callback (as Seth indicated).
> 
> Gr. AvS

Ah, I see you need to run a LOCKDEP-enabled kernel to get this warning.

Gr. AvS

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" 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

* Re: v3.5: NETDEV WATCHDOG: eth0 (r8169): transmit queue 0 timed out
From: Francois Romieu @ 2012-08-01 19:24 UTC (permalink / raw)
  To: George Spelvin; +Cc: netdev
In-Reply-To: <20120730190236.30339.qmail@science.horizon.com>

George Spelvin <linux@horizon.com> :
[...]
> There are a few local patches, but only two are anywhere close to the
> network interface, and they are test patches designed to fix this.
> Should I get rid of them?

It's up to you but I suggest that you keep them until there is something
better.

As long as the device recovers, you may try and lower the watchdog timeout
as well as increase the Tx ring size a bit (x2 or x4) to minimize the
annoyances.

-- 
Ueimor

^ permalink raw reply

* Re: binding UDP port 0 with SO_REUSEADDR
From: Tobias S. Josefowitz @ 2012-08-01 19:38 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1343847776.21269.797.camel@edumazet-glaptop>

On Wed, Aug 1, 2012 at 9:02 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> And why are you using SO_REUSEADDR on UDP unicast sockets ?

Simple. This happens in a "scripting" language. The wrapper code
assumes that it is better to set SO_REUSEADDR than not (which might be
argued, but backwards-compat can be nice) and at the time the code was
written the author must have assumed that even if the 'user' aka
programmer wants to bind to port 0, SO_REUSEADDR doesn't hurt, because
port 0 implicitly meant "please, a free one".

> I mean, this is exactly saying " By using this REUSEADDR, I am allowing
> this port being used by another process, even from another user"

I know. Still, while binding port 0 means "give me any port", I'm
quite sure most people would assume they get a free one. And maybe,
for whatever reasons, you want to share your random port later and
need SO_REUSEADDR because of that. A usecase where someone wants a
randomly chosen free or used port does not come to my mind, though.

Of course, I'm not relying on the kernel to revert back, I adapted the
wrapper code I mentioned above. I still felt like mentioning that it
was kind of unexpected, that's all.

Best,

Tobi

^ permalink raw reply

* Unable to get link beat with Niagara 2264 (Intel 82571EB) and e1000e driver on 3.4.4 (long)
From: Bradley Chapman @ 2012-08-01 22:20 UTC (permalink / raw)
  To: netdev

All,

(please CC me as I am not subscribed to netdev)

I recently acquired an Interface Masters Niagara 2264 quad-port GigE 
network card, based on the Intel 82571EB network controller (see 
http://www.interfacemasters.com/products/2264.html for details). Prior 
to using it in a new system I'm planning to build I decided to try it 
out on my desktop system, which uses as Asus M4A89TD/PRO USB3 
motherboard with the AMD 890FX chipset and a BIOS dated 03/08/2011, 
running Debian 6.0.2.1.

I added the e1000e driver to my Linux 3.4.4 kernel config as a loadable 
module and inserted it, and got the following:

e1000e: Intel(R) PRO/1000 Network Driver - 1.9.5-k
e1000e: Copyright(c) 1999 - 2012 Intel Corporation.
e1000e 0000:06:00.0: Disabling ASPM  L1
e1000e 0000:06:00.0: (unregistered net_device): Interrupt Throttling 
Rate (ints/sec) set to dynamic conservative mode
e1000e 0000:06:00.0: irq 91 for MSI/MSI-X
e1000e 0000:06:00.0: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8c
e1000e 0000:06:00.0: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:06:00.0: eth1: MAC: 0, PHY: 4, PBA No: C98149-002
e1000e 0000:06:00.1: Disabling ASPM  L1
e1000e 0000:06:00.1: (unregistered net_device): Interrupt Throttling 
Rate (ints/sec) set to dynamic conservative mode
e1000e 0000:06:00.1: irq 92 for MSI/MSI-X
udev[1123]: renamed network interface eth1 to eth2
e1000e 0000:06:00.1: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8d
e1000e 0000:06:00.1: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:06:00.1: eth1: MAC: 0, PHY: 4, PBA No: C98149-002
e1000e 0000:05:00.0: Disabling ASPM  L1
e1000e 0000:05:00.0: (unregistered net_device): Interrupt Throttling 
Rate (ints/sec) set to dynamic conservative mode
e1000e 0000:05:00.0: irq 93 for MSI/MSI-X
udev[8376]: renamed network interface eth1 to eth3
e1000e 0000:05:00.0: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8a
e1000e 0000:05:00.0: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:05:00.0: eth1: MAC: 0, PHY: 4, PBA No: C98149-002
e1000e 0000:05:00.1: Disabling ASPM  L1
e1000e 0000:05:00.1: (unregistered net_device): Interrupt Throttling 
Rate (ints/sec) set to dynamic conservative mode
e1000e 0000:05:00.1: irq 94 for MSI/MSI-X
udev[8400]: renamed network interface eth1 to eth4
e1000e 0000:05:00.1: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8b
e1000e 0000:05:00.1: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:05:00.1: eth1: MAC: 0, PHY: 4, PBA No: C98149-002
udev[8429]: renamed network interface eth1 to eth5

After doing so, though, I was unable to get a link beat on any of the 
four RJ45 ports. I tried the Intel-supplied e1000e driver on the same 
kernel and got the following:

e1000e: Intel(R) PRO/1000 Network Driver - 2.0.0.1-NAPI
e1000e: Copyright(c) 1999 - 2012 Intel Corporation.
e1000e 0000:06:00.0: Disabling ASPM  L1
e1000e 0000:06:00.0: irq 91 for MSI/MSI-X
e1000e 0000:06:00.0: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8c
e1000e 0000:06:00.0: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:06:00.0: eth1: MAC: 1, PHY: 4, PBA No: C98149-002
e1000e 0000:06:00.1: Disabling ASPM  L1
e1000e 0000:06:00.1: irq 92 for MSI/MSI-X
udev[8455]: renamed network interface eth1 to eth2
e1000e 0000:06:00.1: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8d
e1000e 0000:06:00.1: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:06:00.1: eth1: MAC: 1, PHY: 4, PBA No: C98149-002
e1000e 0000:05:00.0: Disabling ASPM  L1
e1000e 0000:05:00.0: irq 93 for MSI/MSI-X
udev[8455]: renamed network interface eth1 to eth3
e1000e 0000:05:00.0: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8a
e1000e 0000:05:00.0: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:05:00.0: eth1: MAC: 1, PHY: 4, PBA No: C98149-002
e1000e 0000:05:00.1: Disabling ASPM  L1
e1000e 0000:05:00.1: irq 94 for MSI/MSI-X
udev[8455]: renamed network interface eth1 to eth4
e1000e 0000:05:00.1: eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8b
e1000e 0000:05:00.1: eth1: Intel(R) PRO/1000 Network Connection
e1000e 0000:05:00.1: eth1: MAC: 1, PHY: 4, PBA No: C98149-002
udev[8455]: renamed network interface eth1 to eth5

ethtool -i and ethtool -d report the following for the Intel-supplied 
driver for one of the four interfaces exported to userspace:

ethtool -i
----------
driver: e1000e
version: 2.0.0.1-NAPI
firmware-version: 5.0-2
bus-info: 0000:06:00.0

ethtool -d
----------
MAC Registers
-------------
0x00000: CTRL (Device control register)  0x40480241
       Endian mode (buffers):             little
       Link reset:                        normal
       Set link up:                       1
       Invert Loss-Of-Signal:             no
       Receive flow control:              disabled
       Transmit flow control:             disabled
       VLAN mode:                         enabled
       Auto speed detect:                 disabled
       Speed select:                      1000Mb/s
       Force speed:                       no
       Force duplex:                      no
0x00008: STATUS (Device status register) 0x00080380
       Duplex:                            half
       Link up:                           no link config
       TBI mode:                          disabled
       Link speed:                        1000Mb/s
       Bus type:                          PCI Express
       Port number:                       0
0x00100: RCTL (Receive control register) 0x0400801A
       Receiver:                          enabled
       Store bad packets:                 disabled
       Unicast promiscuous:               enabled
       Multicast promiscuous:             enabled
       Long packet:                       disabled
       Descriptor minimum threshold size: 1/2
       Broadcast accept mode:             accept
       VLAN filter:                       disabled
       Canonical form indicator:          disabled
       Discard pause frames:              filtered
       Pass MAC control frames:           don't pass
       Receive buffer size:               2048
0x02808: RDLEN (Receive desc length)     0x00001000
0x02810: RDH   (Receive desc head)       0x00000000
0x02818: RDT   (Receive desc tail)       0x000000F0
0x02820: RDTR  (Receive delay timer)     0x00000020
0x00400: TCTL (Transmit ctrl register)   0x3003F008
       Transmitter:                       disabled
       Pad short packets:                 enabled
       Software XOFF Transmission:        disabled
       Re-transmit on late collision:     disabled
0x03808: TDLEN (Transmit desc length)    0x00001000
0x03810: TDH   (Transmit desc head)      0x00000000
0x03818: TDT   (Transmit desc tail)      0x00000000
0x03820: TIDV  (Transmit delay timer)    0x00000008
PHY type:                                unknown

mii-diag -a reports the following:

SIOCGMIIREG on eth2 failed: Input/output error
Basic registers of MII PHY #1:  1140 7909 02a8 0380 0de1 0000 0004 ffff.
  Basic mode control register 0x1140: Auto-negotiation enabled.
  Basic mode status register 0x7909 ... 7909.
    Link status: not established.
    End of basic transceiver information.

lspci reports the following:

02:00.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI 
Express Switch (rev ac)
03:00.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI 
Express Switch (rev ac)
03:01.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI 
Express Switch (rev ac)
03:02.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI 
Express Switch (rev ac)
05:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)
05:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)
06:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)
06:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet 
Controller (rev 06)

I tried rebooting since switching to the new driver and it hasn't made a 
difference. I did a bunch of digging in Google and couldn't find 
anything that conclusively suggested a problem - I found lots of stuff 
about BIOS bugs when dealing with ASPM, old regressions fixed in 
previous kernels, and so on, but nothing that specifically identified my 
problem.

Does anyone have any suggestions? I can try Linux 3.5 very easily and if 
necessary I can also learn how to fetch a git tree and bisect it. I also 
sent an e-mail to the manufacturer asking for assistance with this 
device but I haven't received a response yet.

Thanks,

Brad

^ permalink raw reply

* [ANNOUNCE] iproute2 3.5.0
From: Stephen Hemminger @ 2012-08-01 23:05 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel

Following the trend of releasing before going on vacation, here is the
iproute2 release to go with last weeks 3.5.0 kernel release. The changes
were mainly adding support for the new queuing disciplines (codel etc)
and cleaning up the manual pages.


Source:
  http://www.kernel.org/pub/linux/utils/net/iproute2/iproute2-3.5.0.tar.gz

Repository:
  git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git

Andreas Henriksson (1):
      iproute2: man page and /bin/ip disagree on del vs delete

Ben Hutchings (1):
      ss: Report MSS from internal TCP information

Bjarni Ingi Gislason (2):
      tc(8): Negative indent and missing "-" after an escape
      tc-drr(8): tab unquoted in a argument to a macro

Chris Elston (1):
      iproute2: allow IPv6 addresses for l2tp local and remote parameters

Eric Dumazet (3):
      tc_codel: Controlled Delay AQM
      fq_codel: Fair Queue Codel AQM
      ip: speedup ip link

Hiroaki SHIMODA (2):
      tc: u32: Fix icmp_code off.
      tc: u32: Fix firstfrag filter.

Jan Ceuleers (2):
      tc-codel: Fix typos in manpage
      Add reference to tc-codel(8) to the SEE ALSO section

Li Wei (6):
      tc: man: Fix incorrect parameter format in prio.
      tc: prio: Perform more strict check on priomap.
      tc: filter: validate filter priority in userspace.
      tc: man: add 'delete' command.
      tc: man: change man page and comment to confirm to code's behavior.
      tc-bfifo: man: Add parameter value range.

Stephen Hemminger (7):
      Update headers to 3.5 merge window
      Remove derived man pages
      Refactor ipaddr_list_or_flush
      Remove reference to multipath algorithms in usage
      man8: build cleanup
      Add bridge command
      v3.5.0

Vijay Subramanian (6):
      Update tc-netem manpage to add ecn capability
      tc-netem: Add support for ECN packet marking
      tc-codel: Add manpage
      tc-codel: Update usage text
      tc-fq_codel: Add manpage
      tc: Update manpage

^ permalink raw reply

* Re: v3.5: NETDEV WATCHDOG: eth0 (r8169): transmit queue 0 timed out
From: George Spelvin @ 2012-08-01 23:29 UTC (permalink / raw)
  To: romieu; +Cc: linux, netdev
In-Reply-To: <20120801192455.GA29755@electric-eye.fr.zoreil.com>

Thank you for the response!

> It's up to you but I suggest that you keep them until there is something
> better.

I was going to; I just wondered if they interfered with debugging or
something.

> As long as the device recovers, you may try and lower the watchdog timeout
> as well as increase the Tx ring size a bit (x2 or x4) to minimize the
> annoyances.

Out of curiosity, how does increasing the Tx ring size help?

But okay.  Just to make sure I'm doing it right (I'm pretty sure,
but scream if I'm making a mistake), I'm making the following edits to
drivers/net/ethernet/realtek/r8169.c

#define	NUM_TX_DESC	64	/* Number of Tx descriptor registers */

I'll double that to 128.

Now, since I am actually running at gigabit speed into a pretty capable
network that I don't expect to ever block me, I should be able to send
one 1500-byte frame in 12.3 microseconds (with all overhead, one 1500-byte
frame is 1538 bytes or 12304 bits), so 128 frames in 1.6 ms.

There is the issue of TSO, so one descriptor might send more than one
frame, but I think it's likely to break at 4K pages, the worst case is
128 * 4096 / 1500 = 350 frames in that Tx ring, which will take 4.3 ms.

Either way, I can drop the Tx timeout a *lot*.

#define	TL8169_TX_TIMEOUT	(6*HZ)

I want to drop that to HZ/100 or less.  Since I'm currently running with
CONFIG_HZ_100, and I'm not sure about the rounding (do I gain or lose
one tick due to ambiguity?) I'll bump HZ to 300 and change that to HZ/100.
That should give me a minimum of 2 ticks = 6.666 ms, which is still more
than it should take to transmit a full 

To make this short timeout actually work, I have to remove the "round
to nearest second" round_timer() calls in net/sched/sch_generic.c (there
are two that apply to dev->watchdog_timer), since I do want a sub-second
timeout granularity.

^ permalink raw reply

* Re: [PATCH iproute2] ss: report SK_MEMINFO_BACKLOG
From: Stephen Hemminger @ 2012-08-02  0:06 UTC (permalink / raw)
  To: Vijay Subramanian; +Cc: Eric Dumazet, netdev
In-Reply-To: <CAGK4HS-fUp2ZiW9F_ZogOXQo5_2ptcBHT9Y2j25ZaoXrYKnbAQ@mail.gmail.com>

On Thu, 26 Jul 2012 17:29:26 -0700
Vijay Subramanian <subramanian.vijay@gmail.com> wrote:

> On 26 July 2012 02:20, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> > From: Eric Dumazet <edumazet@google.com>
> >
> > linux-3.6-rc1 supports SK_MEMINFO_BACKLOG with commit d594e987c6f54
> > (sock_diag: add SK_MEMINFO_BACKLOG)
> >
> > ss command can display it if provided by the kernel.
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > Cc: Vijay Subramanian <subramanian.vijay@gmail.com>
> 
> 
> Thanks Eric. I see now how you fixed this.
> 
> Tested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
> 
> Vijay

Applied (after 3.5.0 release).

^ permalink raw reply

* Re: Bridge extensions to iproute2
From: Stephen Hemminger @ 2012-08-02  0:07 UTC (permalink / raw)
  To: Maciej Żenczykowski; +Cc: Linux NetDev, David Miller
In-Reply-To: <CAHo-OozFCrcx4FpsuNzEV4Cp_4hbVw896utpstYL2qcD1EwCyA@mail.gmail.com>

On Tue, 10 Jul 2012 15:01:26 -0700
Maciej Żenczykowski <zenczykowski@gmail.com> wrote:

> > I will get back to these. There wasn't a motivation to go fast because
> > there wasn't a user of these. Now with fdb offload support they are needed.
> 
> Do you have some semi-ready patches that could be used for test purposes?
> 
> While it looks like the forwarding database capability is there in the kernel,
> I can't currently find an interface to turn learning off.

I cleaned it up an put in 3.5.0 just released version.

^ permalink raw reply

* Re: [PATCH 02/02] iproute2: VTI support for ip link command.
From: Stephen Hemminger @ 2012-08-02  0:08 UTC (permalink / raw)
  To: Saurabh; +Cc: netdev
In-Reply-To: <20120628010157.GA4005@debian-saurabh-64.vyatta.com>

On Wed, 27 Jun 2012 18:01:57 -0700
Saurabh <saurabh.mohan@vyatta.com> wrote:

> 
> 
> Support for VTI via rt netlink.
> 
> Signed-off-by: Saurabh Mohan <saurabh.mohan@vyatta.com>
> 

Applied for next version.

^ permalink raw reply

* Re: [PATCH V2 05/12] net: Add ndo_set_vif_param operation to serve eIPoIB VIFs
From: Ben Hutchings @ 2012-08-02  0:17 UTC (permalink / raw)
  To: Or Gerlitz; +Cc: davem, roland, netdev, ali, sean.hefty, Erez Shitrit
In-Reply-To: <1343840975-3252-6-git-send-email-ogerlitz@mellanox.com>

On Wed, 2012-08-01 at 20:09 +0300, Or Gerlitz wrote:
> From: Erez Shitrit <erezsh@mellanox.co.il>
> 
> The Ethernet IPoIB driver enslaves IPoIB devices and uses them as
> VIFs (Virtual Interface) which serve an Ethernet NIC e.g present in a 
> guest OS. For each such slave that acts as a VIF, eIPoIB needs to know 
> the mac and optionally the vlan uses by that NIC, the new ndo opertaion 
> is used to associate the mac/vlan for that slave.
> 
> Signed-off-by: Erez Shitrit <erezsh@mellanox.co.il>
> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
> ---
>  include/linux/netdevice.h |    5 ++++-
>  1 files changed, 4 insertions(+), 1 deletions(-)
> 
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index eb06e58..2709551 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -1013,7 +1013,10 @@ struct net_device_ops {
>  						    netdev_features_t features);
>  	int			(*ndo_neigh_construct)(struct neighbour *n);
>  	void			(*ndo_neigh_destroy)(struct neighbour *n);
> -
> +	int			(*ndo_set_vif_param) (struct net_device *dev,
> +						      struct net_device *vif,
> +						      u16 vlan,
> +						      u8 *mac);

The semantics of this operation should be documented in the comment
above the structure definition.  One detail worth covering is whether
'vlan' is just a VID or can also include priority+CFI bits.

If this is specific to eIPoIB, why not put that in the name of the
operation?  If not, this *really* needs explaining because so far I have
no whether it is something I should consider implementing on a real
Ethernet device.

Ben.

>  	int			(*ndo_fdb_add)(struct ndmsg *ndm,
>  					       struct net_device *dev,
>  					       unsigned char *addr,

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* RE: Unable to get link beat with Niagara 2264 (Intel 82571EB) and e1000e driver on 3.4.4 (long)
From: Dave, Tushar N @ 2012-08-02  0:18 UTC (permalink / raw)
  To: kakadu08@comcast.net, netdev@vger.kernel.org
In-Reply-To: <5019ABA3.4080506@comcast.net>



>-----Original Message-----
>From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
>On Behalf Of Bradley Chapman
>Sent: Wednesday, August 01, 2012 3:20 PM
>To: netdev@vger.kernel.org
>Subject: Unable to get link beat with Niagara 2264 (Intel 82571EB) and
>e1000e driver on 3.4.4 (long)
>
>All,
>
>(please CC me as I am not subscribed to netdev)
>
>I recently acquired an Interface Masters Niagara 2264 quad-port GigE
>network card, based on the Intel 82571EB network controller (see
>http://www.interfacemasters.com/products/2264.html for details). Prior to
>using it in a new system I'm planning to build I decided to try it out on
>my desktop system, which uses as Asus M4A89TD/PRO USB3 motherboard with
>the AMD 890FX chipset and a BIOS dated 03/08/2011, running Debian 6.0.2.1.
>
>I added the e1000e driver to my Linux 3.4.4 kernel config as a loadable
>module and inserted it, and got the following:
>
>e1000e: Intel(R) PRO/1000 Network Driver - 1.9.5-k
>e1000e: Copyright(c) 1999 - 2012 Intel Corporation.
>e1000e 0000:06:00.0: Disabling ASPM  L1
>e1000e 0000:06:00.0: (unregistered net_device): Interrupt Throttling Rate
>(ints/sec) set to dynamic conservative mode e1000e 0000:06:00.0: irq 91
>for MSI/MSI-X e1000e 0000:06:00.0: eth1: (PCI Express:2.5GT/s:Width x4)
>00:0c:bd:01:cd:8c e1000e 0000:06:00.0: eth1: Intel(R) PRO/1000 Network
>Connection e1000e 0000:06:00.0: eth1: MAC: 0, PHY: 4, PBA No: C98149-002
>e1000e 0000:06:00.1: Disabling ASPM  L1 e1000e 0000:06:00.1: (unregistered
>net_device): Interrupt Throttling Rate (ints/sec) set to dynamic
>conservative mode e1000e 0000:06:00.1: irq 92 for MSI/MSI-X
>udev[1123]: renamed network interface eth1 to eth2 e1000e 0000:06:00.1:
>eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8d e1000e
>0000:06:00.1: eth1: Intel(R) PRO/1000 Network Connection e1000e
>0000:06:00.1: eth1: MAC: 0, PHY: 4, PBA No: C98149-002 e1000e
>0000:05:00.0: Disabling ASPM  L1 e1000e 0000:05:00.0: (unregistered
>net_device): Interrupt Throttling Rate (ints/sec) set to dynamic
>conservative mode e1000e 0000:05:00.0: irq 93 for MSI/MSI-X
>udev[8376]: renamed network interface eth1 to eth3 e1000e 0000:05:00.0:
>eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8a e1000e
>0000:05:00.0: eth1: Intel(R) PRO/1000 Network Connection e1000e
>0000:05:00.0: eth1: MAC: 0, PHY: 4, PBA No: C98149-002 e1000e
>0000:05:00.1: Disabling ASPM  L1 e1000e 0000:05:00.1: (unregistered
>net_device): Interrupt Throttling Rate (ints/sec) set to dynamic
>conservative mode e1000e 0000:05:00.1: irq 94 for MSI/MSI-X
>udev[8400]: renamed network interface eth1 to eth4 e1000e 0000:05:00.1:
>eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8b e1000e
>0000:05:00.1: eth1: Intel(R) PRO/1000 Network Connection e1000e
>0000:05:00.1: eth1: MAC: 0, PHY: 4, PBA No: C98149-002
>udev[8429]: renamed network interface eth1 to eth5

What is the link partner?
Have you tried connecting device to different link partners?

-Tushar
>
>After doing so, though, I was unable to get a link beat on any of the four
>RJ45 ports. I tried the Intel-supplied e1000e driver on the same kernel
>and got the following:
>
>e1000e: Intel(R) PRO/1000 Network Driver - 2.0.0.1-NAPI
>e1000e: Copyright(c) 1999 - 2012 Intel Corporation.
>e1000e 0000:06:00.0: Disabling ASPM  L1
>e1000e 0000:06:00.0: irq 91 for MSI/MSI-X e1000e 0000:06:00.0: eth1: (PCI
>Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8c e1000e 0000:06:00.0: eth1:
>Intel(R) PRO/1000 Network Connection e1000e 0000:06:00.0: eth1: MAC: 1,
>PHY: 4, PBA No: C98149-002 e1000e 0000:06:00.1: Disabling ASPM  L1 e1000e
>0000:06:00.1: irq 92 for MSI/MSI-X
>udev[8455]: renamed network interface eth1 to eth2 e1000e 0000:06:00.1:
>eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8d e1000e
>0000:06:00.1: eth1: Intel(R) PRO/1000 Network Connection e1000e
>0000:06:00.1: eth1: MAC: 1, PHY: 4, PBA No: C98149-002 e1000e
>0000:05:00.0: Disabling ASPM  L1 e1000e 0000:05:00.0: irq 93 for MSI/MSI-X
>udev[8455]: renamed network interface eth1 to eth3 e1000e 0000:05:00.0:
>eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8a e1000e
>0000:05:00.0: eth1: Intel(R) PRO/1000 Network Connection e1000e
>0000:05:00.0: eth1: MAC: 1, PHY: 4, PBA No: C98149-002 e1000e
>0000:05:00.1: Disabling ASPM  L1 e1000e 0000:05:00.1: irq 94 for MSI/MSI-X
>udev[8455]: renamed network interface eth1 to eth4 e1000e 0000:05:00.1:
>eth1: (PCI Express:2.5GT/s:Width x4) 00:0c:bd:01:cd:8b e1000e
>0000:05:00.1: eth1: Intel(R) PRO/1000 Network Connection e1000e
>0000:05:00.1: eth1: MAC: 1, PHY: 4, PBA No: C98149-002
>udev[8455]: renamed network interface eth1 to eth5
>
>ethtool -i and ethtool -d report the following for the Intel-supplied
>driver for one of the four interfaces exported to userspace:
>
>ethtool -i
>----------
>driver: e1000e
>version: 2.0.0.1-NAPI
>firmware-version: 5.0-2
>bus-info: 0000:06:00.0
>
>ethtool -d
>----------
>MAC Registers
>-------------
>0x00000: CTRL (Device control register)  0x40480241
>       Endian mode (buffers):             little
>       Link reset:                        normal
>       Set link up:                       1
>       Invert Loss-Of-Signal:             no
>       Receive flow control:              disabled
>       Transmit flow control:             disabled
>       VLAN mode:                         enabled
>       Auto speed detect:                 disabled
>       Speed select:                      1000Mb/s
>       Force speed:                       no
>       Force duplex:                      no
>0x00008: STATUS (Device status register) 0x00080380
>       Duplex:                            half
>       Link up:                           no link config
>       TBI mode:                          disabled
>       Link speed:                        1000Mb/s
>       Bus type:                          PCI Express
>       Port number:                       0
>0x00100: RCTL (Receive control register) 0x0400801A
>       Receiver:                          enabled
>       Store bad packets:                 disabled
>       Unicast promiscuous:               enabled
>       Multicast promiscuous:             enabled
>       Long packet:                       disabled
>       Descriptor minimum threshold size: 1/2
>       Broadcast accept mode:             accept
>       VLAN filter:                       disabled
>       Canonical form indicator:          disabled
>       Discard pause frames:              filtered
>       Pass MAC control frames:           don't pass
>       Receive buffer size:               2048
>0x02808: RDLEN (Receive desc length)     0x00001000
>0x02810: RDH   (Receive desc head)       0x00000000
>0x02818: RDT   (Receive desc tail)       0x000000F0
>0x02820: RDTR  (Receive delay timer)     0x00000020
>0x00400: TCTL (Transmit ctrl register)   0x3003F008
>       Transmitter:                       disabled
>       Pad short packets:                 enabled
>       Software XOFF Transmission:        disabled
>       Re-transmit on late collision:     disabled
>0x03808: TDLEN (Transmit desc length)    0x00001000
>0x03810: TDH   (Transmit desc head)      0x00000000
>0x03818: TDT   (Transmit desc tail)      0x00000000
>0x03820: TIDV  (Transmit delay timer)    0x00000008
>PHY type:                                unknown
>
>mii-diag -a reports the following:
>
>SIOCGMIIREG on eth2 failed: Input/output error Basic registers of MII PHY
>#1:  1140 7909 02a8 0380 0de1 0000 0004 ffff.
>  Basic mode control register 0x1140: Auto-negotiation enabled.
>  Basic mode status register 0x7909 ... 7909.
>    Link status: not established.
>    End of basic transceiver information.
>
>lspci reports the following:
>
>02:00.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI
>Express Switch (rev ac)
>03:00.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI
>Express Switch (rev ac)
>03:01.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI
>Express Switch (rev ac)
>03:02.0 PCI bridge: PLX Technology, Inc. PEX 8517 16-lane, 5-port PCI
>Express Switch (rev ac)
>05:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet
>Controller (rev 06)
>05:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet
>Controller (rev 06)
>06:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet
>Controller (rev 06)
>06:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet
>Controller (rev 06)
>
>I tried rebooting since switching to the new driver and it hasn't made a
>difference. I did a bunch of digging in Google and couldn't find anything
>that conclusively suggested a problem - I found lots of stuff about BIOS
>bugs when dealing with ASPM, old regressions fixed in previous kernels,
>and so on, but nothing that specifically identified my problem.
>
>Does anyone have any suggestions? I can try Linux 3.5 very easily and if
>necessary I can also learn how to fetch a git tree and bisect it. I also
>sent an e-mail to the manufacturer asking for assistance with this device
>but I haven't received a response yet.
>
>Thanks,
>
>Brad
>--
>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 V2 06/12] net/core: Add rtnetlink support to vif parameters
From: Ben Hutchings @ 2012-08-02  0:20 UTC (permalink / raw)
  To: Or Gerlitz; +Cc: davem, roland, netdev, ali, sean.hefty, Erez Shitrit
In-Reply-To: <1343840975-3252-7-git-send-email-ogerlitz@mellanox.com>

On Wed, 2012-08-01 at 20:09 +0300, Or Gerlitz wrote:
> From: Erez Shitrit <erezsh@mellanox.co.il>
> 
> Add IFLA_VIF_INFO which allows user space to configure mac/vlan for a VIF
[...]
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -780,7 +780,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
>  	       + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
>  	       + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
>  	       + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
> -	       + rtnl_link_get_af_size(dev); /* IFLA_AF_SPEC */
> +	       + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
> +	       + nla_total_size(sizeof(struct ifla_vif_param)); /* IFLA_VIF_INFO */
>  }
[...]

if_nlmsg_size() returns the size of a message describing the interface.
But IFLA_VIF_INFO is write-only (why?) and therefore shouldn't be
included.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH V2 08/12] net/eipoib: Add ethtool file support
From: Ben Hutchings @ 2012-08-02  0:22 UTC (permalink / raw)
  To: Or Gerlitz; +Cc: davem, roland, netdev, ali, sean.hefty, Erez Shitrit
In-Reply-To: <1343840975-3252-9-git-send-email-ogerlitz@mellanox.com>

On Wed, 2012-08-01 at 20:09 +0300, Or Gerlitz wrote:
> From: Erez Shitrit <erezsh@mellanox.co.il>
> 
> Via ethtool the driver describes its version, ABI version, on what PIF
> interface it runs and various statistics.
[...]
> --- /dev/null
> +++ b/drivers/net/eipoib/eth_ipoib_ethtool.c
[...]
> +static void parent_ethtool_get_drvinfo(struct net_device *parent_dev,
> +				       struct ethtool_drvinfo *drvinfo)
> +{
> +	struct parent *parent = netdev_priv(parent_dev);
> +
> +	strncpy(drvinfo->driver, DRV_NAME, 32);
> +
> +	strncpy(drvinfo->version, DRV_VERSION, 32);
> +
> +	strncpy(drvinfo->bus_info, parent->ipoib_main_interface,
> +		ETHTOOL_BUSINFO_LEN);

These must be null-terminated; therefore use strlcpy().

> +	/* indicates ABI version */
> +	snprintf(drvinfo->fw_version, 32, "%d", EIPOIB_ABI_VER);
[...]

This is an abuse of fw_version.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [E1000-devel] [PATCH net-next] igb: add delay to allow igb loopback test to succeed on 8086:10c9
From: Jeff Kirsher @ 2012-08-02  1:06 UTC (permalink / raw)
  To: Stefan Assmann; +Cc: netdev, e1000-devel
In-Reply-To: <1343821463-18052-1-git-send-email-sassmann@kpanic.de>

[-- Attachment #1: Type: text/plain, Size: 1789 bytes --]

On Wed, 2012-08-01 at 13:44 +0200, Stefan Assmann wrote:
> Some 8086:10c9 NICs have a problem completing the ethtool loopback
> test.
> The result looks like this:
> 
> ethtool -t eth1
> The test result is FAIL
> The test extra info:
> Register test  (offline)         0
> Eeprom test    (offline)         0
> Interrupt test (offline)         0
> Loopback test  (offline)         13
> Link test   (on/offline)         0
> 
> A bisect clearly points to commit
> a95a07445ee97a2fef65befafbadcc30ca1bd145.
> However that seems to only trigger the bug. While adding some printk
> the
> problem disappeared, so this might be a timing issue. After some trial
> and
> error I discovered that adding a small delay just before
> igb_write_phy_reg()
> in igb_integrated_phy_loopback() allows the loopback test to succeed.
> I was unable to figure out the root cause so far but I expect it to be
> somewhere in the following executing path
> igb_integrated_phy_loopback
> ->igb_write_phy_reg_igp
>   ->igb_write_phy_reg_mdic
>     ->igb_acquire_phy_82575
>       ->igb_acquire_swfw_sync_82575
> 
> As this workaround only introduces a minor delay, which is not in the
> hot
> path I hope this is acceptable. The problem could only be oberved on
> 8086:10c9 NICs so far and not all of them show the behaviour. I did
> not
> restrict the workaround to this type of NIC as it should do no harm to
> other igb NICs.
> 
> With the patch below the loopback test succeeded 500 times in a row
> using a NIC that would otherwise fail.
> 
> Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
> ---
>  drivers/net/ethernet/intel/igb/igb_ethtool.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-) 

Thanks Stefan, I have added the patch to my queue.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [RFC v2 1/2] PCI-Express Non-Transparent Bridge Support
From: Jon Mason @ 2012-08-02  1:43 UTC (permalink / raw)
  To: chetan loke; +Cc: Bjorn Helgaas, linux-kernel, netdev, linux-pci, Dave Jiang
In-Reply-To: <CAAsGZS4nhv+s7NVwaaGjQ9fJoHQoaXnUoYw=xTPC-sfen+tj8A@mail.gmail.com>

On Tue, Jul 31, 2012 at 02:02:25PM -0400, chetan loke wrote:
> On Tue, Jul 31, 2012 at 1:27 PM, Jon Mason <jon.mason@intel.com> wrote:
> >
> > I don't see the benefit of having the driver in staging.  Any vendors
> > who would notice the ntb driver in staging would be sitting on these
> > mailing lists and hopefully have planety of comments on the design.
> > Stashing the driver in staging while waiting for these comments (which
> > may never come) doesn't seem the best course of action.
> >
> 
> I thought that since others are talking about it then may be there is
> some WIP code for foo-NTB. Seems like that's not the case. So no need
> to stage.
> 
> Correct me if I'm wrong but wouldn't apps just open a socket and route
> data via ntb_vir_eth_dev? So I don't see an ABI breakage issue and
> hence nothing would prevent us from changing the kernel parts(for
> accommodating some foo-NTB part) in future.

The virtual ethernet device (patch #2) would allow for a generic way
of passing data to the remote side.  The only issue would be changing
how it is encoded in the shared buffer.

> It may not be a bad idea to prefix intel-specific(if any)
> ntb_structs/variables/logic with the 'intc'(Intel ticker or pick your
> string) keyword.

The Intel specific things are current pre-pended with "xeon" or "bwd".

Thanks,
Jon


> 
> Chetan Loke

^ permalink raw reply

* Re: [RFC v2 1/2] PCI-Express Non-Transparent Bridge Support
From: Jon Mason @ 2012-08-02  1:49 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, netdev, linux-pci, Dave Jiang
In-Reply-To: <20120731222555.GB19134@kroah.com>

On Tue, Jul 31, 2012 at 03:25:55PM -0700, Greg KH wrote:
> On Sun, Jul 29, 2012 at 05:26:33PM -0700, Jon Mason wrote:
> > +struct ntb_transport_qp;
> > +
> > +struct ntb_client {
> > +	char *name;
> > +	int (*probe) (struct pci_dev *pdev);
> > +	void (*remove) (struct pci_dev *pdev);
> > +};
> 
> Why isn't this tied into the driver model?  That looks like you really
> want to use a 'struct device' here, right?
> 
> Then you have drivers that bind to them, and your devices show up in
> sysfs, which is probably a requirement you have, right?

I was trying to do something more light-weight than that and avoid the
complexity, but this is probably the direction it needs to go.

Thanks,
Jon

> 
> greg k-h

^ permalink raw reply

* Re: [PATCH iproute2] ss: report SK_MEMINFO_BACKLOG
From: Shan Wei @ 2012-08-02  6:24 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Stephen Hemminger, Vijay Subramanian, netdev
In-Reply-To: <1343409083.2626.13105.camel@edumazet-glaptop>

Eric Dumazet said, at 2012/7/28 1:11:
> 
> By the way, it seems "ss -u" still uses /proc/net/udp , and not
> inet_diag ?

Yes, UDP doesn't use inet_diag.
Can you provide a patch, we are willing to see it?

> 
> 
> 
> 
> --
> 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] firmware: Remove obsolete Chelsio cxgb3 firmware
From: David Miller @ 2012-08-02  7:20 UTC (permalink / raw)
  To: tim.gardner
  Cc: linux-kernel, paul.gortmaker, ben, JBottomley, dan.j.williams,
	divy, netdev
In-Reply-To: <1343848670-31504-1-git-send-email-tim.gardner@canonical.com>

From: Tim Gardner <tim.gardner@canonical.com>
Date: Wed,  1 Aug 2012 13:17:50 -0600

> The current firmware version used by the device driver
> is 7.12.0
> 
> Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
> Cc: Ben Hutchings <ben@decadent.org.uk>
> Cc: James Bottomley <JBottomley@Parallels.com>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Divy Le Ray <divy@chelsio.com>
> Cc: netdev@vger.kernel.org
> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>

"git am" refuses to apply this to current 'net':

Applying: firmware: Remove obsolete Chelsio cxgb3 firmware
error: removal patch leaves file contents
error: firmware/cxgb3/t3fw-7.10.0.bin.ihex: patch does not apply

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox