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