Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102639697
D27631.id81062.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D27631.id81062.diff
View Options
Index: sys/net/if_infiniband.c
===================================================================
--- sys/net/if_infiniband.c
+++ sys/net/if_infiniband.c
@@ -143,141 +143,240 @@
mb->m_pkthdr.len += sizeof(*ibh);
}
+static void
+update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst)
+{
+ int csum_flags = 0;
+
+ if (src->m_pkthdr.csum_flags & CSUM_IP)
+ csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
+ if (src->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
+ csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
+ if (src->m_pkthdr.csum_flags & CSUM_SCTP)
+ csum_flags |= CSUM_SCTP_VALID;
+ dst->m_pkthdr.csum_flags |= csum_flags;
+ if (csum_flags & CSUM_DATA_VALID)
+ dst->m_pkthdr.csum_data = 0xffff;
+}
+
/*
- * Infiniband output routine.
+ * Handle link-layer encapsulation requests.
*/
static int
-infiniband_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
- struct route *ro)
+infiniband_requestencap(struct ifnet *ifp, struct if_encap_req *req)
{
- uint8_t edst[INFINIBAND_ADDR_LEN];
-#if defined(INET) || defined(INET6)
- struct llentry *lle = NULL;
-#endif
- struct infiniband_header *ibh;
- int error = 0;
- uint16_t type;
- bool is_gw;
+ struct infiniband_header *ih;
+ struct arphdr *ah;
+ uint16_t etype;
+ const uint8_t *lladdr;
- NET_EPOCH_ASSERT();
+ if (req->rtype != IFENCAP_LL)
+ return (EOPNOTSUPP);
- is_gw = ((ro != NULL) && (ro->ro_flags & RT_HAS_GW) != 0);
+ if (req->bufsize < INFINIBAND_HDR_LEN)
+ return (ENOMEM);
-#ifdef MAC
- error = mac_ifnet_check_transmit(ifp, m);
- if (error)
- goto bad;
-#endif
+ ih = (struct infiniband_header *)req->buf;
+ lladdr = req->lladdr;
+ req->lladdr_off = 0;
- 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) {
- case AF_LINK:
- goto output;
-#ifdef INET
+ switch (req->family) {
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) {
- infiniband_ipv4_multicast_map(
- ((const 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) {
- if (error == EWOULDBLOCK)
- error = 0;
- m = NULL; /* mbuf is consumed by resolver */
- goto bad;
- }
- }
- type = htons(ETHERTYPE_IP);
+ etype = htons(ETHERTYPE_IP);
break;
- case AF_ARP: {
- struct arphdr *ah;
-
- if (m->m_len < sizeof(*ah)) {
- error = EINVAL;
- goto bad;
- }
-
- ah = mtod(m, struct arphdr *);
-
- if (m->m_len < arphdr_len(ah)) {
- error = EINVAL;
- goto bad;
- }
+ case AF_INET6:
+ etype = htons(ETHERTYPE_IPV6);
+ break;
+ case AF_ARP:
+ ah = (struct arphdr *)req->hdata;
ah->ar_hrd = htons(ARPHRD_INFINIBAND);
- switch (ntohs(ah->ar_op)) {
+ switch(ntohs(ah->ar_op)) {
case ARPOP_REVREQUEST:
case ARPOP_REVREPLY:
- type = htons(ETHERTYPE_REVARP);
+ etype = htons(ETHERTYPE_REVARP);
break;
case ARPOP_REQUEST:
case ARPOP_REPLY:
default:
- type = htons(ETHERTYPE_ARP);
+ etype = htons(ETHERTYPE_ARP);
break;
}
- if (m->m_flags & M_BCAST) {
- memcpy(edst, ifp->if_broadcastaddr, INFINIBAND_ADDR_LEN);
+ if (req->flags & IFENCAP_FLAG_BROADCAST)
+ lladdr = ifp->if_broadcastaddr;
+ break;
+ default:
+ return (EAFNOSUPPORT);
+ }
+
+ ih->ib_protocol = etype;
+ ih->ib_reserved = 0;
+ memcpy(ih->ib_hwaddr, lladdr, INFINIBAND_ADDR_LEN);
+ req->bufsize = sizeof(struct infiniband_header);
+
+ return (0);
+}
+
+static int
+infiniband_resolve_addr(struct ifnet *ifp, struct mbuf *m,
+ const struct sockaddr *dst, struct route *ro, uint8_t *phdr,
+ uint32_t *pflags, struct llentry **plle)
+{
+ struct infiniband_header *ih;
+ uint32_t lleflags = 0;
+ int error = 0;
+
+ if (plle)
+ *plle = NULL;
+ ih = (struct infiniband_header *)phdr;
+
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) {
+ error = arpresolve(ifp, 0, m, dst, phdr, &lleflags, plle);
} else {
- if (ah->ar_hln != INFINIBAND_ADDR_LEN) {
- error = EINVAL;
- goto bad;
+ if (m->m_flags & M_BCAST) {
+ memcpy(ih->ib_hwaddr, ifp->if_broadcastaddr,
+ INFINIBAND_ADDR_LEN);
+ } else {
+ infiniband_ipv4_multicast_map(
+ ((const struct sockaddr_in *)dst)->sin_addr.s_addr,
+ ifp->if_broadcastaddr, ih->ib_hwaddr);
}
- memcpy(edst, ar_tha(ah), INFINIBAND_ADDR_LEN);
+ ih->ib_protocol = htons(ETHERTYPE_IP);
+ ih->ib_reserved = 0;
}
break;
- }
#endif
#ifdef INET6
- case AF_INET6: {
- const struct ip6_hdr *ip6;
-
- ip6 = mtod(m, const struct ip6_hdr *);
- if (m->m_len < sizeof(*ip6)) {
- error = EINVAL;
- goto bad;
- } else if (lle != NULL && (lle->la_flags & LLE_VALID)) {
- memcpy(edst, lle->ll_addr, sizeof(edst));
- } else if (m->m_flags & M_MCAST) {
+ case AF_INET6:
+ if ((m->m_flags & M_MCAST) == 0) {
+ error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags, plle);
+ } else {
infiniband_ipv6_multicast_map(
&((const struct sockaddr_in6 *)dst)->sin6_addr,
- ifp->if_broadcastaddr, edst);
- } else if (ip6->ip6_nxt == IPPROTO_ICMPV6) {
- memcpy(edst, ifp->if_broadcastaddr, INFINIBAND_ADDR_LEN);
- } else {
- error = nd6_resolve(ifp, is_gw, m, dst, edst, NULL, NULL);
- if (error) {
- if (error == EWOULDBLOCK)
- error = 0;
- m = NULL; /* mbuf is consumed by resolver */
- goto bad;
- }
+ ifp->if_broadcastaddr, ih->ib_hwaddr);
+ ih->ib_protocol = htons(ETHERTYPE_IPV6);
+ ih->ib_reserved = 0;
}
- type = htons(ETHERTYPE_IPV6);
break;
+#endif
+ default:
+ if_printf(ifp, "can't handle af%d\n", dst->sa_family);
+ if (m != NULL)
+ m_freem(m);
+ return (EAFNOSUPPORT);
}
+
+ if (error == EHOSTDOWN) {
+ if (ro != NULL && (ro->ro_flags & RT_HAS_GW) != 0)
+ error = EHOSTUNREACH;
+ }
+
+ if (error != 0)
+ return (error);
+
+ *pflags = RT_MAY_LOOP;
+ if (lleflags & LLE_IFADDR)
+ *pflags |= RT_L2_ME;
+
+ return (0);
+}
+
+/*
+ * Infiniband output routine.
+ */
+static int
+infiniband_output(struct ifnet *ifp, struct mbuf *m,
+ const struct sockaddr *dst, struct route *ro)
+{
+ uint8_t linkhdr[INFINIBAND_HDR_LEN];
+ uint8_t *phdr;
+#if defined(INET) || defined(INET6)
+ struct llentry *lle = NULL;
#endif
- default:
- error = EAFNOSUPPORT;
+ struct infiniband_header *ih;
+ int error = 0;
+ int hlen; /* link layer header length */
+ uint32_t pflags;
+ bool addref;
+
+ NET_EPOCH_ASSERT();
+
+ addref = false;
+ phdr = NULL;
+ pflags = 0;
+ if (ro != NULL) {
+ /* XXX BPF uses ro_prepend */
+ if (ro->ro_prepend != NULL) {
+ phdr = ro->ro_prepend;
+ hlen = ro->ro_plen;
+ } else if (!(m->m_flags & (M_BCAST | M_MCAST))) {
+ if ((ro->ro_flags & RT_LLE_CACHE) != 0) {
+ lle = ro->ro_lle;
+ if (lle != NULL &&
+ (lle->la_flags & LLE_VALID) == 0) {
+ LLE_FREE(lle);
+ lle = NULL; /* redundant */
+ ro->ro_lle = NULL;
+ }
+ if (lle == NULL) {
+ /* if we lookup, keep cache */
+ addref = 1;
+ } else
+ /*
+ * Notify LLE code that
+ * the entry was used
+ * by datapath.
+ */
+ llentry_mark_used(lle);
+ }
+ if (lle != NULL) {
+ phdr = lle->r_linkdata;
+ hlen = lle->r_hdrlen;
+ pflags = lle->r_flags;
+ }
+ }
+ }
+
+#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;
+ }
+ if (phdr == NULL) {
+ /* No prepend data supplied. Try to calculate ourselves. */
+ phdr = linkhdr;
+ hlen = INFINIBAND_HDR_LEN;
+ error = infiniband_resolve_addr(ifp, m, dst, ro, phdr, &pflags,
+ addref ? &lle : NULL);
+ if (addref && lle != NULL)
+ ro->ro_lle = lle;
+ if (error != 0)
+ return (error == EWOULDBLOCK ? 0 : error);
+ }
+
+ if ((pflags & RT_L2_ME) != 0) {
+ update_mbuf_csumflags(m, m);
+ return (if_simloop(ifp, m, dst->sa_family, 0));
+ }
+
/*
- * Add local net header. If no space in first mbuf,
+ * Add local ininiband header. If no space in first mbuf,
* allocate another.
*/
M_PREPEND(m, INFINIBAND_HDR_LEN, M_NOWAIT);
@@ -285,16 +384,15 @@
error = ENOBUFS;
goto bad;
}
- ibh = mtod(m, struct infiniband_header *);
+ if ((pflags & RT_HAS_HEADER) == 0) {
+ ih = mtod(m, struct infiniband_header *);
+ memcpy(ih, phdr, hlen);
+ }
- ibh->ib_protocol = type;
- memcpy(ibh->ib_hwaddr, edst, sizeof(edst));
-
/*
* Queue message on interface, update output statistics if
* successful, and start output if interface not yet active.
*/
-output:
return (ifp->if_transmit(ifp, m));
bad:
if (m != NULL)
@@ -484,6 +582,7 @@
ifp->if_output = infiniband_output;
ifp->if_input = infiniband_input;
ifp->if_resolvemulti = infiniband_resolvemulti;
+ ifp->if_requestencap = infiniband_requestencap;
if (ifp->if_baudrate == 0)
ifp->if_baudrate = IF_Gbps(10); /* default value */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 16, 5:00 AM (19 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14653425
Default Alt Text
D27631.id81062.diff (8 KB)
Attached To
Mode
D27631: Streamline infiniband code according to ethernet code
Attached
Detach File
Event Timeline
Log In to Comment