2 * Copyright (c) 2017 QLogic Corporation.
6 * See LICENSE.qede_pmd for copyright and licensing details.
12 #include <rte_errno.h>
14 #include "qede_ethdev.h"
16 #define IP_VERSION (0x40)
17 #define IP_HDRLEN (0x5)
18 #define QEDE_FDIR_IP_DEFAULT_VERSION_IHL (IP_VERSION | IP_HDRLEN)
19 #define QEDE_FDIR_TCP_DEFAULT_DATAOFF (0x50)
20 #define QEDE_FDIR_IPV4_DEF_TTL (64)
22 /* Sum of length of header types of L2, L3, L4.
23 * L2 : ether_hdr + vlan_hdr + vxlan_hdr
27 #define QEDE_MAX_FDIR_PKT_LEN (86)
30 #define IPV6_ADDR_LEN (16)
33 #define QEDE_VALID_FLOW(flow_type) \
34 ((flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_TCP || \
35 (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_UDP || \
36 (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV6_TCP || \
37 (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV6_UDP)
39 /* Note: Flowdir support is only partial.
40 * For ex: drop_queue, FDIR masks, flex_conf are not supported.
41 * Parameters like pballoc/status fields are irrelevant here.
43 int qede_check_fdir_support(struct rte_eth_dev
*eth_dev
)
45 struct qede_dev
*qdev
= QEDE_INIT_QDEV(eth_dev
);
46 struct ecore_dev
*edev
= QEDE_INIT_EDEV(qdev
);
47 struct rte_fdir_conf
*fdir
= ð_dev
->data
->dev_conf
.fdir_conf
;
49 /* check FDIR modes */
51 case RTE_FDIR_MODE_NONE
:
52 qdev
->fdir_info
.arfs
.arfs_enable
= false;
53 DP_INFO(edev
, "flowdir is disabled\n");
55 case RTE_FDIR_MODE_PERFECT
:
56 if (edev
->num_hwfns
> 1) {
57 DP_ERR(edev
, "flowdir is not supported in 100G mode\n");
58 qdev
->fdir_info
.arfs
.arfs_enable
= false;
61 qdev
->fdir_info
.arfs
.arfs_enable
= true;
62 DP_INFO(edev
, "flowdir is enabled\n");
64 case RTE_FDIR_MODE_PERFECT_TUNNEL
:
65 case RTE_FDIR_MODE_SIGNATURE
:
66 case RTE_FDIR_MODE_PERFECT_MAC_VLAN
:
67 DP_ERR(edev
, "Unsupported flowdir mode %d\n", fdir
->mode
);
74 void qede_fdir_dealloc_resc(struct rte_eth_dev
*eth_dev
)
76 struct qede_dev
*qdev
= QEDE_INIT_QDEV(eth_dev
);
77 struct qede_fdir_entry
*tmp
= NULL
;
79 SLIST_FOREACH(tmp
, &qdev
->fdir_info
.fdir_list_head
, list
) {
82 rte_memzone_free(tmp
->mz
);
83 SLIST_REMOVE(&qdev
->fdir_info
.fdir_list_head
, tmp
,
84 qede_fdir_entry
, list
);
91 qede_config_cmn_fdir_filter(struct rte_eth_dev
*eth_dev
,
92 struct rte_eth_fdir_filter
*fdir_filter
,
95 struct qede_dev
*qdev
= QEDE_INIT_QDEV(eth_dev
);
96 struct ecore_dev
*edev
= QEDE_INIT_EDEV(qdev
);
97 char mz_name
[RTE_MEMZONE_NAMESIZE
] = {0};
98 struct qede_fdir_entry
*tmp
= NULL
;
99 struct qede_fdir_entry
*fdir
= NULL
;
100 const struct rte_memzone
*mz
;
101 struct ecore_hwfn
*p_hwfn
;
102 enum _ecore_status_t rc
;
107 if (qdev
->fdir_info
.filter_count
== QEDE_RFS_MAX_FLTR
- 1) {
108 DP_ERR(edev
, "Reached max flowdir filter limit\n");
111 fdir
= rte_malloc(NULL
, sizeof(struct qede_fdir_entry
),
112 RTE_CACHE_LINE_SIZE
);
114 DP_ERR(edev
, "Did not allocate memory for fdir\n");
118 /* soft_id could have been used as memzone string, but soft_id is
119 * not currently used so it has no significance.
121 snprintf(mz_name
, sizeof(mz_name
) - 1, "%lx",
122 (unsigned long)rte_get_timer_cycles());
123 mz
= rte_memzone_reserve_aligned(mz_name
, QEDE_MAX_FDIR_PKT_LEN
,
124 SOCKET_ID_ANY
, 0, RTE_CACHE_LINE_SIZE
);
126 DP_ERR(edev
, "Failed to allocate memzone for fdir, err = %s\n",
127 rte_strerror(rte_errno
));
133 memset(pkt
, 0, QEDE_MAX_FDIR_PKT_LEN
);
134 pkt_len
= qede_fdir_construct_pkt(eth_dev
, fdir_filter
, pkt
,
135 &qdev
->fdir_info
.arfs
);
140 DP_INFO(edev
, "pkt_len = %u memzone = %s\n", pkt_len
, mz_name
);
142 SLIST_FOREACH(tmp
, &qdev
->fdir_info
.fdir_list_head
, list
) {
143 if (memcmp(tmp
->mz
->addr
, pkt
, pkt_len
) == 0) {
144 DP_ERR(edev
, "flowdir filter exist\n");
150 SLIST_FOREACH(tmp
, &qdev
->fdir_info
.fdir_list_head
, list
) {
151 if (memcmp(tmp
->mz
->addr
, pkt
, pkt_len
) == 0)
155 DP_ERR(edev
, "flowdir filter does not exist\n");
160 p_hwfn
= ECORE_LEADING_HWFN(edev
);
162 if (!qdev
->fdir_info
.arfs
.arfs_enable
) {
164 eth_dev
->data
->dev_conf
.fdir_conf
.mode
=
165 RTE_FDIR_MODE_PERFECT
;
166 qdev
->fdir_info
.arfs
.arfs_enable
= true;
167 DP_INFO(edev
, "Force enable flowdir in perfect mode\n");
169 /* Enable ARFS searcher with updated flow_types */
170 ecore_arfs_mode_configure(p_hwfn
, p_hwfn
->p_arfs_ptt
,
171 &qdev
->fdir_info
.arfs
);
173 /* configure filter with ECORE_SPQ_MODE_EBLOCK */
174 rc
= ecore_configure_rfs_ntuple_filter(p_hwfn
, p_hwfn
->p_arfs_ptt
, NULL
,
175 (dma_addr_t
)mz
->phys_addr
,
177 fdir_filter
->action
.rx_queue
,
179 if (rc
== ECORE_SUCCESS
) {
181 fdir
->rx_queue
= fdir_filter
->action
.rx_queue
;
182 fdir
->pkt_len
= pkt_len
;
184 SLIST_INSERT_HEAD(&qdev
->fdir_info
.fdir_list_head
,
186 qdev
->fdir_info
.filter_count
++;
187 DP_INFO(edev
, "flowdir filter added, count = %d\n",
188 qdev
->fdir_info
.filter_count
);
190 rte_memzone_free(tmp
->mz
);
191 SLIST_REMOVE(&qdev
->fdir_info
.fdir_list_head
, tmp
,
192 qede_fdir_entry
, list
);
193 rte_free(tmp
); /* the node deleted */
194 rte_memzone_free(mz
); /* temp node allocated */
195 qdev
->fdir_info
.filter_count
--;
196 DP_INFO(edev
, "Fdir filter deleted, count = %d\n",
197 qdev
->fdir_info
.filter_count
);
200 DP_ERR(edev
, "flowdir filter failed, rc=%d filter_count=%d\n",
201 rc
, qdev
->fdir_info
.filter_count
);
204 /* Disable ARFS searcher if there are no more filters */
205 if (qdev
->fdir_info
.filter_count
== 0) {
206 memset(&qdev
->fdir_info
.arfs
, 0,
207 sizeof(struct ecore_arfs_config_params
));
208 DP_INFO(edev
, "Disabling flowdir\n");
209 qdev
->fdir_info
.arfs
.arfs_enable
= false;
210 ecore_arfs_mode_configure(p_hwfn
, p_hwfn
->p_arfs_ptt
,
211 &qdev
->fdir_info
.arfs
);
216 rte_memzone_free(mz
);
224 qede_fdir_filter_add(struct rte_eth_dev
*eth_dev
,
225 struct rte_eth_fdir_filter
*fdir
,
228 struct qede_dev
*qdev
= QEDE_INIT_QDEV(eth_dev
);
229 struct ecore_dev
*edev
= QEDE_INIT_EDEV(qdev
);
231 if (!QEDE_VALID_FLOW(fdir
->input
.flow_type
)) {
232 DP_ERR(edev
, "invalid flow_type input\n");
236 if (fdir
->action
.rx_queue
>= QEDE_RSS_COUNT(qdev
)) {
237 DP_ERR(edev
, "invalid queue number %u\n",
238 fdir
->action
.rx_queue
);
242 if (fdir
->input
.flow_ext
.is_vf
) {
243 DP_ERR(edev
, "flowdir is not supported over VF\n");
247 return qede_config_cmn_fdir_filter(eth_dev
, fdir
, add
);
250 /* Fills the L3/L4 headers and returns the actual length of flowdir packet */
252 qede_fdir_construct_pkt(struct rte_eth_dev
*eth_dev
,
253 struct rte_eth_fdir_filter
*fdir
,
255 struct ecore_arfs_config_params
*params
)
258 struct qede_dev
*qdev
= QEDE_INIT_QDEV(eth_dev
);
259 struct ecore_dev
*edev
= QEDE_INIT_EDEV(qdev
);
260 uint16_t *ether_type
;
262 struct rte_eth_fdir_input
*input
;
263 static uint8_t vlan_frame
[] = {0x81, 0, 0, 0};
265 struct ipv6_hdr
*ip6
;
269 static const uint8_t next_proto
[] = {
270 [RTE_ETH_FLOW_NONFRAG_IPV4_TCP
] = IPPROTO_TCP
,
271 [RTE_ETH_FLOW_NONFRAG_IPV4_UDP
] = IPPROTO_UDP
,
272 [RTE_ETH_FLOW_NONFRAG_IPV6_TCP
] = IPPROTO_TCP
,
273 [RTE_ETH_FLOW_NONFRAG_IPV6_UDP
] = IPPROTO_UDP
,
275 raw_pkt
= (uint8_t *)buff
;
276 input
= &fdir
->input
;
277 DP_INFO(edev
, "flow_type %d\n", input
->flow_type
);
279 len
= 2 * sizeof(struct ether_addr
);
280 raw_pkt
+= 2 * sizeof(struct ether_addr
);
281 if (input
->flow_ext
.vlan_tci
) {
282 DP_INFO(edev
, "adding VLAN header\n");
283 rte_memcpy(raw_pkt
, vlan_frame
, sizeof(vlan_frame
));
284 rte_memcpy(raw_pkt
+ sizeof(uint16_t),
285 &input
->flow_ext
.vlan_tci
,
287 raw_pkt
+= sizeof(vlan_frame
);
288 len
+= sizeof(vlan_frame
);
290 ether_type
= (uint16_t *)raw_pkt
;
291 raw_pkt
+= sizeof(uint16_t);
292 len
+= sizeof(uint16_t);
294 switch (input
->flow_type
) {
295 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP
:
296 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP
:
297 /* fill the common ip header */
298 ip
= (struct ipv4_hdr
*)raw_pkt
;
299 *ether_type
= rte_cpu_to_be_16(ETHER_TYPE_IPv4
);
300 ip
->version_ihl
= QEDE_FDIR_IP_DEFAULT_VERSION_IHL
;
301 ip
->total_length
= sizeof(struct ipv4_hdr
);
302 ip
->next_proto_id
= input
->flow
.ip4_flow
.proto
?
303 input
->flow
.ip4_flow
.proto
:
304 next_proto
[input
->flow_type
];
305 ip
->time_to_live
= input
->flow
.ip4_flow
.ttl
?
306 input
->flow
.ip4_flow
.ttl
:
307 QEDE_FDIR_IPV4_DEF_TTL
;
308 ip
->type_of_service
= input
->flow
.ip4_flow
.tos
;
309 ip
->dst_addr
= input
->flow
.ip4_flow
.dst_ip
;
310 ip
->src_addr
= input
->flow
.ip4_flow
.src_ip
;
311 len
+= sizeof(struct ipv4_hdr
);
314 raw_pkt
= (uint8_t *)buff
;
316 if (input
->flow_type
== RTE_ETH_FLOW_NONFRAG_IPV4_UDP
) {
317 udp
= (struct udp_hdr
*)(raw_pkt
+ len
);
318 udp
->dst_port
= input
->flow
.udp4_flow
.dst_port
;
319 udp
->src_port
= input
->flow
.udp4_flow
.src_port
;
320 udp
->dgram_len
= sizeof(struct udp_hdr
);
321 len
+= sizeof(struct udp_hdr
);
322 /* adjust ip total_length */
323 ip
->total_length
+= sizeof(struct udp_hdr
);
326 tcp
= (struct tcp_hdr
*)(raw_pkt
+ len
);
327 tcp
->src_port
= input
->flow
.tcp4_flow
.src_port
;
328 tcp
->dst_port
= input
->flow
.tcp4_flow
.dst_port
;
329 tcp
->data_off
= QEDE_FDIR_TCP_DEFAULT_DATAOFF
;
330 len
+= sizeof(struct tcp_hdr
);
331 /* adjust ip total_length */
332 ip
->total_length
+= sizeof(struct tcp_hdr
);
336 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP
:
337 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP
:
338 ip6
= (struct ipv6_hdr
*)raw_pkt
;
339 *ether_type
= rte_cpu_to_be_16(ETHER_TYPE_IPv6
);
340 ip6
->proto
= input
->flow
.ipv6_flow
.proto
?
341 input
->flow
.ipv6_flow
.proto
:
342 next_proto
[input
->flow_type
];
343 rte_memcpy(&ip6
->src_addr
, &input
->flow
.ipv6_flow
.dst_ip
,
345 rte_memcpy(&ip6
->dst_addr
, &input
->flow
.ipv6_flow
.src_ip
,
347 len
+= sizeof(struct ipv6_hdr
);
349 raw_pkt
= (uint8_t *)buff
;
351 if (input
->flow_type
== RTE_ETH_FLOW_NONFRAG_IPV6_UDP
) {
352 udp
= (struct udp_hdr
*)(raw_pkt
+ len
);
353 udp
->src_port
= input
->flow
.udp6_flow
.dst_port
;
354 udp
->dst_port
= input
->flow
.udp6_flow
.src_port
;
355 len
+= sizeof(struct udp_hdr
);
358 tcp
= (struct tcp_hdr
*)(raw_pkt
+ len
);
359 tcp
->src_port
= input
->flow
.tcp4_flow
.src_port
;
360 tcp
->dst_port
= input
->flow
.tcp4_flow
.dst_port
;
361 tcp
->data_off
= QEDE_FDIR_TCP_DEFAULT_DATAOFF
;
362 len
+= sizeof(struct tcp_hdr
);
367 DP_ERR(edev
, "Unsupported flow_type %u\n",
376 qede_fdir_filter_conf(struct rte_eth_dev
*eth_dev
,
377 enum rte_filter_op filter_op
,
380 struct qede_dev
*qdev
= QEDE_INIT_QDEV(eth_dev
);
381 struct ecore_dev
*edev
= QEDE_INIT_EDEV(qdev
);
382 struct rte_eth_fdir_filter
*fdir
;
385 fdir
= (struct rte_eth_fdir_filter
*)arg
;
387 case RTE_ETH_FILTER_NOP
:
388 /* Typically used to query flowdir support */
389 if (edev
->num_hwfns
> 1) {
390 DP_ERR(edev
, "flowdir is not supported in 100G mode\n");
393 return 0; /* means supported */
394 case RTE_ETH_FILTER_ADD
:
395 ret
= qede_fdir_filter_add(eth_dev
, fdir
, 1);
397 case RTE_ETH_FILTER_DELETE
:
398 ret
= qede_fdir_filter_add(eth_dev
, fdir
, 0);
400 case RTE_ETH_FILTER_FLUSH
:
401 case RTE_ETH_FILTER_UPDATE
:
402 case RTE_ETH_FILTER_INFO
:
406 DP_ERR(edev
, "unknown operation %u", filter_op
);
413 int qede_ntuple_filter_conf(struct rte_eth_dev
*eth_dev
,
414 enum rte_filter_op filter_op
,
417 struct qede_dev
*qdev
= QEDE_INIT_QDEV(eth_dev
);
418 struct ecore_dev
*edev
= QEDE_INIT_EDEV(qdev
);
419 struct rte_eth_ntuple_filter
*ntuple
;
420 struct rte_eth_fdir_filter fdir_entry
;
421 struct rte_eth_tcpv4_flow
*tcpv4_flow
;
422 struct rte_eth_udpv4_flow
*udpv4_flow
;
426 case RTE_ETH_FILTER_NOP
:
427 /* Typically used to query fdir support */
428 if (edev
->num_hwfns
> 1) {
429 DP_ERR(edev
, "flowdir is not supported in 100G mode\n");
432 return 0; /* means supported */
433 case RTE_ETH_FILTER_ADD
:
436 case RTE_ETH_FILTER_DELETE
:
438 case RTE_ETH_FILTER_INFO
:
439 case RTE_ETH_FILTER_GET
:
440 case RTE_ETH_FILTER_UPDATE
:
441 case RTE_ETH_FILTER_FLUSH
:
442 case RTE_ETH_FILTER_SET
:
443 case RTE_ETH_FILTER_STATS
:
444 case RTE_ETH_FILTER_OP_MAX
:
445 DP_ERR(edev
, "Unsupported filter_op %d\n", filter_op
);
448 ntuple
= (struct rte_eth_ntuple_filter
*)arg
;
449 /* Internally convert ntuple to fdir entry */
450 memset(&fdir_entry
, 0, sizeof(fdir_entry
));
451 if (ntuple
->proto
== IPPROTO_TCP
) {
452 fdir_entry
.input
.flow_type
= RTE_ETH_FLOW_NONFRAG_IPV4_TCP
;
453 tcpv4_flow
= &fdir_entry
.input
.flow
.tcp4_flow
;
454 tcpv4_flow
->ip
.src_ip
= ntuple
->src_ip
;
455 tcpv4_flow
->ip
.dst_ip
= ntuple
->dst_ip
;
456 tcpv4_flow
->ip
.proto
= IPPROTO_TCP
;
457 tcpv4_flow
->src_port
= ntuple
->src_port
;
458 tcpv4_flow
->dst_port
= ntuple
->dst_port
;
460 fdir_entry
.input
.flow_type
= RTE_ETH_FLOW_NONFRAG_IPV4_UDP
;
461 udpv4_flow
= &fdir_entry
.input
.flow
.udp4_flow
;
462 udpv4_flow
->ip
.src_ip
= ntuple
->src_ip
;
463 udpv4_flow
->ip
.dst_ip
= ntuple
->dst_ip
;
464 udpv4_flow
->ip
.proto
= IPPROTO_TCP
;
465 udpv4_flow
->src_port
= ntuple
->src_port
;
466 udpv4_flow
->dst_port
= ntuple
->dst_port
;
468 return qede_config_cmn_fdir_filter(eth_dev
, &fdir_entry
, add
);