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