1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004 Topspin Communications. All rights reserved. 3219820Sjeff * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 4219820Sjeff * Copyright (c) 2004 Voltaire, Inc. All rights reserved. 5219820Sjeff * 6219820Sjeff * This software is available to you under a choice of one of two 7219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 8219820Sjeff * General Public License (GPL) Version 2, available from the file 9219820Sjeff * COPYING in the main directory of this source tree, or the 10219820Sjeff * OpenIB.org BSD license below: 11219820Sjeff * 12219820Sjeff * Redistribution and use in source and binary forms, with or 13219820Sjeff * without modification, are permitted provided that the following 14219820Sjeff * conditions are met: 15219820Sjeff * 16219820Sjeff * - Redistributions of source code must retain the above 17219820Sjeff * copyright notice, this list of conditions and the following 18219820Sjeff * disclaimer. 19219820Sjeff * 20219820Sjeff * - Redistributions in binary form must reproduce the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer in the documentation and/or other materials 23219820Sjeff * provided with the distribution. 24219820Sjeff * 25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32219820Sjeff * SOFTWARE. 33219820Sjeff */ 34219820Sjeff 35219820Sjeff#include "ipoib.h" 36219820Sjeff 37219820Sjeffstatic int ipoib_resolvemulti(struct ifnet *, struct sockaddr **, 38219820Sjeff struct sockaddr *); 39219820Sjeff 40219820Sjeff 41219820Sjeff#include <linux/module.h> 42219820Sjeff 43219820Sjeff#include <linux/slab.h> 44219820Sjeff#include <linux/kernel.h> 45219820Sjeff#include <linux/vmalloc.h> 46219820Sjeff 47219820Sjeff#include <linux/if_arp.h> /* For ARPHRD_xxx */ 48219820Sjeff#include <linux/if_vlan.h> 49219820Sjeff#include <net/ip.h> 50219820Sjeff#include <net/ipv6.h> 51219820Sjeff 52219820SjeffMODULE_AUTHOR("Roland Dreier"); 53219820SjeffMODULE_DESCRIPTION("IP-over-InfiniBand net driver"); 54219820SjeffMODULE_LICENSE("Dual BSD/GPL"); 55219820Sjeff 56219820Sjeffint ipoib_sendq_size = IPOIB_TX_RING_SIZE; 57219820Sjeffint ipoib_recvq_size = IPOIB_RX_RING_SIZE; 58219820Sjeff 59219820Sjeffmodule_param_named(send_queue_size, ipoib_sendq_size, int, 0444); 60219820SjeffMODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue"); 61219820Sjeffmodule_param_named(recv_queue_size, ipoib_recvq_size, int, 0444); 62219820SjeffMODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue"); 63219820Sjeff 64219820Sjeff#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 65219820Sjeffint ipoib_debug_level = 1; 66219820Sjeff 67219820Sjeffmodule_param_named(debug_level, ipoib_debug_level, int, 0644); 68219820SjeffMODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); 69219820Sjeff#endif 70219820Sjeff 71219820Sjeffstruct ipoib_path_iter { 72219820Sjeff struct ipoib_dev_priv *priv; 73219820Sjeff struct ipoib_path path; 74219820Sjeff}; 75219820Sjeff 76219820Sjeffstatic const u8 ipv4_bcast_addr[] = { 77219820Sjeff 0x00, 0xff, 0xff, 0xff, 78219820Sjeff 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 79219820Sjeff 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff 80219820Sjeff}; 81219820Sjeff 82219820Sjeffstruct workqueue_struct *ipoib_workqueue; 83219820Sjeff 84219820Sjeffstruct ib_sa_client ipoib_sa_client; 85219820Sjeff 86219820Sjeffstatic void ipoib_add_one(struct ib_device *device); 87219820Sjeffstatic void ipoib_remove_one(struct ib_device *device); 88219820Sjeffstatic void ipoib_start(struct ifnet *dev); 89219820Sjeffstatic int ipoib_output(struct ifnet *ifp, struct mbuf *m, 90249976Sglebius const struct sockaddr *dst, struct route *ro); 91219820Sjeffstatic int ipoib_ioctl(struct ifnet *ifp, u_long command, caddr_t data); 92219820Sjeffstatic void ipoib_input(struct ifnet *ifp, struct mbuf *m); 93219820Sjeff 94219820Sjeff#define IPOIB_MTAP(_ifp, _m) \ 95219820Sjeffdo { \ 96219820Sjeff if (bpf_peers_present((_ifp)->if_bpf)) { \ 97219820Sjeff M_ASSERTVALID(_m); \ 98219820Sjeff ipoib_mtap_mb((_ifp), (_m)); \ 99219820Sjeff } \ 100219820Sjeff} while (0) 101219820Sjeff 102219820Sjeff/* 103219820Sjeff * This is for clients that have an ipoib_header in the mbuf. 104219820Sjeff */ 105219820Sjeffstatic void 106219820Sjeffipoib_mtap_mb(struct ifnet *ifp, struct mbuf *mb) 107219820Sjeff{ 108219820Sjeff struct ipoib_header *ih; 109219820Sjeff struct ether_header eh; 110219820Sjeff 111219820Sjeff ih = mtod(mb, struct ipoib_header *); 112219820Sjeff eh.ether_type = ih->proto; 113219820Sjeff bcopy(ih->hwaddr, &eh.ether_dhost, ETHER_ADDR_LEN); 114219820Sjeff bzero(&eh.ether_shost, ETHER_ADDR_LEN); 115219820Sjeff mb->m_data += sizeof(struct ipoib_header); 116219820Sjeff mb->m_len -= sizeof(struct ipoib_header); 117219820Sjeff bpf_mtap2(ifp->if_bpf, &eh, sizeof(eh), mb); 118219820Sjeff mb->m_data -= sizeof(struct ipoib_header); 119219820Sjeff mb->m_len += sizeof(struct ipoib_header); 120219820Sjeff} 121219820Sjeff 122219820Sjeffvoid 123219820Sjeffipoib_mtap_proto(struct ifnet *ifp, struct mbuf *mb, uint16_t proto) 124219820Sjeff{ 125219820Sjeff struct ether_header eh; 126219820Sjeff 127219820Sjeff eh.ether_type = proto; 128219820Sjeff bzero(&eh.ether_shost, ETHER_ADDR_LEN); 129219820Sjeff bzero(&eh.ether_dhost, ETHER_ADDR_LEN); 130219820Sjeff bpf_mtap2(ifp->if_bpf, &eh, sizeof(eh), mb); 131219820Sjeff} 132219820Sjeff 133219820Sjeffstatic struct ib_client ipoib_client = { 134219820Sjeff .name = "ipoib", 135219820Sjeff .add = ipoib_add_one, 136219820Sjeff .remove = ipoib_remove_one 137219820Sjeff}; 138219820Sjeff 139219820Sjeffint 140219820Sjeffipoib_open(struct ipoib_dev_priv *priv) 141219820Sjeff{ 142219820Sjeff struct ifnet *dev = priv->dev; 143219820Sjeff 144219820Sjeff ipoib_dbg(priv, "bringing up interface\n"); 145219820Sjeff 146219820Sjeff set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 147219820Sjeff 148219820Sjeff if (ipoib_pkey_dev_delay_open(priv)) 149219820Sjeff return 0; 150219820Sjeff 151219820Sjeff if (ipoib_ib_dev_open(priv)) 152219820Sjeff goto err_disable; 153219820Sjeff 154219820Sjeff if (ipoib_ib_dev_up(priv)) 155219820Sjeff goto err_stop; 156219820Sjeff 157219820Sjeff if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 158219820Sjeff struct ipoib_dev_priv *cpriv; 159219820Sjeff 160219820Sjeff /* Bring up any child interfaces too */ 161219820Sjeff mutex_lock(&priv->vlan_mutex); 162219820Sjeff list_for_each_entry(cpriv, &priv->child_intfs, list) 163219820Sjeff if ((cpriv->dev->if_drv_flags & IFF_DRV_RUNNING) == 0) 164219820Sjeff ipoib_open(cpriv); 165219820Sjeff mutex_unlock(&priv->vlan_mutex); 166219820Sjeff } 167219820Sjeff dev->if_drv_flags |= IFF_DRV_RUNNING; 168219820Sjeff dev->if_drv_flags &= ~IFF_DRV_OACTIVE; 169219820Sjeff 170219820Sjeff return 0; 171219820Sjeff 172219820Sjefferr_stop: 173219820Sjeff ipoib_ib_dev_stop(priv, 1); 174219820Sjeff 175219820Sjefferr_disable: 176219820Sjeff clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 177219820Sjeff 178219820Sjeff return -EINVAL; 179219820Sjeff} 180219820Sjeff 181219820Sjeffstatic void 182219820Sjeffipoib_init(void *arg) 183219820Sjeff{ 184219820Sjeff struct ifnet *dev; 185219820Sjeff struct ipoib_dev_priv *priv; 186219820Sjeff 187219820Sjeff priv = arg; 188219820Sjeff dev = priv->dev; 189219820Sjeff if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) 190219820Sjeff ipoib_open(priv); 191219820Sjeff queue_work(ipoib_workqueue, &priv->flush_light); 192219820Sjeff} 193219820Sjeff 194219820Sjeff 195219820Sjeffstatic int 196219820Sjeffipoib_stop(struct ipoib_dev_priv *priv) 197219820Sjeff{ 198219820Sjeff struct ifnet *dev = priv->dev; 199219820Sjeff 200219820Sjeff ipoib_dbg(priv, "stopping interface\n"); 201219820Sjeff 202219820Sjeff clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 203219820Sjeff 204219820Sjeff dev->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 205219820Sjeff 206219820Sjeff ipoib_ib_dev_down(priv, 0); 207219820Sjeff ipoib_ib_dev_stop(priv, 0); 208219820Sjeff 209219820Sjeff if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 210219820Sjeff struct ipoib_dev_priv *cpriv; 211219820Sjeff 212219820Sjeff /* Bring down any child interfaces too */ 213219820Sjeff mutex_lock(&priv->vlan_mutex); 214219820Sjeff list_for_each_entry(cpriv, &priv->child_intfs, list) 215219820Sjeff if ((cpriv->dev->if_drv_flags & IFF_DRV_RUNNING) != 0) 216219820Sjeff ipoib_stop(cpriv); 217219820Sjeff mutex_unlock(&priv->vlan_mutex); 218219820Sjeff } 219219820Sjeff 220219820Sjeff return 0; 221219820Sjeff} 222219820Sjeff 223219820Sjeffint 224219820Sjeffipoib_change_mtu(struct ipoib_dev_priv *priv, int new_mtu) 225219820Sjeff{ 226219820Sjeff struct ifnet *dev = priv->dev; 227219820Sjeff 228219820Sjeff /* dev->if_mtu > 2K ==> connected mode */ 229219820Sjeff if (ipoib_cm_admin_enabled(priv)) { 230219820Sjeff if (new_mtu > IPOIB_CM_MTU(ipoib_cm_max_mtu(priv))) 231219820Sjeff return -EINVAL; 232219820Sjeff 233219820Sjeff if (new_mtu > priv->mcast_mtu) 234219820Sjeff ipoib_warn(priv, "mtu > %d will cause multicast packet drops.\n", 235219820Sjeff priv->mcast_mtu); 236219820Sjeff 237219820Sjeff dev->if_mtu = new_mtu; 238219820Sjeff return 0; 239219820Sjeff } 240219820Sjeff 241219820Sjeff if (new_mtu > IPOIB_UD_MTU(priv->max_ib_mtu)) 242219820Sjeff return -EINVAL; 243219820Sjeff 244219820Sjeff priv->admin_mtu = new_mtu; 245219820Sjeff 246219820Sjeff dev->if_mtu = min(priv->mcast_mtu, priv->admin_mtu); 247219820Sjeff 248219820Sjeff queue_work(ipoib_workqueue, &priv->flush_light); 249219820Sjeff 250219820Sjeff return 0; 251219820Sjeff} 252219820Sjeff 253219820Sjeffstatic int 254219820Sjeffipoib_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 255219820Sjeff{ 256219820Sjeff struct ipoib_dev_priv *priv = ifp->if_softc; 257219820Sjeff struct ifaddr *ifa = (struct ifaddr *) data; 258219820Sjeff struct ifreq *ifr = (struct ifreq *) data; 259219820Sjeff int error = 0; 260219820Sjeff 261219820Sjeff switch (command) { 262219820Sjeff case SIOCSIFFLAGS: 263219820Sjeff if (ifp->if_flags & IFF_UP) { 264219820Sjeff if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 265219820Sjeff error = -ipoib_open(priv); 266219820Sjeff } else 267219820Sjeff if (ifp->if_drv_flags & IFF_DRV_RUNNING) 268219820Sjeff ipoib_stop(priv); 269219820Sjeff break; 270219820Sjeff case SIOCADDMULTI: 271219820Sjeff case SIOCDELMULTI: 272219820Sjeff if (ifp->if_drv_flags & IFF_DRV_RUNNING) 273219820Sjeff queue_work(ipoib_workqueue, &priv->restart_task); 274219820Sjeff break; 275219820Sjeff case SIOCSIFADDR: 276219820Sjeff ifp->if_flags |= IFF_UP; 277219820Sjeff 278219820Sjeff switch (ifa->ifa_addr->sa_family) { 279219820Sjeff#ifdef INET 280219820Sjeff case AF_INET: 281219820Sjeff ifp->if_init(ifp->if_softc); /* before arpwhohas */ 282219820Sjeff arp_ifinit(ifp, ifa); 283219820Sjeff break; 284219820Sjeff#endif 285219820Sjeff default: 286219820Sjeff ifp->if_init(ifp->if_softc); 287219820Sjeff break; 288219820Sjeff } 289219820Sjeff break; 290219820Sjeff 291219820Sjeff case SIOCGIFADDR: 292219820Sjeff { 293219820Sjeff struct sockaddr *sa; 294219820Sjeff 295219820Sjeff sa = (struct sockaddr *) & ifr->ifr_data; 296219820Sjeff bcopy(IF_LLADDR(ifp), 297219820Sjeff (caddr_t) sa->sa_data, INFINIBAND_ALEN); 298219820Sjeff } 299219820Sjeff break; 300219820Sjeff 301219820Sjeff case SIOCSIFMTU: 302219820Sjeff /* 303219820Sjeff * Set the interface MTU. 304219820Sjeff */ 305219820Sjeff error = -ipoib_change_mtu(priv, ifr->ifr_mtu); 306219820Sjeff break; 307219820Sjeff default: 308219820Sjeff error = EINVAL; 309219820Sjeff break; 310219820Sjeff } 311219820Sjeff return (error); 312219820Sjeff} 313219820Sjeff 314219820Sjeff 315219820Sjeffstatic struct ipoib_path * 316219820Sjeff__path_find(struct ipoib_dev_priv *priv, void *gid) 317219820Sjeff{ 318219820Sjeff struct rb_node *n = priv->path_tree.rb_node; 319219820Sjeff struct ipoib_path *path; 320219820Sjeff int ret; 321219820Sjeff 322219820Sjeff while (n) { 323219820Sjeff path = rb_entry(n, struct ipoib_path, rb_node); 324219820Sjeff 325219820Sjeff ret = memcmp(gid, path->pathrec.dgid.raw, 326219820Sjeff sizeof (union ib_gid)); 327219820Sjeff 328219820Sjeff if (ret < 0) 329219820Sjeff n = n->rb_left; 330219820Sjeff else if (ret > 0) 331219820Sjeff n = n->rb_right; 332219820Sjeff else 333219820Sjeff return path; 334219820Sjeff } 335219820Sjeff 336219820Sjeff return NULL; 337219820Sjeff} 338219820Sjeff 339219820Sjeffstatic int 340219820Sjeff__path_add(struct ipoib_dev_priv *priv, struct ipoib_path *path) 341219820Sjeff{ 342219820Sjeff struct rb_node **n = &priv->path_tree.rb_node; 343219820Sjeff struct rb_node *pn = NULL; 344219820Sjeff struct ipoib_path *tpath; 345219820Sjeff int ret; 346219820Sjeff 347219820Sjeff while (*n) { 348219820Sjeff pn = *n; 349219820Sjeff tpath = rb_entry(pn, struct ipoib_path, rb_node); 350219820Sjeff 351219820Sjeff ret = memcmp(path->pathrec.dgid.raw, tpath->pathrec.dgid.raw, 352219820Sjeff sizeof (union ib_gid)); 353219820Sjeff if (ret < 0) 354219820Sjeff n = &pn->rb_left; 355219820Sjeff else if (ret > 0) 356219820Sjeff n = &pn->rb_right; 357219820Sjeff else 358219820Sjeff return -EEXIST; 359219820Sjeff } 360219820Sjeff 361219820Sjeff rb_link_node(&path->rb_node, pn, n); 362219820Sjeff rb_insert_color(&path->rb_node, &priv->path_tree); 363219820Sjeff 364219820Sjeff list_add_tail(&path->list, &priv->path_list); 365219820Sjeff 366219820Sjeff return 0; 367219820Sjeff} 368219820Sjeff 369219820Sjeffvoid 370219820Sjeffipoib_path_free(struct ipoib_dev_priv *priv, struct ipoib_path *path) 371219820Sjeff{ 372219820Sjeff 373219820Sjeff _IF_DRAIN(&path->queue); 374219820Sjeff 375219820Sjeff if (path->ah) 376219820Sjeff ipoib_put_ah(path->ah); 377219820Sjeff if (ipoib_cm_get(path)) 378219820Sjeff ipoib_cm_destroy_tx(ipoib_cm_get(path)); 379219820Sjeff 380219820Sjeff kfree(path); 381219820Sjeff} 382219820Sjeff 383219820Sjeff#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 384219820Sjeff 385219820Sjeffstruct ipoib_path_iter * 386219820Sjeffipoib_path_iter_init(struct ipoib_dev_priv *priv) 387219820Sjeff{ 388219820Sjeff struct ipoib_path_iter *iter; 389219820Sjeff 390219820Sjeff iter = kmalloc(sizeof *iter, GFP_KERNEL); 391219820Sjeff if (!iter) 392219820Sjeff return NULL; 393219820Sjeff 394219820Sjeff iter->priv = priv; 395219820Sjeff memset(iter->path.pathrec.dgid.raw, 0, 16); 396219820Sjeff 397219820Sjeff if (ipoib_path_iter_next(iter)) { 398219820Sjeff kfree(iter); 399219820Sjeff return NULL; 400219820Sjeff } 401219820Sjeff 402219820Sjeff return iter; 403219820Sjeff} 404219820Sjeff 405219820Sjeffint 406219820Sjeffipoib_path_iter_next(struct ipoib_path_iter *iter) 407219820Sjeff{ 408219820Sjeff struct ipoib_dev_priv *priv = iter->priv; 409219820Sjeff struct rb_node *n; 410219820Sjeff struct ipoib_path *path; 411219820Sjeff int ret = 1; 412219820Sjeff 413219820Sjeff spin_lock_irq(&priv->lock); 414219820Sjeff 415219820Sjeff n = rb_first(&priv->path_tree); 416219820Sjeff 417219820Sjeff while (n) { 418219820Sjeff path = rb_entry(n, struct ipoib_path, rb_node); 419219820Sjeff 420219820Sjeff if (memcmp(iter->path.pathrec.dgid.raw, path->pathrec.dgid.raw, 421219820Sjeff sizeof (union ib_gid)) < 0) { 422219820Sjeff iter->path = *path; 423219820Sjeff ret = 0; 424219820Sjeff break; 425219820Sjeff } 426219820Sjeff 427219820Sjeff n = rb_next(n); 428219820Sjeff } 429219820Sjeff 430219820Sjeff spin_unlock_irq(&priv->lock); 431219820Sjeff 432219820Sjeff return ret; 433219820Sjeff} 434219820Sjeff 435219820Sjeffvoid 436219820Sjeffipoib_path_iter_read(struct ipoib_path_iter *iter, struct ipoib_path *path) 437219820Sjeff{ 438219820Sjeff *path = iter->path; 439219820Sjeff} 440219820Sjeff 441219820Sjeff#endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */ 442219820Sjeff 443219820Sjeffvoid 444219820Sjeffipoib_mark_paths_invalid(struct ipoib_dev_priv *priv) 445219820Sjeff{ 446219820Sjeff struct ipoib_path *path, *tp; 447219820Sjeff 448219820Sjeff spin_lock_irq(&priv->lock); 449219820Sjeff 450219820Sjeff list_for_each_entry_safe(path, tp, &priv->path_list, list) { 451219820Sjeff ipoib_dbg(priv, "mark path LID 0x%04x GID %16D invalid\n", 452219820Sjeff be16_to_cpu(path->pathrec.dlid), 453219820Sjeff path->pathrec.dgid.raw, ":"); 454219820Sjeff path->valid = 0; 455219820Sjeff } 456219820Sjeff 457219820Sjeff spin_unlock_irq(&priv->lock); 458219820Sjeff} 459219820Sjeff 460219820Sjeffvoid 461219820Sjeffipoib_flush_paths(struct ipoib_dev_priv *priv) 462219820Sjeff{ 463219820Sjeff struct ipoib_path *path, *tp; 464219820Sjeff LIST_HEAD(remove_list); 465219820Sjeff unsigned long flags; 466219820Sjeff 467219820Sjeff spin_lock_irqsave(&priv->lock, flags); 468219820Sjeff 469219820Sjeff list_splice_init(&priv->path_list, &remove_list); 470219820Sjeff 471219820Sjeff list_for_each_entry(path, &remove_list, list) 472219820Sjeff rb_erase(&path->rb_node, &priv->path_tree); 473219820Sjeff 474219820Sjeff list_for_each_entry_safe(path, tp, &remove_list, list) { 475219820Sjeff if (path->query) 476219820Sjeff ib_sa_cancel_query(path->query_id, path->query); 477219820Sjeff spin_unlock_irqrestore(&priv->lock, flags); 478219820Sjeff wait_for_completion(&path->done); 479219820Sjeff ipoib_path_free(priv, path); 480219820Sjeff spin_lock_irqsave(&priv->lock, flags); 481219820Sjeff } 482219820Sjeff 483219820Sjeff spin_unlock_irqrestore(&priv->lock, flags); 484219820Sjeff} 485219820Sjeff 486219820Sjeffstatic void 487219820Sjeffpath_rec_completion(int status, struct ib_sa_path_rec *pathrec, void *path_ptr) 488219820Sjeff{ 489219820Sjeff struct ipoib_path *path = path_ptr; 490219820Sjeff struct ipoib_dev_priv *priv = path->priv; 491219820Sjeff struct ifnet *dev = priv->dev; 492219820Sjeff struct ipoib_ah *ah = NULL; 493219820Sjeff struct ipoib_ah *old_ah = NULL; 494219820Sjeff struct ifqueue mbqueue; 495219820Sjeff struct mbuf *mb; 496219820Sjeff unsigned long flags; 497219820Sjeff 498219820Sjeff if (!status) 499219820Sjeff ipoib_dbg(priv, "PathRec LID 0x%04x for GID %16D\n", 500219820Sjeff be16_to_cpu(pathrec->dlid), pathrec->dgid.raw, ":"); 501219820Sjeff else 502219820Sjeff ipoib_dbg(priv, "PathRec status %d for GID %16D\n", 503219820Sjeff status, path->pathrec.dgid.raw, ":"); 504219820Sjeff 505219820Sjeff bzero(&mbqueue, sizeof(mbqueue)); 506219820Sjeff 507219820Sjeff if (!status) { 508219820Sjeff struct ib_ah_attr av; 509219820Sjeff 510219820Sjeff if (!ib_init_ah_from_path(priv->ca, priv->port, pathrec, &av)) 511219820Sjeff ah = ipoib_create_ah(priv, priv->pd, &av); 512219820Sjeff } 513219820Sjeff 514219820Sjeff spin_lock_irqsave(&priv->lock, flags); 515219820Sjeff 516219820Sjeff if (ah) { 517219820Sjeff path->pathrec = *pathrec; 518219820Sjeff 519219820Sjeff old_ah = path->ah; 520219820Sjeff path->ah = ah; 521219820Sjeff 522219820Sjeff ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n", 523219820Sjeff ah, be16_to_cpu(pathrec->dlid), pathrec->sl); 524219820Sjeff 525219820Sjeff for (;;) { 526219820Sjeff _IF_DEQUEUE(&path->queue, mb); 527219820Sjeff if (mb == NULL) 528219820Sjeff break; 529219820Sjeff _IF_ENQUEUE(&mbqueue, mb); 530219820Sjeff } 531219820Sjeff 532219820Sjeff#ifdef CONFIG_INFINIBAND_IPOIB_CM 533219820Sjeff if (ipoib_cm_enabled(priv, path->hwaddr) && !ipoib_cm_get(path)) 534219820Sjeff ipoib_cm_set(path, ipoib_cm_create_tx(priv, path)); 535219820Sjeff#endif 536219820Sjeff 537219820Sjeff path->valid = 1; 538219820Sjeff } 539219820Sjeff 540219820Sjeff path->query = NULL; 541219820Sjeff complete(&path->done); 542219820Sjeff 543219820Sjeff spin_unlock_irqrestore(&priv->lock, flags); 544219820Sjeff 545219820Sjeff if (old_ah) 546219820Sjeff ipoib_put_ah(old_ah); 547219820Sjeff 548219820Sjeff for (;;) { 549219820Sjeff _IF_DEQUEUE(&mbqueue, mb); 550219820Sjeff if (mb == NULL) 551219820Sjeff break; 552219820Sjeff mb->m_pkthdr.rcvif = dev; 553219820Sjeff if (dev->if_transmit(dev, mb)) 554219820Sjeff ipoib_warn(priv, "dev_queue_xmit failed " 555219820Sjeff "to requeue packet\n"); 556219820Sjeff } 557219820Sjeff} 558219820Sjeff 559219820Sjeffstatic struct ipoib_path * 560219820Sjeffpath_rec_create(struct ipoib_dev_priv *priv, uint8_t *hwaddr) 561219820Sjeff{ 562219820Sjeff struct ipoib_path *path; 563219820Sjeff 564219820Sjeff if (!priv->broadcast) 565219820Sjeff return NULL; 566219820Sjeff 567219820Sjeff path = kzalloc(sizeof *path, GFP_ATOMIC); 568219820Sjeff if (!path) 569219820Sjeff return NULL; 570219820Sjeff 571219820Sjeff path->priv = priv; 572219820Sjeff 573219820Sjeff bzero(&path->queue, sizeof(path->queue)); 574219820Sjeff 575219820Sjeff#ifdef CONFIG_INFINIBAND_IPOIB_CM 576219820Sjeff memcpy(&path->hwaddr, hwaddr, INFINIBAND_ALEN); 577219820Sjeff#endif 578219820Sjeff memcpy(path->pathrec.dgid.raw, &hwaddr[4], sizeof (union ib_gid)); 579219820Sjeff path->pathrec.sgid = priv->local_gid; 580219820Sjeff path->pathrec.pkey = cpu_to_be16(priv->pkey); 581219820Sjeff path->pathrec.numb_path = 1; 582219820Sjeff path->pathrec.traffic_class = priv->broadcast->mcmember.traffic_class; 583219820Sjeff 584219820Sjeff return path; 585219820Sjeff} 586219820Sjeff 587219820Sjeffstatic int 588219820Sjeffpath_rec_start(struct ipoib_dev_priv *priv, struct ipoib_path *path) 589219820Sjeff{ 590219820Sjeff struct ifnet *dev = priv->dev; 591219820Sjeff 592219820Sjeff ib_sa_comp_mask comp_mask = IB_SA_PATH_REC_MTU_SELECTOR | IB_SA_PATH_REC_MTU; 593219820Sjeff struct ib_sa_path_rec p_rec; 594219820Sjeff 595219820Sjeff p_rec = path->pathrec; 596219820Sjeff p_rec.mtu_selector = IB_SA_GT; 597219820Sjeff 598219820Sjeff switch (roundup_pow_of_two(dev->if_mtu + IPOIB_ENCAP_LEN)) { 599219820Sjeff case 512: 600219820Sjeff p_rec.mtu = IB_MTU_256; 601219820Sjeff break; 602219820Sjeff case 1024: 603219820Sjeff p_rec.mtu = IB_MTU_512; 604219820Sjeff break; 605219820Sjeff case 2048: 606219820Sjeff p_rec.mtu = IB_MTU_1024; 607219820Sjeff break; 608219820Sjeff case 4096: 609219820Sjeff p_rec.mtu = IB_MTU_2048; 610219820Sjeff break; 611219820Sjeff default: 612219820Sjeff /* Wildcard everything */ 613219820Sjeff comp_mask = 0; 614219820Sjeff p_rec.mtu = 0; 615219820Sjeff p_rec.mtu_selector = 0; 616219820Sjeff } 617219820Sjeff 618219820Sjeff ipoib_dbg(priv, "Start path record lookup for %16D MTU > %d\n", 619219820Sjeff p_rec.dgid.raw, ":", 620219820Sjeff comp_mask ? ib_mtu_enum_to_int(p_rec.mtu) : 0); 621219820Sjeff 622219820Sjeff init_completion(&path->done); 623219820Sjeff 624219820Sjeff path->query_id = 625219820Sjeff ib_sa_path_rec_get(&ipoib_sa_client, priv->ca, priv->port, 626219820Sjeff &p_rec, comp_mask | 627219820Sjeff IB_SA_PATH_REC_DGID | 628219820Sjeff IB_SA_PATH_REC_SGID | 629219820Sjeff IB_SA_PATH_REC_NUMB_PATH | 630219820Sjeff IB_SA_PATH_REC_TRAFFIC_CLASS | 631219820Sjeff IB_SA_PATH_REC_PKEY, 632219820Sjeff 1000, GFP_ATOMIC, 633219820Sjeff path_rec_completion, 634219820Sjeff path, &path->query); 635219820Sjeff if (path->query_id < 0) { 636219820Sjeff ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); 637219820Sjeff path->query = NULL; 638219820Sjeff complete(&path->done); 639219820Sjeff return path->query_id; 640219820Sjeff } 641219820Sjeff 642219820Sjeff return 0; 643219820Sjeff} 644219820Sjeff 645219820Sjeffstatic void 646219820Sjeffipoib_unicast_send(struct mbuf *mb, struct ipoib_dev_priv *priv, struct ipoib_header *eh) 647219820Sjeff{ 648219820Sjeff struct ipoib_path *path; 649219820Sjeff 650219820Sjeff path = __path_find(priv, eh->hwaddr + 4); 651219820Sjeff if (!path || !path->valid) { 652219820Sjeff int new_path = 0; 653219820Sjeff 654219820Sjeff if (!path) { 655219820Sjeff path = path_rec_create(priv, eh->hwaddr); 656219820Sjeff new_path = 1; 657219820Sjeff } 658219820Sjeff if (path) { 659219820Sjeff _IF_ENQUEUE(&path->queue, mb); 660219820Sjeff if (!path->query && path_rec_start(priv, path)) { 661219820Sjeff spin_unlock_irqrestore(&priv->lock, flags); 662219820Sjeff if (new_path) 663219820Sjeff ipoib_path_free(priv, path); 664219820Sjeff return; 665219820Sjeff } else 666219820Sjeff __path_add(priv, path); 667219820Sjeff } else { 668219820Sjeff ++priv->dev->if_oerrors; 669219820Sjeff m_freem(mb); 670219820Sjeff } 671219820Sjeff 672219820Sjeff return; 673219820Sjeff } 674219820Sjeff 675219820Sjeff if (ipoib_cm_get(path) && ipoib_cm_up(path)) { 676219820Sjeff ipoib_cm_send(priv, mb, ipoib_cm_get(path)); 677219820Sjeff } else if (path->ah) { 678219820Sjeff ipoib_send(priv, mb, path->ah, IPOIB_QPN(eh->hwaddr)); 679219820Sjeff } else if ((path->query || !path_rec_start(priv, path)) && 680219820Sjeff path->queue.ifq_len < IPOIB_MAX_PATH_REC_QUEUE) { 681219820Sjeff _IF_ENQUEUE(&path->queue, mb); 682219820Sjeff } else { 683219820Sjeff ++priv->dev->if_oerrors; 684219820Sjeff m_freem(mb); 685219820Sjeff } 686219820Sjeff} 687219820Sjeff 688219820Sjeffstatic int 689219820Sjeffipoib_send_one(struct ipoib_dev_priv *priv, struct mbuf *mb) 690219820Sjeff{ 691219820Sjeff struct ipoib_header *eh; 692219820Sjeff 693219820Sjeff eh = mtod(mb, struct ipoib_header *); 694219820Sjeff if (IPOIB_IS_MULTICAST(eh->hwaddr)) { 695219820Sjeff /* Add in the P_Key for multicast*/ 696219820Sjeff eh->hwaddr[8] = (priv->pkey >> 8) & 0xff; 697219820Sjeff eh->hwaddr[9] = priv->pkey & 0xff; 698219820Sjeff 699219820Sjeff ipoib_mcast_send(priv, eh->hwaddr + 4, mb); 700219820Sjeff } else 701219820Sjeff ipoib_unicast_send(mb, priv, eh); 702219820Sjeff 703219820Sjeff return 0; 704219820Sjeff} 705219820Sjeff 706219820Sjeff 707219820Sjeffstatic void 708219820Sjeff_ipoib_start(struct ifnet *dev, struct ipoib_dev_priv *priv) 709219820Sjeff{ 710219820Sjeff struct mbuf *mb; 711219820Sjeff 712219820Sjeff if ((dev->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != 713219820Sjeff IFF_DRV_RUNNING) 714219820Sjeff return; 715219820Sjeff 716219820Sjeff spin_lock(&priv->lock); 717219820Sjeff while (!IFQ_DRV_IS_EMPTY(&dev->if_snd) && 718219820Sjeff (dev->if_drv_flags & IFF_DRV_OACTIVE) == 0) { 719219820Sjeff IFQ_DRV_DEQUEUE(&dev->if_snd, mb); 720219820Sjeff if (mb == NULL) 721219820Sjeff break; 722219820Sjeff IPOIB_MTAP(dev, mb); 723219820Sjeff ipoib_send_one(priv, mb); 724219820Sjeff } 725219820Sjeff spin_unlock(&priv->lock); 726219820Sjeff} 727219820Sjeff 728219820Sjeffstatic void 729219820Sjeffipoib_start(struct ifnet *dev) 730219820Sjeff{ 731219820Sjeff _ipoib_start(dev, dev->if_softc); 732219820Sjeff} 733219820Sjeff 734219820Sjeffstatic void 735219820Sjeffipoib_vlan_start(struct ifnet *dev) 736219820Sjeff{ 737219820Sjeff struct ipoib_dev_priv *priv; 738219820Sjeff struct mbuf *mb; 739219820Sjeff 740219820Sjeff priv = VLAN_COOKIE(dev); 741219820Sjeff if (priv != NULL) 742219820Sjeff return _ipoib_start(dev, priv); 743219820Sjeff while (!IFQ_DRV_IS_EMPTY(&dev->if_snd)) { 744219820Sjeff IFQ_DRV_DEQUEUE(&dev->if_snd, mb); 745219820Sjeff if (mb == NULL) 746219820Sjeff break; 747219820Sjeff m_freem(mb); 748219820Sjeff dev->if_oerrors++; 749219820Sjeff } 750219820Sjeff} 751219820Sjeff 752219820Sjeffint 753219820Sjeffipoib_dev_init(struct ipoib_dev_priv *priv, struct ib_device *ca, int port) 754219820Sjeff{ 755219820Sjeff 756219820Sjeff /* Allocate RX/TX "rings" to hold queued mbs */ 757219820Sjeff priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, 758219820Sjeff GFP_KERNEL); 759219820Sjeff if (!priv->rx_ring) { 760219820Sjeff printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", 761219820Sjeff ca->name, ipoib_recvq_size); 762219820Sjeff goto out; 763219820Sjeff } 764219820Sjeff 765219820Sjeff priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring, GFP_KERNEL); 766219820Sjeff if (!priv->tx_ring) { 767219820Sjeff printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", 768219820Sjeff ca->name, ipoib_sendq_size); 769219820Sjeff goto out_rx_ring_cleanup; 770219820Sjeff } 771219820Sjeff memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring); 772219820Sjeff 773219820Sjeff /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ 774219820Sjeff 775219820Sjeff if (ipoib_ib_dev_init(priv, ca, port)) 776219820Sjeff goto out_tx_ring_cleanup; 777219820Sjeff 778219820Sjeff return 0; 779219820Sjeff 780219820Sjeffout_tx_ring_cleanup: 781219820Sjeff kfree(priv->tx_ring); 782219820Sjeff 783219820Sjeffout_rx_ring_cleanup: 784219820Sjeff kfree(priv->rx_ring); 785219820Sjeff 786219820Sjeffout: 787219820Sjeff return -ENOMEM; 788219820Sjeff} 789219820Sjeff 790219820Sjeffstatic void 791219820Sjeffipoib_detach(struct ipoib_dev_priv *priv) 792219820Sjeff{ 793219820Sjeff struct ifnet *dev; 794219820Sjeff 795219820Sjeff dev = priv->dev; 796219820Sjeff if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 797219820Sjeff bpfdetach(dev); 798219820Sjeff if_detach(dev); 799219820Sjeff if_free(dev); 800219820Sjeff } else 801219820Sjeff VLAN_SETCOOKIE(priv->dev, NULL); 802219820Sjeff 803219820Sjeff free(priv, M_TEMP); 804219820Sjeff} 805219820Sjeff 806219820Sjeffvoid 807219820Sjeffipoib_dev_cleanup(struct ipoib_dev_priv *priv) 808219820Sjeff{ 809219820Sjeff struct ipoib_dev_priv *cpriv, *tcpriv; 810219820Sjeff 811219820Sjeff /* Delete any child interfaces first */ 812219820Sjeff list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { 813219820Sjeff ipoib_dev_cleanup(cpriv); 814219820Sjeff ipoib_detach(cpriv); 815219820Sjeff } 816219820Sjeff 817219820Sjeff ipoib_ib_dev_cleanup(priv); 818219820Sjeff 819219820Sjeff kfree(priv->rx_ring); 820219820Sjeff kfree(priv->tx_ring); 821219820Sjeff 822219820Sjeff priv->rx_ring = NULL; 823219820Sjeff priv->tx_ring = NULL; 824219820Sjeff} 825219820Sjeff 826219820Sjeffstatic volatile int ipoib_unit; 827219820Sjeff 828219820Sjeffstatic struct ipoib_dev_priv * 829219820Sjeffipoib_priv_alloc(void) 830219820Sjeff{ 831219820Sjeff struct ipoib_dev_priv *priv; 832219820Sjeff 833219820Sjeff priv = malloc(sizeof(struct ipoib_dev_priv), M_TEMP, M_ZERO|M_WAITOK); 834219820Sjeff spin_lock_init(&priv->lock); 835219820Sjeff mutex_init(&priv->vlan_mutex); 836219820Sjeff INIT_LIST_HEAD(&priv->path_list); 837219820Sjeff INIT_LIST_HEAD(&priv->child_intfs); 838219820Sjeff INIT_LIST_HEAD(&priv->dead_ahs); 839219820Sjeff INIT_LIST_HEAD(&priv->multicast_list); 840219820Sjeff INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll); 841219820Sjeff INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); 842219820Sjeff INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); 843219820Sjeff INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); 844219820Sjeff INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); 845219820Sjeff INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); 846219820Sjeff INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); 847219820Sjeff INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); 848219820Sjeff memcpy(priv->broadcastaddr, ipv4_bcast_addr, INFINIBAND_ALEN); 849219820Sjeff 850219820Sjeff return (priv); 851219820Sjeff} 852219820Sjeff 853219820Sjeffstruct ipoib_dev_priv * 854219820Sjeffipoib_intf_alloc(const char *name) 855219820Sjeff{ 856219820Sjeff struct ipoib_dev_priv *priv; 857219820Sjeff struct sockaddr_dl *sdl; 858219820Sjeff struct ifnet *dev; 859219820Sjeff 860219820Sjeff priv = ipoib_priv_alloc(); 861219820Sjeff dev = priv->dev = if_alloc(IFT_INFINIBAND); 862219820Sjeff if (!dev) { 863219820Sjeff free(priv, M_TEMP); 864219820Sjeff return NULL; 865219820Sjeff } 866219820Sjeff dev->if_softc = priv; 867219820Sjeff if_initname(dev, name, atomic_fetchadd_int(&ipoib_unit, 1)); 868219820Sjeff dev->if_flags = IFF_BROADCAST | IFF_MULTICAST; 869219820Sjeff dev->if_addrlen = INFINIBAND_ALEN; 870219820Sjeff dev->if_hdrlen = IPOIB_HEADER_LEN; 871219820Sjeff if_attach(dev); 872219820Sjeff dev->if_init = ipoib_init; 873219820Sjeff dev->if_ioctl = ipoib_ioctl; 874219820Sjeff dev->if_start = ipoib_start; 875219820Sjeff dev->if_output = ipoib_output; 876219820Sjeff dev->if_input = ipoib_input; 877219820Sjeff dev->if_resolvemulti = ipoib_resolvemulti; 878241696Sjhb if_initbaudrate(dev, IF_Gbps(10)); 879219820Sjeff dev->if_broadcastaddr = priv->broadcastaddr; 880219820Sjeff dev->if_snd.ifq_maxlen = ipoib_sendq_size * 2; 881219820Sjeff sdl = (struct sockaddr_dl *)dev->if_addr->ifa_addr; 882219820Sjeff sdl->sdl_type = IFT_INFINIBAND; 883219820Sjeff sdl->sdl_alen = dev->if_addrlen; 884219820Sjeff priv->dev = dev; 885219820Sjeff if_link_state_change(dev, LINK_STATE_DOWN); 886219820Sjeff bpfattach(dev, DLT_EN10MB, ETHER_HDR_LEN); 887219820Sjeff 888219820Sjeff return dev->if_softc; 889219820Sjeff} 890219820Sjeff 891219820Sjeffint 892219820Sjeffipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) 893219820Sjeff{ 894219820Sjeff struct ib_device_attr *device_attr; 895219820Sjeff int result = -ENOMEM; 896219820Sjeff 897219820Sjeff device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); 898219820Sjeff if (!device_attr) { 899219820Sjeff printk(KERN_WARNING "%s: allocation of %zu bytes failed\n", 900219820Sjeff hca->name, sizeof *device_attr); 901219820Sjeff return result; 902219820Sjeff } 903219820Sjeff 904219820Sjeff result = ib_query_device(hca, device_attr); 905219820Sjeff if (result) { 906219820Sjeff printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n", 907219820Sjeff hca->name, result); 908219820Sjeff kfree(device_attr); 909219820Sjeff return result; 910219820Sjeff } 911219820Sjeff priv->hca_caps = device_attr->device_cap_flags; 912219820Sjeff 913219820Sjeff kfree(device_attr); 914219820Sjeff 915219820Sjeff priv->dev->if_hwassist = 0; 916219820Sjeff priv->dev->if_capabilities = 0; 917219820Sjeff 918219820Sjeff#ifndef CONFIG_INFINIBAND_IPOIB_CM 919219820Sjeff if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { 920219820Sjeff set_bit(IPOIB_FLAG_CSUM, &priv->flags); 921219820Sjeff priv->dev->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP; 922219820Sjeff priv->dev->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; 923219820Sjeff } 924219820Sjeff 925219820Sjeff#if 0 926220555Sbz if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) { 927220555Sbz priv->dev->if_capabilities |= IFCAP_TSO4; 928220555Sbz priv->dev->if_hwassist |= CSUM_TSO; 929220555Sbz } 930219820Sjeff#endif 931219820Sjeff#endif 932219820Sjeff priv->dev->if_capabilities |= 933219820Sjeff IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_LINKSTATE; 934219820Sjeff priv->dev->if_capenable = priv->dev->if_capabilities; 935219820Sjeff 936219820Sjeff return 0; 937219820Sjeff} 938219820Sjeff 939219820Sjeff 940219820Sjeffstatic struct ifnet * 941219820Sjeffipoib_add_port(const char *format, struct ib_device *hca, u8 port) 942219820Sjeff{ 943219820Sjeff struct ipoib_dev_priv *priv; 944219820Sjeff struct ib_port_attr attr; 945219820Sjeff int result = -ENOMEM; 946219820Sjeff 947219820Sjeff priv = ipoib_intf_alloc(format); 948219820Sjeff if (!priv) 949219820Sjeff goto alloc_mem_failed; 950219820Sjeff 951219820Sjeff if (!ib_query_port(hca, port, &attr)) 952219820Sjeff priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); 953219820Sjeff else { 954219820Sjeff printk(KERN_WARNING "%s: ib_query_port %d failed\n", 955219820Sjeff hca->name, port); 956219820Sjeff goto device_init_failed; 957219820Sjeff } 958219820Sjeff 959219820Sjeff /* MTU will be reset when mcast join happens */ 960219820Sjeff priv->dev->if_mtu = IPOIB_UD_MTU(priv->max_ib_mtu); 961219820Sjeff priv->mcast_mtu = priv->admin_mtu = priv->dev->if_mtu; 962219820Sjeff 963219820Sjeff result = ib_query_pkey(hca, port, 0, &priv->pkey); 964219820Sjeff if (result) { 965219820Sjeff printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n", 966219820Sjeff hca->name, port, result); 967219820Sjeff goto device_init_failed; 968219820Sjeff } 969219820Sjeff 970219820Sjeff if (ipoib_set_dev_features(priv, hca)) 971219820Sjeff goto device_init_failed; 972219820Sjeff 973219820Sjeff /* 974219820Sjeff * Set the full membership bit, so that we join the right 975219820Sjeff * broadcast group, etc. 976219820Sjeff */ 977219820Sjeff priv->pkey |= 0x8000; 978219820Sjeff 979219820Sjeff priv->broadcastaddr[8] = priv->pkey >> 8; 980219820Sjeff priv->broadcastaddr[9] = priv->pkey & 0xff; 981219820Sjeff 982219820Sjeff result = ib_query_gid(hca, port, 0, &priv->local_gid); 983219820Sjeff if (result) { 984219820Sjeff printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n", 985219820Sjeff hca->name, port, result); 986219820Sjeff goto device_init_failed; 987219820Sjeff } 988219820Sjeff memcpy(IF_LLADDR(priv->dev) + 4, priv->local_gid.raw, sizeof (union ib_gid)); 989219820Sjeff 990219820Sjeff result = ipoib_dev_init(priv, hca, port); 991219820Sjeff if (result < 0) { 992219820Sjeff printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n", 993219820Sjeff hca->name, port, result); 994219820Sjeff goto device_init_failed; 995219820Sjeff } 996219820Sjeff if (ipoib_cm_admin_enabled(priv)) 997219820Sjeff priv->dev->if_mtu = IPOIB_CM_MTU(ipoib_cm_max_mtu(priv)); 998219820Sjeff 999219820Sjeff INIT_IB_EVENT_HANDLER(&priv->event_handler, 1000219820Sjeff priv->ca, ipoib_event); 1001219820Sjeff result = ib_register_event_handler(&priv->event_handler); 1002219820Sjeff if (result < 0) { 1003219820Sjeff printk(KERN_WARNING "%s: ib_register_event_handler failed for " 1004219820Sjeff "port %d (ret = %d)\n", 1005219820Sjeff hca->name, port, result); 1006219820Sjeff goto event_failed; 1007219820Sjeff } 1008219820Sjeff if_printf(priv->dev, "Attached to %s port %d\n", hca->name, port); 1009219820Sjeff 1010219820Sjeff return priv->dev; 1011219820Sjeff 1012219820Sjeffevent_failed: 1013219820Sjeff ipoib_dev_cleanup(priv); 1014219820Sjeff 1015219820Sjeffdevice_init_failed: 1016219820Sjeff ipoib_detach(priv); 1017219820Sjeff 1018219820Sjeffalloc_mem_failed: 1019219820Sjeff return ERR_PTR(result); 1020219820Sjeff} 1021219820Sjeff 1022219820Sjeffstatic void 1023219820Sjeffipoib_add_one(struct ib_device *device) 1024219820Sjeff{ 1025219820Sjeff struct list_head *dev_list; 1026219820Sjeff struct ifnet *dev; 1027219820Sjeff struct ipoib_dev_priv *priv; 1028219820Sjeff int s, e, p; 1029219820Sjeff 1030219820Sjeff if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) 1031219820Sjeff return; 1032219820Sjeff 1033219820Sjeff dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); 1034219820Sjeff if (!dev_list) 1035219820Sjeff return; 1036219820Sjeff 1037219820Sjeff INIT_LIST_HEAD(dev_list); 1038219820Sjeff 1039219820Sjeff if (device->node_type == RDMA_NODE_IB_SWITCH) { 1040219820Sjeff s = 0; 1041219820Sjeff e = 0; 1042219820Sjeff } else { 1043219820Sjeff s = 1; 1044219820Sjeff e = device->phys_port_cnt; 1045219820Sjeff } 1046219820Sjeff 1047219820Sjeff for (p = s; p <= e; ++p) { 1048219820Sjeff if (rdma_port_get_link_layer(device, p) != IB_LINK_LAYER_INFINIBAND) 1049219820Sjeff continue; 1050219820Sjeff dev = ipoib_add_port("ib", device, p); 1051219820Sjeff if (!IS_ERR(dev)) { 1052219820Sjeff priv = dev->if_softc; 1053219820Sjeff list_add_tail(&priv->list, dev_list); 1054219820Sjeff } 1055219820Sjeff } 1056219820Sjeff 1057219820Sjeff ib_set_client_data(device, &ipoib_client, dev_list); 1058219820Sjeff} 1059219820Sjeff 1060219820Sjeffstatic void 1061219820Sjeffipoib_remove_one(struct ib_device *device) 1062219820Sjeff{ 1063219820Sjeff struct ipoib_dev_priv *priv, *tmp; 1064219820Sjeff struct list_head *dev_list; 1065219820Sjeff 1066219820Sjeff if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) 1067219820Sjeff return; 1068219820Sjeff 1069219820Sjeff dev_list = ib_get_client_data(device, &ipoib_client); 1070219820Sjeff 1071219820Sjeff list_for_each_entry_safe(priv, tmp, dev_list, list) { 1072219820Sjeff if (rdma_port_get_link_layer(device, priv->port) != IB_LINK_LAYER_INFINIBAND) 1073219820Sjeff continue; 1074219820Sjeff 1075254576Sjhb ipoib_stop(priv); 1076254576Sjhb 1077219820Sjeff ib_unregister_event_handler(&priv->event_handler); 1078219820Sjeff 1079219820Sjeff /* dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); */ 1080219820Sjeff 1081219820Sjeff flush_workqueue(ipoib_workqueue); 1082219820Sjeff 1083219820Sjeff ipoib_dev_cleanup(priv); 1084219820Sjeff ipoib_detach(priv); 1085219820Sjeff } 1086219820Sjeff 1087219820Sjeff kfree(dev_list); 1088219820Sjeff} 1089219820Sjeff 1090219820Sjeffstatic void 1091219820Sjeffipoib_config_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag) 1092219820Sjeff{ 1093219820Sjeff struct ipoib_dev_priv *parent; 1094219820Sjeff struct ipoib_dev_priv *priv; 1095219820Sjeff struct ifnet *dev; 1096219820Sjeff uint16_t pkey; 1097219820Sjeff int error; 1098219820Sjeff 1099219820Sjeff if (ifp->if_type != IFT_INFINIBAND) 1100219820Sjeff return; 1101219820Sjeff dev = VLAN_DEVAT(ifp, vtag); 1102219820Sjeff if (dev == NULL) 1103219820Sjeff return; 1104219820Sjeff priv = NULL; 1105219820Sjeff error = 0; 1106219820Sjeff parent = ifp->if_softc; 1107219820Sjeff /* We only support 15 bits of pkey. */ 1108219820Sjeff if (vtag & 0x8000) 1109219820Sjeff return; 1110219820Sjeff pkey = vtag | 0x8000; /* Set full membership bit. */ 1111219820Sjeff if (pkey == parent->pkey) 1112219820Sjeff return; 1113219820Sjeff /* Check for dups */ 1114219820Sjeff mutex_lock(&parent->vlan_mutex); 1115219820Sjeff list_for_each_entry(priv, &parent->child_intfs, list) { 1116219820Sjeff if (priv->pkey == pkey) { 1117219820Sjeff priv = NULL; 1118219820Sjeff error = EBUSY; 1119219820Sjeff goto out; 1120219820Sjeff } 1121219820Sjeff } 1122219820Sjeff priv = ipoib_priv_alloc(); 1123219820Sjeff priv->dev = dev; 1124219820Sjeff priv->max_ib_mtu = parent->max_ib_mtu; 1125219820Sjeff priv->mcast_mtu = priv->admin_mtu = parent->dev->if_mtu; 1126219820Sjeff set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags); 1127219820Sjeff error = ipoib_set_dev_features(priv, parent->ca); 1128219820Sjeff if (error) 1129219820Sjeff goto out; 1130219820Sjeff priv->pkey = pkey; 1131219820Sjeff priv->broadcastaddr[8] = pkey >> 8; 1132219820Sjeff priv->broadcastaddr[9] = pkey & 0xff; 1133219820Sjeff dev->if_broadcastaddr = priv->broadcastaddr; 1134219820Sjeff error = ipoib_dev_init(priv, parent->ca, parent->port); 1135219820Sjeff if (error) 1136219820Sjeff goto out; 1137219820Sjeff priv->parent = parent->dev; 1138219820Sjeff list_add_tail(&priv->list, &parent->child_intfs); 1139219820Sjeff VLAN_SETCOOKIE(dev, priv); 1140219820Sjeff dev->if_start = ipoib_vlan_start; 1141219820Sjeff dev->if_drv_flags &= ~IFF_DRV_RUNNING; 1142219820Sjeff dev->if_hdrlen = IPOIB_HEADER_LEN; 1143219820Sjeff if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1144219820Sjeff ipoib_open(priv); 1145219820Sjeff mutex_unlock(&parent->vlan_mutex); 1146219820Sjeff return; 1147219820Sjeffout: 1148219820Sjeff mutex_unlock(&parent->vlan_mutex); 1149219820Sjeff if (priv) 1150219820Sjeff free(priv, M_TEMP); 1151219820Sjeff if (error) 1152219820Sjeff ipoib_warn(parent, 1153219820Sjeff "failed to initialize subinterface: device %s, port %d vtag 0x%X", 1154219820Sjeff parent->ca->name, parent->port, vtag); 1155219820Sjeff return; 1156219820Sjeff} 1157219820Sjeff 1158219820Sjeffstatic void 1159219820Sjeffipoib_unconfig_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag) 1160219820Sjeff{ 1161219820Sjeff struct ipoib_dev_priv *parent; 1162219820Sjeff struct ipoib_dev_priv *priv; 1163219820Sjeff struct ifnet *dev; 1164219820Sjeff uint16_t pkey; 1165219820Sjeff 1166219820Sjeff if (ifp->if_type != IFT_INFINIBAND) 1167219820Sjeff return; 1168219820Sjeff 1169219820Sjeff dev = VLAN_DEVAT(ifp, vtag); 1170219820Sjeff if (dev) 1171219820Sjeff VLAN_SETCOOKIE(dev, NULL); 1172219820Sjeff pkey = vtag | 0x8000; 1173219820Sjeff parent = ifp->if_softc; 1174219820Sjeff mutex_lock(&parent->vlan_mutex); 1175219820Sjeff list_for_each_entry(priv, &parent->child_intfs, list) { 1176219820Sjeff if (priv->pkey == pkey) { 1177219820Sjeff ipoib_dev_cleanup(priv); 1178219820Sjeff list_del(&priv->list); 1179219820Sjeff break; 1180219820Sjeff } 1181219820Sjeff } 1182219820Sjeff mutex_unlock(&parent->vlan_mutex); 1183219820Sjeff} 1184219820Sjeff 1185219820Sjeffeventhandler_tag ipoib_vlan_attach; 1186219820Sjeffeventhandler_tag ipoib_vlan_detach; 1187219820Sjeff 1188219820Sjeffstatic int __init 1189219820Sjeffipoib_init_module(void) 1190219820Sjeff{ 1191219820Sjeff int ret; 1192219820Sjeff 1193219820Sjeff ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size); 1194219820Sjeff ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE); 1195219820Sjeff ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE); 1196219820Sjeff 1197219820Sjeff ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); 1198219820Sjeff ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); 1199219820Sjeff ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE, 1200219820Sjeff IPOIB_MIN_QUEUE_SIZE)); 1201219820Sjeff#ifdef CONFIG_INFINIBAND_IPOIB_CM 1202219820Sjeff ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); 1203219820Sjeff#endif 1204219820Sjeff 1205219820Sjeff ipoib_vlan_attach = EVENTHANDLER_REGISTER(vlan_config, 1206219820Sjeff ipoib_config_vlan, NULL, EVENTHANDLER_PRI_FIRST); 1207219820Sjeff ipoib_vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, 1208219820Sjeff ipoib_unconfig_vlan, NULL, EVENTHANDLER_PRI_FIRST); 1209219820Sjeff 1210219820Sjeff /* 1211219820Sjeff * We create our own workqueue mainly because we want to be 1212219820Sjeff * able to flush it when devices are being removed. We can't 1213219820Sjeff * use schedule_work()/flush_scheduled_work() because both 1214219820Sjeff * unregister_netdev() and linkwatch_event take the rtnl lock, 1215219820Sjeff * so flush_scheduled_work() can deadlock during device 1216219820Sjeff * removal. 1217219820Sjeff */ 1218219820Sjeff ipoib_workqueue = create_singlethread_workqueue("ipoib"); 1219219820Sjeff if (!ipoib_workqueue) { 1220219820Sjeff ret = -ENOMEM; 1221219820Sjeff goto err_fs; 1222219820Sjeff } 1223219820Sjeff 1224219820Sjeff ib_sa_register_client(&ipoib_sa_client); 1225219820Sjeff 1226219820Sjeff ret = ib_register_client(&ipoib_client); 1227219820Sjeff if (ret) 1228219820Sjeff goto err_sa; 1229219820Sjeff 1230219820Sjeff return 0; 1231219820Sjeff 1232219820Sjefferr_sa: 1233219820Sjeff ib_sa_unregister_client(&ipoib_sa_client); 1234219820Sjeff destroy_workqueue(ipoib_workqueue); 1235219820Sjeff 1236219820Sjefferr_fs: 1237219820Sjeff return ret; 1238219820Sjeff} 1239219820Sjeff 1240219820Sjeffstatic void __exit 1241219820Sjeffipoib_cleanup_module(void) 1242219820Sjeff{ 1243219820Sjeff 1244219820Sjeff EVENTHANDLER_DEREGISTER(vlan_config, ipoib_vlan_attach); 1245219820Sjeff EVENTHANDLER_DEREGISTER(vlan_unconfig, ipoib_vlan_detach); 1246219820Sjeff ib_unregister_client(&ipoib_client); 1247219820Sjeff ib_sa_unregister_client(&ipoib_sa_client); 1248219820Sjeff destroy_workqueue(ipoib_workqueue); 1249219820Sjeff} 1250219820Sjeff 1251219820Sjeff/* 1252219820Sjeff * Infiniband output routine. 1253219820Sjeff */ 1254219820Sjeffstatic int 1255219820Sjeffipoib_output(struct ifnet *ifp, struct mbuf *m, 1256249976Sglebius const struct sockaddr *dst, struct route *ro) 1257219820Sjeff{ 1258219820Sjeff u_char edst[INFINIBAND_ALEN]; 1259219820Sjeff struct llentry *lle = NULL; 1260219820Sjeff struct rtentry *rt0 = NULL; 1261219820Sjeff struct ipoib_header *eh; 1262219820Sjeff int error = 0; 1263219820Sjeff short type; 1264219820Sjeff 1265219820Sjeff if (ro != NULL) { 1266219820Sjeff if (!(m->m_flags & (M_BCAST | M_MCAST))) 1267219820Sjeff lle = ro->ro_lle; 1268219820Sjeff rt0 = ro->ro_rt; 1269219820Sjeff } 1270219820Sjeff#ifdef MAC 1271219820Sjeff error = mac_ifnet_check_transmit(ifp, m); 1272219820Sjeff if (error) 1273219820Sjeff goto bad; 1274219820Sjeff#endif 1275219820Sjeff 1276219820Sjeff M_PROFILE(m); 1277219820Sjeff if (ifp->if_flags & IFF_MONITOR) { 1278219820Sjeff error = ENETDOWN; 1279219820Sjeff goto bad; 1280219820Sjeff } 1281219820Sjeff if (!((ifp->if_flags & IFF_UP) && 1282219820Sjeff (ifp->if_drv_flags & IFF_DRV_RUNNING))) { 1283219820Sjeff error = ENETDOWN; 1284219820Sjeff goto bad; 1285219820Sjeff } 1286219820Sjeff 1287219820Sjeff switch (dst->sa_family) { 1288219820Sjeff#ifdef INET 1289219820Sjeff case AF_INET: 1290219820Sjeff if (lle != NULL && (lle->la_flags & LLE_VALID)) 1291219820Sjeff memcpy(edst, &lle->ll_addr.mac8, sizeof(edst)); 1292219820Sjeff else if (m->m_flags & M_MCAST) 1293219820Sjeff ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst); 1294219820Sjeff else 1295219820Sjeff error = arpresolve(ifp, rt0, m, dst, edst, &lle); 1296219820Sjeff if (error) 1297219820Sjeff return (error == EWOULDBLOCK ? 0 : error); 1298219820Sjeff type = htons(ETHERTYPE_IP); 1299219820Sjeff break; 1300219820Sjeff case AF_ARP: 1301219820Sjeff { 1302219820Sjeff struct arphdr *ah; 1303219820Sjeff ah = mtod(m, struct arphdr *); 1304219820Sjeff ah->ar_hrd = htons(ARPHRD_INFINIBAND); 1305219820Sjeff 1306219820Sjeff switch(ntohs(ah->ar_op)) { 1307219820Sjeff case ARPOP_REVREQUEST: 1308219820Sjeff case ARPOP_REVREPLY: 1309219820Sjeff type = htons(ETHERTYPE_REVARP); 1310219820Sjeff break; 1311219820Sjeff case ARPOP_REQUEST: 1312219820Sjeff case ARPOP_REPLY: 1313219820Sjeff default: 1314219820Sjeff type = htons(ETHERTYPE_ARP); 1315219820Sjeff break; 1316219820Sjeff } 1317219820Sjeff 1318219820Sjeff if (m->m_flags & M_BCAST) 1319219820Sjeff bcopy(ifp->if_broadcastaddr, edst, INFINIBAND_ALEN); 1320219820Sjeff else 1321219820Sjeff bcopy(ar_tha(ah), edst, INFINIBAND_ALEN); 1322219820Sjeff 1323219820Sjeff } 1324219820Sjeff break; 1325219820Sjeff#endif 1326219820Sjeff#ifdef INET6 1327219820Sjeff case AF_INET6: 1328219820Sjeff if (lle != NULL && (lle->la_flags & LLE_VALID)) 1329219820Sjeff memcpy(edst, &lle->ll_addr.mac8, sizeof(edst)); 1330219820Sjeff else if (m->m_flags & M_MCAST) 1331219820Sjeff ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst); 1332219820Sjeff else 1333219820Sjeff error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle); 1334219820Sjeff if (error) 1335219820Sjeff return error; 1336219820Sjeff type = htons(ETHERTYPE_IPV6); 1337219820Sjeff break; 1338219820Sjeff#endif 1339219820Sjeff 1340219820Sjeff default: 1341219820Sjeff if_printf(ifp, "can't handle af%d\n", dst->sa_family); 1342219820Sjeff error = EAFNOSUPPORT; 1343219820Sjeff goto bad; 1344219820Sjeff } 1345219820Sjeff 1346219820Sjeff /* 1347219820Sjeff * Add local net header. If no space in first mbuf, 1348219820Sjeff * allocate another. 1349219820Sjeff */ 1350243882Sglebius M_PREPEND(m, IPOIB_HEADER_LEN, M_NOWAIT); 1351219820Sjeff if (m == NULL) { 1352219820Sjeff error = ENOBUFS; 1353219820Sjeff goto bad; 1354219820Sjeff } 1355219820Sjeff eh = mtod(m, struct ipoib_header *); 1356219820Sjeff (void)memcpy(&eh->proto, &type, sizeof(eh->proto)); 1357219820Sjeff (void)memcpy(&eh->hwaddr, edst, sizeof (edst)); 1358219820Sjeff 1359219820Sjeff /* 1360219820Sjeff * Queue message on interface, update output statistics if 1361219820Sjeff * successful, and start output if interface not yet active. 1362219820Sjeff */ 1363219820Sjeff return ((ifp->if_transmit)(ifp, m)); 1364219820Sjeffbad: 1365219820Sjeff if (m != NULL) 1366219820Sjeff m_freem(m); 1367219820Sjeff return (error); 1368219820Sjeff} 1369219820Sjeff 1370219820Sjeff/* 1371219820Sjeff * Upper layer processing for a received Infiniband packet. 1372219820Sjeff */ 1373219820Sjeffvoid 1374219820Sjeffipoib_demux(struct ifnet *ifp, struct mbuf *m, u_short proto) 1375219820Sjeff{ 1376219820Sjeff int isr; 1377219820Sjeff 1378219820Sjeff#ifdef MAC 1379219820Sjeff /* 1380219820Sjeff * Tag the mbuf with an appropriate MAC label before any other 1381219820Sjeff * consumers can get to it. 1382219820Sjeff */ 1383219820Sjeff mac_ifnet_create_mbuf(ifp, m); 1384219820Sjeff#endif 1385219820Sjeff /* Allow monitor mode to claim this frame, after stats are updated. */ 1386219820Sjeff if (ifp->if_flags & IFF_MONITOR) { 1387219820Sjeff if_printf(ifp, "discard frame at IFF_MONITOR\n"); 1388219820Sjeff m_freem(m); 1389219820Sjeff return; 1390219820Sjeff } 1391219820Sjeff /* 1392219820Sjeff * Dispatch frame to upper layer. 1393219820Sjeff */ 1394219820Sjeff switch (proto) { 1395219820Sjeff#ifdef INET 1396219820Sjeff case ETHERTYPE_IP: 1397219820Sjeff isr = NETISR_IP; 1398219820Sjeff break; 1399219820Sjeff 1400219820Sjeff case ETHERTYPE_ARP: 1401219820Sjeff if (ifp->if_flags & IFF_NOARP) { 1402219820Sjeff /* Discard packet if ARP is disabled on interface */ 1403219820Sjeff m_freem(m); 1404219820Sjeff return; 1405219820Sjeff } 1406219820Sjeff isr = NETISR_ARP; 1407219820Sjeff break; 1408219820Sjeff#endif 1409219820Sjeff#ifdef INET6 1410219820Sjeff case ETHERTYPE_IPV6: 1411219820Sjeff isr = NETISR_IPV6; 1412219820Sjeff break; 1413219820Sjeff#endif 1414219820Sjeff default: 1415219820Sjeff goto discard; 1416219820Sjeff } 1417219820Sjeff netisr_dispatch(isr, m); 1418219820Sjeff return; 1419219820Sjeff 1420219820Sjeffdiscard: 1421219820Sjeff m_freem(m); 1422219820Sjeff} 1423219820Sjeff 1424219820Sjeff/* 1425219820Sjeff * Process a received Infiniband packet. 1426219820Sjeff */ 1427219820Sjeffstatic void 1428219820Sjeffipoib_input(struct ifnet *ifp, struct mbuf *m) 1429219820Sjeff{ 1430219820Sjeff struct ipoib_header *eh; 1431219820Sjeff 1432219820Sjeff if ((ifp->if_flags & IFF_UP) == 0) { 1433219820Sjeff m_freem(m); 1434219820Sjeff return; 1435219820Sjeff } 1436219820Sjeff CURVNET_SET_QUIET(ifp->if_vnet); 1437219820Sjeff 1438219820Sjeff /* Let BPF have it before we strip the header. */ 1439219820Sjeff IPOIB_MTAP(ifp, m); 1440219820Sjeff eh = mtod(m, struct ipoib_header *); 1441219820Sjeff /* 1442219820Sjeff * Reset layer specific mbuf flags to avoid confusing upper layers. 1443219820Sjeff * Strip off Infiniband header. 1444219820Sjeff */ 1445219820Sjeff m->m_flags &= ~M_VLANTAG; 1446254523Sandre m_clrprotoflags(m); 1447219820Sjeff m_adj(m, IPOIB_HEADER_LEN); 1448219820Sjeff 1449219820Sjeff if (IPOIB_IS_MULTICAST(eh->hwaddr)) { 1450219820Sjeff if (memcmp(eh->hwaddr, ifp->if_broadcastaddr, 1451219820Sjeff ifp->if_addrlen) == 0) 1452219820Sjeff m->m_flags |= M_BCAST; 1453219820Sjeff else 1454219820Sjeff m->m_flags |= M_MCAST; 1455219820Sjeff ifp->if_imcasts++; 1456219820Sjeff } 1457219820Sjeff 1458219820Sjeff ipoib_demux(ifp, m, ntohs(eh->proto)); 1459219820Sjeff CURVNET_RESTORE(); 1460219820Sjeff} 1461219820Sjeff 1462219820Sjeffstatic int 1463219820Sjeffipoib_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 1464219820Sjeff struct sockaddr *sa) 1465219820Sjeff{ 1466219820Sjeff struct sockaddr_dl *sdl; 1467219820Sjeff#ifdef INET 1468219820Sjeff struct sockaddr_in *sin; 1469219820Sjeff#endif 1470219820Sjeff#ifdef INET6 1471219820Sjeff struct sockaddr_in6 *sin6; 1472219820Sjeff#endif 1473219820Sjeff u_char *e_addr; 1474219820Sjeff 1475219820Sjeff switch(sa->sa_family) { 1476219820Sjeff case AF_LINK: 1477219820Sjeff /* 1478219820Sjeff * No mapping needed. Just check that it's a valid MC address. 1479219820Sjeff */ 1480219820Sjeff sdl = (struct sockaddr_dl *)sa; 1481219820Sjeff e_addr = LLADDR(sdl); 1482219820Sjeff if (!IPOIB_IS_MULTICAST(e_addr)) 1483219820Sjeff return EADDRNOTAVAIL; 1484219820Sjeff *llsa = 0; 1485219820Sjeff return 0; 1486219820Sjeff 1487219820Sjeff#ifdef INET 1488219820Sjeff case AF_INET: 1489219820Sjeff sin = (struct sockaddr_in *)sa; 1490219820Sjeff if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 1491219820Sjeff return EADDRNOTAVAIL; 1492219820Sjeff sdl = malloc(sizeof *sdl, M_IFMADDR, 1493219820Sjeff M_NOWAIT|M_ZERO); 1494219820Sjeff if (sdl == NULL) 1495219820Sjeff return ENOMEM; 1496219820Sjeff sdl->sdl_len = sizeof *sdl; 1497219820Sjeff sdl->sdl_family = AF_LINK; 1498219820Sjeff sdl->sdl_index = ifp->if_index; 1499219820Sjeff sdl->sdl_type = IFT_INFINIBAND; 1500219820Sjeff sdl->sdl_alen = INFINIBAND_ALEN; 1501219820Sjeff e_addr = LLADDR(sdl); 1502219820Sjeff ip_ib_mc_map(sin->sin_addr.s_addr, ifp->if_broadcastaddr, 1503219820Sjeff e_addr); 1504219820Sjeff *llsa = (struct sockaddr *)sdl; 1505219820Sjeff return 0; 1506219820Sjeff#endif 1507219820Sjeff#ifdef INET6 1508219820Sjeff case AF_INET6: 1509219820Sjeff sin6 = (struct sockaddr_in6 *)sa; 1510219820Sjeff /* 1511219820Sjeff * An IP6 address of 0 means listen to all 1512219820Sjeff * of the multicast address used for IP6. 1513219820Sjeff * This has no meaning in ipoib. 1514219820Sjeff */ 1515219820Sjeff if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 1516219820Sjeff return EADDRNOTAVAIL; 1517219820Sjeff if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 1518219820Sjeff return EADDRNOTAVAIL; 1519219820Sjeff sdl = malloc(sizeof *sdl, M_IFMADDR, 1520219820Sjeff M_NOWAIT|M_ZERO); 1521219820Sjeff if (sdl == NULL) 1522219820Sjeff return (ENOMEM); 1523219820Sjeff sdl->sdl_len = sizeof *sdl; 1524219820Sjeff sdl->sdl_family = AF_LINK; 1525219820Sjeff sdl->sdl_index = ifp->if_index; 1526219820Sjeff sdl->sdl_type = IFT_INFINIBAND; 1527219820Sjeff sdl->sdl_alen = INFINIBAND_ALEN; 1528219820Sjeff e_addr = LLADDR(sdl); 1529219820Sjeff ipv6_ib_mc_map(&sin6->sin6_addr, ifp->if_broadcastaddr, e_addr); 1530219820Sjeff *llsa = (struct sockaddr *)sdl; 1531219820Sjeff return 0; 1532219820Sjeff#endif 1533219820Sjeff 1534219820Sjeff default: 1535219820Sjeff return EAFNOSUPPORT; 1536219820Sjeff } 1537219820Sjeff} 1538219820Sjeff 1539219820Sjeffmodule_init(ipoib_init_module); 1540219820Sjeffmodule_exit(ipoib_cleanup_module); 1541255932Salfred 1542255932Salfred#undef MODULE_VERSION 1543255932Salfred#include <sys/module.h> 1544255932Salfredstatic int 1545255932Salfredipoib_evhand(module_t mod, int event, void *arg) 1546255932Salfred{ 1547255932Salfred return (0); 1548255932Salfred} 1549255932Salfred 1550255932Salfredstatic moduledata_t ipoib_mod = { 1551255932Salfred .name = "ipoib", 1552255932Salfred .evhand = ipoib_evhand, 1553255932Salfred}; 1554255932Salfred 1555255932SalfredDECLARE_MODULE(ipoib, ipoib_mod, SI_SUB_SMP, SI_ORDER_ANY); 1556255932SalfredMODULE_DEPEND(ipoib, ibcore, 1, 1, 1); 1557255932Salfred 1558