xref: /netbsd-src/sys/dev/pci/ixgbe/if_fdir.c (revision 55485da1d7c3dd560cd83aca0370533ca1207584)
1*55485da1Smsaitoh /* $NetBSD: if_fdir.c,v 1.6 2023/10/06 14:37:04 msaitoh Exp $ */
2dc7f84c8Smsaitoh /******************************************************************************
3dc7f84c8Smsaitoh 
4dc7f84c8Smsaitoh   Copyright (c) 2001-2017, Intel Corporation
5dc7f84c8Smsaitoh   All rights reserved.
6dc7f84c8Smsaitoh 
7dc7f84c8Smsaitoh   Redistribution and use in source and binary forms, with or without
8dc7f84c8Smsaitoh   modification, are permitted provided that the following conditions are met:
9dc7f84c8Smsaitoh 
10dc7f84c8Smsaitoh    1. Redistributions of source code must retain the above copyright notice,
11dc7f84c8Smsaitoh       this list of conditions and the following disclaimer.
12dc7f84c8Smsaitoh 
13dc7f84c8Smsaitoh    2. Redistributions in binary form must reproduce the above copyright
14dc7f84c8Smsaitoh       notice, this list of conditions and the following disclaimer in the
15dc7f84c8Smsaitoh       documentation and/or other materials provided with the distribution.
16dc7f84c8Smsaitoh 
17dc7f84c8Smsaitoh    3. Neither the name of the Intel Corporation nor the names of its
18dc7f84c8Smsaitoh       contributors may be used to endorse or promote products derived from
19dc7f84c8Smsaitoh       this software without specific prior written permission.
20dc7f84c8Smsaitoh 
21dc7f84c8Smsaitoh   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22dc7f84c8Smsaitoh   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23dc7f84c8Smsaitoh   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24dc7f84c8Smsaitoh   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25dc7f84c8Smsaitoh   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26dc7f84c8Smsaitoh   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27dc7f84c8Smsaitoh   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28dc7f84c8Smsaitoh   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29dc7f84c8Smsaitoh   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30dc7f84c8Smsaitoh   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31dc7f84c8Smsaitoh   POSSIBILITY OF SUCH DAMAGE.
32dc7f84c8Smsaitoh 
33dc7f84c8Smsaitoh ******************************************************************************/
34a06ca633Smsaitoh /*$FreeBSD: head/sys/dev/ixgbe/if_fdir.c 327031 2017-12-20 18:15:06Z erj $*/
35dc7f84c8Smsaitoh 
36ab119b16Smsaitoh #include <sys/cdefs.h>
37*55485da1Smsaitoh __KERNEL_RCSID(0, "$NetBSD: if_fdir.c,v 1.6 2023/10/06 14:37:04 msaitoh Exp $");
38ab119b16Smsaitoh 
39dc7f84c8Smsaitoh #include "ixgbe.h"
40dc7f84c8Smsaitoh 
41dc7f84c8Smsaitoh #ifdef IXGBE_FDIR
42dc7f84c8Smsaitoh 
43dc7f84c8Smsaitoh void
ixgbe_init_fdir(struct ixgbe_softc * sc)44*55485da1Smsaitoh ixgbe_init_fdir(struct ixgbe_softc *sc)
45dc7f84c8Smsaitoh {
46dc7f84c8Smsaitoh 	u32 hdrm = 32 << fdir_pballoc;
47dc7f84c8Smsaitoh 
48*55485da1Smsaitoh 	if (!(sc->feat_en & IXGBE_FEATURE_FDIR))
49dc7f84c8Smsaitoh 		return;
50dc7f84c8Smsaitoh 
51*55485da1Smsaitoh 	sc->hw.mac.ops.setup_rxpba(&sc->hw, 0, hdrm,
52dc7f84c8Smsaitoh 	    PBA_STRATEGY_EQUAL);
53*55485da1Smsaitoh 	ixgbe_init_fdir_signature_82599(&sc->hw, fdir_pballoc);
54dc7f84c8Smsaitoh } /* ixgbe_init_fdir */
55dc7f84c8Smsaitoh 
56dc7f84c8Smsaitoh void
ixgbe_reinit_fdir(void * context)57dc7f84c8Smsaitoh ixgbe_reinit_fdir(void *context)
58dc7f84c8Smsaitoh {
59*55485da1Smsaitoh 	struct ixgbe_softc *sc = context;
60*55485da1Smsaitoh 	struct ifnet   *ifp = sc->ifp;
61dc7f84c8Smsaitoh 
62*55485da1Smsaitoh 	KASSERT(mutex_owned(&sc->core_mtx));
6364088230Smsaitoh 
64*55485da1Smsaitoh 	if (!(sc->feat_en & IXGBE_FEATURE_FDIR))
65dc7f84c8Smsaitoh 		return;
66*55485da1Smsaitoh 	if (sc->fdir_reinit != 1) /* Shouldn't happen */
67dc7f84c8Smsaitoh 		return;
68*55485da1Smsaitoh 	ixgbe_reinit_fdir_tables_82599(&sc->hw);
69*55485da1Smsaitoh 	sc->fdir_reinit = 0;
70dc7f84c8Smsaitoh 	/* re-enable flow director interrupts */
71*55485da1Smsaitoh 	IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
72dc7f84c8Smsaitoh 	/* Restart the interface */
73dc7f84c8Smsaitoh 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
74dc7f84c8Smsaitoh } /* ixgbe_reinit_fdir */
75dc7f84c8Smsaitoh 
76dc7f84c8Smsaitoh /************************************************************************
77dc7f84c8Smsaitoh  * ixgbe_atr
78dc7f84c8Smsaitoh  *
79dc7f84c8Smsaitoh  *   Parse packet headers so that Flow Director can make
80dc7f84c8Smsaitoh  *   a hashed filter table entry allowing traffic flows
81dc7f84c8Smsaitoh  *   to be identified and kept on the same cpu.  This
82dc7f84c8Smsaitoh  *   would be a performance hit, but we only do it at
83dc7f84c8Smsaitoh  *   IXGBE_FDIR_RATE of packets.
84dc7f84c8Smsaitoh  ************************************************************************/
85dc7f84c8Smsaitoh void
ixgbe_atr(struct tx_ring * txr,struct mbuf * mp)86dc7f84c8Smsaitoh ixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
87dc7f84c8Smsaitoh {
88*55485da1Smsaitoh 	struct ixgbe_softc             *sc = txr->sc;
89dc7f84c8Smsaitoh 	struct ix_queue            *que;
90dc7f84c8Smsaitoh 	struct ip                  *ip;
91dc7f84c8Smsaitoh 	struct tcphdr              *th;
92dc7f84c8Smsaitoh 	struct udphdr              *uh;
93dc7f84c8Smsaitoh 	struct ether_vlan_header   *eh;
94dc7f84c8Smsaitoh 	union ixgbe_atr_hash_dword input = {.dword = 0};
95dc7f84c8Smsaitoh 	union ixgbe_atr_hash_dword common = {.dword = 0};
96dc7f84c8Smsaitoh 	int                        ehdrlen, ip_hlen;
97dc7f84c8Smsaitoh 	u16                        etype;
98dc7f84c8Smsaitoh 
99dc7f84c8Smsaitoh 	eh = mtod(mp, struct ether_vlan_header *);
100dc7f84c8Smsaitoh 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
101dc7f84c8Smsaitoh 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
102dc7f84c8Smsaitoh 		etype = eh->evl_proto;
103dc7f84c8Smsaitoh 	} else {
104dc7f84c8Smsaitoh 		ehdrlen = ETHER_HDR_LEN;
105dc7f84c8Smsaitoh 		etype = eh->evl_encap_proto;
106dc7f84c8Smsaitoh 	}
107dc7f84c8Smsaitoh 
108dc7f84c8Smsaitoh 	/* Only handling IPv4 */
109dc7f84c8Smsaitoh 	if (etype != htons(ETHERTYPE_IP))
110dc7f84c8Smsaitoh 		return;
111dc7f84c8Smsaitoh 
112dc7f84c8Smsaitoh 	ip = (struct ip *)(mp->m_data + ehdrlen);
113dc7f84c8Smsaitoh 	ip_hlen = ip->ip_hl << 2;
114dc7f84c8Smsaitoh 
115dc7f84c8Smsaitoh 	/* check if we're UDP or TCP */
116dc7f84c8Smsaitoh 	switch (ip->ip_p) {
117dc7f84c8Smsaitoh 	case IPPROTO_TCP:
118dc7f84c8Smsaitoh 		th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
119dc7f84c8Smsaitoh 		/* src and dst are inverted */
120dc7f84c8Smsaitoh 		common.port.dst ^= th->th_sport;
121dc7f84c8Smsaitoh 		common.port.src ^= th->th_dport;
122dc7f84c8Smsaitoh 		input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_TCPV4;
123dc7f84c8Smsaitoh 		break;
124dc7f84c8Smsaitoh 	case IPPROTO_UDP:
125dc7f84c8Smsaitoh 		uh = (struct udphdr *)((caddr_t)ip + ip_hlen);
126dc7f84c8Smsaitoh 		/* src and dst are inverted */
127dc7f84c8Smsaitoh 		common.port.dst ^= uh->uh_sport;
128dc7f84c8Smsaitoh 		common.port.src ^= uh->uh_dport;
129dc7f84c8Smsaitoh 		input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_UDPV4;
130dc7f84c8Smsaitoh 		break;
131dc7f84c8Smsaitoh 	default:
132dc7f84c8Smsaitoh 		return;
133dc7f84c8Smsaitoh 	}
134dc7f84c8Smsaitoh 
135dc7f84c8Smsaitoh 	input.formatted.vlan_id = htobe16(mp->m_pkthdr.ether_vtag);
136dc7f84c8Smsaitoh 	if (mp->m_pkthdr.ether_vtag)
137dc7f84c8Smsaitoh 		common.flex_bytes ^= htons(ETHERTYPE_VLAN);
138dc7f84c8Smsaitoh 	else
139dc7f84c8Smsaitoh 		common.flex_bytes ^= etype;
140dc7f84c8Smsaitoh 	common.ip ^= ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
141dc7f84c8Smsaitoh 
142*55485da1Smsaitoh 	que = &sc->queues[txr->me];
143dc7f84c8Smsaitoh 	/*
144dc7f84c8Smsaitoh 	 * This assumes the Rx queue and Tx
145dc7f84c8Smsaitoh 	 * queue are bound to the same CPU
146dc7f84c8Smsaitoh 	 */
147*55485da1Smsaitoh 	ixgbe_fdir_add_signature_filter_82599(&sc->hw,
148dc7f84c8Smsaitoh 	    input, common, que->msix);
149dc7f84c8Smsaitoh } /* ixgbe_atr */
150dc7f84c8Smsaitoh 
151dc7f84c8Smsaitoh #else
152dc7f84c8Smsaitoh 
153dc7f84c8Smsaitoh /* TASK_INIT needs this function defined regardless if it's enabled */
154dc7f84c8Smsaitoh void
ixgbe_reinit_fdir(void * context)155dc7f84c8Smsaitoh ixgbe_reinit_fdir(void *context)
156dc7f84c8Smsaitoh {
157dc7f84c8Smsaitoh 	UNREFERENCED_1PARAMETER(context);
158dc7f84c8Smsaitoh } /* ixgbe_reinit_fdir */
159dc7f84c8Smsaitoh 
160dc7f84c8Smsaitoh void
ixgbe_atr(struct tx_ring * txr,struct mbuf * mp)161dc7f84c8Smsaitoh ixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
162dc7f84c8Smsaitoh {
163dc7f84c8Smsaitoh 	UNREFERENCED_2PARAMETER(txr, mp);
164dc7f84c8Smsaitoh } /* ixgbe_atr */
165dc7f84c8Smsaitoh 
166dc7f84c8Smsaitoh #endif
167