Skip to content

Commit 3da28eb

Browse files
aloktionanguy11
authored andcommitted
iavf: add RSS support for GTP protocol via ethtool
Extend the iavf driver to support Receive Side Scaling (RSS) configuration for GTP (GPRS Tunneling Protocol) flows using ethtool. The implementation introduces new RSS flow segment headers and hash field definitions for various GTP encapsulations, including: - GTPC - GTPU (IP, Extension Header, Uplink, Downlink) - TEID-based hashing The ethtool interface is updated to parse and apply these new flow types and hash fields, enabling fine-grained traffic distribution for GTP-based mobile workloads. This enhancement improves performance and scalability for virtualized network functions (VNFs) and user plane functions (UPFs) in 5G and LTE deployments. Reviewed-by: Jedrzej Jagielski <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: Aleksandr Loktionov <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 41e880e commit 3da28eb

File tree

3 files changed

+216
-23
lines changed

3 files changed

+216
-23
lines changed

drivers/net/ethernet/intel/iavf/iavf_adv_rss.c

Lines changed: 96 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,55 @@ iavf_fill_adv_rss_sctp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
9090
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, DST_PORT);
9191
}
9292

93+
/**
94+
* iavf_fill_adv_rss_gtp_hdr - Fill GTP-related RSS protocol headers
95+
* @proto_hdrs: pointer to the virtchnl protocol headers structure to populate
96+
* @packet_hdrs: bitmask of packet header types to configure
97+
* @hash_flds: RSS hash field configuration
98+
*
99+
* This function populates the virtchnl protocol header structure with
100+
* appropriate GTP-related header types based on the specified packet_hdrs.
101+
* It supports GTPC, GTPU with extension headers, and uplink/downlink PDU
102+
* types. For certain GTPU types, it also appends an IPv4 header to enable
103+
* hashing on the destination IP address.
104+
*
105+
* Return: 0 on success or -EOPNOTSUPP if the packet_hdrs value is unsupported.
106+
*/
107+
static int
108+
iavf_fill_adv_rss_gtp_hdr(struct virtchnl_proto_hdrs *proto_hdrs,
109+
u32 packet_hdrs, u64 hash_flds)
110+
{
111+
struct virtchnl_proto_hdr *hdr;
112+
113+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count - 1];
114+
115+
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_GTP) {
116+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC_TEID:
117+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC:
118+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPC);
119+
break;
120+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_EH:
121+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_EH);
122+
break;
123+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_UP:
124+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_EH_PDU_UP);
125+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
126+
iavf_fill_adv_rss_ip4_hdr(hdr, IAVF_ADV_RSS_HASH_FLD_IPV4_DA);
127+
break;
128+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_DWN:
129+
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_EH_PDU_DWN);
130+
fallthrough;
131+
case IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_IP:
132+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
133+
iavf_fill_adv_rss_ip4_hdr(hdr, IAVF_ADV_RSS_HASH_FLD_IPV4_DA);
134+
break;
135+
default:
136+
return -EOPNOTSUPP;
137+
}
138+
139+
return 0;
140+
}
141+
93142
/**
94143
* iavf_fill_adv_rss_cfg_msg - fill the RSS configuration into virtchnl message
95144
* @rss_cfg: the virtchnl message to be filled with RSS configuration setting
@@ -103,6 +152,8 @@ int
103152
iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
104153
u32 packet_hdrs, u64 hash_flds, bool symm)
105154
{
155+
const u32 packet_l3_hdrs = packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L3;
156+
const u32 packet_l4_hdrs = packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L4;
106157
struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs;
107158
struct virtchnl_proto_hdr *hdr;
108159

@@ -113,31 +164,41 @@ iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
113164

114165
proto_hdrs->tunnel_level = 0; /* always outer layer */
115166

116-
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
117-
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L3) {
118-
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4:
119-
iavf_fill_adv_rss_ip4_hdr(hdr, hash_flds);
120-
break;
121-
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6:
122-
iavf_fill_adv_rss_ip6_hdr(hdr, hash_flds);
123-
break;
124-
default:
125-
return -EINVAL;
167+
if (packet_l3_hdrs) {
168+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
169+
switch (packet_l3_hdrs) {
170+
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4:
171+
iavf_fill_adv_rss_ip4_hdr(hdr, hash_flds);
172+
break;
173+
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6:
174+
iavf_fill_adv_rss_ip6_hdr(hdr, hash_flds);
175+
break;
176+
default:
177+
return -EINVAL;
178+
}
126179
}
127180

128-
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
129-
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L4) {
130-
case IAVF_ADV_RSS_FLOW_SEG_HDR_TCP:
131-
iavf_fill_adv_rss_tcp_hdr(hdr, hash_flds);
132-
break;
133-
case IAVF_ADV_RSS_FLOW_SEG_HDR_UDP:
134-
iavf_fill_adv_rss_udp_hdr(hdr, hash_flds);
135-
break;
136-
case IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP:
137-
iavf_fill_adv_rss_sctp_hdr(hdr, hash_flds);
138-
break;
139-
default:
140-
return -EINVAL;
181+
if (packet_l4_hdrs) {
182+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
183+
switch (packet_l4_hdrs) {
184+
case IAVF_ADV_RSS_FLOW_SEG_HDR_TCP:
185+
iavf_fill_adv_rss_tcp_hdr(hdr, hash_flds);
186+
break;
187+
case IAVF_ADV_RSS_FLOW_SEG_HDR_UDP:
188+
iavf_fill_adv_rss_udp_hdr(hdr, hash_flds);
189+
break;
190+
case IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP:
191+
iavf_fill_adv_rss_sctp_hdr(hdr, hash_flds);
192+
break;
193+
default:
194+
return -EINVAL;
195+
}
196+
}
197+
198+
if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_GTP) {
199+
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
200+
if (iavf_fill_adv_rss_gtp_hdr(proto_hdrs, packet_hdrs, hash_flds))
201+
return -EINVAL;
141202
}
142203

143204
return 0;
@@ -186,6 +247,8 @@ iavf_print_adv_rss_cfg(struct iavf_adapter *adapter, struct iavf_adv_rss *rss,
186247
proto = "UDP";
187248
else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP)
188249
proto = "SCTP";
250+
else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_GTP)
251+
proto = "GTP";
189252
else
190253
return;
191254

@@ -211,6 +274,16 @@ iavf_print_adv_rss_cfg(struct iavf_adapter *adapter, struct iavf_adv_rss *rss,
211274
IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT |
212275
IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT))
213276
strcat(hash_opt, "dst port,");
277+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPC_TEID)
278+
strcat(hash_opt, "gtp-c,");
279+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_IP_TEID)
280+
strcat(hash_opt, "gtp-u ip,");
281+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_EH_TEID)
282+
strcat(hash_opt, "gtp-u ext,");
283+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_UP_TEID)
284+
strcat(hash_opt, "gtp-u ul,");
285+
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_GTPU_DWN_TEID)
286+
strcat(hash_opt, "gtp-u dl,");
214287

215288
if (!action)
216289
action = "";

drivers/net/ethernet/intel/iavf/iavf_adv_rss.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ enum iavf_adv_rss_flow_seg_hdr {
2222
IAVF_ADV_RSS_FLOW_SEG_HDR_TCP = 0x00000004,
2323
IAVF_ADV_RSS_FLOW_SEG_HDR_UDP = 0x00000008,
2424
IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP = 0x00000010,
25+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC = 0x00000400,
26+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC_TEID = 0x00000800,
27+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_IP = 0x00001000,
28+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_EH = 0x00002000,
29+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_DWN = 0x00004000,
30+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_UP = 0x00008000,
2531
};
2632

2733
#define IAVF_ADV_RSS_FLOW_SEG_HDR_L3 \
@@ -33,6 +39,14 @@ enum iavf_adv_rss_flow_seg_hdr {
3339
IAVF_ADV_RSS_FLOW_SEG_HDR_UDP | \
3440
IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP)
3541

42+
#define IAVF_ADV_RSS_FLOW_SEG_HDR_GTP \
43+
(IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC | \
44+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC_TEID | \
45+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_IP | \
46+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_EH | \
47+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_DWN | \
48+
IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_UP)
49+
3650
enum iavf_adv_rss_flow_field {
3751
/* L3 */
3852
IAVF_ADV_RSS_FLOW_FIELD_IDX_IPV4_SA,
@@ -46,6 +60,17 @@ enum iavf_adv_rss_flow_field {
4660
IAVF_ADV_RSS_FLOW_FIELD_IDX_UDP_DST_PORT,
4761
IAVF_ADV_RSS_FLOW_FIELD_IDX_SCTP_SRC_PORT,
4862
IAVF_ADV_RSS_FLOW_FIELD_IDX_SCTP_DST_PORT,
63+
/* GTPC_TEID */
64+
IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPC_TEID,
65+
/* GTPU_IP */
66+
IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_IP_TEID,
67+
/* GTPU_EH */
68+
IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_EH_TEID,
69+
IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_EH_QFI,
70+
/* GTPU_UP */
71+
IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_UP_TEID,
72+
/* GTPU_DWN */
73+
IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_DWN_TEID,
4974

5075
/* The total number of enums must not exceed 64 */
5176
IAVF_ADV_RSS_FLOW_FIELD_IDX_MAX
@@ -72,6 +97,12 @@ enum iavf_adv_rss_flow_field {
7297
BIT_ULL(IAVF_ADV_RSS_FLOW_FIELD_IDX_SCTP_SRC_PORT)
7398
#define IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT \
7499
BIT_ULL(IAVF_ADV_RSS_FLOW_FIELD_IDX_SCTP_DST_PORT)
100+
#define IAVF_ADV_RSS_HASH_FLD_GTPC_TEID BIT_ULL(IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPC_TEID)
101+
#define IAVF_ADV_RSS_HASH_FLD_GTPU_IP_TEID BIT_ULL(IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_IP_TEID)
102+
#define IAVF_ADV_RSS_HASH_FLD_GTPU_EH_TEID BIT_ULL(IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_EH_TEID)
103+
#define IAVF_ADV_RSS_HASH_FLD_GTPU_UP_TEID BIT_ULL(IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_UP_TEID)
104+
#define IAVF_ADV_RSS_HASH_FLD_GTPU_DWN_TEID \
105+
BIT_ULL(IAVF_ADV_RSS_FLOW_FIELD_IDX_GTPU_DWN_TEID)
75106

76107
/* bookkeeping of advanced RSS configuration */
77108
struct iavf_adv_rss {

drivers/net/ethernet/intel/iavf/iavf_ethtool.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,56 @@ static u32 iavf_adv_rss_parse_hdrs(const struct ethtool_rxfh_fields *cmd)
13361336
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP |
13371337
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;
13381338
break;
1339+
case GTPU_V4_FLOW:
1340+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_IP |
1341+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;
1342+
break;
1343+
case GTPC_V4_FLOW:
1344+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC |
1345+
IAVF_ADV_RSS_FLOW_SEG_HDR_UDP |
1346+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;
1347+
break;
1348+
case GTPC_TEID_V4_FLOW:
1349+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC_TEID |
1350+
IAVF_ADV_RSS_FLOW_SEG_HDR_UDP |
1351+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;
1352+
break;
1353+
case GTPU_EH_V4_FLOW:
1354+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_EH |
1355+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;
1356+
break;
1357+
case GTPU_UL_V4_FLOW:
1358+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_UP |
1359+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;
1360+
break;
1361+
case GTPU_DL_V4_FLOW:
1362+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_DWN |
1363+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;
1364+
break;
1365+
case GTPU_V6_FLOW:
1366+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_IP |
1367+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;
1368+
break;
1369+
case GTPC_V6_FLOW:
1370+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC |
1371+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;
1372+
break;
1373+
case GTPC_TEID_V6_FLOW:
1374+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPC_TEID |
1375+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;
1376+
break;
1377+
case GTPU_EH_V6_FLOW:
1378+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_EH |
1379+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;
1380+
break;
1381+
case GTPU_UL_V6_FLOW:
1382+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_UP |
1383+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;
1384+
break;
1385+
case GTPU_DL_V6_FLOW:
1386+
hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_GTPU_DWN |
1387+
IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;
1388+
break;
13391389
default:
13401390
break;
13411391
}
@@ -1353,6 +1403,12 @@ iavf_adv_rss_parse_hash_flds(const struct ethtool_rxfh_fields *cmd, bool symm)
13531403
case TCP_V4_FLOW:
13541404
case UDP_V4_FLOW:
13551405
case SCTP_V4_FLOW:
1406+
case GTPU_V4_FLOW:
1407+
case GTPC_V4_FLOW:
1408+
case GTPC_TEID_V4_FLOW:
1409+
case GTPU_EH_V4_FLOW:
1410+
case GTPU_UL_V4_FLOW:
1411+
case GTPU_DL_V4_FLOW:
13561412
if (cmd->data & RXH_IP_SRC)
13571413
hfld |= IAVF_ADV_RSS_HASH_FLD_IPV4_SA;
13581414
if (cmd->data & RXH_IP_DST)
@@ -1361,6 +1417,12 @@ iavf_adv_rss_parse_hash_flds(const struct ethtool_rxfh_fields *cmd, bool symm)
13611417
case TCP_V6_FLOW:
13621418
case UDP_V6_FLOW:
13631419
case SCTP_V6_FLOW:
1420+
case GTPU_V6_FLOW:
1421+
case GTPC_V6_FLOW:
1422+
case GTPC_TEID_V6_FLOW:
1423+
case GTPU_EH_V6_FLOW:
1424+
case GTPU_UL_V6_FLOW:
1425+
case GTPU_DL_V6_FLOW:
13641426
if (cmd->data & RXH_IP_SRC)
13651427
hfld |= IAVF_ADV_RSS_HASH_FLD_IPV6_SA;
13661428
if (cmd->data & RXH_IP_DST)
@@ -1382,6 +1444,7 @@ iavf_adv_rss_parse_hash_flds(const struct ethtool_rxfh_fields *cmd, bool symm)
13821444
break;
13831445
case UDP_V4_FLOW:
13841446
case UDP_V6_FLOW:
1447+
case GTPC_V4_FLOW:
13851448
if (cmd->data & RXH_L4_B_0_1)
13861449
hfld |= IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT;
13871450
if (cmd->data & RXH_L4_B_2_3)
@@ -1398,6 +1461,32 @@ iavf_adv_rss_parse_hash_flds(const struct ethtool_rxfh_fields *cmd, bool symm)
13981461
break;
13991462
}
14001463
}
1464+
if (cmd->data & RXH_GTP_TEID) {
1465+
switch (cmd->flow_type) {
1466+
case GTPC_TEID_V4_FLOW:
1467+
case GTPC_TEID_V6_FLOW:
1468+
hfld |= IAVF_ADV_RSS_HASH_FLD_GTPC_TEID;
1469+
break;
1470+
case GTPU_V4_FLOW:
1471+
case GTPU_V6_FLOW:
1472+
hfld |= IAVF_ADV_RSS_HASH_FLD_GTPU_IP_TEID;
1473+
break;
1474+
case GTPU_EH_V4_FLOW:
1475+
case GTPU_EH_V6_FLOW:
1476+
hfld |= IAVF_ADV_RSS_HASH_FLD_GTPU_EH_TEID;
1477+
break;
1478+
case GTPU_UL_V4_FLOW:
1479+
case GTPU_UL_V6_FLOW:
1480+
hfld |= IAVF_ADV_RSS_HASH_FLD_GTPU_UP_TEID;
1481+
break;
1482+
case GTPU_DL_V4_FLOW:
1483+
case GTPU_DL_V6_FLOW:
1484+
hfld |= IAVF_ADV_RSS_HASH_FLD_GTPU_DWN_TEID;
1485+
break;
1486+
default:
1487+
break;
1488+
}
1489+
}
14011490

14021491
return hfld;
14031492
}

0 commit comments

Comments
 (0)