Hello Dmitry, I followed your suggestions, and this is what I came up with: #include "../include/flow.h" #include #include 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 #include #include #include #include #include #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 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 > >