@@ -544,7 +544,7 @@ init_kni(void)
544544#endif
545545
546546//RSS reta update will failed when enable flow isolate
547- #ifndef FF_FLOW_ISOLATE
547+ #if !defined( FF_FLOW_ISOLATE ) && !defined( FF_FLOW_IPIP )
548548static void
549549set_rss_table (uint16_t port_id , uint16_t reta_size , uint16_t nb_queues )
550550{
@@ -826,7 +826,7 @@ init_port_start(void)
826826 }
827827
828828//RSS reta update will failed when enable flow isolate
829- #ifndef FF_FLOW_ISOLATE
829+ #if !defined( FF_FLOW_ISOLATE ) && !defined( FF_FLOW_IPIP )
830830 if (nb_queues > 1 ) {
831831 /*
832832 * FIXME: modify RSS set to FDIR
@@ -1081,6 +1081,121 @@ init_flow(uint16_t port_id, uint16_t tcp_port) {
10811081
10821082#endif
10831083
1084+ #ifdef FF_FLOW_IPIP
1085+ static int
1086+ create_ipip_flow (uint16_t port_id ) {
1087+ struct rte_flow_attr attr = {.ingress = 1 };
1088+ struct ff_port_cfg * pconf = & ff_global_cfg .dpdk .port_cfgs [port_id ];
1089+ int nb_queues = pconf -> nb_lcores ;
1090+ uint16_t queue [RTE_MAX_QUEUES_PER_PORT ];
1091+ // 1. Queue configuration check
1092+ if (nb_queues > RTE_MAX_QUEUES_PER_PORT ) {
1093+ rte_exit (EXIT_FAILURE , "Queue count exceeds limit (%d > %d)\n" ,
1094+ nb_queues , RTE_MAX_QUEUES_PER_PORT );
1095+ }
1096+ for (int i = 0 ; i < nb_queues ; i ++ )
1097+ queue [i ] = i ;
1098+
1099+ // 2. Get device info and check return value
1100+ struct rte_eth_dev_info dev_info ;
1101+ int ret = rte_eth_dev_info_get (port_id , & dev_info );
1102+ if (ret != 0 ) {
1103+ rte_exit (EXIT_FAILURE , "Error during getting device (port %u) info: %s\n" ,
1104+ port_id , strerror (- ret ));
1105+ }
1106+ // 3. RSS config - key: set inner hash
1107+ struct rte_flow_action_rss rss = {
1108+ .func = RTE_ETH_HASH_FUNCTION_DEFAULT ,
1109+ .level = 2 , // inner encapsulation layer RSS - hash based on inner protocol
1110+ .types = ETH_RSS_NONFRAG_IPV4_TCP , // inner IPv4+TCP hash
1111+ .key_len = rsskey_len ,
1112+ .key = rsskey ,
1113+ .queue_num = nb_queues ,
1114+ .queue = queue ,
1115+ };
1116+ // 4. Hardware capability check and fallback handling
1117+ if (!(dev_info .flow_type_rss_offloads & ETH_RSS_NONFRAG_IPV4_TCP )) {
1118+ // printf("warning: inner TCP RSS not supported, fallback to outer RSS\n");
1119+ fprintf (stderr , "Fallback handling!!!\n" );
1120+ printf ("I'm three,Warning: inner TCP RSS is not supported, falling back to outer RSS.\n" );
1121+ rss .level = 0 ; // fallback to outer RSS
1122+ rss .types = RTE_ETH_FLOW_IPV4 ; // update to outer protocol type
1123+ }
1124+
1125+ // 5. Outer IPv4 matches IPIP protocol
1126+ struct rte_flow_item_ipv4 outer_ipv4_spec = {
1127+ .hdr = {
1128+ .next_proto_id = IPPROTO_IPIP
1129+ }
1130+ };
1131+ struct rte_flow_item_ipv4 outer_ipv4_mask = {
1132+ .hdr = {
1133+ .next_proto_id = 0xFF
1134+ }
1135+ };
1136+
1137+ // 6. Pattern chain definition - match inner TCP to enable inner RSS
1138+ struct rte_flow_item pattern [] = {
1139+ // Outer Ethernet header (wildcard)
1140+ {
1141+ .type = RTE_FLOW_ITEM_TYPE_ETH ,
1142+ .spec = NULL ,
1143+ .mask = NULL
1144+ },
1145+ // Outer IPv4 header (match only IPIP protocol)
1146+ {
1147+ .type = RTE_FLOW_ITEM_TYPE_IPV4 ,
1148+ .spec = & outer_ipv4_spec ,
1149+ .mask = & outer_ipv4_mask
1150+ },
1151+ // Inner IPv4 header (wildcard, RSS hashes based on this layer)
1152+ {
1153+ .type = RTE_FLOW_ITEM_TYPE_IPV4 ,
1154+ .spec = NULL ,
1155+ .mask = NULL
1156+ },
1157+ // Inner TCP header (wildcard, RSS hashes based on this layer)
1158+ {
1159+ .type = RTE_FLOW_ITEM_TYPE_TCP ,
1160+ .spec = NULL ,
1161+ .mask = NULL
1162+ },
1163+ {
1164+ .type = RTE_FLOW_ITEM_TYPE_END
1165+ }
1166+ };
1167+
1168+ // 7. Action configuration
1169+ struct rte_flow_action action [] = {
1170+ {
1171+ .type = RTE_FLOW_ACTION_TYPE_RSS ,
1172+ .conf = & rss
1173+ },
1174+ {
1175+ .type = RTE_FLOW_ACTION_TYPE_END
1176+ }
1177+ };
1178+
1179+ // 8. Validate and create flow rule
1180+ struct rte_flow_error error ;
1181+ struct rte_flow * flow = NULL ;
1182+
1183+ if (!rte_flow_validate (port_id , & attr , pattern , action , & error )) {
1184+ flow = rte_flow_create (port_id , & attr , pattern , action , & error );
1185+ if (!flow ) {
1186+ fprintf (stderr , "Flow rule creation failed: %s\n" , error .message );
1187+ return - error .type ;
1188+ }
1189+ } else {
1190+ fprintf (stderr , "Flow rule validation failed: %s\n" , error .message );
1191+ return - error .type ;
1192+ }
1193+ fprintf (stderr , "IPIP flow rule created successfully (port %d, RSS level=%d)\n" , port_id , rss .level );
1194+ printf ("IPIP flow rule created successfully (port %d, RSS level=%d)\n" , port_id , rss .level );
1195+ return 0 ;
1196+ }
1197+ #endif
1198+
10841199#ifdef FF_FDIR
10851200/*
10861201 * Flow director allows the traffic to specific port to be processed on the
@@ -1254,6 +1369,17 @@ ff_dpdk_init(int argc, char **argv)
12541369 }
12551370#endif
12561371
1372+
1373+ #ifdef FF_FLOW_IPIP
1374+ // create ipip flow for port 0
1375+ if (0 == lcore_conf .tx_queue_id [0 ]){
1376+ ret = create_ipip_flow (0 );
1377+ if (ret != 0 ) {
1378+ rte_exit (EXIT_FAILURE , "create_ipip_flow failed\n" );
1379+ }
1380+ }
1381+ #endif
1382+
12571383#ifdef FF_FDIR
12581384 /*
12591385 * Refer function header section for usage.
0 commit comments