if_infiniband.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /*-
  2. * Copyright (c) 2020 Mellanox Technologies. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
  17. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23. * SUCH DAMAGE.
  24. */
  25. #include "opt_inet.h"
  26. #include "opt_inet6.h"
  27. #include "opt_kbd.h"
  28. #include <sys/param.h>
  29. #include <sys/systm.h>
  30. #include <sys/devctl.h>
  31. #include <sys/eventhandler.h>
  32. #include <sys/kernel.h>
  33. #include <sys/mbuf.h>
  34. #include <sys/module.h>
  35. #include <sys/socket.h>
  36. #include <sys/sysctl.h>
  37. #ifdef KDB
  38. #include <sys/kdb.h>
  39. #endif
  40. #include <net/bpf.h>
  41. #include <net/ethernet.h>
  42. #include <net/infiniband.h>
  43. #include <net/if.h>
  44. #include <net/if_var.h>
  45. #include <net/if_private.h>
  46. #include <net/if_dl.h>
  47. #include <net/if_media.h>
  48. #include <net/if_lagg.h>
  49. #include <net/if_llatbl.h>
  50. #include <net/if_types.h>
  51. #include <net/netisr.h>
  52. #include <net/route.h>
  53. #include <netinet/if_ether.h>
  54. #include <netinet/in.h>
  55. #include <netinet/ip6.h>
  56. #include <netinet6/in6_var.h>
  57. #include <netinet6/nd6.h>
  58. #include <security/mac/mac_framework.h>
  59. /* if_lagg(4) support */
  60. struct mbuf *(*lagg_input_infiniband_p)(struct ifnet *, struct mbuf *);
  61. #ifdef INET
  62. static inline void
  63. infiniband_ipv4_multicast_map(uint32_t addr,
  64. const uint8_t *broadcast, uint8_t *buf)
  65. {
  66. uint8_t scope;
  67. addr = ntohl(addr);
  68. scope = broadcast[5] & 0xF;
  69. buf[0] = 0;
  70. buf[1] = 0xff;
  71. buf[2] = 0xff;
  72. buf[3] = 0xff;
  73. buf[4] = 0xff;
  74. buf[5] = 0x10 | scope;
  75. buf[6] = 0x40;
  76. buf[7] = 0x1b;
  77. buf[8] = broadcast[8];
  78. buf[9] = broadcast[9];
  79. buf[10] = 0;
  80. buf[11] = 0;
  81. buf[12] = 0;
  82. buf[13] = 0;
  83. buf[14] = 0;
  84. buf[15] = 0;
  85. buf[16] = (addr >> 24) & 0xff;
  86. buf[17] = (addr >> 16) & 0xff;
  87. buf[18] = (addr >> 8) & 0xff;
  88. buf[19] = addr & 0xff;
  89. }
  90. #endif
  91. #ifdef INET6
  92. static inline void
  93. infiniband_ipv6_multicast_map(const struct in6_addr *addr,
  94. const uint8_t *broadcast, uint8_t *buf)
  95. {
  96. uint8_t scope;
  97. scope = broadcast[5] & 0xF;
  98. buf[0] = 0;
  99. buf[1] = 0xff;
  100. buf[2] = 0xff;
  101. buf[3] = 0xff;
  102. buf[4] = 0xff;
  103. buf[5] = 0x10 | scope;
  104. buf[6] = 0x60;
  105. buf[7] = 0x1b;
  106. buf[8] = broadcast[8];
  107. buf[9] = broadcast[9];
  108. memcpy(&buf[10], &addr->s6_addr[6], 10);
  109. }
  110. #endif
  111. /*
  112. * This is for clients that have an infiniband_header in the mbuf.
  113. */
  114. void
  115. infiniband_bpf_mtap(struct ifnet *ifp, struct mbuf *mb)
  116. {
  117. struct infiniband_header *ibh;
  118. struct ether_header eh;
  119. if (!bpf_peers_present(ifp->if_bpf))
  120. return;
  121. M_ASSERTVALID(mb);
  122. if (mb->m_len < sizeof(*ibh))
  123. return;
  124. ibh = mtod(mb, struct infiniband_header *);
  125. eh.ether_type = ibh->ib_protocol;
  126. memset(eh.ether_shost, 0, ETHER_ADDR_LEN);
  127. memcpy(eh.ether_dhost, ibh->ib_hwaddr + 4, ETHER_ADDR_LEN);
  128. mb->m_data += sizeof(*ibh);
  129. mb->m_len -= sizeof(*ibh);
  130. mb->m_pkthdr.len -= sizeof(*ibh);
  131. bpf_mtap2(ifp->if_bpf, &eh, sizeof(eh), mb);
  132. mb->m_data -= sizeof(*ibh);
  133. mb->m_len += sizeof(*ibh);
  134. mb->m_pkthdr.len += sizeof(*ibh);
  135. }
  136. static void
  137. update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst)
  138. {
  139. int csum_flags = 0;
  140. if (src->m_pkthdr.csum_flags & CSUM_IP)
  141. csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
  142. if (src->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
  143. csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
  144. if (src->m_pkthdr.csum_flags & CSUM_SCTP)
  145. csum_flags |= CSUM_SCTP_VALID;
  146. dst->m_pkthdr.csum_flags |= csum_flags;
  147. if (csum_flags & CSUM_DATA_VALID)
  148. dst->m_pkthdr.csum_data = 0xffff;
  149. }
  150. /*
  151. * Handle link-layer encapsulation requests.
  152. */
  153. static int
  154. infiniband_requestencap(struct ifnet *ifp, struct if_encap_req *req)
  155. {
  156. struct infiniband_header *ih;
  157. struct arphdr *ah;
  158. uint16_t etype;
  159. const uint8_t *lladdr;
  160. if (req->rtype != IFENCAP_LL)
  161. return (EOPNOTSUPP);
  162. if (req->bufsize < INFINIBAND_HDR_LEN)
  163. return (ENOMEM);
  164. ih = (struct infiniband_header *)req->buf;
  165. lladdr = req->lladdr;
  166. req->lladdr_off = 0;
  167. switch (req->family) {
  168. case AF_INET:
  169. etype = htons(ETHERTYPE_IP);
  170. break;
  171. case AF_INET6:
  172. etype = htons(ETHERTYPE_IPV6);
  173. break;
  174. case AF_ARP:
  175. ah = (struct arphdr *)req->hdata;
  176. ah->ar_hrd = htons(ARPHRD_INFINIBAND);
  177. switch (ntohs(ah->ar_op)) {
  178. case ARPOP_REVREQUEST:
  179. case ARPOP_REVREPLY:
  180. etype = htons(ETHERTYPE_REVARP);
  181. break;
  182. case ARPOP_REQUEST:
  183. case ARPOP_REPLY:
  184. default:
  185. etype = htons(ETHERTYPE_ARP);
  186. break;
  187. }
  188. if (req->flags & IFENCAP_FLAG_BROADCAST)
  189. lladdr = ifp->if_broadcastaddr;
  190. break;
  191. default:
  192. return (EAFNOSUPPORT);
  193. }
  194. ih->ib_protocol = etype;
  195. ih->ib_reserved = 0;
  196. memcpy(ih->ib_hwaddr, lladdr, INFINIBAND_ADDR_LEN);
  197. req->bufsize = sizeof(struct infiniband_header);
  198. return (0);
  199. }
  200. static int
  201. infiniband_resolve_addr(struct ifnet *ifp, struct mbuf *m,
  202. const struct sockaddr *dst, struct route *ro, uint8_t *phdr,
  203. uint32_t *pflags, struct llentry **plle)
  204. {
  205. #if defined(INET) || defined(INET6)
  206. struct infiniband_header *ih = (struct infiniband_header *)phdr;
  207. #endif
  208. uint32_t lleflags = 0;
  209. int error = 0;
  210. if (plle)
  211. *plle = NULL;
  212. switch (dst->sa_family) {
  213. #ifdef INET
  214. case AF_INET:
  215. if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) {
  216. error = arpresolve(ifp, 0, m, dst, phdr, &lleflags, plle);
  217. } else {
  218. if (m->m_flags & M_BCAST) {
  219. memcpy(ih->ib_hwaddr, ifp->if_broadcastaddr,
  220. INFINIBAND_ADDR_LEN);
  221. } else {
  222. infiniband_ipv4_multicast_map(
  223. ((const struct sockaddr_in *)dst)->sin_addr.s_addr,
  224. ifp->if_broadcastaddr, ih->ib_hwaddr);
  225. }
  226. ih->ib_protocol = htons(ETHERTYPE_IP);
  227. ih->ib_reserved = 0;
  228. }
  229. break;
  230. #endif
  231. #ifdef INET6
  232. case AF_INET6:
  233. if ((m->m_flags & M_MCAST) == 0) {
  234. int af = RO_GET_FAMILY(ro, dst);
  235. error = nd6_resolve(ifp, LLE_SF(af, 0), m, dst, phdr,
  236. &lleflags, plle);
  237. } else {
  238. infiniband_ipv6_multicast_map(
  239. &((const struct sockaddr_in6 *)dst)->sin6_addr,
  240. ifp->if_broadcastaddr, ih->ib_hwaddr);
  241. ih->ib_protocol = htons(ETHERTYPE_IPV6);
  242. ih->ib_reserved = 0;
  243. }
  244. break;
  245. #endif
  246. default:
  247. if_printf(ifp, "can't handle af%d\n", dst->sa_family);
  248. if (m != NULL)
  249. m_freem(m);
  250. return (EAFNOSUPPORT);
  251. }
  252. if (error == EHOSTDOWN) {
  253. if (ro != NULL && (ro->ro_flags & RT_HAS_GW) != 0)
  254. error = EHOSTUNREACH;
  255. }
  256. if (error != 0)
  257. return (error);
  258. *pflags = RT_MAY_LOOP;
  259. if (lleflags & LLE_IFADDR)
  260. *pflags |= RT_L2_ME;
  261. return (0);
  262. }
  263. /*
  264. * Infiniband output routine.
  265. */
  266. static int
  267. infiniband_output(struct ifnet *ifp, struct mbuf *m,
  268. const struct sockaddr *dst, struct route *ro)
  269. {
  270. uint8_t linkhdr[INFINIBAND_HDR_LEN];
  271. uint8_t *phdr;
  272. struct llentry *lle = NULL;
  273. struct infiniband_header *ih;
  274. int error = 0;
  275. int hlen; /* link layer header length */
  276. uint32_t pflags;
  277. bool addref;
  278. NET_EPOCH_ASSERT();
  279. addref = false;
  280. phdr = NULL;
  281. pflags = 0;
  282. if (ro != NULL) {
  283. /* XXX BPF uses ro_prepend */
  284. if (ro->ro_prepend != NULL) {
  285. phdr = ro->ro_prepend;
  286. hlen = ro->ro_plen;
  287. } else if (!(m->m_flags & (M_BCAST | M_MCAST))) {
  288. if ((ro->ro_flags & RT_LLE_CACHE) != 0) {
  289. lle = ro->ro_lle;
  290. if (lle != NULL &&
  291. (lle->la_flags & LLE_VALID) == 0) {
  292. LLE_FREE(lle);
  293. lle = NULL; /* redundant */
  294. ro->ro_lle = NULL;
  295. }
  296. if (lle == NULL) {
  297. /* if we lookup, keep cache */
  298. addref = 1;
  299. } else
  300. /*
  301. * Notify LLE code that
  302. * the entry was used
  303. * by datapath.
  304. */
  305. llentry_provide_feedback(lle);
  306. }
  307. if (lle != NULL) {
  308. phdr = lle->r_linkdata;
  309. hlen = lle->r_hdrlen;
  310. pflags = lle->r_flags;
  311. }
  312. }
  313. }
  314. #ifdef MAC
  315. error = mac_ifnet_check_transmit(ifp, m);
  316. if (error)
  317. goto bad;
  318. #endif
  319. M_PROFILE(m);
  320. if (ifp->if_flags & IFF_MONITOR) {
  321. error = ENETDOWN;
  322. goto bad;
  323. }
  324. if (!((ifp->if_flags & IFF_UP) &&
  325. (ifp->if_drv_flags & IFF_DRV_RUNNING))) {
  326. error = ENETDOWN;
  327. goto bad;
  328. }
  329. if (phdr == NULL) {
  330. /* No prepend data supplied. Try to calculate ourselves. */
  331. phdr = linkhdr;
  332. hlen = INFINIBAND_HDR_LEN;
  333. error = infiniband_resolve_addr(ifp, m, dst, ro, phdr, &pflags,
  334. addref ? &lle : NULL);
  335. if (addref && lle != NULL)
  336. ro->ro_lle = lle;
  337. if (error != 0)
  338. return (error == EWOULDBLOCK ? 0 : error);
  339. }
  340. if ((pflags & RT_L2_ME) != 0) {
  341. update_mbuf_csumflags(m, m);
  342. return (if_simloop(ifp, m, RO_GET_FAMILY(ro, dst), 0));
  343. }
  344. /*
  345. * Add local infiniband header. If no space in first mbuf,
  346. * allocate another.
  347. */
  348. M_PREPEND(m, INFINIBAND_HDR_LEN, M_NOWAIT);
  349. if (m == NULL) {
  350. error = ENOBUFS;
  351. goto bad;
  352. }
  353. if ((pflags & RT_HAS_HEADER) == 0) {
  354. ih = mtod(m, struct infiniband_header *);
  355. memcpy(ih, phdr, hlen);
  356. }
  357. /*
  358. * Queue message on interface, update output statistics if
  359. * successful, and start output if interface not yet active.
  360. */
  361. return (ifp->if_transmit(ifp, m));
  362. bad:
  363. if (m != NULL)
  364. m_freem(m);
  365. return (error);
  366. }
  367. /*
  368. * Process a received Infiniband packet.
  369. */
  370. static void
  371. infiniband_input(struct ifnet *ifp, struct mbuf *m)
  372. {
  373. struct infiniband_header *ibh;
  374. struct epoch_tracker et;
  375. int isr;
  376. bool needs_epoch;
  377. needs_epoch = (ifp->if_flags & IFF_NEEDSEPOCH);
  378. #ifdef INVARIANTS
  379. /*
  380. * This temporary code is here to prevent epoch unaware and unmarked
  381. * drivers to panic the system. Once all drivers are taken care of,
  382. * the whole INVARIANTS block should go away.
  383. */
  384. if (!needs_epoch && !in_epoch(net_epoch_preempt)) {
  385. static bool printedonce;
  386. needs_epoch = true;
  387. if (!printedonce) {
  388. printedonce = true;
  389. if_printf(ifp, "called %s w/o net epoch! "
  390. "PLEASE file a bug report.", __func__);
  391. #ifdef KDB
  392. kdb_backtrace();
  393. #endif
  394. }
  395. }
  396. #endif
  397. CURVNET_SET_QUIET(ifp->if_vnet);
  398. if (__predict_false(needs_epoch))
  399. NET_EPOCH_ENTER(et);
  400. if ((ifp->if_flags & IFF_UP) == 0) {
  401. if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  402. m_freem(m);
  403. goto done;
  404. }
  405. ibh = mtod(m, struct infiniband_header *);
  406. /*
  407. * Reset layer specific mbuf flags to avoid confusing upper
  408. * layers:
  409. */
  410. m->m_flags &= ~M_VLANTAG;
  411. m_clrprotoflags(m);
  412. if (INFINIBAND_IS_MULTICAST(ibh->ib_hwaddr)) {
  413. if (memcmp(ibh->ib_hwaddr, ifp->if_broadcastaddr,
  414. ifp->if_addrlen) == 0)
  415. m->m_flags |= M_BCAST;
  416. else
  417. m->m_flags |= M_MCAST;
  418. if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1);
  419. }
  420. /* Let BPF have it before we strip the header. */
  421. infiniband_bpf_mtap(ifp, m);
  422. /* Allow monitor mode to claim this frame, after stats are updated. */
  423. if (ifp->if_flags & IFF_MONITOR) {
  424. m_freem(m);
  425. goto done;
  426. }
  427. /* Direct packet to correct FIB based on interface config. */
  428. M_SETFIB(m, ifp->if_fib);
  429. /* Handle input from a lagg<N> port */
  430. if (ifp->if_type == IFT_INFINIBANDLAG) {
  431. KASSERT(lagg_input_infiniband_p != NULL,
  432. ("%s: if_lagg not loaded!", __func__));
  433. m = (*lagg_input_infiniband_p)(ifp, m);
  434. if (__predict_false(m == NULL))
  435. goto done;
  436. ifp = m->m_pkthdr.rcvif;
  437. }
  438. /*
  439. * Dispatch frame to upper layer.
  440. */
  441. switch (ibh->ib_protocol) {
  442. #ifdef INET
  443. case htons(ETHERTYPE_IP):
  444. isr = NETISR_IP;
  445. break;
  446. case htons(ETHERTYPE_ARP):
  447. if (ifp->if_flags & IFF_NOARP) {
  448. /* Discard packet if ARP is disabled on interface */
  449. m_freem(m);
  450. goto done;
  451. }
  452. isr = NETISR_ARP;
  453. break;
  454. #endif
  455. #ifdef INET6
  456. case htons(ETHERTYPE_IPV6):
  457. isr = NETISR_IPV6;
  458. break;
  459. #endif
  460. default:
  461. if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  462. m_freem(m);
  463. goto done;
  464. }
  465. /* Strip off the Infiniband header. */
  466. m_adj(m, INFINIBAND_HDR_LEN);
  467. #ifdef MAC
  468. /*
  469. * Tag the mbuf with an appropriate MAC label before any other
  470. * consumers can get to it.
  471. */
  472. mac_ifnet_create_mbuf(ifp, m);
  473. #endif
  474. /* Allow monitor mode to claim this frame, after stats are updated. */
  475. netisr_dispatch(isr, m);
  476. done:
  477. if (__predict_false(needs_epoch))
  478. NET_EPOCH_EXIT(et);
  479. CURVNET_RESTORE();
  480. }
  481. static int
  482. infiniband_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa,
  483. struct sockaddr *sa)
  484. {
  485. struct sockaddr_dl *sdl;
  486. #ifdef INET
  487. struct sockaddr_in *sin;
  488. #endif
  489. #ifdef INET6
  490. struct sockaddr_in6 *sin6;
  491. #endif
  492. uint8_t *e_addr;
  493. switch (sa->sa_family) {
  494. case AF_LINK:
  495. /*
  496. * No mapping needed. Just check that it's a valid MC address.
  497. */
  498. sdl = (struct sockaddr_dl *)sa;
  499. e_addr = LLADDR(sdl);
  500. if (!INFINIBAND_IS_MULTICAST(e_addr))
  501. return (EADDRNOTAVAIL);
  502. *llsa = NULL;
  503. return 0;
  504. #ifdef INET
  505. case AF_INET:
  506. sin = (struct sockaddr_in *)sa;
  507. if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
  508. return (EADDRNOTAVAIL);
  509. sdl = link_init_sdl(ifp, *llsa, IFT_INFINIBAND);
  510. sdl->sdl_alen = INFINIBAND_ADDR_LEN;
  511. e_addr = LLADDR(sdl);
  512. infiniband_ipv4_multicast_map(
  513. sin->sin_addr.s_addr, ifp->if_broadcastaddr, e_addr);
  514. *llsa = (struct sockaddr *)sdl;
  515. return (0);
  516. #endif
  517. #ifdef INET6
  518. case AF_INET6:
  519. sin6 = (struct sockaddr_in6 *)sa;
  520. /*
  521. * An IP6 address of 0 means listen to all of the
  522. * multicast address used for IP6. This has no meaning
  523. * in infiniband.
  524. */
  525. if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
  526. return (EADDRNOTAVAIL);
  527. if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
  528. return (EADDRNOTAVAIL);
  529. sdl = link_init_sdl(ifp, *llsa, IFT_INFINIBAND);
  530. sdl->sdl_alen = INFINIBAND_ADDR_LEN;
  531. e_addr = LLADDR(sdl);
  532. infiniband_ipv6_multicast_map(
  533. &sin6->sin6_addr, ifp->if_broadcastaddr, e_addr);
  534. *llsa = (struct sockaddr *)sdl;
  535. return (0);
  536. #endif
  537. default:
  538. return (EAFNOSUPPORT);
  539. }
  540. }
  541. void
  542. infiniband_ifattach(struct ifnet *ifp, const uint8_t *lla, const uint8_t *llb)
  543. {
  544. struct sockaddr_dl *sdl;
  545. struct ifaddr *ifa;
  546. int i;
  547. ifp->if_addrlen = INFINIBAND_ADDR_LEN;
  548. ifp->if_hdrlen = INFINIBAND_HDR_LEN;
  549. ifp->if_mtu = INFINIBAND_MTU;
  550. if_attach(ifp);
  551. ifp->if_output = infiniband_output;
  552. ifp->if_input = infiniband_input;
  553. ifp->if_resolvemulti = infiniband_resolvemulti;
  554. ifp->if_requestencap = infiniband_requestencap;
  555. if (ifp->if_baudrate == 0)
  556. ifp->if_baudrate = IF_Gbps(10); /* default value */
  557. if (llb != NULL)
  558. ifp->if_broadcastaddr = llb;
  559. ifa = ifp->if_addr;
  560. KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__));
  561. sdl = (struct sockaddr_dl *)ifa->ifa_addr;
  562. sdl->sdl_type = IFT_INFINIBAND;
  563. sdl->sdl_alen = ifp->if_addrlen;
  564. if (lla != NULL) {
  565. memcpy(LLADDR(sdl), lla, ifp->if_addrlen);
  566. if (ifp->if_hw_addr != NULL)
  567. memcpy(ifp->if_hw_addr, lla, ifp->if_addrlen);
  568. } else {
  569. lla = LLADDR(sdl);
  570. }
  571. /* Attach ethernet compatible network device */
  572. bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
  573. /* Announce Infiniband MAC address if non-zero. */
  574. for (i = 0; i < ifp->if_addrlen; i++)
  575. if (lla[i] != 0)
  576. break;
  577. if (i != ifp->if_addrlen)
  578. if_printf(ifp, "Infiniband address: %20D\n", lla, ":");
  579. /* Add necessary bits are setup; announce it now. */
  580. EVENTHANDLER_INVOKE(infiniband_ifattach_event, ifp);
  581. if (IS_DEFAULT_VNET(curvnet))
  582. devctl_notify("INFINIBAND", ifp->if_xname, "IFATTACH", NULL);
  583. }
  584. /*
  585. * Perform common duties while detaching an Infiniband interface
  586. */
  587. void
  588. infiniband_ifdetach(struct ifnet *ifp)
  589. {
  590. bpfdetach(ifp);
  591. if_detach(ifp);
  592. }
  593. static int
  594. infiniband_modevent(module_t mod, int type, void *data)
  595. {
  596. switch (type) {
  597. case MOD_LOAD:
  598. case MOD_UNLOAD:
  599. return (0);
  600. default:
  601. return (EOPNOTSUPP);
  602. }
  603. }
  604. static moduledata_t infiniband_mod = {
  605. .name = "if_infiniband",
  606. .evhand = &infiniband_modevent,
  607. };
  608. DECLARE_MODULE(if_infiniband, infiniband_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
  609. MODULE_VERSION(if_infiniband, 1);