svn commit: r217179 - in projects/ofed/head/sys/ofed:
drivers/infiniband/hw/mlx4 drivers/infiniband/ulp/ipoib
include/linux include/rdma
Jeff Roberson
jeff at FreeBSD.org
Sun Jan 9 04:48:50 UTC 2011
Author: jeff
Date: Sun Jan 9 04:48:50 2011
New Revision: 217179
URL: http://svn.freebsd.org/changeset/base/217179
Log:
- Add support for VLANs to ipoib. A seperate softc is allocated for
each vlan and cached along with the virtual interface.
- Fixup vlan support for IBOE in ib_addr.h.
Sponsored by: Isilon Systems, iX Systems, and Panasas.
Modified:
projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c
projects/ofed/head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
projects/ofed/head/sys/ofed/include/linux/if_vlan.h
projects/ofed/head/sys/ofed/include/rdma/ib_addr.h
Modified: projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c
==============================================================================
--- projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c Sun Jan 9 04:47:34 2011 (r217178)
+++ projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c Sun Jan 9 04:48:50 2011 (r217179)
@@ -1124,15 +1124,14 @@ static int update_ipv6_gids(struct mlx4_
goto out;
}
- /* XXX vlan */
#ifdef __linux__
read_lock(&dev_base_lock);
for_each_netdev(&init_net, tmp) {
- if (ndev && (tmp == ndev || rdma_vlan_dev_real_dev(tmp) == ndev)) {
#else
- tmp = ndev;
- if (ndev) {
+ IFNET_RLOCK();
+ TAILQ_FOREACH(tmp, &V_ifnet, if_link) {
#endif
+ if (ndev && (tmp == ndev || rdma_vlan_dev_real_dev(tmp) == ndev)) {
gid.global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
vid = rdma_vlan_dev_vlan_id(tmp);
mlx4_addrconf_ifid_eui48(&gid.raw[8], vid, ndev);
@@ -1164,6 +1163,9 @@ static int update_ipv6_gids(struct mlx4_
#ifdef __linux__
}
read_unlock(&dev_base_lock);
+#else
+ }
+ IFNET_RUNLOCK();
#endif
for (i = 0; i < MLX4_MAX_EFF_VLANS + 1; ++i)
Modified: projects/ofed/head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
==============================================================================
--- projects/ofed/head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c Sun Jan 9 04:47:34 2011 (r217178)
+++ projects/ofed/head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c Sun Jan 9 04:48:50 2011 (r217179)
@@ -46,6 +46,7 @@ static int ipoib_resolvemulti(struct ifn
#include <linux/vmalloc.h>
#include <linux/if_arp.h> /* For ARPHRD_xxx */
+#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -115,24 +116,16 @@ ipoib_open(struct ipoib_dev_priv *priv)
if (ipoib_ib_dev_up(priv))
goto err_stop;
-#if 0 /* XXX */
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
struct ipoib_dev_priv *cpriv;
/* Bring up any child interfaces too */
mutex_lock(&priv->vlan_mutex);
- list_for_each_entry(cpriv, &priv->child_intfs, list) {
- int flags;
-
- flags = cpriv->dev->flags;
- if (flags & IFF_UP)
- continue;
-
- dev_change_flags(cpriv->dev, flags | IFF_UP);
- }
+ list_for_each_entry(cpriv, &priv->child_intfs, list)
+ if ((cpriv->dev->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ ipoib_open(cpriv);
mutex_unlock(&priv->vlan_mutex);
}
-#endif
dev->if_drv_flags |= IFF_DRV_RUNNING;
dev->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -175,24 +168,16 @@ ipoib_stop(struct ipoib_dev_priv *priv)
ipoib_ib_dev_down(priv, 0);
ipoib_ib_dev_stop(priv, 0);
-#if 0 /* XXX */
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
struct ipoib_dev_priv *cpriv;
/* Bring down any child interfaces too */
mutex_lock(&priv->vlan_mutex);
- list_for_each_entry(cpriv, &priv->child_intfs, list) {
- int flags;
-
- flags = cpriv->dev->if_flags;
- if (!(flags & IFF_UP))
- continue;
-
- dev_change_flags(cpriv->dev, flags & ~IFF_UP);
- }
+ list_for_each_entry(cpriv, &priv->child_intfs, list)
+ if ((cpriv->dev->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ ipoib_stop(cpriv);
mutex_unlock(&priv->vlan_mutex);
}
-#endif
return 0;
}
@@ -235,13 +220,6 @@ ipoib_ioctl(struct ifnet *ifp, u_long co
struct ifreq *ifr = (struct ifreq *) data;
int error = 0;
- /*
- * We may be called if if_vlan.c doesn't handle something however,
- * if_softc is not our softc in this case.
- */
- if (ifp->if_type != IFT_INFINIBAND)
- return (EINVAL);
-
switch (command) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
@@ -687,30 +665,52 @@ ipoib_send_one(struct ipoib_dev_priv *pr
return 0;
}
+
static void
-ipoib_start(struct ifnet *dev)
+_ipoib_start(struct ifnet *dev, struct ipoib_dev_priv *priv)
{
- struct ipoib_dev_priv *priv;
struct mbuf *mb;
if ((dev->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING)
return;
- priv = dev->if_softc;
spin_lock(&priv->lock);
while (!IFQ_DRV_IS_EMPTY(&dev->if_snd) &&
(dev->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
IFQ_DRV_DEQUEUE(&dev->if_snd, mb);
if (mb == NULL)
break;
-
BPF_MTAP(dev, mb);
ipoib_send_one(priv, mb);
}
spin_unlock(&priv->lock);
}
+static void
+ipoib_start(struct ifnet *dev)
+{
+ _ipoib_start(dev, dev->if_softc);
+}
+
+static void
+ipoib_vlan_start(struct ifnet *dev)
+{
+ struct ipoib_dev_priv *priv;
+ struct mbuf *mb;
+
+ priv = VLAN_COOKIE(dev);
+ if (priv != NULL)
+ return _ipoib_start(dev, priv);
+ while (!IFQ_DRV_IS_EMPTY(&dev->if_snd)) {
+ IFQ_DRV_DEQUEUE(&dev->if_snd, mb);
+ if (mb == NULL)
+ break;
+ m_freem(mb);
+ dev->if_oerrors++;
+ }
+}
+
int
ipoib_dev_init(struct ipoib_dev_priv *priv, struct ib_device *ca, int port)
{
@@ -750,13 +750,18 @@ out:
}
static void
-ipoib_detach(struct ifnet *dev)
+ipoib_detach(struct ipoib_dev_priv *priv)
{
- struct ipoib_dev_priv *priv = dev->if_softc;
+ struct ifnet *dev;
+
+ dev = priv->dev;
+ if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
+ bpfdetach(dev);
+ if_detach(dev);
+ if_free(dev);
+ } else
+ VLAN_SETCOOKIE(priv->dev, NULL);
- bpfdetach(dev);
- if_detach(dev);
- if_free(dev);
free(priv, M_TEMP);
}
@@ -768,7 +773,7 @@ ipoib_dev_cleanup(struct ipoib_dev_priv
/* Delete any child interfaces first */
list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
ipoib_dev_cleanup(cpriv);
- ipoib_detach(cpriv->dev);
+ ipoib_detach(cpriv);
}
ipoib_ib_dev_cleanup(priv);
@@ -821,6 +826,31 @@ static int get_mb_hdr(struct mbuf *mb, v
static volatile int ipoib_unit;
+static struct ipoib_dev_priv *
+ipoib_priv_alloc(void)
+{
+ struct ipoib_dev_priv *priv;
+
+ priv = malloc(sizeof(struct ipoib_dev_priv), M_TEMP, M_ZERO|M_WAITOK);
+ spin_lock_init(&priv->lock);
+ mutex_init(&priv->vlan_mutex);
+ INIT_LIST_HEAD(&priv->path_list);
+ INIT_LIST_HEAD(&priv->child_intfs);
+ INIT_LIST_HEAD(&priv->dead_ahs);
+ INIT_LIST_HEAD(&priv->multicast_list);
+ INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
+ INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task);
+ INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task);
+ INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light);
+ INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal);
+ INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy);
+ INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task);
+ INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah);
+ memcpy(priv->broadcastaddr, ipv4_bcast_addr, INFINIBAND_ALEN);
+
+ return (priv);
+}
+
struct ipoib_dev_priv *
ipoib_intf_alloc(const char *name)
{
@@ -828,7 +858,7 @@ ipoib_intf_alloc(const char *name)
struct sockaddr_dl *sdl;
struct ifnet *dev;
- priv = malloc(sizeof(struct ipoib_dev_priv), M_TEMP, M_ZERO|M_WAITOK);
+ priv = ipoib_priv_alloc();
dev = priv->dev = if_alloc(IFT_INFINIBAND);
if (!dev) {
free(priv, M_TEMP);
@@ -848,35 +878,14 @@ ipoib_intf_alloc(const char *name)
dev->if_resolvemulti = ipoib_resolvemulti;
dev->if_baudrate = IF_Gbps(10LL);
dev->if_broadcastaddr = priv->broadcastaddr;
- memcpy(priv->broadcastaddr, ipv4_bcast_addr, INFINIBAND_ALEN);
dev->if_snd.ifq_maxlen = ipoib_sendq_size * 2;
sdl = (struct sockaddr_dl *)dev->if_addr->ifa_addr;
sdl->sdl_type = IFT_INFINIBAND;
sdl->sdl_alen = dev->if_addrlen;
priv->dev = dev;
if_link_state_change(dev, LINK_STATE_DOWN);
-
bpfattach(dev, DLT_EN10MB, IPOIB_HEADER_LEN);
- spin_lock_init(&priv->lock);
-
- mutex_init(&priv->vlan_mutex);
-
- INIT_LIST_HEAD(&priv->path_list);
- INIT_LIST_HEAD(&priv->child_intfs);
- INIT_LIST_HEAD(&priv->dead_ahs);
- INIT_LIST_HEAD(&priv->multicast_list);
-
- INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
- INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task);
- INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task);
- INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light);
- INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal);
- INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy);
- INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task);
- INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah);
-
-
return dev->if_softc;
}
@@ -999,7 +1008,7 @@ event_failed:
ipoib_dev_cleanup(priv);
device_init_failed:
- ipoib_detach(priv->dev);
+ ipoib_detach(priv);
alloc_mem_failed:
return ERR_PTR(result);
@@ -1065,12 +1074,110 @@ ipoib_remove_one(struct ib_device *devic
flush_workqueue(ipoib_workqueue);
ipoib_dev_cleanup(priv);
- ipoib_detach(priv->dev);
+ ipoib_detach(priv);
}
kfree(dev_list);
}
+static void
+ipoib_config_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
+{
+ struct ipoib_dev_priv *parent;
+ struct ipoib_dev_priv *priv;
+ struct ifnet *dev;
+ uint16_t pkey;
+ int error;
+
+ if (ifp->if_type != IFT_INFINIBAND)
+ return;
+ dev = VLAN_DEVAT(ifp, vtag);
+ if (dev == NULL)
+ return;
+ priv = NULL;
+ error = 0;
+ parent = ifp->if_softc;
+ /* We only support 15 bits of pkey. */
+ if (vtag & 0x8000)
+ return;
+ pkey = vtag | 0x8000; /* Set full membership bit. */
+ if (pkey == parent->pkey)
+ return;
+ /* Check for dups */
+ mutex_lock(&parent->vlan_mutex);
+ list_for_each_entry(priv, &parent->child_intfs, list) {
+ if (priv->pkey == pkey) {
+ priv = NULL;
+ error = EBUSY;
+ goto out;
+ }
+ }
+ priv = ipoib_priv_alloc();
+ priv->dev = dev;
+ priv->max_ib_mtu = parent->max_ib_mtu;
+ priv->mcast_mtu = priv->admin_mtu = parent->dev->if_mtu;
+ set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
+ error = ipoib_set_dev_features(priv, parent->ca);
+ if (error)
+ goto out;
+ priv->pkey = pkey;
+ priv->broadcastaddr[8] = pkey >> 8;
+ priv->broadcastaddr[9] = pkey & 0xff;
+ dev->if_broadcastaddr = priv->broadcastaddr;
+ error = ipoib_dev_init(priv, parent->ca, parent->port);
+ if (error)
+ goto out;
+ priv->parent = parent->dev;
+ list_add_tail(&priv->list, &parent->child_intfs);
+ VLAN_SETCOOKIE(dev, priv);
+ dev->if_start = ipoib_vlan_start;
+ dev->if_drv_flags &= ~IFF_DRV_RUNNING;
+ dev->if_hdrlen = IPOIB_HEADER_LEN;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ipoib_open(priv);
+ mutex_unlock(&parent->vlan_mutex);
+ return;
+out:
+ mutex_unlock(&parent->vlan_mutex);
+ if (priv)
+ free(priv, M_TEMP);
+ if (error)
+ ipoib_warn(parent,
+ "failed to initialize subinterface: device %s, port %d vtag 0x%X",
+ parent->ca->name, parent->port, vtag);
+ return;
+}
+
+static void
+ipoib_unconfig_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
+{
+ struct ipoib_dev_priv *parent;
+ struct ipoib_dev_priv *priv;
+ struct ifnet *dev;
+ uint16_t pkey;
+
+ if (ifp->if_type != IFT_INFINIBAND)
+ return;
+
+ dev = VLAN_DEVAT(ifp, vtag);
+ if (dev)
+ VLAN_SETCOOKIE(dev, NULL);
+ pkey = vtag | 0x8000;
+ parent = ifp->if_softc;
+ mutex_lock(&parent->vlan_mutex);
+ list_for_each_entry(priv, &parent->child_intfs, list) {
+ if (priv->pkey == pkey) {
+ ipoib_dev_cleanup(priv);
+ list_del(&priv->list);
+ break;
+ }
+ }
+ mutex_unlock(&parent->vlan_mutex);
+}
+
+eventhandler_tag ipoib_vlan_attach;
+eventhandler_tag ipoib_vlan_detach;
+
static int __init
ipoib_init_module(void)
{
@@ -1088,6 +1195,11 @@ ipoib_init_module(void)
ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP);
#endif
+ ipoib_vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
+ ipoib_config_vlan, NULL, EVENTHANDLER_PRI_FIRST);
+ ipoib_vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
+ ipoib_unconfig_vlan, NULL, EVENTHANDLER_PRI_FIRST);
+
/*
* We create our own workqueue mainly because we want to be
* able to flush it when devices are being removed. We can't
@@ -1121,6 +1233,9 @@ err_fs:
static void __exit
ipoib_cleanup_module(void)
{
+
+ EVENTHANDLER_DEREGISTER(vlan_config, ipoib_vlan_attach);
+ EVENTHANDLER_DEREGISTER(vlan_unconfig, ipoib_vlan_detach);
ib_unregister_client(&ipoib_client);
ib_sa_unregister_client(&ipoib_sa_client);
destroy_workqueue(ipoib_workqueue);
Modified: projects/ofed/head/sys/ofed/include/linux/if_vlan.h
==============================================================================
--- projects/ofed/head/sys/ofed/include/linux/if_vlan.h Sun Jan 9 04:47:34 2011 (r217178)
+++ projects/ofed/head/sys/ofed/include/linux/if_vlan.h Sun Jan 9 04:48:50 2011 (r217179)
@@ -28,4 +28,8 @@
#ifndef _LINUX_IF_VLAN_H_
#define _LINUX_IF_VLAN_H_
+
+#include <net/ethernet.h>
+#include <net/if_vlan_var.h>
+
#endif /* _LINUX_IF_VLAN_H_ */
Modified: projects/ofed/head/sys/ofed/include/rdma/ib_addr.h
==============================================================================
--- projects/ofed/head/sys/ofed/include/rdma/ib_addr.h Sun Jan 9 04:47:34 2011 (r217178)
+++ projects/ofed/head/sys/ofed/include/rdma/ib_addr.h Sun Jan 9 04:48:50 2011 (r217179)
@@ -154,8 +154,11 @@ static inline u16 rdma_vlan_dev_vlan_id(
return dev->priv_flags & IFF_802_1Q_VLAN ?
vlan_dev_vlan_id(dev) : 0xffff;
#else
- /* XXX vlan */
- return 0xffff;
+ int tag;
+
+ if (VLAN_TAG(__DECONST(struct ifnet *, dev), &tag) != 0)
+ return 0xffff;
+ return tag;
#endif
}
@@ -302,7 +305,7 @@ static inline struct net_device *rdma_vl
return dev->priv_flags & IFF_802_1Q_VLAN ?
vlan_dev_real_dev(dev) : 0;
#else
- return __DECONST(struct net_device *, dev);
+ return VLAN_TRUNKDEV(__DECONST(struct ifnet *, dev));
#endif
}
More information about the svn-src-projects
mailing list