Changeset View
Changeset View
Standalone View
Standalone View
sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
Show All 34 Lines | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "ipoib.h" | #include "ipoib.h" | ||||
#include <sys/eventhandler.h> | #include <sys/eventhandler.h> | ||||
static int ipoib_resolvemulti(struct ifnet *, struct sockaddr **, | |||||
struct sockaddr *); | |||||
#include <linux/module.h> | #include <linux/module.h> | ||||
#include <linux/slab.h> | #include <linux/slab.h> | ||||
#include <linux/kernel.h> | #include <linux/kernel.h> | ||||
#include <linux/vmalloc.h> | #include <linux/vmalloc.h> | ||||
#include <linux/if_arp.h> /* For ARPHRD_xxx */ | |||||
#include <linux/if_vlan.h> | #include <linux/if_vlan.h> | ||||
#include <net/ip.h> | |||||
#include <net/ipv6.h> | |||||
#include <net/infiniband.h> | |||||
#include <rdma/ib_cache.h> | #include <rdma/ib_cache.h> | ||||
MODULE_AUTHOR("Roland Dreier"); | MODULE_AUTHOR("Roland Dreier"); | ||||
MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); | MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); | ||||
MODULE_LICENSE("Dual BSD/GPL"); | MODULE_LICENSE("Dual BSD/GPL"); | ||||
int ipoib_sendq_size = IPOIB_TX_RING_SIZE; | int ipoib_sendq_size = IPOIB_TX_RING_SIZE; | ||||
int ipoib_recvq_size = IPOIB_RX_RING_SIZE; | int ipoib_recvq_size = IPOIB_RX_RING_SIZE; | ||||
Show All 27 Lines | |||||
static void ipoib_add_one(struct ib_device *device); | static void ipoib_add_one(struct ib_device *device); | ||||
static void ipoib_remove_one(struct ib_device *device, void *client_data); | static void ipoib_remove_one(struct ib_device *device, void *client_data); | ||||
static struct net_device *ipoib_get_net_dev_by_params( | static struct net_device *ipoib_get_net_dev_by_params( | ||||
struct ib_device *dev, u8 port, u16 pkey, | struct ib_device *dev, u8 port, u16 pkey, | ||||
const union ib_gid *gid, const struct sockaddr *addr, | const union ib_gid *gid, const struct sockaddr *addr, | ||||
void *client_data); | void *client_data); | ||||
static void ipoib_start(struct ifnet *dev); | static void ipoib_start(struct ifnet *dev); | ||||
static int ipoib_output(struct ifnet *ifp, struct mbuf *m, | |||||
const struct sockaddr *dst, struct route *ro); | |||||
static int ipoib_ioctl(struct ifnet *ifp, u_long command, caddr_t data); | static int ipoib_ioctl(struct ifnet *ifp, u_long command, caddr_t data); | ||||
static void ipoib_input(struct ifnet *ifp, struct mbuf *m); | |||||
#define IPOIB_MTAP(_ifp, _m) \ | |||||
do { \ | |||||
if (bpf_peers_present((_ifp)->if_bpf)) { \ | |||||
M_ASSERTVALID(_m); \ | |||||
ipoib_mtap_mb((_ifp), (_m)); \ | |||||
} \ | |||||
} while (0) | |||||
static struct unrhdr *ipoib_unrhdr; | static struct unrhdr *ipoib_unrhdr; | ||||
static void | static void | ||||
ipoib_unrhdr_init(void *arg) | ipoib_unrhdr_init(void *arg) | ||||
{ | { | ||||
ipoib_unrhdr = new_unrhdr(0, 65535, NULL); | ipoib_unrhdr = new_unrhdr(0, 65535, NULL); | ||||
} | } | ||||
Show All 9 Lines | if (ipoib_unrhdr != NULL) { | ||||
hdr = ipoib_unrhdr; | hdr = ipoib_unrhdr; | ||||
ipoib_unrhdr = NULL; | ipoib_unrhdr = NULL; | ||||
delete_unrhdr(hdr); | delete_unrhdr(hdr); | ||||
} | } | ||||
} | } | ||||
SYSUNINIT(ipoib_unrhdr_uninit, SI_SUB_KLD - 1, SI_ORDER_ANY, ipoib_unrhdr_uninit, NULL); | SYSUNINIT(ipoib_unrhdr_uninit, SI_SUB_KLD - 1, SI_ORDER_ANY, ipoib_unrhdr_uninit, NULL); | ||||
/* | |||||
* This is for clients that have an ipoib_header in the mbuf. | |||||
*/ | |||||
static void | |||||
ipoib_mtap_mb(struct ifnet *ifp, struct mbuf *mb) | |||||
{ | |||||
struct ipoib_header *ih; | |||||
struct ether_header eh; | |||||
ih = mtod(mb, struct ipoib_header *); | |||||
eh.ether_type = ih->proto; | |||||
bcopy(ih->hwaddr, &eh.ether_dhost, ETHER_ADDR_LEN); | |||||
bzero(&eh.ether_shost, ETHER_ADDR_LEN); | |||||
mb->m_data += sizeof(struct ipoib_header); | |||||
mb->m_len -= sizeof(struct ipoib_header); | |||||
bpf_mtap2(ifp->if_bpf, &eh, sizeof(eh), mb); | |||||
mb->m_data -= sizeof(struct ipoib_header); | |||||
mb->m_len += sizeof(struct ipoib_header); | |||||
} | |||||
void | |||||
ipoib_mtap_proto(struct ifnet *ifp, struct mbuf *mb, uint16_t proto) | |||||
{ | |||||
struct ether_header eh; | |||||
eh.ether_type = proto; | |||||
bzero(&eh.ether_shost, ETHER_ADDR_LEN); | |||||
bzero(&eh.ether_dhost, ETHER_ADDR_LEN); | |||||
bpf_mtap2(ifp->if_bpf, &eh, sizeof(eh), mb); | |||||
} | |||||
static struct ib_client ipoib_client = { | static struct ib_client ipoib_client = { | ||||
.name = "ipoib", | .name = "ipoib", | ||||
.add = ipoib_add_one, | .add = ipoib_add_one, | ||||
.remove = ipoib_remove_one, | .remove = ipoib_remove_one, | ||||
.get_net_dev_by_params = ipoib_get_net_dev_by_params, | .get_net_dev_by_params = ipoib_get_net_dev_by_params, | ||||
}; | }; | ||||
int | int | ||||
▲ Show 20 Lines • Show All 604 Lines • ▼ Show 20 Lines | ipoib_start_locked(struct ifnet *dev, struct ipoib_dev_priv *priv) | ||||
assert_spin_locked(&priv->lock); | assert_spin_locked(&priv->lock); | ||||
while (!IFQ_DRV_IS_EMPTY(&dev->if_snd) && | while (!IFQ_DRV_IS_EMPTY(&dev->if_snd) && | ||||
(dev->if_drv_flags & IFF_DRV_OACTIVE) == 0) { | (dev->if_drv_flags & IFF_DRV_OACTIVE) == 0) { | ||||
IFQ_DRV_DEQUEUE(&dev->if_snd, mb); | IFQ_DRV_DEQUEUE(&dev->if_snd, mb); | ||||
if (mb == NULL) | if (mb == NULL) | ||||
break; | break; | ||||
IPOIB_MTAP(dev, mb); | INFINIBAND_BPF_MTAP(dev, mb); | ||||
ipoib_send_one(priv, mb); | ipoib_send_one(priv, mb); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
_ipoib_start(struct ifnet *dev, struct ipoib_dev_priv *priv) | _ipoib_start(struct ifnet *dev, struct ipoib_dev_priv *priv) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
ipoib_detach(struct ipoib_dev_priv *priv) | ipoib_detach(struct ipoib_dev_priv *priv) | ||||
{ | { | ||||
struct ifnet *dev; | struct ifnet *dev; | ||||
dev = priv->dev; | dev = priv->dev; | ||||
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { | ||||
priv->gone = 1; | priv->gone = 1; | ||||
bpfdetach(dev); | infiniband_ifdetach(dev); | ||||
if_detach(dev); | |||||
if_free(dev); | if_free(dev); | ||||
free_unr(ipoib_unrhdr, priv->unit); | free_unr(ipoib_unrhdr, priv->unit); | ||||
} else | } else | ||||
VLAN_SETCOOKIE(priv->dev, NULL); | VLAN_SETCOOKIE(priv->dev, NULL); | ||||
free(priv, M_TEMP); | free(priv, M_TEMP); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | ipoib_priv_alloc(void) | ||||
return (priv); | return (priv); | ||||
} | } | ||||
struct ipoib_dev_priv * | struct ipoib_dev_priv * | ||||
ipoib_intf_alloc(const char *name) | ipoib_intf_alloc(const char *name) | ||||
{ | { | ||||
struct ipoib_dev_priv *priv; | struct ipoib_dev_priv *priv; | ||||
struct sockaddr_dl *sdl; | |||||
struct ifnet *dev; | struct ifnet *dev; | ||||
priv = ipoib_priv_alloc(); | priv = ipoib_priv_alloc(); | ||||
dev = priv->dev = if_alloc(IFT_INFINIBAND); | dev = priv->dev = if_alloc(IFT_INFINIBAND); | ||||
if (!dev) { | if (!dev) { | ||||
free(priv, M_TEMP); | free(priv, M_TEMP); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
dev->if_softc = priv; | dev->if_softc = priv; | ||||
priv->unit = alloc_unr(ipoib_unrhdr); | priv->unit = alloc_unr(ipoib_unrhdr); | ||||
if (priv->unit == -1) { | if (priv->unit == -1) { | ||||
if_free(dev); | if_free(dev); | ||||
free(priv, M_TEMP); | free(priv, M_TEMP); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if_initname(dev, name, priv->unit); | if_initname(dev, name, priv->unit); | ||||
dev->if_flags = IFF_BROADCAST | IFF_MULTICAST; | dev->if_flags = IFF_BROADCAST | IFF_MULTICAST; | ||||
dev->if_addrlen = INFINIBAND_ALEN; | |||||
dev->if_hdrlen = IPOIB_HEADER_LEN; | infiniband_ifattach(dev, NULL, priv->broadcastaddr); | ||||
if_attach(dev); | |||||
dev->if_init = ipoib_init; | dev->if_init = ipoib_init; | ||||
dev->if_ioctl = ipoib_ioctl; | dev->if_ioctl = ipoib_ioctl; | ||||
dev->if_start = ipoib_start; | dev->if_start = ipoib_start; | ||||
dev->if_output = ipoib_output; | |||||
dev->if_input = ipoib_input; | |||||
dev->if_resolvemulti = ipoib_resolvemulti; | |||||
dev->if_baudrate = IF_Gbps(10); | |||||
dev->if_broadcastaddr = priv->broadcastaddr; | |||||
dev->if_snd.ifq_maxlen = ipoib_sendq_size * 2; | 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; | priv->dev = dev; | ||||
if_link_state_change(dev, LINK_STATE_DOWN); | if_link_state_change(dev, LINK_STATE_DOWN); | ||||
bpfattach(dev, DLT_EN10MB, ETHER_HDR_LEN); | |||||
return dev->if_softc; | return dev->if_softc; | ||||
} | } | ||||
int | int | ||||
ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) | ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca) | ||||
{ | { | ||||
struct ib_device_attr *device_attr = &hca->attrs; | struct ib_device_attr *device_attr = &hca->attrs; | ||||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
ipoib_match_dev_addr(const struct sockaddr *addr, struct net_device *dev) | ipoib_match_dev_addr(const struct sockaddr *addr, struct net_device *dev) | ||||
{ | { | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
int retval = 0; | int retval = 0; | ||||
CURVNET_SET(dev->if_vnet); | |||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
CK_STAILQ_FOREACH(ifa, &dev->if_addrhead, ifa_link) { | CK_STAILQ_FOREACH(ifa, &dev->if_addrhead, ifa_link) { | ||||
if (ifa->ifa_addr == NULL || | if (ifa->ifa_addr == NULL || | ||||
ifa->ifa_addr->sa_family != addr->sa_family || | ifa->ifa_addr->sa_family != addr->sa_family || | ||||
ifa->ifa_addr->sa_len != addr->sa_len) { | ifa->ifa_addr->sa_len != addr->sa_len) { | ||||
continue; | continue; | ||||
} | } | ||||
if (memcmp(ifa->ifa_addr, addr, addr->sa_len) == 0) { | if (memcmp(ifa->ifa_addr, addr, addr->sa_len) == 0) { | ||||
retval = 1; | retval = 1; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
CURVNET_RESTORE(); | |||||
return (retval); | return (retval); | ||||
} | } | ||||
/* | /* | ||||
* ipoib_match_gid_pkey_addr - returns the number of IPoIB netdevs on | * ipoib_match_gid_pkey_addr - returns the number of IPoIB netdevs on | ||||
* top a given ipoib device matching a pkey_index and address, if one | * top a given ipoib device matching a pkey_index and address, if one | ||||
* exists. | * exists. | ||||
▲ Show 20 Lines • Show All 279 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
EVENTHANDLER_DEREGISTER(vlan_config, ipoib_vlan_attach); | EVENTHANDLER_DEREGISTER(vlan_config, ipoib_vlan_attach); | ||||
EVENTHANDLER_DEREGISTER(vlan_unconfig, ipoib_vlan_detach); | EVENTHANDLER_DEREGISTER(vlan_unconfig, ipoib_vlan_detach); | ||||
ib_unregister_client(&ipoib_client); | ib_unregister_client(&ipoib_client); | ||||
ib_sa_unregister_client(&ipoib_sa_client); | ib_sa_unregister_client(&ipoib_sa_client); | ||||
destroy_workqueue(ipoib_workqueue); | destroy_workqueue(ipoib_workqueue); | ||||
} | } | ||||
/* | |||||
* Infiniband output routine. | |||||
*/ | |||||
static int | |||||
ipoib_output(struct ifnet *ifp, struct mbuf *m, | |||||
const struct sockaddr *dst, struct route *ro) | |||||
{ | |||||
u_char edst[INFINIBAND_ALEN]; | |||||
#if defined(INET) || defined(INET6) | |||||
struct llentry *lle = NULL; | |||||
#endif | |||||
struct ipoib_header *eh; | |||||
int error = 0, is_gw = 0; | |||||
short type; | |||||
NET_EPOCH_ASSERT(); | |||||
if (ro != NULL) | |||||
is_gw = (ro->ro_flags & RT_HAS_GW) != 0; | |||||
#ifdef MAC | |||||
error = mac_ifnet_check_transmit(ifp, m); | |||||
if (error) | |||||
goto bad; | |||||
#endif | |||||
M_PROFILE(m); | |||||
if (ifp->if_flags & IFF_MONITOR) { | |||||
error = ENETDOWN; | |||||
goto bad; | |||||
} | |||||
if (!((ifp->if_flags & IFF_UP) && | |||||
(ifp->if_drv_flags & IFF_DRV_RUNNING))) { | |||||
error = ENETDOWN; | |||||
goto bad; | |||||
} | |||||
switch (dst->sa_family) { | |||||
#ifdef INET | |||||
case AF_INET: | |||||
if (lle != NULL && (lle->la_flags & LLE_VALID)) | |||||
memcpy(edst, lle->ll_addr, sizeof(edst)); | |||||
else if (m->m_flags & M_MCAST) | |||||
ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst); | |||||
else | |||||
error = arpresolve(ifp, is_gw, m, dst, edst, NULL, NULL); | |||||
if (error) | |||||
return (error == EWOULDBLOCK ? 0 : error); | |||||
type = htons(ETHERTYPE_IP); | |||||
break; | |||||
case AF_ARP: | |||||
{ | |||||
struct arphdr *ah; | |||||
ah = mtod(m, struct arphdr *); | |||||
ah->ar_hrd = htons(ARPHRD_INFINIBAND); | |||||
switch(ntohs(ah->ar_op)) { | |||||
case ARPOP_REVREQUEST: | |||||
case ARPOP_REVREPLY: | |||||
type = htons(ETHERTYPE_REVARP); | |||||
break; | |||||
case ARPOP_REQUEST: | |||||
case ARPOP_REPLY: | |||||
default: | |||||
type = htons(ETHERTYPE_ARP); | |||||
break; | |||||
} | |||||
if (m->m_flags & M_BCAST) | |||||
bcopy(ifp->if_broadcastaddr, edst, INFINIBAND_ALEN); | |||||
else | |||||
bcopy(ar_tha(ah), edst, INFINIBAND_ALEN); | |||||
} | |||||
break; | |||||
#endif | |||||
#ifdef INET6 | |||||
case AF_INET6: | |||||
if (lle != NULL && (lle->la_flags & LLE_VALID)) | |||||
memcpy(edst, lle->ll_addr, sizeof(edst)); | |||||
else if (m->m_flags & M_MCAST) | |||||
ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst); | |||||
else | |||||
error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL); | |||||
if (error) | |||||
return error; | |||||
type = htons(ETHERTYPE_IPV6); | |||||
break; | |||||
#endif | |||||
default: | |||||
if_printf(ifp, "can't handle af%d\n", dst->sa_family); | |||||
error = EAFNOSUPPORT; | |||||
goto bad; | |||||
} | |||||
/* | |||||
* Add local net header. If no space in first mbuf, | |||||
* allocate another. | |||||
*/ | |||||
M_PREPEND(m, IPOIB_HEADER_LEN, M_NOWAIT); | |||||
if (m == NULL) { | |||||
error = ENOBUFS; | |||||
goto bad; | |||||
} | |||||
eh = mtod(m, struct ipoib_header *); | |||||
(void)memcpy(&eh->proto, &type, sizeof(eh->proto)); | |||||
(void)memcpy(&eh->hwaddr, edst, sizeof (edst)); | |||||
/* | |||||
* Queue message on interface, update output statistics if | |||||
* successful, and start output if interface not yet active. | |||||
*/ | |||||
return ((ifp->if_transmit)(ifp, m)); | |||||
bad: | |||||
if (m != NULL) | |||||
m_freem(m); | |||||
return (error); | |||||
} | |||||
/* | |||||
* Upper layer processing for a received Infiniband packet. | |||||
*/ | |||||
void | |||||
ipoib_demux(struct ifnet *ifp, struct mbuf *m, u_short proto) | |||||
{ | |||||
struct epoch_tracker et; | |||||
int isr; | |||||
#ifdef MAC | |||||
/* | |||||
* Tag the mbuf with an appropriate MAC label before any other | |||||
* consumers can get to it. | |||||
*/ | |||||
mac_ifnet_create_mbuf(ifp, m); | |||||
#endif | |||||
/* Allow monitor mode to claim this frame, after stats are updated. */ | |||||
if (ifp->if_flags & IFF_MONITOR) { | |||||
if_printf(ifp, "discard frame at IFF_MONITOR\n"); | |||||
m_freem(m); | |||||
return; | |||||
} | |||||
/* Direct packet to correct FIB based on interface config */ | |||||
M_SETFIB(m, ifp->if_fib); | |||||
/* | |||||
* Dispatch frame to upper layer. | |||||
*/ | |||||
switch (proto) { | |||||
#ifdef INET | |||||
case ETHERTYPE_IP: | |||||
isr = NETISR_IP; | |||||
break; | |||||
case ETHERTYPE_ARP: | |||||
if (ifp->if_flags & IFF_NOARP) { | |||||
/* Discard packet if ARP is disabled on interface */ | |||||
m_freem(m); | |||||
return; | |||||
} | |||||
isr = NETISR_ARP; | |||||
break; | |||||
#endif | |||||
#ifdef INET6 | |||||
case ETHERTYPE_IPV6: | |||||
isr = NETISR_IPV6; | |||||
break; | |||||
#endif | |||||
default: | |||||
goto discard; | |||||
} | |||||
NET_EPOCH_ENTER(et); | |||||
netisr_dispatch(isr, m); | |||||
NET_EPOCH_EXIT(et); | |||||
return; | |||||
discard: | |||||
m_freem(m); | |||||
} | |||||
/* | |||||
* Process a received Infiniband packet. | |||||
*/ | |||||
static void | |||||
ipoib_input(struct ifnet *ifp, struct mbuf *m) | |||||
{ | |||||
struct ipoib_header *eh; | |||||
if ((ifp->if_flags & IFF_UP) == 0) { | |||||
m_freem(m); | |||||
return; | |||||
} | |||||
CURVNET_SET_QUIET(ifp->if_vnet); | |||||
/* Let BPF have it before we strip the header. */ | |||||
IPOIB_MTAP(ifp, m); | |||||
eh = mtod(m, struct ipoib_header *); | |||||
/* | |||||
* Reset layer specific mbuf flags to avoid confusing upper layers. | |||||
* Strip off Infiniband header. | |||||
*/ | |||||
m->m_flags &= ~M_VLANTAG; | |||||
m_clrprotoflags(m); | |||||
m_adj(m, IPOIB_HEADER_LEN); | |||||
if (IPOIB_IS_MULTICAST(eh->hwaddr)) { | |||||
if (memcmp(eh->hwaddr, ifp->if_broadcastaddr, | |||||
ifp->if_addrlen) == 0) | |||||
m->m_flags |= M_BCAST; | |||||
else | |||||
m->m_flags |= M_MCAST; | |||||
if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); | |||||
} | |||||
ipoib_demux(ifp, m, ntohs(eh->proto)); | |||||
CURVNET_RESTORE(); | |||||
} | |||||
static int | |||||
ipoib_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, | |||||
struct sockaddr *sa) | |||||
{ | |||||
struct sockaddr_dl *sdl; | |||||
#ifdef INET | |||||
struct sockaddr_in *sin; | |||||
#endif | |||||
#ifdef INET6 | |||||
struct sockaddr_in6 *sin6; | |||||
#endif | |||||
u_char *e_addr; | |||||
switch(sa->sa_family) { | |||||
case AF_LINK: | |||||
/* | |||||
* No mapping needed. Just check that it's a valid MC address. | |||||
*/ | |||||
sdl = (struct sockaddr_dl *)sa; | |||||
e_addr = LLADDR(sdl); | |||||
if (!IPOIB_IS_MULTICAST(e_addr)) | |||||
return EADDRNOTAVAIL; | |||||
*llsa = NULL; | |||||
return 0; | |||||
#ifdef INET | |||||
case AF_INET: | |||||
sin = (struct sockaddr_in *)sa; | |||||
if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) | |||||
return EADDRNOTAVAIL; | |||||
sdl = link_init_sdl(ifp, *llsa, IFT_INFINIBAND); | |||||
sdl->sdl_alen = INFINIBAND_ALEN; | |||||
e_addr = LLADDR(sdl); | |||||
ip_ib_mc_map(sin->sin_addr.s_addr, ifp->if_broadcastaddr, | |||||
e_addr); | |||||
*llsa = (struct sockaddr *)sdl; | |||||
return 0; | |||||
#endif | |||||
#ifdef INET6 | |||||
case AF_INET6: | |||||
sin6 = (struct sockaddr_in6 *)sa; | |||||
/* | |||||
* An IP6 address of 0 means listen to all | |||||
* of the multicast address used for IP6. | |||||
* This has no meaning in ipoib. | |||||
*/ | |||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) | |||||
return EADDRNOTAVAIL; | |||||
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) | |||||
return EADDRNOTAVAIL; | |||||
sdl = link_init_sdl(ifp, *llsa, IFT_INFINIBAND); | |||||
sdl->sdl_alen = INFINIBAND_ALEN; | |||||
e_addr = LLADDR(sdl); | |||||
ipv6_ib_mc_map(&sin6->sin6_addr, ifp->if_broadcastaddr, e_addr); | |||||
*llsa = (struct sockaddr *)sdl; | |||||
return 0; | |||||
#endif | |||||
default: | |||||
return EAFNOSUPPORT; | |||||
} | |||||
} | |||||
module_init_order(ipoib_init_module, SI_ORDER_FIFTH); | module_init_order(ipoib_init_module, SI_ORDER_FIFTH); | ||||
module_exit_order(ipoib_cleanup_module, SI_ORDER_FIFTH); | module_exit_order(ipoib_cleanup_module, SI_ORDER_FIFTH); | ||||
static int | static int | ||||
ipoib_evhand(module_t mod, int event, void *arg) | ipoib_evhand(module_t mod, int event, void *arg) | ||||
{ | { | ||||
return (0); | return (0); | ||||
} | } | ||||
static moduledata_t ipoib_mod = { | static moduledata_t ipoib_mod = { | ||||
.name = "ipoib", | .name = "ipoib", | ||||
.evhand = ipoib_evhand, | .evhand = ipoib_evhand, | ||||
}; | }; | ||||
DECLARE_MODULE(ipoib, ipoib_mod, SI_SUB_LAST, SI_ORDER_ANY); | DECLARE_MODULE(ipoib, ipoib_mod, SI_SUB_LAST, SI_ORDER_ANY); | ||||
MODULE_DEPEND(ipoib, ibcore, 1, 1, 1); | MODULE_DEPEND(ipoib, ibcore, 1, 1, 1); | ||||
MODULE_DEPEND(ipoib, if_infiniband, 1, 1, 1); | |||||
MODULE_DEPEND(ipoib, linuxkpi, 1, 1, 1); | MODULE_DEPEND(ipoib, linuxkpi, 1, 1, 1); |