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