1320688Serj/******************************************************************************
2320688Serj
3320688Serj  Copyright (c) 2001-2017, Intel Corporation
4320688Serj  All rights reserved.
5320688Serj
6320688Serj  Redistribution and use in source and binary forms, with or without
7320688Serj  modification, are permitted provided that the following conditions are met:
8320688Serj
9320688Serj   1. Redistributions of source code must retain the above copyright notice,
10320688Serj      this list of conditions and the following disclaimer.
11320688Serj
12320688Serj   2. Redistributions in binary form must reproduce the above copyright
13320688Serj      notice, this list of conditions and the following disclaimer in the
14320688Serj      documentation and/or other materials provided with the distribution.
15320688Serj
16320688Serj   3. Neither the name of the Intel Corporation nor the names of its
17320688Serj      contributors may be used to endorse or promote products derived from
18320688Serj      this software without specific prior written permission.
19320688Serj
20320688Serj  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21320688Serj  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22320688Serj  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23320688Serj  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24320688Serj  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25320688Serj  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26320688Serj  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27320688Serj  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28320688Serj  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29320688Serj  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30320688Serj  POSSIBILITY OF SUCH DAMAGE.
31320688Serj
32320688Serj******************************************************************************/
33320688Serj/*$FreeBSD: stable/11/sys/dev/ixgbe/if_fdir.c 347419 2019-05-10 00:46:43Z erj $*/
34320688Serj
35320688Serj#include "ixgbe.h"
36320688Serj
37320688Serj#ifdef IXGBE_FDIR
38320688Serj
39320688Serjvoid
40320688Serjixgbe_init_fdir(struct adapter *adapter)
41320688Serj{
42320688Serj	u32 hdrm = 32 << fdir_pballoc;
43320688Serj
44320688Serj	if (!(adapter->feat_en & IXGBE_FEATURE_FDIR))
45320688Serj		return;
46320688Serj
47320688Serj	adapter->hw.mac.ops.setup_rxpba(&adapter->hw, 0, hdrm,
48320688Serj	    PBA_STRATEGY_EQUAL);
49320688Serj	ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
50320688Serj} /* ixgbe_init_fdir */
51320688Serj
52320688Serjvoid
53347419Serjixgbe_reinit_fdir(void *context)
54320688Serj{
55320688Serj	struct adapter *adapter = context;
56320688Serj	struct ifnet   *ifp = adapter->ifp;
57320688Serj
58320688Serj	if (!(adapter->feat_en & IXGBE_FEATURE_FDIR))
59320688Serj		return;
60320688Serj	if (adapter->fdir_reinit != 1) /* Shouldn't happen */
61320688Serj		return;
62320688Serj	ixgbe_reinit_fdir_tables_82599(&adapter->hw);
63320688Serj	adapter->fdir_reinit = 0;
64320688Serj	/* re-enable flow director interrupts */
65320688Serj	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
66320688Serj	/* Restart the interface */
67320688Serj	ifp->if_drv_flags |= IFF_DRV_RUNNING;
68320688Serj} /* ixgbe_reinit_fdir */
69320688Serj
70320688Serj/************************************************************************
71320688Serj * ixgbe_atr
72320688Serj *
73320688Serj *   Parse packet headers so that Flow Director can make
74320688Serj *   a hashed filter table entry allowing traffic flows
75320688Serj *   to be identified and kept on the same cpu.  This
76320688Serj *   would be a performance hit, but we only do it at
77320688Serj *   IXGBE_FDIR_RATE of packets.
78320688Serj ************************************************************************/
79320688Serjvoid
80320688Serjixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
81320688Serj{
82320688Serj	struct adapter             *adapter = txr->adapter;
83320688Serj	struct ix_queue            *que;
84320688Serj	struct ip                  *ip;
85320688Serj	struct tcphdr              *th;
86320688Serj	struct udphdr              *uh;
87320688Serj	struct ether_vlan_header   *eh;
88320688Serj	union ixgbe_atr_hash_dword input = {.dword = 0};
89320688Serj	union ixgbe_atr_hash_dword common = {.dword = 0};
90320688Serj	int                        ehdrlen, ip_hlen;
91320688Serj	u16                        etype;
92320688Serj
93320688Serj	eh = mtod(mp, struct ether_vlan_header *);
94320688Serj	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
95320688Serj		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
96320688Serj		etype = eh->evl_proto;
97320688Serj	} else {
98320688Serj		ehdrlen = ETHER_HDR_LEN;
99320688Serj		etype = eh->evl_encap_proto;
100320688Serj	}
101320688Serj
102320688Serj	/* Only handling IPv4 */
103320688Serj	if (etype != htons(ETHERTYPE_IP))
104320688Serj		return;
105320688Serj
106320688Serj	ip = (struct ip *)(mp->m_data + ehdrlen);
107320688Serj	ip_hlen = ip->ip_hl << 2;
108320688Serj
109320688Serj	/* check if we're UDP or TCP */
110320688Serj	switch (ip->ip_p) {
111320688Serj	case IPPROTO_TCP:
112320688Serj		th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
113320688Serj		/* src and dst are inverted */
114320688Serj		common.port.dst ^= th->th_sport;
115320688Serj		common.port.src ^= th->th_dport;
116320688Serj		input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_TCPV4;
117320688Serj		break;
118320688Serj	case IPPROTO_UDP:
119320688Serj		uh = (struct udphdr *)((caddr_t)ip + ip_hlen);
120320688Serj		/* src and dst are inverted */
121320688Serj		common.port.dst ^= uh->uh_sport;
122320688Serj		common.port.src ^= uh->uh_dport;
123320688Serj		input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_UDPV4;
124320688Serj		break;
125320688Serj	default:
126320688Serj		return;
127320688Serj	}
128320688Serj
129320688Serj	input.formatted.vlan_id = htobe16(mp->m_pkthdr.ether_vtag);
130320688Serj	if (mp->m_pkthdr.ether_vtag)
131320688Serj		common.flex_bytes ^= htons(ETHERTYPE_VLAN);
132320688Serj	else
133320688Serj		common.flex_bytes ^= etype;
134320688Serj	common.ip ^= ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
135320688Serj
136320688Serj	que = &adapter->queues[txr->me];
137320688Serj	/*
138320688Serj	 * This assumes the Rx queue and Tx
139320688Serj	 * queue are bound to the same CPU
140320688Serj	 */
141320688Serj	ixgbe_fdir_add_signature_filter_82599(&adapter->hw,
142320688Serj	    input, common, que->msix);
143320688Serj} /* ixgbe_atr */
144320688Serj
145320688Serj#else
146320688Serj
147320688Serj/* TASK_INIT needs this function defined regardless if it's enabled */
148320688Serjvoid
149347419Serjixgbe_reinit_fdir(void *context)
150320688Serj{
151347419Serj	UNREFERENCED_1PARAMETER(context);
152320688Serj} /* ixgbe_reinit_fdir */
153320688Serj
154320688Serjvoid
155320688Serjixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
156320688Serj{
157320688Serj	UNREFERENCED_2PARAMETER(txr, mp);
158320688Serj} /* ixgbe_atr */
159320688Serj
160320688Serj#endif
161