xref: /freebsd-src/sys/dev/ixgbe/if_fdir.c (revision c58d34dd67a419866ee50f152044e49cecbae261)
1*c58d34ddSKevin Bowling /*****************************************************************************
28eb6488eSEric Joyner 
38eb6488eSEric Joyner   Copyright (c) 2001-2017, Intel Corporation
48eb6488eSEric Joyner   All rights reserved.
58eb6488eSEric Joyner 
68eb6488eSEric Joyner   Redistribution and use in source and binary forms, with or without
78eb6488eSEric Joyner   modification, are permitted provided that the following conditions are met:
88eb6488eSEric Joyner 
98eb6488eSEric Joyner    1. Redistributions of source code must retain the above copyright notice,
108eb6488eSEric Joyner       this list of conditions and the following disclaimer.
118eb6488eSEric Joyner 
128eb6488eSEric Joyner    2. Redistributions in binary form must reproduce the above copyright
138eb6488eSEric Joyner       notice, this list of conditions and the following disclaimer in the
148eb6488eSEric Joyner       documentation and/or other materials provided with the distribution.
158eb6488eSEric Joyner 
168eb6488eSEric Joyner    3. Neither the name of the Intel Corporation nor the names of its
178eb6488eSEric Joyner       contributors may be used to endorse or promote products derived from
188eb6488eSEric Joyner       this software without specific prior written permission.
198eb6488eSEric Joyner 
208eb6488eSEric Joyner   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
218eb6488eSEric Joyner   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228eb6488eSEric Joyner   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238eb6488eSEric Joyner   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248eb6488eSEric Joyner   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258eb6488eSEric Joyner   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268eb6488eSEric Joyner   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278eb6488eSEric Joyner   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288eb6488eSEric Joyner   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298eb6488eSEric Joyner   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
308eb6488eSEric Joyner   POSSIBILITY OF SUCH DAMAGE.
318eb6488eSEric Joyner 
32*c58d34ddSKevin Bowling *****************************************************************************/
338eb6488eSEric Joyner 
348eb6488eSEric Joyner #include "ixgbe.h"
358eb6488eSEric Joyner 
368eb6488eSEric Joyner #ifdef IXGBE_FDIR
378eb6488eSEric Joyner 
388eb6488eSEric Joyner void
39b1d5caf3SKevin Bowling ixgbe_init_fdir(struct ixgbe_softc *sc)
408eb6488eSEric Joyner {
418eb6488eSEric Joyner 	u32 hdrm = 32 << fdir_pballoc;
428eb6488eSEric Joyner 
43b1d5caf3SKevin Bowling 	if (!(sc->feat_en & IXGBE_FEATURE_FDIR))
448eb6488eSEric Joyner 		return;
458eb6488eSEric Joyner 
46b1d5caf3SKevin Bowling 	sc->hw.mac.ops.setup_rxpba(&sc->hw, 0, hdrm,
478eb6488eSEric Joyner 	    PBA_STRATEGY_EQUAL);
48b1d5caf3SKevin Bowling 	ixgbe_init_fdir_signature_82599(&sc->hw, fdir_pballoc);
498eb6488eSEric Joyner } /* ixgbe_init_fdir */
508eb6488eSEric Joyner 
518eb6488eSEric Joyner void
52c19c7afeSEric Joyner ixgbe_reinit_fdir(void *context)
538eb6488eSEric Joyner {
54c19c7afeSEric Joyner 	if_ctx_t ctx = context;
55b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
56ff06a8dbSJustin Hibbits 	if_t ifp = iflib_get_ifp(ctx);
578eb6488eSEric Joyner 
58b1d5caf3SKevin Bowling 	if (!(sc->feat_en & IXGBE_FEATURE_FDIR))
598eb6488eSEric Joyner 		return;
60b1d5caf3SKevin Bowling 	if (sc->fdir_reinit != 1) /* Shouldn't happen */
618eb6488eSEric Joyner 		return;
62b1d5caf3SKevin Bowling 	ixgbe_reinit_fdir_tables_82599(&sc->hw);
63b1d5caf3SKevin Bowling 	sc->fdir_reinit = 0;
648eb6488eSEric Joyner 	/* re-enable flow director interrupts */
65b1d5caf3SKevin Bowling 	IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
668eb6488eSEric Joyner 	/* Restart the interface */
67ff06a8dbSJustin Hibbits 	if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0);
688eb6488eSEric Joyner } /* ixgbe_reinit_fdir */
698eb6488eSEric Joyner 
708eb6488eSEric Joyner /************************************************************************
718eb6488eSEric Joyner  * ixgbe_atr
728eb6488eSEric Joyner  *
738eb6488eSEric Joyner  *   Parse packet headers so that Flow Director can make
748eb6488eSEric Joyner  *   a hashed filter table entry allowing traffic flows
758eb6488eSEric Joyner  *   to be identified and kept on the same cpu.  This
768eb6488eSEric Joyner  *   would be a performance hit, but we only do it at
778eb6488eSEric Joyner  *   IXGBE_FDIR_RATE of packets.
788eb6488eSEric Joyner  ************************************************************************/
798eb6488eSEric Joyner void
808eb6488eSEric Joyner ixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
818eb6488eSEric Joyner {
82b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = txr->sc;
838eb6488eSEric Joyner 	struct ix_queue *que;
848eb6488eSEric Joyner 	struct ip *ip;
858eb6488eSEric Joyner 	struct tcphdr *th;
868eb6488eSEric Joyner 	struct udphdr *uh;
878eb6488eSEric Joyner 	struct ether_vlan_header *eh;
888eb6488eSEric Joyner 	union ixgbe_atr_hash_dword input = {.dword = 0};
898eb6488eSEric Joyner 	union ixgbe_atr_hash_dword common = {.dword = 0};
908eb6488eSEric Joyner 	int ehdrlen, ip_hlen;
918eb6488eSEric Joyner 	u16 etype;
928eb6488eSEric Joyner 
938eb6488eSEric Joyner 	eh = mtod(mp, struct ether_vlan_header *);
948eb6488eSEric Joyner 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
958eb6488eSEric Joyner 		ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
968eb6488eSEric Joyner 		etype = eh->evl_proto;
978eb6488eSEric Joyner 	} else {
988eb6488eSEric Joyner 		ehdrlen = ETHER_HDR_LEN;
998eb6488eSEric Joyner 		etype = eh->evl_encap_proto;
1008eb6488eSEric Joyner 	}
1018eb6488eSEric Joyner 
1028eb6488eSEric Joyner 	/* Only handling IPv4 */
1038eb6488eSEric Joyner 	if (etype != htons(ETHERTYPE_IP))
1048eb6488eSEric Joyner 		return;
1058eb6488eSEric Joyner 
1068eb6488eSEric Joyner 	ip = (struct ip *)(mp->m_data + ehdrlen);
1078eb6488eSEric Joyner 	ip_hlen = ip->ip_hl << 2;
1088eb6488eSEric Joyner 
1098eb6488eSEric Joyner 	/* check if we're UDP or TCP */
1108eb6488eSEric Joyner 	switch (ip->ip_p) {
1118eb6488eSEric Joyner 	case IPPROTO_TCP:
1128eb6488eSEric Joyner 		th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
1138eb6488eSEric Joyner 		/* src and dst are inverted */
1148eb6488eSEric Joyner 		common.port.dst ^= th->th_sport;
1158eb6488eSEric Joyner 		common.port.src ^= th->th_dport;
1168eb6488eSEric Joyner 		input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_TCPV4;
1178eb6488eSEric Joyner 		break;
1188eb6488eSEric Joyner 	case IPPROTO_UDP:
1198eb6488eSEric Joyner 		uh = (struct udphdr *)((caddr_t)ip + ip_hlen);
1208eb6488eSEric Joyner 		/* src and dst are inverted */
1218eb6488eSEric Joyner 		common.port.dst ^= uh->uh_sport;
1228eb6488eSEric Joyner 		common.port.src ^= uh->uh_dport;
1238eb6488eSEric Joyner 		input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_UDPV4;
1248eb6488eSEric Joyner 		break;
1258eb6488eSEric Joyner 	default:
1268eb6488eSEric Joyner 		return;
1278eb6488eSEric Joyner 	}
1288eb6488eSEric Joyner 
1298eb6488eSEric Joyner 	input.formatted.vlan_id = htobe16(mp->m_pkthdr.ether_vtag);
1308eb6488eSEric Joyner 	if (mp->m_pkthdr.ether_vtag)
1318eb6488eSEric Joyner 		common.flex_bytes ^= htons(ETHERTYPE_VLAN);
1328eb6488eSEric Joyner 	else
1338eb6488eSEric Joyner 		common.flex_bytes ^= etype;
1348eb6488eSEric Joyner 	common.ip ^= ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
1358eb6488eSEric Joyner 
136b1d5caf3SKevin Bowling 	que = &sc->queues[txr->me];
1378eb6488eSEric Joyner 	/*
1388eb6488eSEric Joyner 	 * This assumes the Rx queue and Tx
1398eb6488eSEric Joyner 	 * queue are bound to the same CPU
1408eb6488eSEric Joyner 	 */
141b1d5caf3SKevin Bowling 	ixgbe_fdir_add_signature_filter_82599(&sc->hw,
1428eb6488eSEric Joyner 	    input, common, que->msix);
1438eb6488eSEric Joyner } /* ixgbe_atr */
1448eb6488eSEric Joyner 
1458eb6488eSEric Joyner #else
1468eb6488eSEric Joyner 
1478eb6488eSEric Joyner /* TASK_INIT needs this function defined regardless if it's enabled */
1488eb6488eSEric Joyner void
149c19c7afeSEric Joyner ixgbe_reinit_fdir(void *context)
1508eb6488eSEric Joyner {
151c19c7afeSEric Joyner 	UNREFERENCED_PARAMETER(context);
1528eb6488eSEric Joyner } /* ixgbe_reinit_fdir */
1538eb6488eSEric Joyner 
1548eb6488eSEric Joyner void
1558eb6488eSEric Joyner ixgbe_atr(struct tx_ring *txr, struct mbuf *mp)
1568eb6488eSEric Joyner {
1578eb6488eSEric Joyner 	UNREFERENCED_2PARAMETER(txr, mp);
1588eb6488eSEric Joyner } /* ixgbe_atr */
1598eb6488eSEric Joyner 
1608eb6488eSEric Joyner #endif
161