Skip to content

Commit 4b4f06f

Browse files
hirowang1jfb8856606
authored andcommitted
Add inner IP and port-based flow steering capabilities for the IPIP protocol.
1 parent f026266 commit 4b4f06f

File tree

2 files changed

+133
-3
lines changed

2 files changed

+133
-3
lines changed

lib/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ endif
3838

3939
#FF_FLOW_ISOLATE=1
4040
#FF_FDIR=1
41-
41+
#FF_FLOW_IPIP=1
4242
# NETGRAPH drivers ipfw
4343
#FF_NETGRAPH=1
4444
#FF_IPFW=1
@@ -101,6 +101,10 @@ ifdef FF_FLOW_ISOLATE
101101
HOST_CFLAGS+= -DFF_FLOW_ISOLATE
102102
endif
103103

104+
ifdef FF_FLOW_IPIP
105+
HOST_CFLAGS+= -DFF_FLOW_IPIP
106+
endif
107+
104108
ifdef FF_NETGRAPH
105109
HOST_CFLAGS+= -DFF_NETGRAPH
106110
endif

lib/ff_dpdk_if.c

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
548548
static void
549549
set_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

Comments
 (0)