xref: /freebsd/sys/dev/ixgbe/ix_txrx.c (revision b54dcb897a5fa66ff1013d0ea403ed8894e34b8a)
1 /*****************************************************************************
2 
3   Copyright (c) 2001-2017, Intel Corporation
4   All rights reserved.
5 
6   Redistribution and use in source and binary forms, with or without
7   modification, are permitted provided that the following conditions are met:
8 
9    1. Redistributions of source code must retain the above copyright notice,
10       this list of conditions and the following disclaimer.
11 
12    2. Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in the
14       documentation and/or other materials provided with the distribution.
15 
16    3. Neither the name of the Intel Corporation nor the names of its
17       contributors may be used to endorse or promote products derived from
18       this software without specific prior written permission.
19 
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   POSSIBILITY OF SUCH DAMAGE.
31 
32 *****************************************************************************/
33 
34 #ifndef IXGBE_STANDALONE_BUILD
35 #include "opt_inet.h"
36 #include "opt_inet6.h"
37 #include "opt_rss.h"
38 #endif
39 
40 #include "ixgbe.h"
41 
42 /************************************************************************
43  * Local Function prototypes
44  ************************************************************************/
45 static int ixgbe_isc_txd_encap(void *, if_pkt_info_t);
46 static void ixgbe_isc_txd_flush(void *, uint16_t, qidx_t);
47 static int ixgbe_isc_txd_credits_update(void *, uint16_t, bool);
48 
49 static void ixgbe_isc_rxd_refill(void *, if_rxd_update_t);
50 static void ixgbe_isc_rxd_flush(void *, uint16_t, uint8_t, qidx_t);
51 static int ixgbe_isc_rxd_available(void *, uint16_t, qidx_t, qidx_t);
52 static int ixgbe_isc_rxd_pkt_get(void *, if_rxd_info_t);
53 
54 static void ixgbe_rx_checksum(uint32_t, if_rxd_info_t, uint32_t);
55 static int ixgbe_tx_ctx_setup(struct ixgbe_adv_tx_context_desc *,
56     if_pkt_info_t);
57 
58 extern void ixgbe_if_enable_intr(if_ctx_t ctx);
59 static int ixgbe_determine_rsstype(uint16_t pkt_info);
60 
61 struct if_txrx ixgbe_txrx  = {
62 	.ift_txd_encap = ixgbe_isc_txd_encap,
63 	.ift_txd_flush = ixgbe_isc_txd_flush,
64 	.ift_txd_credits_update = ixgbe_isc_txd_credits_update,
65 	.ift_rxd_available = ixgbe_isc_rxd_available,
66 	.ift_rxd_pkt_get = ixgbe_isc_rxd_pkt_get,
67 	.ift_rxd_refill = ixgbe_isc_rxd_refill,
68 	.ift_rxd_flush = ixgbe_isc_rxd_flush,
69 	.ift_legacy_intr = NULL
70 };
71 
72 /************************************************************************
73  * ixgbe_tx_ctx_setup
74  *
75  *   Advanced Context Descriptor setup for VLAN, CSUM or TSO
76  *
77  ************************************************************************/
78 static int
79 ixgbe_tx_ctx_setup(struct ixgbe_adv_tx_context_desc *TXD, if_pkt_info_t pi)
80 {
81 	uint32_t vlan_macip_lens, type_tucmd_mlhl;
82 	uint32_t olinfo_status, mss_l4len_idx, pktlen, offload;
83 	u8 ehdrlen;
84 
85 	offload = true;
86 	olinfo_status = mss_l4len_idx = vlan_macip_lens = type_tucmd_mlhl = 0;
87 	/* VLAN MACLEN IPLEN */
88 	vlan_macip_lens |= (htole16(pi->ipi_vtag) << IXGBE_ADVTXD_VLAN_SHIFT);
89 
90 	/*
91 	 * Some of our VF devices need a context descriptor for every
92 	 * packet.  That means the ehdrlen needs to be non-zero in order
93 	 * for the host driver not to flag a malicious event. The stack
94 	 * will most likely populate this for all other reasons of why
95 	 * this function was called.
96 	 */
97 	if (pi->ipi_ehdrlen == 0) {
98 		ehdrlen = ETHER_HDR_LEN;
99 		ehdrlen += (pi->ipi_vtag != 0) ? ETHER_VLAN_ENCAP_LEN : 0;
100 	} else
101 		ehdrlen = pi->ipi_ehdrlen;
102 	vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
103 
104 	pktlen = pi->ipi_len;
105 	/* First check if TSO is to be used */
106 	if (pi->ipi_csum_flags & CSUM_TSO) {
107 		/* This is used in the transmit desc in encap */
108 		pktlen = pi->ipi_len - ehdrlen - pi->ipi_ip_hlen -
109 		    pi->ipi_tcp_hlen;
110 		mss_l4len_idx |=
111 		    (pi->ipi_tso_segsz << IXGBE_ADVTXD_MSS_SHIFT);
112 		mss_l4len_idx |=
113 		    (pi->ipi_tcp_hlen << IXGBE_ADVTXD_L4LEN_SHIFT);
114 	}
115 
116 	olinfo_status |= pktlen << IXGBE_ADVTXD_PAYLEN_SHIFT;
117 
118 	if (pi->ipi_flags & IPI_TX_IPV4) {
119 		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
120 		/* Tell transmit desc to also do IPv4 checksum. */
121 		if (pi->ipi_csum_flags & (CSUM_IP|CSUM_TSO))
122 			olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
123 	} else if (pi->ipi_flags & IPI_TX_IPV6)
124 		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
125 	else
126 		offload = false;
127 
128 	vlan_macip_lens |= pi->ipi_ip_hlen;
129 
130 	switch (pi->ipi_ipproto) {
131 	case IPPROTO_TCP:
132 		if (pi->ipi_csum_flags &
133 		    (CSUM_IP_TCP | CSUM_IP6_TCP | CSUM_TSO))
134 			type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
135 		else
136 			offload = false;
137 		break;
138 	case IPPROTO_UDP:
139 		if (pi->ipi_csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP))
140 			type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
141 		else
142 			offload = false;
143 		break;
144 	case IPPROTO_SCTP:
145 		if (pi->ipi_csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP))
146 			type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP;
147 		else
148 			offload = false;
149 		break;
150 	default:
151 		offload = false;
152 		break;
153 	}
154 	/* Insert L4 checksum into data descriptors */
155 	if (offload)
156 		olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
157 
158 	type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
159 
160 	/* Now copy bits into descriptor */
161 	TXD->vlan_macip_lens = htole32(vlan_macip_lens);
162 	TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
163 	TXD->seqnum_seed = htole32(0);
164 	TXD->mss_l4len_idx = htole32(mss_l4len_idx);
165 
166 	return (olinfo_status);
167 } /* ixgbe_tx_ctx_setup */
168 
169 /************************************************************************
170  * ixgbe_isc_txd_encap
171  ************************************************************************/
172 static int
173 ixgbe_isc_txd_encap(void *arg, if_pkt_info_t pi)
174 {
175 	struct ixgbe_softc *sc = arg;
176 	if_softc_ctx_t scctx = sc->shared;
177 	struct ix_tx_queue *que = &sc->tx_queues[pi->ipi_qsidx];
178 	struct tx_ring *txr = &que->txr;
179 	int nsegs = pi->ipi_nsegs;
180 	bus_dma_segment_t *segs = pi->ipi_segs;
181 	union ixgbe_adv_tx_desc *txd = NULL;
182 	struct ixgbe_adv_tx_context_desc *TXD;
183 	int i, j, first, pidx_last;
184 	uint32_t olinfo_status, cmd, flags;
185 	qidx_t ntxd;
186 
187 	cmd =  (IXGBE_ADVTXD_DTYP_DATA |
188 		IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);
189 
190 	if (pi->ipi_mflags & M_VLANTAG)
191 		cmd |= IXGBE_ADVTXD_DCMD_VLE;
192 
193 	i = first = pi->ipi_pidx;
194 	flags = (pi->ipi_flags & IPI_TX_INTR) ? IXGBE_TXD_CMD_RS : 0;
195 	ntxd = scctx->isc_ntxd[0];
196 
197 	TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[first];
198 	if ((pi->ipi_csum_flags & CSUM_OFFLOAD) ||
199 	    (sc->feat_en & IXGBE_FEATURE_NEEDS_CTXD) ||
200 	    (sc->feat_en & IXGBE_FEATURE_SRIOV) ||
201 	    pi->ipi_vtag) {
202 		/*********************************************
203 		 * Set up the appropriate offload context
204 		 * this will consume the first descriptor
205 		 *********************************************/
206 		olinfo_status = ixgbe_tx_ctx_setup(TXD, pi);
207 		if (pi->ipi_csum_flags & CSUM_TSO) {
208 			cmd |= IXGBE_ADVTXD_DCMD_TSE;
209 			++txr->tso_tx;
210 		}
211 
212 		if (++i == scctx->isc_ntxd[0])
213 			i = 0;
214 	} else {
215 		/* Indicate the whole packet as payload when not doing TSO */
216 		olinfo_status = pi->ipi_len << IXGBE_ADVTXD_PAYLEN_SHIFT;
217 	}
218 
219 	olinfo_status |= IXGBE_ADVTXD_CC;
220 	pidx_last = 0;
221 	for (j = 0; j < nsegs; j++) {
222 		bus_size_t seglen;
223 
224 		txd = &txr->tx_base[i];
225 		seglen = segs[j].ds_len;
226 
227 		txd->read.buffer_addr = htole64(segs[j].ds_addr);
228 		txd->read.cmd_type_len = htole32(cmd | seglen);
229 		txd->read.olinfo_status = htole32(olinfo_status);
230 
231 		pidx_last = i;
232 		if (++i == scctx->isc_ntxd[0]) {
233 			i = 0;
234 		}
235 	}
236 
237 	if (flags) {
238 		txr->tx_rsq[txr->tx_rs_pidx] = pidx_last;
239 		txr->tx_rs_pidx = (txr->tx_rs_pidx + 1) & (ntxd - 1);
240 	}
241 	txd->read.cmd_type_len |= htole32(IXGBE_TXD_CMD_EOP | flags);
242 
243 	txr->bytes += pi->ipi_len;
244 	pi->ipi_new_pidx = i;
245 
246 	++txr->total_packets;
247 
248 	return (0);
249 } /* ixgbe_isc_txd_encap */
250 
251 /************************************************************************
252  * ixgbe_isc_txd_flush
253  ************************************************************************/
254 static void
255 ixgbe_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
256 {
257 	struct ixgbe_softc *sc = arg;
258 	struct ix_tx_queue *que = &sc->tx_queues[txqid];
259 	struct tx_ring *txr = &que->txr;
260 
261 	IXGBE_WRITE_REG(&sc->hw, txr->tail, pidx);
262 } /* ixgbe_isc_txd_flush */
263 
264 /************************************************************************
265  * ixgbe_isc_txd_credits_update
266  ************************************************************************/
267 static int
268 ixgbe_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
269 {
270 	struct ixgbe_softc *sc = arg;
271 	if_softc_ctx_t scctx = sc->shared;
272 	struct ix_tx_queue *que = &sc->tx_queues[txqid];
273 	struct tx_ring *txr = &que->txr;
274 	qidx_t processed = 0;
275 	int updated;
276 	qidx_t cur, prev, ntxd, rs_cidx;
277 	int32_t delta;
278 	uint8_t status;
279 
280 	rs_cidx = txr->tx_rs_cidx;
281 	if (rs_cidx == txr->tx_rs_pidx)
282 		return (0);
283 
284 	cur = txr->tx_rsq[rs_cidx];
285 	status = txr->tx_base[cur].wb.status;
286 	updated = !!(status & IXGBE_TXD_STAT_DD);
287 
288 	if (!updated)
289 		return (0);
290 
291 	/* If clear is false just let caller know that there
292 	 * are descriptors to reclaim */
293 	if (!clear)
294 		return (1);
295 
296 	prev = txr->tx_cidx_processed;
297 	ntxd = scctx->isc_ntxd[0];
298 	do {
299 		MPASS(prev != cur);
300 		delta = (int32_t)cur - (int32_t)prev;
301 		if (delta < 0)
302 			delta += ntxd;
303 		MPASS(delta > 0);
304 
305 		processed += delta;
306 		prev = cur;
307 		rs_cidx = (rs_cidx + 1) & (ntxd - 1);
308 		if (rs_cidx == txr->tx_rs_pidx)
309 			break;
310 
311 		cur = txr->tx_rsq[rs_cidx];
312 		status = txr->tx_base[cur].wb.status;
313 	} while ((status & IXGBE_TXD_STAT_DD));
314 
315 	txr->tx_rs_cidx = rs_cidx;
316 	txr->tx_cidx_processed = prev;
317 
318 	return (processed);
319 } /* ixgbe_isc_txd_credits_update */
320 
321 /************************************************************************
322  * ixgbe_isc_rxd_refill
323  ************************************************************************/
324 static void
325 ixgbe_isc_rxd_refill(void *arg, if_rxd_update_t iru)
326 {
327 	struct ixgbe_softc *sc = arg;
328 	struct ix_rx_queue *que = &sc->rx_queues[iru->iru_qsidx];
329 	struct rx_ring *rxr = &que->rxr;
330 	uint64_t *paddrs;
331 	int i;
332 	uint32_t next_pidx, pidx;
333 	uint16_t count;
334 
335 	paddrs = iru->iru_paddrs;
336 	pidx = iru->iru_pidx;
337 	count = iru->iru_count;
338 
339 	for (i = 0, next_pidx = pidx; i < count; i++) {
340 		rxr->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]);
341 		if (++next_pidx == sc->shared->isc_nrxd[0])
342 			next_pidx = 0;
343 	}
344 } /* ixgbe_isc_rxd_refill */
345 
346 /************************************************************************
347  * ixgbe_isc_rxd_flush
348  ************************************************************************/
349 static void
350 ixgbe_isc_rxd_flush(void *arg, uint16_t qsidx, uint8_t flidx __unused,
351     qidx_t pidx)
352 {
353 	struct ixgbe_softc *sc = arg;
354 	struct ix_rx_queue *que = &sc->rx_queues[qsidx];
355 	struct rx_ring *rxr = &que->rxr;
356 
357 	IXGBE_WRITE_REG(&sc->hw, rxr->tail, pidx);
358 } /* ixgbe_isc_rxd_flush */
359 
360 /************************************************************************
361  * ixgbe_isc_rxd_available
362  ************************************************************************/
363 static int
364 ixgbe_isc_rxd_available(void *arg, uint16_t qsidx, qidx_t pidx, qidx_t budget)
365 {
366 	struct ixgbe_softc *sc = arg;
367 	struct ix_rx_queue *que = &sc->rx_queues[qsidx];
368 	struct rx_ring *rxr = &que->rxr;
369 	union ixgbe_adv_rx_desc *rxd;
370 	uint32_t staterr;
371 	int cnt, i, nrxd;
372 
373 	nrxd = sc->shared->isc_nrxd[0];
374 	for (cnt = 0, i = pidx; cnt < nrxd && cnt <= budget;) {
375 		rxd = &rxr->rx_base[i];
376 		staterr = le32toh(rxd->wb.upper.status_error);
377 
378 		if ((staterr & IXGBE_RXD_STAT_DD) == 0)
379 			break;
380 		if (++i == nrxd)
381 			i = 0;
382 		if (staterr & IXGBE_RXD_STAT_EOP)
383 			cnt++;
384 	}
385 	return (cnt);
386 } /* ixgbe_isc_rxd_available */
387 
388 /************************************************************************
389  * ixgbe_isc_rxd_pkt_get
390  *
391  *   Routine sends data which has been dma'ed into host memory
392  *   to upper layer. Initialize ri structure.
393  *
394  *   Returns 0 upon success, errno on failure
395  ************************************************************************/
396 
397 static int
398 ixgbe_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
399 {
400 	struct ixgbe_softc *sc = arg;
401 	if_softc_ctx_t scctx = sc->shared;
402 	struct ix_rx_queue *que = &sc->rx_queues[ri->iri_qsidx];
403 	struct rx_ring *rxr = &que->rxr;
404 	union ixgbe_adv_rx_desc *rxd;
405 
406 	uint16_t pkt_info, len, cidx, i, vid, vtag;
407 	uint32_t ptype;
408 	uint32_t staterr = 0;
409 	bool eop;
410 
411 	i = 0;
412 	cidx = ri->iri_cidx;
413 	do {
414 		rxd = &rxr->rx_base[cidx];
415 		staterr = le32toh(rxd->wb.upper.status_error);
416 		pkt_info = le16toh(rxd->wb.lower.lo_dword.hs_rss.pkt_info);
417 
418 		/* Error Checking then decrement count */
419 		MPASS ((staterr & IXGBE_RXD_STAT_DD) != 0);
420 
421 		len = le16toh(rxd->wb.upper.length);
422 		ptype = le32toh(rxd->wb.lower.lo_dword.data) &
423 			IXGBE_RXDADV_PKTTYPE_MASK;
424 
425 		ri->iri_len += len;
426 		rxr->bytes += len;
427 
428 		rxd->wb.upper.status_error = 0;
429 		eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);
430 
431 		/* Make sure bad packets are discarded */
432 		if (eop && (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) {
433 			if (sc->feat_en & IXGBE_FEATURE_VF)
434 				if_inc_counter(ri->iri_ifp, IFCOUNTER_IERRORS,
435 				    1);
436 
437 			rxr->rx_discarded++;
438 			return (EBADMSG);
439 		}
440 		ri->iri_frags[i].irf_flid = 0;
441 		ri->iri_frags[i].irf_idx = cidx;
442 		ri->iri_frags[i].irf_len = len;
443 		if (++cidx == sc->shared->isc_nrxd[0])
444 			cidx = 0;
445 		i++;
446 		/* even a 16K packet shouldn't consume more than 8 clusters */
447 		MPASS(i < 9);
448 	} while (!eop);
449 
450 	rxr->rx_packets++;
451 	rxr->packets++;
452 	rxr->rx_bytes += ri->iri_len;
453 
454 	if ((scctx->isc_capenable & IFCAP_RXCSUM) != 0)
455 		ixgbe_rx_checksum(staterr, ri,  ptype);
456 
457 	ri->iri_flowid = le32toh(rxd->wb.lower.hi_dword.rss);
458 	ri->iri_rsstype = ixgbe_determine_rsstype(pkt_info);
459 	if ((sc->feat_en & IXGBE_FEATURE_RSS) == 0) {
460 		if (ri->iri_rsstype == M_HASHTYPE_OPAQUE)
461 			ri->iri_rsstype = M_HASHTYPE_NONE;
462 		else
463 			ri->iri_rsstype = M_HASHTYPE_OPAQUE_HASH;
464 	}
465 	if ((rxr->vtag_strip) && (staterr & IXGBE_RXD_STAT_VP)) {
466 		vtag = le16toh(rxd->wb.upper.vlan);
467 		vid = EVL_VLANOFTAG(vtag);
468 		/*
469 		 * A PF-assigned port VLAN is stripped before a VF receives the
470 		 * frame, but it is not one of the VLANs registered by the VF.
471 		 * Do not expose that administrative tag to the VF's network
472 		 * stack.  Priority tags and locally registered trunk VLANs retain
473 		 * M_VLANTAG.
474 		 */
475 		if ((sc->feat_en & IXGBE_FEATURE_VF) == 0 || vid == 0 ||
476 		    (sc->shadow_vfta[vid >> 5] &
477 		    (1U << (vid & 0x1f))) != 0) {
478 			ri->iri_vtag = vtag;
479 			ri->iri_flags |= M_VLANTAG;
480 		}
481 	}
482 
483 	ri->iri_nfrags = i;
484 	return (0);
485 } /* ixgbe_isc_rxd_pkt_get */
486 
487 /************************************************************************
488  * ixgbe_rx_checksum
489  *
490  *   Verify that the hardware indicated that the checksum is valid.
491  *   Inform the stack about the status of checksum so that stack
492  *   doesn't spend time verifying the checksum.
493  ************************************************************************/
494 static void
495 ixgbe_rx_checksum(uint32_t staterr, if_rxd_info_t ri, uint32_t ptype)
496 {
497 	uint16_t status = (uint16_t)staterr;
498 	uint8_t errors = (uint8_t)(staterr >> 24);
499 
500 	/* If there is a layer 3 or 4 error we are done */
501 	if (__predict_false(errors &
502 	    (IXGBE_RXD_ERR_IPE | IXGBE_RXD_ERR_TCPE)))
503 		return;
504 
505 	/* IP Checksum Good */
506 	if (status & IXGBE_RXD_STAT_IPCS)
507 		ri->iri_csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID);
508 
509 	/* Valid L4E checksum */
510 	if (__predict_true(status & IXGBE_RXD_STAT_L4CS)) {
511 		/* SCTP header present. */
512 		if (__predict_false((ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&
513 		    (ptype & IXGBE_RXDADV_PKTTYPE_SCTP) != 0)) {
514 			ri->iri_csum_flags |= CSUM_SCTP_VALID;
515 		} else {
516 			ri->iri_csum_flags |=
517 			    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
518 			ri->iri_csum_data = htons(0xffff);
519 		}
520 	}
521 } /* ixgbe_rx_checksum */
522 
523 /************************************************************************
524  * ixgbe_determine_rsstype
525  *
526  *   Parse the packet type to determine the appropriate hash
527  ************************************************************************/
528 static int
529 ixgbe_determine_rsstype(uint16_t pkt_info)
530 {
531 	switch (pkt_info & IXGBE_RXDADV_RSSTYPE_MASK) {
532 	case IXGBE_RXDADV_RSSTYPE_IPV4_TCP:
533 		return M_HASHTYPE_RSS_TCP_IPV4;
534 	case IXGBE_RXDADV_RSSTYPE_IPV4:
535 		return M_HASHTYPE_RSS_IPV4;
536 	case IXGBE_RXDADV_RSSTYPE_IPV6_TCP:
537 		return M_HASHTYPE_RSS_TCP_IPV6;
538 	case IXGBE_RXDADV_RSSTYPE_IPV6_EX:
539 		return M_HASHTYPE_RSS_IPV6_EX;
540 	case IXGBE_RXDADV_RSSTYPE_IPV6:
541 		return M_HASHTYPE_RSS_IPV6;
542 	case IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX:
543 		return M_HASHTYPE_RSS_TCP_IPV6_EX;
544 	case IXGBE_RXDADV_RSSTYPE_IPV4_UDP:
545 		return M_HASHTYPE_RSS_UDP_IPV4;
546 	case IXGBE_RXDADV_RSSTYPE_IPV6_UDP:
547 		return M_HASHTYPE_RSS_UDP_IPV6;
548 	case IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX:
549 		return M_HASHTYPE_RSS_UDP_IPV6_EX;
550 	default:
551 		return M_HASHTYPE_OPAQUE;
552 	}
553 } /* ixgbe_determine_rsstype */
554