DPDK usage discussions
 help / color / mirror / Atom feed
* DPDK Flow Filtering Not Working as Expected
@ 2025-01-28 16:50 Sid ali cherrati
  0 siblings, 0 replies; 12+ messages in thread
From: Sid ali cherrati @ 2025-01-28 16:50 UTC (permalink / raw)
  To: users

[-- Attachment #1: Type: text/plain, Size: 2770 bytes --]

Dear DPDK Team,

I am attempting to use DPDK's rte_flow API to filter incoming packets at
the hardware level. My goal is to drop all packets except those with a
specific IP address and UDP port.

I have implemented the following flow filtering rule in my code:
int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port) {
struct rte_flow_error error;
struct rte_flow_attr attr;
struct rte_flow_item pattern[4]; // 4 pour inclure END
struct rte_flow_action action[2];
struct rte_flow *flow;

// Remplir l'attribut de la règle
memset(&attr, 0, sizeof(struct rte_flow_attr));
attr.ingress = 1; // Règle pour le trafic entrant
attr.priority = 1000; // Priorité haute pour que cette règle soit appliquée
en premier

// Définir le motif de filtrage (IP + UDP)
memset(pattern, 0, sizeof(pattern));

pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;

// Motif IPv4
pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
pattern[1].spec = &(struct rte_flow_item_ipv4){
.hdr = {
.dst_addr = RTE_BE32(ip_addr), // Adresse IP de destination
}
};
pattern[1].mask = &(struct rte_flow_item_ipv4){
.hdr = {
.dst_addr = RTE_BE32(0xFFFFFFFF), // Masque pour l'adresse IP
}
};

// Motif UDP
pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
pattern[2].spec = &(struct rte_flow_item_udp){
.hdr = {
.dst_port = RTE_BE16(udp_port), // Port de destination
}
};
pattern[2].mask = &(struct rte_flow_item_udp){
.hdr = {
.dst_port = RTE_BE16(0xFFFF), // Masque pour le port
}
};

// Fin du motif
pattern[3].type = RTE_FLOW_ITEM_TYPE_END;

// Définir l'action (accepter le paquet)
memset(action, 0, sizeof(action));

// Envoyer à la file RX_ID
action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
action[0].conf = &(struct rte_flow_action_queue){
.index = RX_ID, // Envoyer les paquets à la file RX_ID
};

// Fin de la liste d'actions
action[1].type = RTE_FLOW_ACTION_TYPE_END;

// Créer la règle de filtrage
flow = rte_flow_create(port_id, &attr, pattern, action, &error);
if (flow == NULL) {
printf("Erreur lors de la création de la règle de filtrage : %s\n", error.
message);
return -1;
}

// Afficher un message de succès
printf(
"Règle de filtrage créee avec succès pour l'IP %u.%u.%u.%u et le port %u\n",
(ip_addr >> 24) & 0xFF,
(ip_addr >> 16) & 0xFF,
(ip_addr >> 8) & 0xFF,
ip_addr & 0xFF,
udp_port
);

return 0;
}

However, despite this configuration, I continue to receive packets with
other IP addresses and ports that do not match the specified filter.

Could you provide any insights into why the filtering isn't working as
expected? Any advice on ensuring the rule is properly applied at the
hardware level would be greatly appreciated.

Thank you for your assistance.

Best regards,

Ali

[-- Attachment #2: Type: text/html, Size: 24542 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-02-04 15:50               ` Sid ali cherrati
@ 2025-02-04 17:41                 ` Medvedkin, Vladimir
  0 siblings, 0 replies; 12+ messages in thread
From: Medvedkin, Vladimir @ 2025-02-04 17:41 UTC (permalink / raw)
  To: Sid ali cherrati
  Cc: Dariusz Sosnowski, Dmitry Kozlyuk, Anatoly Burakov, users

[-- Attachment #1: Type: text/plain, Size: 3353 bytes --]

You can also try with the existing X540-AT2 NIC the following :

- Init NIC with 2 queues

- set the FDIR flow for your particular ip/port to route your packet to 
a queue number, say 1

- Instead of using rte_flow to drop all other packets, use RSS. Rewrite 
the RSS ReTa (see rte_eth_dev_rss_reta_update) with queue id you are not 
going to poll, so in this case with queue id = 0. All ReTa entries will 
be 0, so packets not matched with the FDIR will be assigned to this queue.

- ignore rx on the queue 0

I believe this approach would be better for your particular use case, 
than relying on rte_flow to drop all the traffic, which, as we could 
see, depends on the internal HW implementation.

On 04/02/2025 15:50, Sid ali cherrati wrote:
>
> Hello Vladimir,
>
> Thank you for the clarification.
>
> I'll try using the E810 and provide an update on the issue.
>
> Best regards,
> Ali
>
>
> Le mar. 4 févr. 2025 à 16:41, Medvedkin, Vladimir 
> <vladimir.medvedkin@intel.com> a écrit :
>
>     Hi all,
>
>     The goal that Ali is trying to achieve is not possible with the
>     X540-AT2
>     NIC (as with any other ixgbe NIC). The problem is related to:
>
>     1. The first rule is processed by the FDIR engine
>
>     2. FDIR engine is executed in the HW pipeline almost in the end (just
>     before RSS), i.e. after other filters that we could use to match all
>     other packets (5tuple filter engine in this particular case).
>
>     Therefore my recommendations here would be to use a modern NIC
>     such as
>     E810 to implement the required filtering logic.
>
>     On 04/02/2025 09:28, Dariusz Sosnowski wrote:
>     > Hi,
>     >
>     > Anatoly, Vladimir - Would you be able to help with the issue
>     regarding DROP action not being supported on X540-AT2?
>     >
>     > Best regards,
>     > Dariusz Sosnowski
>     >
>     >> From: Sid ali cherrati <scherrati1@gmail.com>
>     >> Sent: Monday, February 3, 2025 18:12
>     >> To: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
>     >> Cc: users@dpdk.org
>     >> Subject: Re: DPDK Flow Filtering Not Working as Expected
>     >>
>     >> External email: Use caution opening links or attachments
>     >>
>     >> Here is a better version of the code :
>     >>
>     <snip>
>     >>
>     >> Le lun. 3 févr. 2025 à 16:00, Dmitry Kozlyuk
>     <mailto:dmitry.kozliuk@gmail.com> a écrit :
>     >> 2025-02-03 14:51 (UTC+0100), Sid ali cherrati:
>     >>> [...]
>     >>> if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
>     >>> flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
>     >>> }
>     >>>
>     >>> if(flow != 0){
>     >>> printf("Filed to create drop flow filter \n");
>     >>> return -1;
>     >>> }
>     >>> [...]
>     >>> The issue is that when I implement this, I get an error on the
>     drop filter:
>     >>> "Failed to create rule." Do you have any idea why this might
>     be happening?
>     >> There is no this exact error text in your code or DPDK,
>     >> I assume we're talking about the quoted fragment.
>     >> `flow` is a pointer, the correct error condition is `if (flow
>     == NULL)`,
>     >> so your code probably misinterprets success as error.
>     >> Also `flow` is not assigned if `rte_flow_validate()` returns non-0.
>
>     -- 
>     Regards,
>     Vladimir
>
-- 
Regards,
Vladimir

[-- Attachment #2: Type: text/html, Size: 5959 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-02-04 15:41             ` Medvedkin, Vladimir
@ 2025-02-04 15:50               ` Sid ali cherrati
  2025-02-04 17:41                 ` Medvedkin, Vladimir
  0 siblings, 1 reply; 12+ messages in thread
From: Sid ali cherrati @ 2025-02-04 15:50 UTC (permalink / raw)
  To: Medvedkin, Vladimir
  Cc: Dariusz Sosnowski, Dmitry Kozlyuk, Anatoly Burakov, users

[-- Attachment #1: Type: text/plain, Size: 2398 bytes --]

Hello Vladimir,

Thank you for the clarification.

I'll try using the E810 and provide an update on the issue.

Best regards,
Ali

Le mar. 4 févr. 2025 à 16:41, Medvedkin, Vladimir <
vladimir.medvedkin@intel.com> a écrit :

> Hi all,
>
> The goal that Ali is trying to achieve is not possible with the X540-AT2
> NIC (as with any other ixgbe NIC). The problem is related to:
>
> 1. The first rule is processed by the FDIR engine
>
> 2. FDIR engine is executed in the HW pipeline almost in the end (just
> before RSS), i.e. after other filters that we could use to match all
> other packets (5tuple filter engine in this particular case).
>
> Therefore my recommendations here would be to use a modern NIC such as
> E810 to implement the required filtering logic.
>
> On 04/02/2025 09:28, Dariusz Sosnowski wrote:
> > Hi,
> >
> > Anatoly, Vladimir - Would you be able to help with the issue regarding
> DROP action not being supported on X540-AT2?
> >
> > Best regards,
> > Dariusz Sosnowski
> >
> >> From: Sid ali cherrati <scherrati1@gmail.com>
> >> Sent: Monday, February 3, 2025 18:12
> >> To: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> >> Cc: users@dpdk.org
> >> Subject: Re: DPDK Flow Filtering Not Working as Expected
> >>
> >> External email: Use caution opening links or attachments
> >>
> >> Here is a better version of the code :
> >>
> <snip>
> >>
> >> Le lun. 3 févr. 2025 à 16:00, Dmitry Kozlyuk <mailto:
> dmitry.kozliuk@gmail.com> a écrit :
> >> 2025-02-03 14:51 (UTC+0100), Sid ali cherrati:
> >>> [...]
> >>> if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
> >>> flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
> >>> }
> >>>
> >>> if(flow != 0){
> >>> printf("Filed to create drop flow filter \n");
> >>> return -1;
> >>> }
> >>> [...]
> >>> The issue is that when I implement this, I get an error on the drop
> filter:
> >>> "Failed to create rule." Do you have any idea why this might be
> happening?
> >> There is no this exact error text in your code or DPDK,
> >> I assume we're talking about the quoted fragment.
> >> `flow` is a pointer, the correct error condition is `if (flow == NULL)`,
> >> so your code probably misinterprets success as error.
> >> Also `flow` is not assigned if `rte_flow_validate()` returns non-0.
>
> --
> Regards,
> Vladimir
>
>

[-- Attachment #2: Type: text/html, Size: 3395 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-02-04  9:28           ` Dariusz Sosnowski
@ 2025-02-04 15:41             ` Medvedkin, Vladimir
  2025-02-04 15:50               ` Sid ali cherrati
  0 siblings, 1 reply; 12+ messages in thread
From: Medvedkin, Vladimir @ 2025-02-04 15:41 UTC (permalink / raw)
  To: Dariusz Sosnowski, Sid ali cherrati, Dmitry Kozlyuk, Anatoly Burakov
  Cc: users

Hi all,

The goal that Ali is trying to achieve is not possible with the X540-AT2 
NIC (as with any other ixgbe NIC). The problem is related to:

1. The first rule is processed by the FDIR engine

2. FDIR engine is executed in the HW pipeline almost in the end (just 
before RSS), i.e. after other filters that we could use to match all 
other packets (5tuple filter engine in this particular case).

Therefore my recommendations here would be to use a modern NIC such as 
E810 to implement the required filtering logic.

On 04/02/2025 09:28, Dariusz Sosnowski wrote:
> Hi,
>
> Anatoly, Vladimir - Would you be able to help with the issue regarding DROP action not being supported on X540-AT2?
>
> Best regards,
> Dariusz Sosnowski
>
>> From: Sid ali cherrati <scherrati1@gmail.com>
>> Sent: Monday, February 3, 2025 18:12
>> To: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
>> Cc: users@dpdk.org
>> Subject: Re: DPDK Flow Filtering Not Working as Expected
>>
>> External email: Use caution opening links or attachments
>>
>> Here is a better version of the code :
>>
<snip>
>>
>> Le lun. 3 févr. 2025 à 16:00, Dmitry Kozlyuk <mailto:dmitry.kozliuk@gmail.com> a écrit :
>> 2025-02-03 14:51 (UTC+0100), Sid ali cherrati:
>>> [...]
>>> if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
>>> flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
>>> }
>>>
>>> if(flow != 0){
>>> printf("Filed to create drop flow filter \n");
>>> return -1;
>>> }
>>> [...]
>>> The issue is that when I implement this, I get an error on the drop filter:
>>> "Failed to create rule." Do you have any idea why this might be happening?
>> There is no this exact error text in your code or DPDK,
>> I assume we're talking about the quoted fragment.
>> `flow` is a pointer, the correct error condition is `if (flow == NULL)`,
>> so your code probably misinterprets success as error.
>> Also `flow` is not assigned if `rte_flow_validate()` returns non-0.

-- 
Regards,
Vladimir


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: DPDK Flow Filtering Not Working as Expected
  2025-02-03 17:12         ` Sid ali cherrati
@ 2025-02-04  9:28           ` Dariusz Sosnowski
  2025-02-04 15:41             ` Medvedkin, Vladimir
  0 siblings, 1 reply; 12+ messages in thread
From: Dariusz Sosnowski @ 2025-02-04  9:28 UTC (permalink / raw)
  To: Sid ali cherrati, Dmitry Kozlyuk, Anatoly Burakov, Vladimir Medvedkin
  Cc: users

Hi,

Anatoly, Vladimir - Would you be able to help with the issue regarding DROP action not being supported on X540-AT2?

Best regards,
Dariusz Sosnowski

> From: Sid ali cherrati <scherrati1@gmail.com> 
> Sent: Monday, February 3, 2025 18:12
> To: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
> Cc: users@dpdk.org
> Subject: Re: DPDK Flow Filtering Not Working as Expected
> 
> External email: Use caution opening links or attachments 
> 
> Here is a better version of the code : 
> 
> #include
> "../include/flow.h"
> 
> #include
> <stdio.h>
> 
> #include
> <string.h>
> 
> 
> 
> int
> flow_filtering(uint16_t
> port_id,
> uint32_t
> ip_addr,
> uint16_t
> udp_port) {
> 
> struct
> rte_flow_error
> error;
> 
> struct
> rte_flow_attr
> attr
> = { .ingress
> =
> 1, .priority
> =
> 0 };
> 
> struct
> rte_flow_item
> pattern[4];
> 
> struct
> rte_flow_action
> action[2];
> 
> struct
> rte_flow
> *flow;
> 
> 
> 
> // Définir le motif Ethernet
> 
> memset(pattern,
> 0,
> sizeof(pattern));
> 
> pattern[0].type
> =
> RTE_FLOW_ITEM_TYPE_ETH;
> 
> 
> 
> // Définir le motif IPv4
> 
> struct
> rte_flow_item_ipv4
> ipv4_spec
> = { .hdr.dst_addr
> =
> RTE_BE32(ip_addr) };
> 
> struct
> rte_flow_item_ipv4
> ipv4_mask
> = { .hdr.dst_addr
> =
> RTE_BE32(0xFFFFFFFF) };
> 
> pattern[1].type
> =
> RTE_FLOW_ITEM_TYPE_IPV4;
> 
> pattern[1].spec
> =
> &ipv4_spec;
> 
> pattern[1].mask
> =
> &ipv4_mask;
> 
> 
> 
> // Définir le motif UDP
> 
> struct
> rte_flow_item_udp
> udp_spec
> = { .hdr.dst_port
> =
> RTE_BE16(udp_port) };
> 
> struct
> rte_flow_item_udp
> udp_mask
> = { .hdr.dst_port
> =
> RTE_BE16(0xFFFF) };
> 
> pattern[2].type
> =
> RTE_FLOW_ITEM_TYPE_UDP;
> 
> pattern[2].spec
> =
> &udp_spec;
> 
> pattern[2].mask
> =
> &udp_mask;
> 
> 
> 
> // Terminer le motif
> 
> pattern[3].type
> =
> RTE_FLOW_ITEM_TYPE_END;
> 
> 
> 
> // Définir l'action
> 
> action[0].type
> =
> RTE_FLOW_ACTION_TYPE_QUEUE;
> 
> struct
> rte_flow_action_queue
> queue_action
> = { .index
> =
> 0 };
> 
> action[0].conf
> =
> &queue_action;
> 
> action[1].type
> =
> RTE_FLOW_ACTION_TYPE_END;
> 
> 
> 
> // Créer la règle de flux
> 
> flow
> =
> rte_flow_create(port_id,
> &attr,
> pattern,
> action,
> &error);
> 
> if (flow
> ==
> NULL) {
> 
> printf("Erreur lors de la création de la règle de flux :
> %s\n",
> error.message);
> 
> return
> -1;
> 
> }
> 
> 
> 
> printf("Règle de flux créée avec succès pour IP
> %u.%u.%u.%u
> et port UDP %u\n",
> 
> (ip_addr
> >>
> 24)
> &
> 0xFF, (ip_addr
> >>
> 16)
> &
> 0xFF,
> 
> (ip_addr
> >>
> 8)
> &
> 0xFF,
> ip_addr
> &
> 0xFF,
> udp_port);
> 
> 
> 
> return
> 0;
> 
> }
> 
> 
> 
> int
> create_drop_all_rule(uint16_t
> port_id) {
> 
> struct
> rte_flow_attr
> attr
> = { .ingress
> =
> 1, .priority
> =
> 1 };
> 
> struct
> rte_flow_item
> pattern[2];
> 
> struct
> rte_flow_action
> actions[2];
> 
> struct
> rte_flow
> *flow
> =
> NULL;
> 
> struct
> rte_flow_error
> error;
> 
> 
> 
> pattern[0].type
> =
> RTE_FLOW_ITEM_TYPE_ETH;
> 
> pattern[1].type
> =
> RTE_FLOW_ITEM_TYPE_END;
> 
> 
> 
> // Actions
> 
> actions[0].type
> =
> RTE_FLOW_ACTION_TYPE_DROP;
> 
> actions[0].conf
> =
> NULL;
> 
> actions[1].type
> =
> RTE_FLOW_ACTION_TYPE_END;
> 
> 
> 
> // Validation & Création
> 
> if (rte_flow_validate(port_id,
> &attr,
> pattern,
> actions,
> &error)
> !=
> 0) {
> 
> printf("Échec validation:
> %s\n",
> error.message);
> 
> return
> -1;
> 
> }
> 
> 
> 
> flow
> =
> rte_flow_create(port_id,
> &attr,
> pattern,
> actions,
> &error);
> 
> if (flow
> ==
> NULL) {
> 
> printf("Échec création:
> %s\n",
> error.message);
> 
> return
> -1;
> 
> }
> 
> 
> 
> printf("Règle DROP créée.\n");
> 
> return
> 0;
> 
> }
> 
> 
> 
> 
> 
> 
> Le lun. 3 févr. 2025 à 16:05, Sid ali cherrati <mailto:scherrati1@gmail.com> a écrit :
> I pointed where the error is occurring on the code below : 
> #include "../include/flow.h"
> #include <stdio.h>
> #include <string.h>
> 
> int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port) {
> struct rte_flow_error error;
> struct rte_flow_attr attr = { .ingress = 1, .priority = 0 };
> struct rte_flow_item pattern[4];
> struct rte_flow_action action[2];
> struct rte_flow *flow;
> 
> // Définir le motif Ethernet
> memset(pattern, 0, sizeof(pattern));
> pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> 
> // Définir le motif IPv4
> struct rte_flow_item_ipv4 ipv4_spec = { .hdr.dst_addr = RTE_BE32(ip_addr) };
> struct rte_flow_item_ipv4 ipv4_mask = { .hdr.dst_addr = RTE_BE32(0xFFFFFFFF) };
> pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> pattern[1].spec = &ipv4_spec;
> pattern[1].mask = &ipv4_mask;
> 
> // Définir le motif UDP
> struct rte_flow_item_udp udp_spec = { .hdr.dst_port = RTE_BE16(udp_port) };
> struct rte_flow_item_udp udp_mask = { .hdr.dst_port = RTE_BE16(0xFFFF) };
> pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
> pattern[2].spec = &udp_spec;
> pattern[2].mask = &udp_mask;
> 
> // Terminer le motif
> pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> 
> // Définir l'action
> action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> struct rte_flow_action_queue queue_action = { .index = 0 };
> action[0].conf = &queue_action;
> action[1].type = RTE_FLOW_ACTION_TYPE_END;
> 
> // Créer la règle de flux
> flow = rte_flow_create(port_id, &attr, pattern, action, &error);
> if (!flow) {
> printf("Erreur lors de la création de la règle de flux : %s\n", error.message);
> return -1;
> }
> 
> printf("Règle de flux créée avec succès pour IP %u.%u.%u.%u et port UDP %u\n",
> (ip_addr >> 24) & 0xFF, (ip_addr >> 16) & 0xFF,
> (ip_addr >> 8) & 0xFF, ip_addr & 0xFF, udp_port);
> 
> return 0;
> }
> 
> int create_drop_all_rule(uint16_t port_id) {
> struct rte_flow_attr attr = { .ingress = 1, .priority = 1};
> struct rte_flow_item pattern[2];
> struct rte_flow_action actions[2];
> struct rte_flow *flow;
> struct rte_flow_error error;
> 
> pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
> 
> actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
> actions[1].type = RTE_FLOW_ACTION_TYPE_END;
> 
> if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
> flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
> }
> 
> if (flow != 0) { // Its happening Here <--- !!! --->
> printf("Erreur création règle DROP: %s (Type: %d, Cause: %p)\n", 
> error.message, error.type, error.cause);
> return -1;
> }
> 
> printf("Default drop rule created successfully.\n");
> return 0;
> }
> 
> Here is what it returns : 
> EAL: Detected CPU lcores: 6
> EAL: Detected NUMA nodes: 1
> EAL: Detected shared linkage of DPDK
> EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
> EAL: Selected IOVA mode 'VA'
> EAL: VFIO support initialized
> EAL: Using IOMMU type 1 (Type 1)
> Port 0 initialisé avec succès
> Capacités de la NIC (port 0):
> - Groupes supportés : 232756
> - Actions supportées : 9a69f
> Règle de flux créée avec succès pour IP 10.81.16.111 et port UDP 1234
> Erreur création règle DROP: Not supported action. (Type: 16, Cause: 0x7ffe87ef63e0)
> EAL: Error - exiting with code: 1
> Erreur création règle drop-all
> 
> Le lun. 3 févr. 2025 à 16:00, Dmitry Kozlyuk <mailto:dmitry.kozliuk@gmail.com> a écrit :
> 2025-02-03 14:51 (UTC+0100), Sid ali cherrati:
> > [...]
> > if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
> > flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
> > }
> > 
> > if(flow != 0){
> > printf("Filed to create drop flow filter \n");
> > return -1;
> > }
> > [...] 
> > The issue is that when I implement this, I get an error on the drop filter:
> > "Failed to create rule." Do you have any idea why this might be happening?
> 
> There is no this exact error text in your code or DPDK,
> I assume we're talking about the quoted fragment.
> `flow` is a pointer, the correct error condition is `if (flow == NULL)`,
> so your code probably misinterprets success as error.
> Also `flow` is not assigned if `rte_flow_validate()` returns non-0.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-02-03 15:05       ` Sid ali cherrati
@ 2025-02-03 17:12         ` Sid ali cherrati
  2025-02-04  9:28           ` Dariusz Sosnowski
  0 siblings, 1 reply; 12+ messages in thread
From: Sid ali cherrati @ 2025-02-03 17:12 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: users

[-- Attachment #1: Type: text/plain, Size: 7059 bytes --]

Here is a better version of the code :
#include "../include/flow.h"
#include <stdio.h>
#include <string.h>

int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port) {
struct rte_flow_error error;
struct rte_flow_attr attr = { .ingress = 1, .priority = 0 };
struct rte_flow_item pattern[4];
struct rte_flow_action action[2];
struct rte_flow *flow;

// Définir le motif Ethernet
memset(pattern, 0, sizeof(pattern));
pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;

// Définir le motif IPv4
struct rte_flow_item_ipv4 ipv4_spec = { .hdr.dst_addr = RTE_BE32(ip_addr) };
struct rte_flow_item_ipv4 ipv4_mask = { .hdr.dst_addr = RTE_BE32(0xFFFFFFFF)
};
pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
pattern[1].spec = &ipv4_spec;
pattern[1].mask = &ipv4_mask;

// Définir le motif UDP
struct rte_flow_item_udp udp_spec = { .hdr.dst_port = RTE_BE16(udp_port) };
struct rte_flow_item_udp udp_mask = { .hdr.dst_port = RTE_BE16(0xFFFF) };
pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
pattern[2].spec = &udp_spec;
pattern[2].mask = &udp_mask;

// Terminer le motif
pattern[3].type = RTE_FLOW_ITEM_TYPE_END;

// Définir l'action
action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
struct rte_flow_action_queue queue_action = { .index = 0 };
action[0].conf = &queue_action;
action[1].type = RTE_FLOW_ACTION_TYPE_END;

// Créer la règle de flux
flow = rte_flow_create(port_id, &attr, pattern, action, &error);
if (flow == NULL) {
printf("Erreur lors de la création de la règle de flux : %s\n", error.
message);
return -1;
}

printf("Règle de flux créée avec succès pour IP %u.%u.%u.%u et port UDP %u\n
",
(ip_addr >> 24) & 0xFF, (ip_addr >> 16) & 0xFF,
(ip_addr >> 8) & 0xFF, ip_addr & 0xFF, udp_port);

return 0;
}

int create_drop_all_rule(uint16_t port_id) {
struct rte_flow_attr attr = { .ingress = 1, .priority = 1 };
struct rte_flow_item pattern[2];
struct rte_flow_action actions[2];
struct rte_flow *flow = NULL;
struct rte_flow_error error;

pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
pattern[1].type = RTE_FLOW_ITEM_TYPE_END;

// Actions
actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
actions[0].conf = NULL;
actions[1].type = RTE_FLOW_ACTION_TYPE_END;

// Validation & Création
if (rte_flow_validate(port_id, &attr, pattern, actions, &error) != 0) {
printf("Échec validation: %s\n", error.message);
return -1;
}

flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
if (flow == NULL) {
printf("Échec création: %s\n", error.message);
return -1;
}

printf("Règle DROP créée.\n");
return 0;
}



Le lun. 3 févr. 2025 à 16:05, Sid ali cherrati <scherrati1@gmail.com> a
écrit :

> I pointed where the error is occurring on the code below :
>
> #include "../include/flow.h"
> #include <stdio.h>
> #include <string.h>
>
> int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port)
> {
> struct rte_flow_error error;
> struct rte_flow_attr attr = { .ingress = 1, .priority = 0 };
> struct rte_flow_item pattern[4];
> struct rte_flow_action action[2];
> struct rte_flow *flow;
>
> // Définir le motif Ethernet
> memset(pattern, 0, sizeof(pattern));
> pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
>
> // Définir le motif IPv4
> struct rte_flow_item_ipv4 ipv4_spec = { .hdr.dst_addr = RTE_BE32(ip_addr)
> };
> struct rte_flow_item_ipv4 ipv4_mask = { .hdr.dst_addr = RTE_BE32(
> 0xFFFFFFFF) };
> pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> pattern[1].spec = &ipv4_spec;
> pattern[1].mask = &ipv4_mask;
>
> // Définir le motif UDP
> struct rte_flow_item_udp udp_spec = { .hdr.dst_port = RTE_BE16(udp_port)
> };
> struct rte_flow_item_udp udp_mask = { .hdr.dst_port = RTE_BE16(0xFFFF) };
> pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
> pattern[2].spec = &udp_spec;
> pattern[2].mask = &udp_mask;
>
> // Terminer le motif
> pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
>
> // Définir l'action
> action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> struct rte_flow_action_queue queue_action = { .index = 0 };
> action[0].conf = &queue_action;
> action[1].type = RTE_FLOW_ACTION_TYPE_END;
>
> // Créer la règle de flux
> flow = rte_flow_create(port_id, &attr, pattern, action, &error);
> if (!flow) {
> printf("Erreur lors de la création de la règle de flux : %s\n", error.
> message);
> return -1;
> }
>
> printf("Règle de flux créée avec succès pour IP %u.%u.%u.%u et port UDP %u
> \n",
> (ip_addr >> 24) & 0xFF, (ip_addr >> 16) & 0xFF,
> (ip_addr >> 8) & 0xFF, ip_addr & 0xFF, udp_port);
>
> return 0;
> }
>
> int create_drop_all_rule(uint16_t port_id) {
> struct rte_flow_attr attr = { .ingress = 1, .priority = 1};
> struct rte_flow_item pattern[2];
> struct rte_flow_action actions[2];
> struct rte_flow *flow;
> struct rte_flow_error error;
>
> pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
>
> actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
> actions[1].type = RTE_FLOW_ACTION_TYPE_END;
>
> if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
> flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
> }
>
> if (flow != 0) { // Its happening Here <--- !!! --->
> printf("Erreur création règle DROP: %s (Type: %d, Cause: %p)\n",
> error.message, error.type, error.cause);
> return -1;
> }
>
> printf("Default drop rule created successfully.\n");
> return 0;
> }
>
> Here is what it returns :
>
>> EAL: Detected CPU lcores: 6
>> EAL: Detected NUMA nodes: 1
>> EAL: Detected shared linkage of DPDK
>> EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
>> EAL: Selected IOVA mode 'VA'
>> EAL: VFIO support initialized
>> EAL: Using IOMMU type 1 (Type 1)
>> Port 0 initialisé avec succès
>> Capacités de la NIC (port 0):
>> - Groupes supportés : 232756
>> - Actions supportées : 9a69f
>> Règle de flux créée avec succès pour IP 10.81.16.111 et port UDP 1234
>> Erreur création règle DROP: Not supported action. (Type: 16, Cause:
>> 0x7ffe87ef63e0)
>> EAL: Error - exiting with code: 1
>> Erreur création règle drop-all
>>
>
> Le lun. 3 févr. 2025 à 16:00, Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> a
> écrit :
>
>> 2025-02-03 14:51 (UTC+0100), Sid ali cherrati:
>> > [...]
>> > if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
>> > flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
>> > }
>> >
>> > if(flow != 0){
>> > printf("Filed to create drop flow filter \n");
>> > return -1;
>> > }
>> > [...]
>> > The issue is that when I implement this, I get an error on the drop
>> filter:
>> > "Failed to create rule." Do you have any idea why this might be
>> happening?
>>
>> There is no this exact error text in your code or DPDK,
>> I assume we're talking about the quoted fragment.
>> `flow` is a pointer, the correct error condition is `if (flow == NULL)`,
>> so your code probably misinterprets success as error.
>> Also `flow` is not assigned if `rte_flow_validate()` returns non-0.
>>
>

[-- Attachment #2: Type: text/html, Size: 66348 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-02-03 15:00     ` Dmitry Kozlyuk
@ 2025-02-03 15:05       ` Sid ali cherrati
  2025-02-03 17:12         ` Sid ali cherrati
  0 siblings, 1 reply; 12+ messages in thread
From: Sid ali cherrati @ 2025-02-03 15:05 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: users

[-- Attachment #1: Type: text/plain, Size: 4157 bytes --]

I pointed where the error is occurring on the code below :

#include "../include/flow.h"
#include <stdio.h>
#include <string.h>

int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port) {
struct rte_flow_error error;
struct rte_flow_attr attr = { .ingress = 1, .priority = 0 };
struct rte_flow_item pattern[4];
struct rte_flow_action action[2];
struct rte_flow *flow;

// Définir le motif Ethernet
memset(pattern, 0, sizeof(pattern));
pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;

// Définir le motif IPv4
struct rte_flow_item_ipv4 ipv4_spec = { .hdr.dst_addr = RTE_BE32(ip_addr) };
struct rte_flow_item_ipv4 ipv4_mask = { .hdr.dst_addr = RTE_BE32(0xFFFFFFFF)
};
pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
pattern[1].spec = &ipv4_spec;
pattern[1].mask = &ipv4_mask;

// Définir le motif UDP
struct rte_flow_item_udp udp_spec = { .hdr.dst_port = RTE_BE16(udp_port) };
struct rte_flow_item_udp udp_mask = { .hdr.dst_port = RTE_BE16(0xFFFF) };
pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
pattern[2].spec = &udp_spec;
pattern[2].mask = &udp_mask;

// Terminer le motif
pattern[3].type = RTE_FLOW_ITEM_TYPE_END;

// Définir l'action
action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
struct rte_flow_action_queue queue_action = { .index = 0 };
action[0].conf = &queue_action;
action[1].type = RTE_FLOW_ACTION_TYPE_END;

// Créer la règle de flux
flow = rte_flow_create(port_id, &attr, pattern, action, &error);
if (!flow) {
printf("Erreur lors de la création de la règle de flux : %s\n", error.
message);
return -1;
}

printf("Règle de flux créée avec succès pour IP %u.%u.%u.%u et port UDP %u\n
",
(ip_addr >> 24) & 0xFF, (ip_addr >> 16) & 0xFF,
(ip_addr >> 8) & 0xFF, ip_addr & 0xFF, udp_port);

return 0;
}

int create_drop_all_rule(uint16_t port_id) {
struct rte_flow_attr attr = { .ingress = 1, .priority = 1};
struct rte_flow_item pattern[2];
struct rte_flow_action actions[2];
struct rte_flow *flow;
struct rte_flow_error error;

pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
pattern[1].type = RTE_FLOW_ITEM_TYPE_END;

actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
actions[1].type = RTE_FLOW_ACTION_TYPE_END;

if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
}

if (flow != 0) { // Its happening Here <--- !!! --->
printf("Erreur création règle DROP: %s (Type: %d, Cause: %p)\n",
error.message, error.type, error.cause);
return -1;
}

printf("Default drop rule created successfully.\n");
return 0;
}

Here is what it returns :

> EAL: Detected CPU lcores: 6
> EAL: Detected NUMA nodes: 1
> EAL: Detected shared linkage of DPDK
> EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
> EAL: Selected IOVA mode 'VA'
> EAL: VFIO support initialized
> EAL: Using IOMMU type 1 (Type 1)
> Port 0 initialisé avec succès
> Capacités de la NIC (port 0):
> - Groupes supportés : 232756
> - Actions supportées : 9a69f
> Règle de flux créée avec succès pour IP 10.81.16.111 et port UDP 1234
> Erreur création règle DROP: Not supported action. (Type: 16, Cause:
> 0x7ffe87ef63e0)
> EAL: Error - exiting with code: 1
> Erreur création règle drop-all
>

Le lun. 3 févr. 2025 à 16:00, Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> a
écrit :

> 2025-02-03 14:51 (UTC+0100), Sid ali cherrati:
> > [...]
> > if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
> > flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
> > }
> >
> > if(flow != 0){
> > printf("Filed to create drop flow filter \n");
> > return -1;
> > }
> > [...]
> > The issue is that when I implement this, I get an error on the drop
> filter:
> > "Failed to create rule." Do you have any idea why this might be
> happening?
>
> There is no this exact error text in your code or DPDK,
> I assume we're talking about the quoted fragment.
> `flow` is a pointer, the correct error condition is `if (flow == NULL)`,
> so your code probably misinterprets success as error.
> Also `flow` is not assigned if `rte_flow_validate()` returns non-0.
>

[-- Attachment #2: Type: text/html, Size: 33408 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-02-03 13:51   ` Sid ali cherrati
@ 2025-02-03 15:00     ` Dmitry Kozlyuk
  2025-02-03 15:05       ` Sid ali cherrati
  0 siblings, 1 reply; 12+ messages in thread
From: Dmitry Kozlyuk @ 2025-02-03 15:00 UTC (permalink / raw)
  To: Sid ali cherrati; +Cc: users

2025-02-03 14:51 (UTC+0100), Sid ali cherrati:
> [...]
> if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
> flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
> }
> 
> if(flow != 0){
> printf("Filed to create drop flow filter \n");
> return -1;
> }
> [...] 
> The issue is that when I implement this, I get an error on the drop filter:
> "Failed to create rule." Do you have any idea why this might be happening?

There is no this exact error text in your code or DPDK,
I assume we're talking about the quoted fragment.
`flow` is a pointer, the correct error condition is `if (flow == NULL)`,
so your code probably misinterprets success as error.
Also `flow` is not assigned if `rte_flow_validate()` returns non-0.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-01-28 18:46 ` Dmitry Kozlyuk
@ 2025-02-03 13:51   ` Sid ali cherrati
  2025-02-03 15:00     ` Dmitry Kozlyuk
  0 siblings, 1 reply; 12+ messages in thread
From: Sid ali cherrati @ 2025-02-03 13:51 UTC (permalink / raw)
  To: Dmitry Kozlyuk; +Cc: users

[-- Attachment #1: Type: text/plain, Size: 7463 bytes --]

Hello Dmitry,

I followed your suggestions, and this is what I came up with:
#include "../include/flow.h"
#include <stdio.h>
#include <string.h>

int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port) {
struct rte_flow_error error;
struct rte_flow_attr attr = { .ingress = 1, .priority = 0 };
struct rte_flow_item pattern[4];
struct rte_flow_action action[2];
struct rte_flow *flow;

// Définir le motif Ethernet
memset(pattern, 0, sizeof(pattern));
pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;

// Définir le motif IPv4
struct rte_flow_item_ipv4 ipv4_spec = { .hdr.dst_addr = RTE_BE32(ip_addr) };
struct rte_flow_item_ipv4 ipv4_mask = { .hdr.dst_addr = RTE_BE32(0xFFFFFFFF)
};
pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
pattern[1].spec = &ipv4_spec;
pattern[1].mask = &ipv4_mask;

// Définir le motif UDP
struct rte_flow_item_udp udp_spec = { .hdr.dst_port = RTE_BE16(udp_port) };
struct rte_flow_item_udp udp_mask = { .hdr.dst_port = RTE_BE16(0xFFFF) };
pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
pattern[2].spec = &udp_spec;
pattern[2].mask = &udp_mask;

// Terminer le motif
pattern[3].type = RTE_FLOW_ITEM_TYPE_END;

// Définir l'action
action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
struct rte_flow_action_queue queue_action = { .index = 0 };
action[0].conf = &queue_action;
action[1].type = RTE_FLOW_ACTION_TYPE_END;

// Créer la règle de flux
flow = rte_flow_create(port_id, &attr, pattern, action, &error);
if (!flow) {
printf("Erreur lors de la création de la règle de flux : %s\n", error.
message);
return -1;
}

// rte_flow_isolate(port_id, 1, &error);

printf("Règle de flux créée avec succès pour IP %u.%u.%u.%u et port UDP %u\n
",
(ip_addr >> 24) & 0xFF, (ip_addr >> 16) & 0xFF,
(ip_addr >> 8) & 0xFF, ip_addr & 0xFF, udp_port);

return 0;
}

int create_drop_all_rule(uint16_t port_id) {
struct rte_flow_attr attr = { .ingress = 1, .priority = 1};
struct rte_flow_item pattern[2];
struct rte_flow_action actions[2];
struct rte_flow *flow;
struct rte_flow_error error;

pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
pattern[1].type = RTE_FLOW_ITEM_TYPE_END;

actions[0].type = RTE_FLOW_ACTION_TYPE_DROP;
actions[1].type = RTE_FLOW_ACTION_TYPE_END;

if (!rte_flow_validate(port_id, &attr, pattern, actions, &error)){
flow = rte_flow_create(port_id, &attr, pattern, actions, &error);
}

if(flow != 0){
printf("Filed to create drop flow filter \n");
return -1;
}

printf("Default drop rule created successfully.\n");
return 0;
}

#include "../include/port.h"
#include "../include/flow.h"
#include <rte_eal.h>
#include <rte_mbuf.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <arpa/inet.h>

#define MAX_PKT_BURST 32

int main(int argc, char **argv) {
struct rte_mempool *mbuf_pool;
int ret;

// Initialiser l'EAL
ret = rte_eal_init(argc, argv);
if (ret < 0) {
rte_exit(EXIT_FAILURE, "Erreur lors de l'initialisation de l'EAL\n");
}

// Créer le pool de mbufs
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS, MBUF_CACHE_SIZE,
0,
RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
if (!mbuf_pool) {
rte_exit(EXIT_FAILURE, "Impossible de créer le pool de mbufs\n");
}

if (port_init(PORT_ID, mbuf_pool) != 0) {
rte_exit(EXIT_FAILURE, "Erreur initialisation port\n");
}

// Créer la règle principale
uint32_t ip_addr = RTE_IPV4(10, 81, 16, 111);
uint16_t udp_port = 1234;

if (flow_filtering(PORT_ID, ip_addr, udp_port) != 0) {
rte_exit(EXIT_FAILURE, "Erreur création règle principale\n");
}

// Créer la règle drop-all
if (create_drop_all_rule(PORT_ID) != 0) {
rte_exit(EXIT_FAILURE, "Erreur création règle drop-all\n");
}

printf("Traitement des paquets...\n");
struct rte_mbuf *bufs[MAX_PKT_BURST];

while (1) {
// Récupérer un burst de paquets sur la file RX de la queue 0
const uint16_t nb_rx = rte_eth_rx_burst(PORT_ID, 0, bufs, MAX_PKT_BURST);
if (nb_rx > 0) {
printf("Reçu %u paquet(s)\n", nb_rx);
for (uint16_t i = 0; i < nb_rx; i++) {
// Afficher la taille du paquet
printf("Paquet %u : taille = %u octets\n",
i, rte_pktmbuf_pkt_len(bufs[i]));

// Traiter le paquet pour afficher les adresses source et destination
struct rte_ether_hdr *eth_hdr;
eth_hdr = rte_pktmbuf_mtod(bufs[i], struct rte_ether_hdr *);

// Vérifier que le paquet est de type IPv4
if (rte_be_to_cpu_16(eth_hdr->ether_type) == RTE_ETHER_TYPE_IPV4) {
struct rte_ipv4_hdr *ip_hdr;
ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);

// Récupérer les adresses source et destination (conversion en format hôte)
uint32_t src_ip = rte_be_to_cpu_32(ip_hdr->src_addr);
uint32_t dst_ip = rte_be_to_cpu_32(ip_hdr->dst_addr);

// Convertir les adresses en chaîne de caractères lisible
char src_str[INET_ADDRSTRLEN];
char dst_str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &src_ip, src_str, INET_ADDRSTRLEN);
inet_ntop(AF_INET, &dst_ip, dst_str, INET_ADDRSTRLEN);

printf("Adresse source : %s\n", src_str);
printf("Adresse destination : %s\n", dst_str);
} else {
printf("Paquet non IPv4, impossible d'extraire les adresses\n");
}

// Libérer le mbuf une fois le traitement terminé
rte_pktmbuf_free(bufs[i]);
}
}
// Petite pause pour éviter une utilisation CPU trop intensive
rte_delay_us_block(100);
}

// Nettoyage
port_cleanup(PORT_ID);
return 0;
}



The issue is that when I implement this, I get an error on the drop filter:
"Failed to create rule." Do you have any idea why this might be happening?

Thank you for your time.

Best regards,
Ali

Le mar. 28 janv. 2025 à 19:46, Dmitry Kozlyuk <dmitry.kozliuk@gmail.com> a
écrit :

> Hi Ali,
>
> 2025-01-28 17:54 (UTC+0100), Sid ali cherrati:
> > I am attempting to use DPDK's rte_flow API to filter incoming packets at
> > the hardware level. My goal is to drop all packets except those with a
> > specific IP address and UDP port.
> >
> > I have implemented the following flow filtering rule in my code:
> > [...]
> > However, despite this configuration, I continue to receive packets with
> > other IP addresses and ports that do not match the specified filter.
>
> Packets that do not match the rule pattern are processed as usual.
> If without the rule queue RX_ID could receive any packet,
> it will also receive them after the rule is created.
> You need another rule with lower priority (BTW, 0 is the highest one)
> that matches all packets and drops them or steers to other queues.
> If you want your DPDK app to only process packets matching the rule
> and to leave all other traffic for the OS to process,
> flow isolated mode may be what you're looking for:
>
>
> https://doc.dpdk.org/guides/prog_guide/ethdev/flow_offload.html#flow-isolated-mode
>
> > Could you provide any insights into why the filtering isn't working as
> > expected? Any advice on ensuring the rule is properly applied at the
> > hardware level would be greatly appreciated.
>
> The usual way to check that the rule is matched
> is to all a counter to the rule and check if it increases.
> I suggest using testpmd for playing with flow rules:
>
>
> https://doc.dpdk.org/guides/testpmd_app_ug/testpmd_funcs.html#flow-rules-management
>
> There was also a useful talk abound HW rules debugging on DPDK Summit:
>
>
> https://dpdksummit2024.sched.com/event/1iAtU/debug-functional-and-performance-issues-in-rteflow-dariusz-sosnowski-nvidia-corp
>
>

[-- Attachment #2: Type: text/html, Size: 61617 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-01-28 16:54 Sid ali cherrati
  2025-01-28 18:46 ` Dmitry Kozlyuk
@ 2025-01-28 18:47 ` Stephen Hemminger
  1 sibling, 0 replies; 12+ messages in thread
From: Stephen Hemminger @ 2025-01-28 18:47 UTC (permalink / raw)
  To: Sid ali cherrati; +Cc: users

On Tue, 28 Jan 2025 17:54:40 +0100
Sid ali cherrati <scherrati1@gmail.com> wrote:

> Dear DPDK Team,
> 
> I am attempting to use DPDK's rte_flow API to filter incoming packets at
> the hardware level. My goal is to drop all packets except those with a
> specific IP address and UDP port.
> 
> I have implemented the following flow filtering rule in my code:
> int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port) {
> struct rte_flow_error error;
> struct rte_flow_attr attr;
> struct rte_flow_item pattern[4]; // 4 pour inclure END
> struct rte_flow_action action[2];
> struct rte_flow *flow;
> 
> // Remplir l'attribut de la règle
> memset(&attr, 0, sizeof(struct rte_flow_attr));
> attr.ingress = 1; // Règle pour le trafic entrant
> attr.priority = 1000; // Priorité haute pour que cette règle soit appliquée
> en premier
> 
> // Définir le motif de filtrage (IP + UDP)
> memset(pattern, 0, sizeof(pattern));
> 
> pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
> 
> // Motif IPv4
> pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
> pattern[1].spec = &(struct rte_flow_item_ipv4){
> .hdr = {
> .dst_addr = RTE_BE32(ip_addr), // Adresse IP de destination
> }
> };
> pattern[1].mask = &(struct rte_flow_item_ipv4){
> .hdr = {
> .dst_addr = RTE_BE32(0xFFFFFFFF), // Masque pour l'adresse IP
> }
> };
> 
> // Motif UDP
> pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
> pattern[2].spec = &(struct rte_flow_item_udp){
> .hdr = {
> .dst_port = RTE_BE16(udp_port), // Port de destination
> }
> };
> pattern[2].mask = &(struct rte_flow_item_udp){
> .hdr = {
> .dst_port = RTE_BE16(0xFFFF), // Masque pour le port
> }
> };
> 
> // Fin du motif
> pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
> 
> // Définir l'action (accepter le paquet)
> memset(action, 0, sizeof(action));
> 
> // Envoyer à la file RX_ID
> action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
> action[0].conf = &(struct rte_flow_action_queue){
> .index = RX_ID, // Envoyer les paquets à la file RX_ID
> };
> 
> // Fin de la liste d'actions
> action[1].type = RTE_FLOW_ACTION_TYPE_END;
> 
> // Créer la règle de filtrage
> flow = rte_flow_create(port_id, &attr, pattern, action, &error);
> if (flow == NULL) {
> printf("Erreur lors de la création de la règle de filtrage : %s\n", error.
> message);
> return -1;
> }
> 
> // Afficher un message de succès
> printf(
> "Règle de filtrage créee avec succès pour l'IP %u.%u.%u.%u et le port %u\n",
> (ip_addr >> 24) & 0xFF,
> (ip_addr >> 16) & 0xFF,
> (ip_addr >> 8) & 0xFF,
> ip_addr & 0xFF,
> udp_port
> );
> 
> return 0;
> }
> 
> However, despite this configuration, I continue to receive packets with
> other IP addresses and ports that do not match the specified filter.
> 
> Could you provide any insights into why the filtering isn't working as
> expected? Any advice on ensuring the rule is properly applied at the
> hardware level would be greatly appreciated.
> 
> Thank you for your assistance.
> 
> Best regards,
> 
> Ali

You need to add a wildcard flow filter (ie match all) with with a drop action.
The default when no matches to any flow is process packet as normal using
default queues.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: DPDK Flow Filtering Not Working as Expected
  2025-01-28 16:54 Sid ali cherrati
@ 2025-01-28 18:46 ` Dmitry Kozlyuk
  2025-02-03 13:51   ` Sid ali cherrati
  2025-01-28 18:47 ` Stephen Hemminger
  1 sibling, 1 reply; 12+ messages in thread
From: Dmitry Kozlyuk @ 2025-01-28 18:46 UTC (permalink / raw)
  To: Sid ali cherrati; +Cc: users

Hi Ali,

2025-01-28 17:54 (UTC+0100), Sid ali cherrati:
> I am attempting to use DPDK's rte_flow API to filter incoming packets at
> the hardware level. My goal is to drop all packets except those with a
> specific IP address and UDP port.
> 
> I have implemented the following flow filtering rule in my code:
> [...] 
> However, despite this configuration, I continue to receive packets with
> other IP addresses and ports that do not match the specified filter.

Packets that do not match the rule pattern are processed as usual.
If without the rule queue RX_ID could receive any packet,
it will also receive them after the rule is created.
You need another rule with lower priority (BTW, 0 is the highest one)
that matches all packets and drops them or steers to other queues.
If you want your DPDK app to only process packets matching the rule
and to leave all other traffic for the OS to process,
flow isolated mode may be what you're looking for:

https://doc.dpdk.org/guides/prog_guide/ethdev/flow_offload.html#flow-isolated-mode
 
> Could you provide any insights into why the filtering isn't working as
> expected? Any advice on ensuring the rule is properly applied at the
> hardware level would be greatly appreciated.

The usual way to check that the rule is matched
is to all a counter to the rule and check if it increases.
I suggest using testpmd for playing with flow rules:

https://doc.dpdk.org/guides/testpmd_app_ug/testpmd_funcs.html#flow-rules-management

There was also a useful talk abound HW rules debugging on DPDK Summit:

https://dpdksummit2024.sched.com/event/1iAtU/debug-functional-and-performance-issues-in-rteflow-dariusz-sosnowski-nvidia-corp


^ permalink raw reply	[flat|nested] 12+ messages in thread

* DPDK Flow Filtering Not Working as Expected
@ 2025-01-28 16:54 Sid ali cherrati
  2025-01-28 18:46 ` Dmitry Kozlyuk
  2025-01-28 18:47 ` Stephen Hemminger
  0 siblings, 2 replies; 12+ messages in thread
From: Sid ali cherrati @ 2025-01-28 16:54 UTC (permalink / raw)
  To: users

[-- Attachment #1: Type: text/plain, Size: 2770 bytes --]

Dear DPDK Team,

I am attempting to use DPDK's rte_flow API to filter incoming packets at
the hardware level. My goal is to drop all packets except those with a
specific IP address and UDP port.

I have implemented the following flow filtering rule in my code:
int flow_filtering(uint16_t port_id, uint32_t ip_addr, uint16_t udp_port) {
struct rte_flow_error error;
struct rte_flow_attr attr;
struct rte_flow_item pattern[4]; // 4 pour inclure END
struct rte_flow_action action[2];
struct rte_flow *flow;

// Remplir l'attribut de la règle
memset(&attr, 0, sizeof(struct rte_flow_attr));
attr.ingress = 1; // Règle pour le trafic entrant
attr.priority = 1000; // Priorité haute pour que cette règle soit appliquée
en premier

// Définir le motif de filtrage (IP + UDP)
memset(pattern, 0, sizeof(pattern));

pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;

// Motif IPv4
pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
pattern[1].spec = &(struct rte_flow_item_ipv4){
.hdr = {
.dst_addr = RTE_BE32(ip_addr), // Adresse IP de destination
}
};
pattern[1].mask = &(struct rte_flow_item_ipv4){
.hdr = {
.dst_addr = RTE_BE32(0xFFFFFFFF), // Masque pour l'adresse IP
}
};

// Motif UDP
pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
pattern[2].spec = &(struct rte_flow_item_udp){
.hdr = {
.dst_port = RTE_BE16(udp_port), // Port de destination
}
};
pattern[2].mask = &(struct rte_flow_item_udp){
.hdr = {
.dst_port = RTE_BE16(0xFFFF), // Masque pour le port
}
};

// Fin du motif
pattern[3].type = RTE_FLOW_ITEM_TYPE_END;

// Définir l'action (accepter le paquet)
memset(action, 0, sizeof(action));

// Envoyer à la file RX_ID
action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
action[0].conf = &(struct rte_flow_action_queue){
.index = RX_ID, // Envoyer les paquets à la file RX_ID
};

// Fin de la liste d'actions
action[1].type = RTE_FLOW_ACTION_TYPE_END;

// Créer la règle de filtrage
flow = rte_flow_create(port_id, &attr, pattern, action, &error);
if (flow == NULL) {
printf("Erreur lors de la création de la règle de filtrage : %s\n", error.
message);
return -1;
}

// Afficher un message de succès
printf(
"Règle de filtrage créee avec succès pour l'IP %u.%u.%u.%u et le port %u\n",
(ip_addr >> 24) & 0xFF,
(ip_addr >> 16) & 0xFF,
(ip_addr >> 8) & 0xFF,
ip_addr & 0xFF,
udp_port
);

return 0;
}

However, despite this configuration, I continue to receive packets with
other IP addresses and ports that do not match the specified filter.

Could you provide any insights into why the filtering isn't working as
expected? Any advice on ensuring the rule is properly applied at the
hardware level would be greatly appreciated.

Thank you for your assistance.

Best regards,

Ali

[-- Attachment #2: Type: text/html, Size: 24550 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2025-02-04 17:41 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-28 16:50 DPDK Flow Filtering Not Working as Expected Sid ali cherrati
2025-01-28 16:54 Sid ali cherrati
2025-01-28 18:46 ` Dmitry Kozlyuk
2025-02-03 13:51   ` Sid ali cherrati
2025-02-03 15:00     ` Dmitry Kozlyuk
2025-02-03 15:05       ` Sid ali cherrati
2025-02-03 17:12         ` Sid ali cherrati
2025-02-04  9:28           ` Dariusz Sosnowski
2025-02-04 15:41             ` Medvedkin, Vladimir
2025-02-04 15:50               ` Sid ali cherrati
2025-02-04 17:41                 ` Medvedkin, Vladimir
2025-01-28 18:47 ` Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).