Date: Sun, 9 Jan 2011 04:48:50 +0000 (UTC) From: Jeff Roberson <jeff@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r217179 - in projects/ofed/head/sys/ofed: drivers/infiniband/hw/mlx4 drivers/infiniband/ulp/ipoib include/linux include/rdma Message-ID: <201101090448.p094moND028064@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101090448.p094moND028064>