4632f1a530ffdbf869187db1b7dcb6e517657c55
[dpdk.git] / drivers / net / ice / base / ice_fdir.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2019
3  */
4
5 #include "ice_common.h"
6 #include "ice_fdir.h"
7
8 /* These are training packet headers used to program flow director filters. */
9 static const u8 ice_fdir_tcpv4_pkt[] = {
10         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
12         0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
13         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00,
16         0x20, 0x00, 0x00, 0x00, 0x00, 0x00
17 };
18
19 static const u8 ice_fdir_udpv4_pkt[] = {
20         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
22         0x00, 0x1C, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
23         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25         0x00, 0x00,
26 };
27
28 static const u8 ice_fdir_sctpv4_pkt[] = {
29         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
31         0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x84,
32         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 };
36
37 static const u8 ice_fdir_ipv4_pkt[] = {
38         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
40         0x00, 0x14, 0x00, 0x00, 0x40, 0x00, 0x40, 0x10,
41         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42         0x00, 0x00
43 };
44
45 static const u8 ice_fdir_tcpv6_pkt[] = {
46         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
48         0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54         0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00,
55         0x00, 0x00,
56 };
57
58 static const u8 ice_fdir_udpv6_pkt[] = {
59         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
61         0x00, 0x00, 0x00, 0x08, 0x11, 0x40, 0x00, 0x00,
62         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66         0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
67 };
68
69 static const u8 ice_fdir_sctpv6_pkt[] = {
70         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
72         0x00, 0x00, 0x00, 0x0C, 0x84, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78         0x00, 0x00,
79 };
80
81 static const u8 ice_fdir_ipv6_pkt[] = {
82         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83         0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
84         0x00, 0x00, 0x00, 0x00, 0x3B, 0x40, 0x00, 0x00,
85         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 };
90
91 static const u8 ice_fdir_tcp4_tun_pkt[] = {
92         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
94         0x00, 0x5a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
95         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
98         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
100         0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x00,
101         0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104         0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
105 };
106
107 static const u8 ice_fdir_udp4_tun_pkt[] = {
108         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
110         0x00, 0x4e, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
111         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
114         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
116         0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x00,
117         0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119         0x00, 0x00, 0x00, 0x00,
120 };
121
122 static const u8 ice_fdir_sctp4_tun_pkt[] = {
123         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
125         0x00, 0x52, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
126         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
129         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
131         0x45, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00,
132         0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 };
136
137 static const u8 ice_fdir_ip4_tun_pkt[] = {
138         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
140         0x00, 0x46, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
141         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
144         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
146         0x45, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
147         0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148         0x00, 0x00, 0x00, 0x00,
149 };
150
151 static const u8 ice_fdir_tcp6_tun_pkt[] = {
152         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
154         0x00, 0x6e, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
155         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
158         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
160         0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40,
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, 0x00, 0x00, 0x00, 0x00,
165         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166         0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x20, 0x00,
167         0x00, 0x00, 0x00, 0x00,
168 };
169
170 static const u8 ice_fdir_udp6_tun_pkt[] = {
171         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
173         0x00, 0x62, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
174         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
177         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
179         0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x11, 0x40,
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         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 };
186
187 static const u8 ice_fdir_sctp6_tun_pkt[] = {
188         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
190         0x00, 0x66, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
191         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
194         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
196         0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x84, 0x40,
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, 0x00, 0x00, 0x00, 0x00,
201         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202         0x00, 0x00, 0x00, 0x00,
203 };
204
205 static const u8 ice_fdir_ip6_tun_pkt[] = {
206         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207         0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
208         0x00, 0x5a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
209         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211         0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
212         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
214         0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x40,
215         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 };
220
221 /* Flow Director no-op training packet table */
222 static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
223         {
224                 ICE_FLTR_PTYPE_NONF_IPV4_TCP,
225                 sizeof(ice_fdir_tcpv4_pkt), ice_fdir_tcpv4_pkt,
226                 sizeof(ice_fdir_tcp4_tun_pkt), ice_fdir_tcp4_tun_pkt,
227         },
228         {
229                 ICE_FLTR_PTYPE_NONF_IPV4_UDP,
230                 sizeof(ice_fdir_udpv4_pkt), ice_fdir_udpv4_pkt,
231                 sizeof(ice_fdir_udp4_tun_pkt), ice_fdir_udp4_tun_pkt,
232         },
233         {
234                 ICE_FLTR_PTYPE_NONF_IPV4_SCTP,
235                 sizeof(ice_fdir_sctpv4_pkt), ice_fdir_sctpv4_pkt,
236                 sizeof(ice_fdir_sctp4_tun_pkt), ice_fdir_sctp4_tun_pkt,
237         },
238         {
239                 ICE_FLTR_PTYPE_NONF_IPV4_OTHER,
240                 sizeof(ice_fdir_ipv4_pkt), ice_fdir_ipv4_pkt,
241                 sizeof(ice_fdir_ip4_tun_pkt), ice_fdir_ip4_tun_pkt,
242         },
243         {
244                 ICE_FLTR_PTYPE_NONF_IPV6_TCP,
245                 sizeof(ice_fdir_tcpv6_pkt), ice_fdir_tcpv6_pkt,
246                 sizeof(ice_fdir_tcp6_tun_pkt), ice_fdir_tcp6_tun_pkt,
247         },
248         {
249                 ICE_FLTR_PTYPE_NONF_IPV6_UDP,
250                 sizeof(ice_fdir_udpv6_pkt), ice_fdir_udpv6_pkt,
251                 sizeof(ice_fdir_udp6_tun_pkt), ice_fdir_udp6_tun_pkt,
252         },
253         {
254                 ICE_FLTR_PTYPE_NONF_IPV6_SCTP,
255                 sizeof(ice_fdir_sctpv6_pkt), ice_fdir_sctpv6_pkt,
256                 sizeof(ice_fdir_sctp6_tun_pkt), ice_fdir_sctp6_tun_pkt,
257         },
258         {
259                 ICE_FLTR_PTYPE_NONF_IPV6_OTHER,
260                 sizeof(ice_fdir_ipv6_pkt), ice_fdir_ipv6_pkt,
261                 sizeof(ice_fdir_ip6_tun_pkt), ice_fdir_ip6_tun_pkt,
262         },
263 };
264
265 #define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt)
266
267 /* Flow Direcotr (FD) filter program descriptor Context */
268 static const struct ice_ctx_ele ice_fd_fltr_desc_ctx_info[] = {
269                                            /* Field             Width   LSB */
270         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, qindex,             11,     0),
271         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_q,             1,      11),
272         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_report,        2,      12),
273         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_space,           2,      14),
274         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_index,          13,     16),
275         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_ena,            2,      29),
276         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, evict_ena,          1,      31),
277         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq,                3,      32),
278         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq_prio,           3,      35),
279         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, dpu_recipe,         2,      38),
280         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, drop,               1,      40),
281         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_prio,          3,      41),
282         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_mdid,          4,      44),
283         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_val,           16,     48),
284         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, dtype,              4,      64),
285         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, pcmd,               1,      68),
286         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof_prio,     3,      69),
287         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof,          6,      72),
288         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_vsi,             10,     78),
289         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, swap,               1,      88),
290         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_prio,          3,      89),
291         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_mdid,          4,      92),
292         ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid,               32,     96),
293         { 0 }
294 };
295
296 /**
297  * ice_set_dflt_val_fd_desc
298  * @fd_fltr_ctx: pointer to fd filter descriptor
299  */
300 void
301 ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx)
302 {
303         fd_fltr_ctx->comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
304         fd_fltr_ctx->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
305         fd_fltr_ctx->fd_space = ICE_FXD_FLTR_QW0_FD_SPACE_GUAR_BEST;
306         fd_fltr_ctx->cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
307         fd_fltr_ctx->evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_TRUE;
308         fd_fltr_ctx->toq = ICE_FXD_FLTR_QW0_TO_Q_EQUALS_QINDEX;
309         fd_fltr_ctx->toq_prio = ICE_FXD_FLTR_QW0_TO_Q_PRIO1;
310         fd_fltr_ctx->dpu_recipe = ICE_FXD_FLTR_QW0_DPU_RECIPE_DFLT;
311         fd_fltr_ctx->drop = ICE_FXD_FLTR_QW0_DROP_NO;
312         fd_fltr_ctx->flex_prio = ICE_FXD_FLTR_QW0_FLEX_PRI_NONE;
313         fd_fltr_ctx->flex_mdid = ICE_FXD_FLTR_QW0_FLEX_MDID0;
314         fd_fltr_ctx->flex_val = ICE_FXD_FLTR_QW0_FLEX_VAL0;
315         fd_fltr_ctx->dtype = ICE_TX_DESC_DTYPE_FLTR_PROG;
316         fd_fltr_ctx->desc_prof_prio = ICE_FXD_FLTR_QW1_PROF_PRIO_ZERO;
317         fd_fltr_ctx->desc_prof = ICE_FXD_FLTR_QW1_PROF_ZERO;
318         fd_fltr_ctx->swap = ICE_FXD_FLTR_QW1_SWAP_SET;
319         fd_fltr_ctx->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ONE;
320         fd_fltr_ctx->fdid_mdid = ICE_FXD_FLTR_QW1_FDID_MDID_FD;
321         fd_fltr_ctx->fdid = ICE_FXD_FLTR_QW1_FDID_ZERO;
322 }
323
324 /**
325  * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct
326  * @hw: pointer to the hardware structure
327  * @input: filter
328  * @fdesc: filter descriptor
329  * @add: if add is true, this is an add operation, false implies delete
330  */
331 void
332 ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
333                        struct ice_fltr_desc *fdesc, bool add)
334 {
335         struct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 };
336
337         /* set default context info */
338         ice_set_dflt_val_fd_desc(&fdir_fltr_ctx);
339
340         /* change sideband filtering values */
341         fdir_fltr_ctx.fdid = input->fltr_id;
342         if (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT) {
343                 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_YES;
344                 fdir_fltr_ctx.qindex = 0;
345         } else {
346                 if (input->dest_ctl ==
347                     ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP)
348                         fdir_fltr_ctx.toq = input->q_region;
349                 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
350                 fdir_fltr_ctx.qindex = input->q_index;
351         }
352         fdir_fltr_ctx.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
353         fdir_fltr_ctx.cnt_index = input->cnt_index;
354         fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);
355         fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;
356         fdir_fltr_ctx.toq_prio = 3;
357         fdir_fltr_ctx.pcmd = (add) ? ICE_FXD_FLTR_QW1_PCMD_ADD :
358                 ICE_FXD_FLTR_QW1_PCMD_REMOVE;
359         fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;
360         fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
361         fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW;
362         fdir_fltr_ctx.fdid_prio = 3;
363         fdir_fltr_ctx.desc_prof = 1;
364         fdir_fltr_ctx.desc_prof_prio = 3;
365         ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);
366 }
367
368 /**
369  * ice_set_fd_desc_val
370  * @fd_fltr_ctx: pointer to fd filter descriptor context
371  * @fdir_desc: populated with fd filter descriptor values
372  */
373 void
374 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx,
375                     struct ice_fltr_desc *fdir_desc)
376 {
377         u64 ctx_buf[2] = { 0 };
378
379         ice_set_ctx((u8 *)fd_fltr_ctx, (u8 *)ctx_buf,
380                     ice_fd_fltr_desc_ctx_info);
381         fdir_desc->qidx_compq_space_stat = CPU_TO_LE64(ctx_buf[0]);
382         fdir_desc->dtype_cmd_vsi_fdid = CPU_TO_LE64(ctx_buf[1]);
383 }
384
385 /**
386  * ice_alloc_fd_res_cntr - obtain counter resource for FD type
387  * @hw: pointer to the hardware structure
388  * @cntr_id: returns counter index
389  */
390 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)
391 {
392         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
393                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
394 }
395
396 /**
397  * ice_free_fd_res_cntr - Free counter resource for FD type
398  * @hw: pointer to the hardware structure
399  * @cntr_id: counter index to be freed
400  */
401 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)
402 {
403         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
404                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
405 }
406
407 /**
408  * ice_alloc_fd_guar_item - allocate resource for FD guaranteed entries
409  * @hw: pointer to the hardware structure
410  * @cntr_id: returns counter index
411  * @num_fltr: number of filter entries to be allocated
412  */
413 enum ice_status
414 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
415 {
416         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
417                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
418                                   cntr_id);
419 }
420
421 /**
422  * ice_free_fd_guar_item - Free flow director guaranteed entries
423  * @hw: pointer to the hardware structure
424  * @cntr_id: counter index that needs to be freed
425  * @num_fltr: number of filters to be freed
426  */
427 enum ice_status
428 ice_free_fd_guar_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
429 {
430         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
431                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
432                                  cntr_id);
433 }
434
435 /**
436  * ice_alloc_fd_shrd_item - allocate resource for flow director shared entries
437  * @hw: pointer to the hardware structure
438  * @cntr_id: returns counter index
439  * @num_fltr: number of filter entries to be allocated
440  */
441 enum ice_status
442 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
443 {
444         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
445                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
446                                   cntr_id);
447 }
448
449 /**
450  * ice_free_fd_shrd_item - Free flow director shared entries
451  * @hw: pointer to the hardware structure
452  * @cntr_id: counter index that needs to be freed
453  * @num_fltr: number of filters to be freed
454  */
455 enum ice_status
456 ice_free_fd_shrd_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
457 {
458         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
459                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
460                                  cntr_id);
461 }
462
463 /**
464  * ice_get_fdir_cnt_all - get the number of Flow Director filters
465  * @hw: hardware data structure
466  *
467  * Returns the number of filters available on device
468  */
469 int ice_get_fdir_cnt_all(struct ice_hw *hw)
470 {
471         return hw->func_caps.fd_fltr_guar +
472                hw->func_caps.fd_fltr_best_effort;
473 }
474
475 /**
476  * ice_pkt_insert_ipv6_addr - insert a be32 IPv6 address into a memory buffer.
477  * @pkt: packet buffer
478  * @offset: offset into buffer
479  * @addr: IPv6 address to convert and insert into pkt at offset
480  */
481 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)
482 {
483         int idx;
484
485         for (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++)
486                 ice_memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx],
487                            sizeof(*addr), ICE_NONDMA_TO_NONDMA);
488 }
489
490 /**
491  * ice_pkt_insert_u8 - insert a u8 value into a memory buffer.
492  * @pkt: packet buffer
493  * @offset: offset into buffer
494  * @data: 8 bit value to convert and insert into pkt at offset
495  */
496 static void ice_pkt_insert_u8(u8 *pkt, int offset, u8 data)
497 {
498         ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
499 }
500
501 /**
502  * ice_pkt_insert_u8_tc - insert a u8 value into a memory buffer for tc ipv6.
503  * @pkt: packet buffer
504  * @offset: offset into buffer
505  * @data: 8 bit value to convert and insert into pkt at offset
506  *
507  * This function is designed for inserting Traffic Class (tc) for IPv6,
508  * since that tc is not aligned in number of bytes. Here we split it out
509  * into two part and fill each byte with data copy from pkt, then insert
510  * the two bytes data one by one.
511  */
512 static void ice_pkt_insert_u8_tc(u8 *pkt, int offset, u8 data)
513 {
514         u8 high, low;
515
516         high = (data >> 4) + (*(pkt + offset) & 0xF0);
517         ice_memcpy(pkt + offset, &high, sizeof(high), ICE_NONDMA_TO_NONDMA);
518
519         low = (*(pkt + offset + 1) & 0x0F) + ((data & 0x0F) << 4);
520         ice_memcpy(pkt + offset + 1, &low, sizeof(low), ICE_NONDMA_TO_NONDMA);
521 }
522
523 /**
524  * ice_pkt_insert_u16 - insert a be16 value into a memory buffer.
525  * @pkt: packet buffer
526  * @offset: offset into buffer
527  * @data: 16 bit value to convert and insert into pkt at offset
528  */
529 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)
530 {
531         ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
532 }
533
534 /**
535  * ice_pkt_insert_u32 - insert a be32 value into a memory buffer.
536  * @pkt: packet buffer
537  * @offset: offset into buffer
538  * @data: 32 bit value to convert and insert into pkt at offset
539  */
540 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)
541 {
542         ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
543 }
544
545 /**
546  * ice_fdir_get_gen_prgm_pkt - generate a training packet
547  * @hw: pointer to the hardware structure
548  * @input: flow director filter data structure
549  * @pkt: pointer to return filter packet
550  * @frag: generate a fragment packet
551  * @tun: true implies generate a tunnel packet
552  */
553 enum ice_status
554 ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
555                           u8 *pkt, bool frag, bool tun)
556 {
557         enum ice_fltr_ptype flow;
558         u16 tnl_port;
559         u8 *loc;
560         u16 idx;
561
562         if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
563                 switch (input->ip.v4.proto) {
564                 case ICE_IP_PROTO_TCP:
565                         flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
566                         break;
567                 case ICE_IP_PROTO_UDP:
568                         flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
569                         break;
570                 case ICE_IP_PROTO_SCTP:
571                         flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
572                         break;
573                 default:
574                         flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
575                         break;
576                 }
577         } else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
578                 switch (input->ip.v6.proto) {
579                 case ICE_IP_PROTO_TCP:
580                         flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
581                         break;
582                 case ICE_IP_PROTO_UDP:
583                         flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
584                         break;
585                 case ICE_IP_PROTO_SCTP:
586                         flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
587                         break;
588                 default:
589                         flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
590                         break;
591                 }
592         } else {
593                 flow = input->flow_type;
594         }
595
596         for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
597                 if (ice_fdir_pkt[idx].flow == flow)
598                         break;
599         if (idx == ICE_FDIR_NUM_PKT)
600                 return ICE_ERR_PARAM;
601         if (!tun) {
602                 ice_memcpy(pkt, ice_fdir_pkt[idx].pkt,
603                            ice_fdir_pkt[idx].pkt_len, ICE_NONDMA_TO_NONDMA);
604                 loc = pkt;
605         } else {
606                 if (!ice_get_open_tunnel_port(hw, TNL_ALL, &tnl_port))
607                         return ICE_ERR_DOES_NOT_EXIST;
608                 if (!ice_fdir_pkt[idx].tun_pkt)
609                         return ICE_ERR_PARAM;
610                 ice_memcpy(pkt, ice_fdir_pkt[idx].tun_pkt,
611                            ice_fdir_pkt[idx].tun_pkt_len, ICE_NONDMA_TO_NONDMA);
612                 ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,
613                                    HTONS(tnl_port));
614                 loc = &pkt[ICE_FDIR_TUN_PKT_OFF];
615         }
616
617         switch (flow) {
618         case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
619                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
620                                    input->ip.v4.dst_ip);
621                 ice_pkt_insert_u16(loc, ICE_IPV4_TCP_DST_PORT_OFFSET,
622                                    input->ip.v4.dst_port);
623                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
624                                    input->ip.v4.src_ip);
625                 ice_pkt_insert_u16(loc, ICE_IPV4_TCP_SRC_PORT_OFFSET,
626                                    input->ip.v4.src_port);
627                 ice_pkt_insert_u8(loc, ICE_IPV4_TOS_OFFSET, input->ip.v4.tos);
628                 ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
629                 if (frag)
630                         loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
631                 break;
632         case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
633                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
634                                    input->ip.v4.dst_ip);
635                 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_DST_PORT_OFFSET,
636                                    input->ip.v4.dst_port);
637                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
638                                    input->ip.v4.src_ip);
639                 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_SRC_PORT_OFFSET,
640                                    input->ip.v4.src_port);
641                 ice_pkt_insert_u8(loc, ICE_IPV4_TOS_OFFSET, input->ip.v4.tos);
642                 ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
643                 break;
644         case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
645                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
646                                    input->ip.v4.dst_ip);
647                 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_DST_PORT_OFFSET,
648                                    input->ip.v4.dst_port);
649                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
650                                    input->ip.v4.src_ip);
651                 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_SRC_PORT_OFFSET,
652                                    input->ip.v4.src_port);
653                 ice_pkt_insert_u8(loc, ICE_IPV4_TOS_OFFSET, input->ip.v4.tos);
654                 ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
655                 break;
656         case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
657                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
658                                    input->ip.v4.dst_ip);
659                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
660                                    input->ip.v4.src_ip);
661                 ice_pkt_insert_u8(loc, ICE_IPV4_TOS_OFFSET, input->ip.v4.tos);
662                 ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
663                 ice_pkt_insert_u8(loc, ICE_IPV4_PROTO_OFFSET,
664                                   input->ip.v4.proto);
665                 break;
666         case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
667                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
668                                          input->ip.v6.dst_ip);
669                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
670                                          input->ip.v6.src_ip);
671                 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_DST_PORT_OFFSET,
672                                    input->ip.v6.dst_port);
673                 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_SRC_PORT_OFFSET,
674                                    input->ip.v6.src_port);
675                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
676                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
677                 break;
678         case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
679                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
680                                          input->ip.v6.dst_ip);
681                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
682                                          input->ip.v6.src_ip);
683                 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_DST_PORT_OFFSET,
684                                    input->ip.v6.dst_port);
685                 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_SRC_PORT_OFFSET,
686                                    input->ip.v6.src_port);
687                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
688                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
689                 break;
690         case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
691                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
692                                          input->ip.v6.dst_ip);
693                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
694                                          input->ip.v6.src_ip);
695                 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_DST_PORT_OFFSET,
696                                    input->ip.v6.dst_port);
697                 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_SRC_PORT_OFFSET,
698                                    input->ip.v6.src_port);
699                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
700                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
701                 break;
702         case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
703                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
704                                          input->ip.v6.dst_ip);
705                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
706                                          input->ip.v6.src_ip);
707                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
708                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
709                 ice_pkt_insert_u8(loc, ICE_IPV6_PROTO_OFFSET,
710                                   input->ip.v6.proto);
711                 break;
712         default:
713                 return ICE_ERR_PARAM;
714         }
715
716         if (input->flex_fltr)
717                 ice_pkt_insert_u16(loc, input->flex_offset, input->flex_word);
718
719         return ICE_SUCCESS;
720 }
721
722 /**
723  * ice_fdir_get_prgm_pkt - generate a training packet
724  * @input: flow director filter data structure
725  * @pkt: pointer to return filter packet
726  * @frag: generate a fragment packet
727  */
728 enum ice_status
729 ice_fdir_get_prgm_pkt(struct ice_fdir_fltr *input, u8 *pkt, bool frag)
730 {
731         return ice_fdir_get_gen_prgm_pkt(NULL, input, pkt, frag, false);
732 }
733
734 /**
735  * ice_fdir_has_frag - does flow type have 2 ptypes
736  * @flow: flow ptype
737  *
738  * returns true is there is a fragment packet for this ptype
739  */
740 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
741 {
742         if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
743                 return true;
744         else
745                 return false;
746 }
747
748 /**
749  * ice_fdir_find_by_idx - find filter with idx
750  * @hw: pointer to hardware structure
751  * @fltr_idx: index to find.
752  *
753  * Returns pointer to filter if found or null
754  */
755 struct ice_fdir_fltr *
756 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
757 {
758         struct ice_fdir_fltr *rule = NULL;
759
760         LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
761                             fltr_node) {
762                 /* rule ID found in the list */
763                 if (fltr_idx == rule->fltr_id)
764                         return rule;
765                 if (fltr_idx < rule->fltr_id)
766                         break;
767         }
768         return NULL;
769 }
770
771 /**
772  * ice_fdir_list_add_fltr - add a new node to the flow director filter list
773  * @hw: hardware structure
774  * @fltr: filter node to add to structure
775  */
776 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
777 {
778         struct ice_fdir_fltr *rule, *parent = NULL;
779
780         LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
781                             fltr_node) {
782                 /* rule ID found or pass its spot in the list */
783                 if (rule->fltr_id >= fltr->fltr_id)
784                         break;
785                 parent = rule;
786         }
787
788         if (parent)
789                 LIST_ADD_AFTER(&fltr->fltr_node, &parent->fltr_node);
790         else
791                 LIST_ADD(&fltr->fltr_node, &hw->fdir_list_head);
792 }
793
794 /**
795  * ice_fdir_update_cntrs - increment / decrement filter counter
796  * @hw: pointer to hardware structure
797  * @flow: filter flow type
798  * @add: true implies filters added
799  */
800 void
801 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
802 {
803         int incr;
804
805         incr = (add) ? 1 : -1;
806         hw->fdir_active_fltr += incr;
807         if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)
808                 ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow);
809         else
810                 hw->fdir_fltr_cnt[flow] += incr;
811 }
812
813 /**
814  * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
815  * @a: IP v6 address
816  * @b: IP v6 address
817  *
818  * Returns 0 on equal, returns non-0 if different
819  */
820 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
821 {
822         return memcmp(a, b, 4 * sizeof(__be32));
823 }
824
825 /**
826  * ice_fdir_comp_ipv6_rules - compare 2 filters
827  * @a: a Flow Director filter data structure
828  * @b: a Flow Director filter data structure
829  * @v6: bool true if v6 filter
830  *
831  * Returns true if the filters match
832  */
833 static bool
834 ice_fdir_comp_rules(struct ice_fdir_fltr *a,  struct ice_fdir_fltr *b, bool v6)
835 {
836         enum ice_fltr_ptype flow_type = a->flow_type;
837
838         /* The calling function already checks that the two filters have the
839          * same flow_type.
840          */
841         if (!v6) {
842                 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
843                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
844                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
845                         if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
846                             a->ip.v4.src_ip == b->ip.v4.src_ip &&
847                             a->ip.v4.dst_port == b->ip.v4.dst_port &&
848                             a->ip.v4.src_port == b->ip.v4.src_port)
849                                 return true;
850                 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
851                         if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
852                             a->ip.v4.src_ip == b->ip.v4.src_ip &&
853                             a->ip.v4.l4_header == b->ip.v4.l4_header &&
854                             a->ip.v4.proto == b->ip.v4.proto &&
855                             a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
856                             a->ip.v4.tos == b->ip.v4.tos)
857                                 return true;
858                 }
859         } else {
860                 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
861                     flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
862                     flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
863                         if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
864                             a->ip.v6.src_port == b->ip.v6.src_port &&
865                             !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
866                                                b->ip.v6.dst_ip) &&
867                             !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
868                                                b->ip.v6.src_ip))
869                                 return true;
870                 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
871                         if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
872                             a->ip.v6.src_port == b->ip.v6.src_port)
873                                 return true;
874                 }
875         }
876
877         return false;
878 }
879
880 /**
881  * ice_fdir_is_dup_fltr - test if filter is already in list for PF
882  * @hw: hardware data structure
883  * @input: Flow Director filter data structure
884  *
885  * Returns true if the filter is found in the list
886  */
887 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
888 {
889         enum ice_fltr_ptype flow_type;
890         struct ice_fdir_fltr *rule;
891         bool ret = false;
892
893         rule = NULL;
894
895         LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
896                             fltr_node) {
897                 if (rule->flow_type == input->flow_type) {
898                         flow_type = input->flow_type;
899                         if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
900                             flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
901                             flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
902                             flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
903                                 ret = ice_fdir_comp_rules(rule, input, false);
904                         else
905                                 ret = ice_fdir_comp_rules(rule, input, true);
906                         if (ret) {
907                                 if (rule->fltr_id == input->fltr_id &&
908                                     rule->q_index != input->q_index)
909                                         ret = false;
910                                 else
911                                         break;
912                         }
913                 }
914         }
915
916         return ret;
917 }
918
919 /**
920  * ice_clear_vsi_fd_table - admin command to clear FD table for a VSI
921  * @hw: hardware data structure
922  * @vsi_num: vsi_num (HW VSI num)
923  *
924  * Clears FD table entries by issuing admin command (direct, 0x0B06)
925  * Must to pass valid vsi_num as returned by "AddVSI".
926  */
927 enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num)
928 {
929         struct ice_aqc_clear_fd_table *cmd;
930         struct ice_aq_desc desc;
931
932         cmd = &desc.params.clear_fd_table;
933         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
934         cmd->clear_type = CL_FD_VM_VF_TYPE_VSI_IDX;
935
936         cmd->vsi_index = CPU_TO_LE16(vsi_num);
937         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
938 }
939
940 /**
941  * ice_clear_pf_fd_table - admin command to clear FD table for PF
942  * @hw: hardware data structure
943  *
944  * Clears FD table entries for a PF by issuing admin command (direct, 0x0B06)
945  */
946 enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw)
947 {
948         struct ice_aqc_clear_fd_table *cmd;
949         struct ice_aq_desc desc;
950
951         cmd = &desc.params.clear_fd_table;
952         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
953         cmd->clear_type = CL_FD_VM_VF_TYPE_PF_IDX;
954         /* vsi_index must be 0 to clear FD table for a PF */
955         cmd->vsi_index = CPU_TO_LE16(0);
956
957         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
958 }