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
ixgbe_tx_ctx_setup(struct ixgbe_adv_tx_context_desc * TXD,if_pkt_info_t pi)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
ixgbe_isc_txd_encap(void * arg,if_pkt_info_t pi)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
ixgbe_isc_txd_flush(void * arg,uint16_t txqid,qidx_t pidx)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
ixgbe_isc_txd_credits_update(void * arg,uint16_t txqid,bool clear)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
ixgbe_isc_rxd_refill(void * arg,if_rxd_update_t iru)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
ixgbe_isc_rxd_flush(void * arg,uint16_t qsidx,uint8_t flidx __unused,qidx_t pidx)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
ixgbe_isc_rxd_available(void * arg,uint16_t qsidx,qidx_t pidx,qidx_t budget)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
ixgbe_isc_rxd_pkt_get(void * arg,if_rxd_info_t ri)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
ixgbe_rx_checksum(uint32_t staterr,if_rxd_info_t ri,uint32_t ptype)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
ixgbe_determine_rsstype(uint16_t pkt_info)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