1e77f43b3b3e8019c95fee740dad8e831f46445e
[linux-2.6-microblaze.git] / drivers / net / ethernet / intel / ice / ice_fdir.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2018-2020, Intel Corporation. */
3
4 #include "ice_common.h"
5
6 /* These are training packet headers used to program flow director filters. */
7 static const u8 ice_fdir_tcpv4_pkt[] = {
8         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
10         0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
11         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00,
14         0x20, 0x00, 0x00, 0x00, 0x00, 0x00
15 };
16
17 static const u8 ice_fdir_udpv4_pkt[] = {
18         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
20         0x00, 0x1C, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
21         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23         0x00, 0x00,
24 };
25
26 static const u8 ice_fdir_sctpv4_pkt[] = {
27         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
29         0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x84,
30         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 };
34
35 static const u8 ice_fdir_ipv4_pkt[] = {
36         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
38         0x00, 0x14, 0x00, 0x00, 0x40, 0x00, 0x40, 0x10,
39         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40         0x00, 0x00
41 };
42
43 static const u8 ice_fdir_tcpv6_pkt[] = {
44         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
46         0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
47         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52         0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00,
53         0x00, 0x00,
54 };
55
56 static const u8 ice_fdir_udpv6_pkt[] = {
57         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
59         0x00, 0x00, 0x00, 0x08, 0x11, 0x40, 0x00, 0x00,
60         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64         0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
65 };
66
67 static const u8 ice_fdir_sctpv6_pkt[] = {
68         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
70         0x00, 0x00, 0x00, 0x0C, 0x84, 0x40, 0x00, 0x00,
71         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76         0x00, 0x00,
77 };
78
79 static const u8 ice_fdir_ipv6_pkt[] = {
80         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
82         0x00, 0x00, 0x00, 0x00, 0x3B, 0x40, 0x00, 0x00,
83         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 };
88
89 static const u8 ice_fdir_tcp4_tun_pkt[] = {
90         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
92         0x00, 0x5a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
93         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
96         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
98         0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x00,
99         0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102         0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
103 };
104
105 static const u8 ice_fdir_udp4_tun_pkt[] = {
106         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
108         0x00, 0x4e, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
109         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
112         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
114         0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x00,
115         0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117         0x00, 0x00, 0x00, 0x00,
118 };
119
120 static const u8 ice_fdir_sctp4_tun_pkt[] = {
121         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
123         0x00, 0x52, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
124         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
127         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
129         0x45, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00,
130         0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 };
134
135 static const u8 ice_fdir_ip4_tun_pkt[] = {
136         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
138         0x00, 0x46, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
139         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
142         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
144         0x45, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
145         0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146         0x00, 0x00, 0x00, 0x00,
147 };
148
149 static const u8 ice_fdir_tcp6_tun_pkt[] = {
150         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
152         0x00, 0x6e, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
153         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
156         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
158         0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40,
159         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164         0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x20, 0x00,
165         0x00, 0x00, 0x00, 0x00,
166 };
167
168 static const u8 ice_fdir_udp6_tun_pkt[] = {
169         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
171         0x00, 0x62, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
172         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
175         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
177         0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x11, 0x40,
178         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 };
184
185 static const u8 ice_fdir_sctp6_tun_pkt[] = {
186         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
188         0x00, 0x66, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
189         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
192         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
194         0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x84, 0x40,
195         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200         0x00, 0x00, 0x00, 0x00,
201 };
202
203 static const u8 ice_fdir_ip6_tun_pkt[] = {
204         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
206         0x00, 0x5a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
207         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
210         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
212         0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x40,
213         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 };
218
219 /* Flow Director no-op training packet table */
220 static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
221         {
222                 ICE_FLTR_PTYPE_NONF_IPV4_TCP,
223                 sizeof(ice_fdir_tcpv4_pkt), ice_fdir_tcpv4_pkt,
224                 sizeof(ice_fdir_tcp4_tun_pkt), ice_fdir_tcp4_tun_pkt,
225         },
226         {
227                 ICE_FLTR_PTYPE_NONF_IPV4_UDP,
228                 sizeof(ice_fdir_udpv4_pkt), ice_fdir_udpv4_pkt,
229                 sizeof(ice_fdir_udp4_tun_pkt), ice_fdir_udp4_tun_pkt,
230         },
231         {
232                 ICE_FLTR_PTYPE_NONF_IPV4_SCTP,
233                 sizeof(ice_fdir_sctpv4_pkt), ice_fdir_sctpv4_pkt,
234                 sizeof(ice_fdir_sctp4_tun_pkt), ice_fdir_sctp4_tun_pkt,
235         },
236         {
237                 ICE_FLTR_PTYPE_NONF_IPV4_OTHER,
238                 sizeof(ice_fdir_ipv4_pkt), ice_fdir_ipv4_pkt,
239                 sizeof(ice_fdir_ip4_tun_pkt), ice_fdir_ip4_tun_pkt,
240         },
241         {
242                 ICE_FLTR_PTYPE_NONF_IPV6_TCP,
243                 sizeof(ice_fdir_tcpv6_pkt), ice_fdir_tcpv6_pkt,
244                 sizeof(ice_fdir_tcp6_tun_pkt), ice_fdir_tcp6_tun_pkt,
245         },
246         {
247                 ICE_FLTR_PTYPE_NONF_IPV6_UDP,
248                 sizeof(ice_fdir_udpv6_pkt), ice_fdir_udpv6_pkt,
249                 sizeof(ice_fdir_udp6_tun_pkt), ice_fdir_udp6_tun_pkt,
250         },
251         {
252                 ICE_FLTR_PTYPE_NONF_IPV6_SCTP,
253                 sizeof(ice_fdir_sctpv6_pkt), ice_fdir_sctpv6_pkt,
254                 sizeof(ice_fdir_sctp6_tun_pkt), ice_fdir_sctp6_tun_pkt,
255         },
256         {
257                 ICE_FLTR_PTYPE_NONF_IPV6_OTHER,
258                 sizeof(ice_fdir_ipv6_pkt), ice_fdir_ipv6_pkt,
259                 sizeof(ice_fdir_ip6_tun_pkt), ice_fdir_ip6_tun_pkt,
260         },
261 };
262
263 #define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt)
264
265 /**
266  * ice_set_dflt_val_fd_desc
267  * @fd_fltr_ctx: pointer to fd filter descriptor
268  */
269 static void ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx)
270 {
271         fd_fltr_ctx->comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
272         fd_fltr_ctx->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
273         fd_fltr_ctx->fd_space = ICE_FXD_FLTR_QW0_FD_SPACE_GUAR_BEST;
274         fd_fltr_ctx->cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
275         fd_fltr_ctx->evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_TRUE;
276         fd_fltr_ctx->toq = ICE_FXD_FLTR_QW0_TO_Q_EQUALS_QINDEX;
277         fd_fltr_ctx->toq_prio = ICE_FXD_FLTR_QW0_TO_Q_PRIO1;
278         fd_fltr_ctx->dpu_recipe = ICE_FXD_FLTR_QW0_DPU_RECIPE_DFLT;
279         fd_fltr_ctx->drop = ICE_FXD_FLTR_QW0_DROP_NO;
280         fd_fltr_ctx->flex_prio = ICE_FXD_FLTR_QW0_FLEX_PRI_NONE;
281         fd_fltr_ctx->flex_mdid = ICE_FXD_FLTR_QW0_FLEX_MDID0;
282         fd_fltr_ctx->flex_val = ICE_FXD_FLTR_QW0_FLEX_VAL0;
283         fd_fltr_ctx->dtype = ICE_TX_DESC_DTYPE_FLTR_PROG;
284         fd_fltr_ctx->desc_prof_prio = ICE_FXD_FLTR_QW1_PROF_PRIO_ZERO;
285         fd_fltr_ctx->desc_prof = ICE_FXD_FLTR_QW1_PROF_ZERO;
286         fd_fltr_ctx->swap = ICE_FXD_FLTR_QW1_SWAP_SET;
287         fd_fltr_ctx->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ONE;
288         fd_fltr_ctx->fdid_mdid = ICE_FXD_FLTR_QW1_FDID_MDID_FD;
289         fd_fltr_ctx->fdid = ICE_FXD_FLTR_QW1_FDID_ZERO;
290 }
291
292 /**
293  * ice_set_fd_desc_val
294  * @ctx: pointer to fd filter descriptor context
295  * @fdir_desc: populated with fd filter descriptor values
296  */
297 static void
298 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *ctx,
299                     struct ice_fltr_desc *fdir_desc)
300 {
301         u64 qword;
302
303         /* prep QW0 of FD filter programming desc */
304         qword = ((u64)ctx->qindex << ICE_FXD_FLTR_QW0_QINDEX_S) &
305                 ICE_FXD_FLTR_QW0_QINDEX_M;
306         qword |= ((u64)ctx->comp_q << ICE_FXD_FLTR_QW0_COMP_Q_S) &
307                  ICE_FXD_FLTR_QW0_COMP_Q_M;
308         qword |= ((u64)ctx->comp_report << ICE_FXD_FLTR_QW0_COMP_REPORT_S) &
309                  ICE_FXD_FLTR_QW0_COMP_REPORT_M;
310         qword |= ((u64)ctx->fd_space << ICE_FXD_FLTR_QW0_FD_SPACE_S) &
311                  ICE_FXD_FLTR_QW0_FD_SPACE_M;
312         qword |= ((u64)ctx->cnt_index << ICE_FXD_FLTR_QW0_STAT_CNT_S) &
313                  ICE_FXD_FLTR_QW0_STAT_CNT_M;
314         qword |= ((u64)ctx->cnt_ena << ICE_FXD_FLTR_QW0_STAT_ENA_S) &
315                  ICE_FXD_FLTR_QW0_STAT_ENA_M;
316         qword |= ((u64)ctx->evict_ena << ICE_FXD_FLTR_QW0_EVICT_ENA_S) &
317                  ICE_FXD_FLTR_QW0_EVICT_ENA_M;
318         qword |= ((u64)ctx->toq << ICE_FXD_FLTR_QW0_TO_Q_S) &
319                  ICE_FXD_FLTR_QW0_TO_Q_M;
320         qword |= ((u64)ctx->toq_prio << ICE_FXD_FLTR_QW0_TO_Q_PRI_S) &
321                  ICE_FXD_FLTR_QW0_TO_Q_PRI_M;
322         qword |= ((u64)ctx->dpu_recipe << ICE_FXD_FLTR_QW0_DPU_RECIPE_S) &
323                  ICE_FXD_FLTR_QW0_DPU_RECIPE_M;
324         qword |= ((u64)ctx->drop << ICE_FXD_FLTR_QW0_DROP_S) &
325                  ICE_FXD_FLTR_QW0_DROP_M;
326         qword |= ((u64)ctx->flex_prio << ICE_FXD_FLTR_QW0_FLEX_PRI_S) &
327                  ICE_FXD_FLTR_QW0_FLEX_PRI_M;
328         qword |= ((u64)ctx->flex_mdid << ICE_FXD_FLTR_QW0_FLEX_MDID_S) &
329                  ICE_FXD_FLTR_QW0_FLEX_MDID_M;
330         qword |= ((u64)ctx->flex_val << ICE_FXD_FLTR_QW0_FLEX_VAL_S) &
331                  ICE_FXD_FLTR_QW0_FLEX_VAL_M;
332         fdir_desc->qidx_compq_space_stat = cpu_to_le64(qword);
333
334         /* prep QW1 of FD filter programming desc */
335         qword = ((u64)ctx->dtype << ICE_FXD_FLTR_QW1_DTYPE_S) &
336                 ICE_FXD_FLTR_QW1_DTYPE_M;
337         qword |= ((u64)ctx->pcmd << ICE_FXD_FLTR_QW1_PCMD_S) &
338                  ICE_FXD_FLTR_QW1_PCMD_M;
339         qword |= ((u64)ctx->desc_prof_prio << ICE_FXD_FLTR_QW1_PROF_PRI_S) &
340                  ICE_FXD_FLTR_QW1_PROF_PRI_M;
341         qword |= ((u64)ctx->desc_prof << ICE_FXD_FLTR_QW1_PROF_S) &
342                  ICE_FXD_FLTR_QW1_PROF_M;
343         qword |= ((u64)ctx->fd_vsi << ICE_FXD_FLTR_QW1_FD_VSI_S) &
344                  ICE_FXD_FLTR_QW1_FD_VSI_M;
345         qword |= ((u64)ctx->swap << ICE_FXD_FLTR_QW1_SWAP_S) &
346                  ICE_FXD_FLTR_QW1_SWAP_M;
347         qword |= ((u64)ctx->fdid_prio << ICE_FXD_FLTR_QW1_FDID_PRI_S) &
348                  ICE_FXD_FLTR_QW1_FDID_PRI_M;
349         qword |= ((u64)ctx->fdid_mdid << ICE_FXD_FLTR_QW1_FDID_MDID_S) &
350                  ICE_FXD_FLTR_QW1_FDID_MDID_M;
351         qword |= ((u64)ctx->fdid << ICE_FXD_FLTR_QW1_FDID_S) &
352                  ICE_FXD_FLTR_QW1_FDID_M;
353         fdir_desc->dtype_cmd_vsi_fdid = cpu_to_le64(qword);
354 }
355
356 /**
357  * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct
358  * @hw: pointer to the hardware structure
359  * @input: filter
360  * @fdesc: filter descriptor
361  * @add: if add is true, this is an add operation, false implies delete
362  */
363 void
364 ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
365                        struct ice_fltr_desc *fdesc, bool add)
366 {
367         struct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 };
368
369         /* set default context info */
370         ice_set_dflt_val_fd_desc(&fdir_fltr_ctx);
371
372         /* change sideband filtering values */
373         fdir_fltr_ctx.fdid = input->fltr_id;
374         if (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT) {
375                 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_YES;
376                 fdir_fltr_ctx.qindex = 0;
377         } else {
378                 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
379                 fdir_fltr_ctx.qindex = input->q_index;
380         }
381         fdir_fltr_ctx.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
382         fdir_fltr_ctx.cnt_index = input->cnt_index;
383         fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);
384         fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;
385         fdir_fltr_ctx.toq_prio = 3;
386         fdir_fltr_ctx.pcmd = add ? ICE_FXD_FLTR_QW1_PCMD_ADD :
387                 ICE_FXD_FLTR_QW1_PCMD_REMOVE;
388         fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;
389         fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
390         fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
391         fdir_fltr_ctx.fdid_prio = 3;
392         fdir_fltr_ctx.desc_prof = 1;
393         fdir_fltr_ctx.desc_prof_prio = 3;
394         ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);
395 }
396
397 /**
398  * ice_alloc_fd_res_cntr - obtain counter resource for FD type
399  * @hw: pointer to the hardware structure
400  * @cntr_id: returns counter index
401  */
402 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)
403 {
404         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
405                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
406 }
407
408 /**
409  * ice_free_fd_res_cntr - Free counter resource for FD type
410  * @hw: pointer to the hardware structure
411  * @cntr_id: counter index to be freed
412  */
413 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)
414 {
415         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
416                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
417 }
418
419 /**
420  * ice_alloc_fd_guar_item - allocate resource for FD guaranteed entries
421  * @hw: pointer to the hardware structure
422  * @cntr_id: returns counter index
423  * @num_fltr: number of filter entries to be allocated
424  */
425 enum ice_status
426 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
427 {
428         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
429                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
430                                   cntr_id);
431 }
432
433 /**
434  * ice_alloc_fd_shrd_item - allocate resource for flow director shared entries
435  * @hw: pointer to the hardware structure
436  * @cntr_id: returns counter index
437  * @num_fltr: number of filter entries to be allocated
438  */
439 enum ice_status
440 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
441 {
442         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
443                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
444                                   cntr_id);
445 }
446
447 /**
448  * ice_get_fdir_cnt_all - get the number of Flow Director filters
449  * @hw: hardware data structure
450  *
451  * Returns the number of filters available on device
452  */
453 int ice_get_fdir_cnt_all(struct ice_hw *hw)
454 {
455         return hw->func_caps.fd_fltr_guar + hw->func_caps.fd_fltr_best_effort;
456 }
457
458 /**
459  * ice_pkt_insert_ipv6_addr - insert a be32 IPv6 address into a memory buffer
460  * @pkt: packet buffer
461  * @offset: offset into buffer
462  * @addr: IPv6 address to convert and insert into pkt at offset
463  */
464 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)
465 {
466         int idx;
467
468         for (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++)
469                 memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx],
470                        sizeof(*addr));
471 }
472
473 /**
474  * ice_pkt_insert_u16 - insert a be16 value into a memory buffer
475  * @pkt: packet buffer
476  * @offset: offset into buffer
477  * @data: 16 bit value to convert and insert into pkt at offset
478  */
479 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)
480 {
481         memcpy(pkt + offset, &data, sizeof(data));
482 }
483
484 /**
485  * ice_pkt_insert_u32 - insert a be32 value into a memory buffer
486  * @pkt: packet buffer
487  * @offset: offset into buffer
488  * @data: 32 bit value to convert and insert into pkt at offset
489  */
490 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)
491 {
492         memcpy(pkt + offset, &data, sizeof(data));
493 }
494
495 /**
496  * ice_pkt_insert_mac_addr - insert a MAC addr into a memory buffer.
497  * @pkt: packet buffer
498  * @addr: MAC address to convert and insert into pkt at offset
499  */
500 static void ice_pkt_insert_mac_addr(u8 *pkt, u8 *addr)
501 {
502         ether_addr_copy(pkt, addr);
503 }
504
505 /**
506  * ice_fdir_get_gen_prgm_pkt - generate a training packet
507  * @hw: pointer to the hardware structure
508  * @input: flow director filter data structure
509  * @pkt: pointer to return filter packet
510  * @frag: generate a fragment packet
511  * @tun: true implies generate a tunnel packet
512  */
513 enum ice_status
514 ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
515                           u8 *pkt, bool frag, bool tun)
516 {
517         enum ice_fltr_ptype flow;
518         u16 tnl_port;
519         u8 *loc;
520         u16 idx;
521
522         if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
523                 switch (input->ip.v4.proto) {
524                 case IPPROTO_TCP:
525                         flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
526                         break;
527                 case IPPROTO_UDP:
528                         flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
529                         break;
530                 case IPPROTO_SCTP:
531                         flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
532                         break;
533                 case IPPROTO_IP:
534                         flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
535                         break;
536                 default:
537                         return ICE_ERR_PARAM;
538                 }
539         } else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
540                 switch (input->ip.v6.proto) {
541                 case IPPROTO_TCP:
542                         flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
543                         break;
544                 case IPPROTO_UDP:
545                         flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
546                         break;
547                 case IPPROTO_SCTP:
548                         flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
549                         break;
550                 case IPPROTO_IP:
551                         flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
552                         break;
553                 default:
554                         return ICE_ERR_PARAM;
555                 }
556         } else {
557                 flow = input->flow_type;
558         }
559
560         for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
561                 if (ice_fdir_pkt[idx].flow == flow)
562                         break;
563         if (idx == ICE_FDIR_NUM_PKT)
564                 return ICE_ERR_PARAM;
565         if (!tun) {
566                 memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len);
567                 loc = pkt;
568         } else {
569                 if (!ice_get_open_tunnel_port(hw, &tnl_port))
570                         return ICE_ERR_DOES_NOT_EXIST;
571                 if (!ice_fdir_pkt[idx].tun_pkt)
572                         return ICE_ERR_PARAM;
573                 memcpy(pkt, ice_fdir_pkt[idx].tun_pkt,
574                        ice_fdir_pkt[idx].tun_pkt_len);
575                 ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,
576                                    htons(tnl_port));
577                 loc = &pkt[ICE_FDIR_TUN_PKT_OFF];
578         }
579
580         /* Reverse the src and dst, since the HW expects them to be from Tx
581          * perspective. The input from user is from Rx filter perspective.
582          */
583         switch (flow) {
584         case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
585                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
586                                    input->ip.v4.src_ip);
587                 ice_pkt_insert_u16(loc, ICE_IPV4_TCP_DST_PORT_OFFSET,
588                                    input->ip.v4.src_port);
589                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
590                                    input->ip.v4.dst_ip);
591                 ice_pkt_insert_u16(loc, ICE_IPV4_TCP_SRC_PORT_OFFSET,
592                                    input->ip.v4.dst_port);
593                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
594                 if (frag)
595                         loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
596                 break;
597         case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
598                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
599                                    input->ip.v4.src_ip);
600                 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_DST_PORT_OFFSET,
601                                    input->ip.v4.src_port);
602                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
603                                    input->ip.v4.dst_ip);
604                 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_SRC_PORT_OFFSET,
605                                    input->ip.v4.dst_port);
606                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
607                 ice_pkt_insert_mac_addr(loc + ETH_ALEN,
608                                         input->ext_data.src_mac);
609                 break;
610         case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
611                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
612                                    input->ip.v4.src_ip);
613                 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_DST_PORT_OFFSET,
614                                    input->ip.v4.src_port);
615                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
616                                    input->ip.v4.dst_ip);
617                 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_SRC_PORT_OFFSET,
618                                    input->ip.v4.dst_port);
619                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
620                 break;
621         case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
622                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
623                                    input->ip.v4.src_ip);
624                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
625                                    input->ip.v4.dst_ip);
626                 ice_pkt_insert_u16(loc, ICE_IPV4_PROTO_OFFSET, 0);
627                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
628                 break;
629         case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
630                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
631                                          input->ip.v6.src_ip);
632                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
633                                          input->ip.v6.dst_ip);
634                 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_DST_PORT_OFFSET,
635                                    input->ip.v6.src_port);
636                 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_SRC_PORT_OFFSET,
637                                    input->ip.v6.dst_port);
638                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
639                 break;
640         case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
641                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
642                                          input->ip.v6.src_ip);
643                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
644                                          input->ip.v6.dst_ip);
645                 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_DST_PORT_OFFSET,
646                                    input->ip.v6.src_port);
647                 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_SRC_PORT_OFFSET,
648                                    input->ip.v6.dst_port);
649                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
650                 break;
651         case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
652                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
653                                          input->ip.v6.src_ip);
654                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
655                                          input->ip.v6.dst_ip);
656                 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_DST_PORT_OFFSET,
657                                    input->ip.v6.src_port);
658                 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_SRC_PORT_OFFSET,
659                                    input->ip.v6.dst_port);
660                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
661                 break;
662         case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
663                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
664                                          input->ip.v6.src_ip);
665                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
666                                          input->ip.v6.dst_ip);
667                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
668                 break;
669         default:
670                 return ICE_ERR_PARAM;
671         }
672
673         if (input->flex_fltr)
674                 ice_pkt_insert_u16(loc, input->flex_offset, input->flex_word);
675
676         return 0;
677 }
678
679 /**
680  * ice_fdir_has_frag - does flow type have 2 ptypes
681  * @flow: flow ptype
682  *
683  * returns true is there is a fragment packet for this ptype
684  */
685 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
686 {
687         if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
688                 return true;
689         else
690                 return false;
691 }
692
693 /**
694  * ice_fdir_find_by_idx - find filter with idx
695  * @hw: pointer to hardware structure
696  * @fltr_idx: index to find.
697  *
698  * Returns pointer to filter if found or null
699  */
700 struct ice_fdir_fltr *
701 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
702 {
703         struct ice_fdir_fltr *rule;
704
705         list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
706                 /* rule ID found in the list */
707                 if (fltr_idx == rule->fltr_id)
708                         return rule;
709                 if (fltr_idx < rule->fltr_id)
710                         break;
711         }
712         return NULL;
713 }
714
715 /**
716  * ice_fdir_list_add_fltr - add a new node to the flow director filter list
717  * @hw: hardware structure
718  * @fltr: filter node to add to structure
719  */
720 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
721 {
722         struct ice_fdir_fltr *rule, *parent = NULL;
723
724         list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
725                 /* rule ID found or pass its spot in the list */
726                 if (rule->fltr_id >= fltr->fltr_id)
727                         break;
728                 parent = rule;
729         }
730
731         if (parent)
732                 list_add(&fltr->fltr_node, &parent->fltr_node);
733         else
734                 list_add(&fltr->fltr_node, &hw->fdir_list_head);
735 }
736
737 /**
738  * ice_fdir_update_cntrs - increment / decrement filter counter
739  * @hw: pointer to hardware structure
740  * @flow: filter flow type
741  * @add: true implies filters added
742  */
743 void
744 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
745 {
746         int incr;
747
748         incr = add ? 1 : -1;
749         hw->fdir_active_fltr += incr;
750
751         if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)
752                 ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow);
753         else
754                 hw->fdir_fltr_cnt[flow] += incr;
755 }
756
757 /**
758  * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
759  * @a: IP v6 address
760  * @b: IP v6 address
761  *
762  * Returns 0 on equal, returns non-0 if different
763  */
764 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
765 {
766         return memcmp(a, b, 4 * sizeof(__be32));
767 }
768
769 /**
770  * ice_fdir_comp_rules - compare 2 filters
771  * @a: a Flow Director filter data structure
772  * @b: a Flow Director filter data structure
773  * @v6: bool true if v6 filter
774  *
775  * Returns true if the filters match
776  */
777 static bool
778 ice_fdir_comp_rules(struct ice_fdir_fltr *a,  struct ice_fdir_fltr *b, bool v6)
779 {
780         enum ice_fltr_ptype flow_type = a->flow_type;
781
782         /* The calling function already checks that the two filters have the
783          * same flow_type.
784          */
785         if (!v6) {
786                 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
787                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
788                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
789                         if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
790                             a->ip.v4.src_ip == b->ip.v4.src_ip &&
791                             a->ip.v4.dst_port == b->ip.v4.dst_port &&
792                             a->ip.v4.src_port == b->ip.v4.src_port)
793                                 return true;
794                 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
795                         if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
796                             a->ip.v4.src_ip == b->ip.v4.src_ip &&
797                             a->ip.v4.l4_header == b->ip.v4.l4_header &&
798                             a->ip.v4.proto == b->ip.v4.proto &&
799                             a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
800                             a->ip.v4.tos == b->ip.v4.tos)
801                                 return true;
802                 }
803         } else {
804                 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
805                     flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
806                     flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
807                         if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
808                             a->ip.v6.src_port == b->ip.v6.src_port &&
809                             !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
810                                                b->ip.v6.dst_ip) &&
811                             !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
812                                                b->ip.v6.src_ip))
813                                 return true;
814                 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
815                         if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
816                             a->ip.v6.src_port == b->ip.v6.src_port)
817                                 return true;
818                 }
819         }
820
821         return false;
822 }
823
824 /**
825  * ice_fdir_is_dup_fltr - test if filter is already in list for PF
826  * @hw: hardware data structure
827  * @input: Flow Director filter data structure
828  *
829  * Returns true if the filter is found in the list
830  */
831 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
832 {
833         struct ice_fdir_fltr *rule;
834         bool ret = false;
835
836         list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
837                 enum ice_fltr_ptype flow_type;
838
839                 if (rule->flow_type != input->flow_type)
840                         continue;
841
842                 flow_type = input->flow_type;
843                 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
844                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
845                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
846                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
847                         ret = ice_fdir_comp_rules(rule, input, false);
848                 else
849                         ret = ice_fdir_comp_rules(rule, input, true);
850                 if (ret) {
851                         if (rule->fltr_id == input->fltr_id &&
852                             rule->q_index != input->q_index)
853                                 ret = false;
854                         else
855                                 break;
856                 }
857         }
858
859         return ret;
860 }