Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164140539
D5320.id13418.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D5320.id13418.diff
View Options
Index: sys/dev/vnic/nicvf_main.c
===================================================================
--- sys/dev/vnic/nicvf_main.c
+++ sys/dev/vnic/nicvf_main.c
@@ -353,6 +353,13 @@
if_setmtu(ifp, ETHERMTU);
if_setcapabilities(ifp, IFCAP_VLAN_MTU);
+ /*
+ * HW offload capabilities
+ */
+ /* IP/TCP/UDP HW checksums */
+ if_setcapabilitiesbit(ifp, IFCAP_HWCSUM, 0);
+ if_sethwassistbits(ifp, (CSUM_IP | CSUM_TCP | CSUM_UDP), 0);
+
#ifdef DEVICE_POLLING
#error "DEVICE_POLLING not supported in VNIC driver yet"
if_setcapabilitiesbit(ifp, IFCAP_POLLING, 0);
@@ -500,6 +507,10 @@
/* No work to do except acknowledge the change took. */
ifp->if_capenable ^= IFCAP_VLAN_MTU;
}
+ if (mask & IFCAP_TXCSUM)
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ if (mask & IFCAP_RXCSUM)
+ ifp->if_capenable ^= IFCAP_RXCSUM;
break;
default:
@@ -591,6 +602,7 @@
struct nicvf *nic = if_getsoftc(ifp);
struct queue_set *qs = nic->qs;
struct snd_queue *sq;
+ struct mbuf *mtmp;
int qidx;
int err = 0;
@@ -610,16 +622,24 @@
if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING) {
- if (mbuf != NULL)
- err = drbr_enqueue(ifp, sq->br, mbuf);
+ err = drbr_enqueue(ifp, sq->br, mbuf);
return (err);
}
- if (mbuf != NULL) {
+ if (mbuf->m_next != NULL &&
+ (mbuf->m_pkthdr.csum_flags &
+ (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)) != 0) {
+ if (M_WRITABLE(mbuf) == 0) {
+ mtmp = m_dup(mbuf, M_NOWAIT);
+ m_freem(mbuf);
+ if (mtmp == NULL)
+ return (ENOBUFS);
+ mbuf = mtmp;
+ }
+ }
err = drbr_enqueue(ifp, sq->br, mbuf);
if (err != 0)
return (err);
- }
taskqueue_enqueue(sq->snd_taskq, &sq->snd_task);
Index: sys/dev/vnic/nicvf_queues.c
===================================================================
--- sys/dev/vnic/nicvf_queues.c
+++ sys/dev/vnic/nicvf_queues.c
@@ -29,6 +29,9 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitset.h>
@@ -64,6 +67,16 @@
#include <net/if_media.h>
#include <net/ifq.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/sctp.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_lro.h>
+#include <netinet/udp.h>
+
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -1658,11 +1671,17 @@
* Add SQ HEADER subdescriptor.
* First subdescriptor for every send descriptor.
*/
-static __inline void
+static __inline int
nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qentry,
int subdesc_cnt, struct mbuf *mbuf, int len)
{
struct sq_hdr_subdesc *hdr;
+ struct ether_vlan_header *eh;
+#ifdef INET
+ struct ip *ip;
+#endif
+ uint16_t etype;
+ int ehdrlen, iphlen, poff;
hdr = (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, qentry);
sq->snd_buff[qentry].mbuf = mbuf;
@@ -1675,7 +1694,93 @@
hdr->subdesc_cnt = subdesc_cnt;
hdr->tot_len = len;
- /* ARM64TODO: Implement HW checksums calculation */
+ if (mbuf->m_pkthdr.csum_flags != 0) {
+ hdr->csum_l3 = 1; /* Enable IP csum calculation */
+
+ eh = mtod(mbuf, struct ether_vlan_header *);
+ if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
+ ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+ etype = ntohs(eh->evl_proto);
+ } else {
+ ehdrlen = ETHER_HDR_LEN;
+ etype = ntohs(eh->evl_encap_proto);
+ }
+
+ if (mbuf->m_len < ehdrlen + sizeof(struct ip)) {
+ mbuf = m_pullup(mbuf, ehdrlen + sizeof(struct ip));
+ sq->snd_buff[qentry].mbuf = mbuf;
+ if (mbuf == NULL)
+ return (ENOBUFS);
+ }
+
+ switch (etype) {
+#ifdef INET6
+ case ETHERTYPE_IPV6:
+ /* ARM64TODO: Add support for IPv6 */
+ hdr->csum_l3 = 0;
+ sq->snd_buff[qentry].mbuf = NULL;
+ return (ENXIO);
+#endif
+#ifdef INET
+ case ETHERTYPE_IP:
+ ip = (struct ip *)(mbuf->m_data + ehdrlen);
+ ip->ip_sum = 0;
+ iphlen = ip->ip_hl << 2;
+ poff = ehdrlen + iphlen;
+
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ if ((mbuf->m_pkthdr.csum_flags & CSUM_TCP) == 0)
+ break;
+
+ if (mbuf->m_len < (poff + sizeof(struct tcphdr))) {
+ mbuf = m_pullup(mbuf, poff + sizeof(struct tcphdr));
+ sq->snd_buff[qentry].mbuf = mbuf;
+ if (mbuf == NULL)
+ return (ENOBUFS);
+ }
+ hdr->csum_l4 = SEND_L4_CSUM_TCP;
+ break;
+ case IPPROTO_UDP:
+ if ((mbuf->m_pkthdr.csum_flags & CSUM_UDP) == 0)
+ break;
+
+ if (mbuf->m_len < (poff + sizeof(struct udphdr))) {
+ mbuf = m_pullup(mbuf, poff + sizeof(struct udphdr));
+ sq->snd_buff[qentry].mbuf = mbuf;
+ if (mbuf == NULL)
+ return (ENOBUFS);
+ }
+ hdr->csum_l4 = SEND_L4_CSUM_UDP;
+ break;
+ case IPPROTO_SCTP:
+ if ((mbuf->m_pkthdr.csum_flags & CSUM_SCTP) == 0)
+ break;
+
+ if (mbuf->m_len < (poff + sizeof(struct sctphdr))) {
+ mbuf = m_pullup(mbuf, poff + sizeof(struct sctphdr));
+ sq->snd_buff[qentry].mbuf = mbuf;
+ if (mbuf == NULL)
+ return (ENOBUFS);
+ }
+ hdr->csum_l4 = SEND_L4_CSUM_SCTP;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+ default:
+ hdr->csum_l3 = 0;
+ return (0);
+ }
+
+ hdr->l3_offset = ehdrlen;
+ hdr->l4_offset = ehdrlen + iphlen;
+ } else
+ hdr->csum_l3 = 0;
+
+ return (0);
}
/*
@@ -1734,8 +1839,12 @@
qentry = nicvf_get_sq_desc(sq, subdesc_cnt);
/* Add SQ header subdesc */
- nicvf_sq_add_hdr_subdesc(sq, qentry, subdesc_cnt - 1, mbuf,
+ err = nicvf_sq_add_hdr_subdesc(sq, qentry, subdesc_cnt - 1, mbuf,
mbuf->m_pkthdr.len);
+ if (err != 0) {
+ bus_dmamap_unload(sq->snd_buff_dmat, snd_buff->dmap);
+ return (err);
+ }
/* Add SQ gather subdescs */
for (seg = 0; seg < nsegs; seg++) {
@@ -1806,6 +1915,25 @@
m_fixhdr(mbuf);
mbuf->m_pkthdr.flowid = cqe_rx->rq_idx;
M_HASHTYPE_SET(mbuf, M_HASHTYPE_OPAQUE);
+ if (__predict_true((if_getcapenable(nic->ifp) & IFCAP_RXCSUM) != 0)) {
+ /*
+ * HW by default verifies IP & TCP/UDP/SCTP checksums
+ */
+
+ /* XXX: Do we need to include IP with options too? */
+ if (__predict_true(cqe_rx->l3_type == L3TYPE_IPV4 ||
+ cqe_rx->l3_type == L3TYPE_IPV6)) {
+ mbuf->m_pkthdr.csum_flags =
+ (CSUM_IP_CHECKED | CSUM_IP_VALID);
+ }
+ if (cqe_rx->l4_type == L4TYPE_TCP ||
+ cqe_rx->l4_type == L4TYPE_UDP ||
+ cqe_rx->l4_type == L4TYPE_SCTP) {
+ mbuf->m_pkthdr.csum_flags |=
+ (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+ mbuf->m_pkthdr.csum_data = htons(0xffff);
+ }
+ }
}
return (mbuf);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 30, 2:45 AM (3 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35722887
Default Alt Text
D5320.id13418.diff (6 KB)
Attached To
Mode
D5320: Add support for hardware Tx and Rx checksums to VNIC driver
Attached
Detach File
Event Timeline
Log In to Comment