Skip to content

Commit c6fbd3f

Browse files
authored
Merge pull request #625 from AltraMayor/i40e
lib/net: add support to the PMD i40e
2 parents 99b31a8 + a601b26 commit c6fbd3f

File tree

4 files changed

+174
-36
lines changed

4 files changed

+174
-36
lines changed

include/gatekeeper_net.h

+19
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,25 @@ struct gatekeeper_if {
246246
*/
247247
bool guarantee_random_entropy;
248248

249+
/*
250+
* Some NICs do not support the RSS hash functions
251+
* ETH_RSS_IPV4 amd ETH_RSS_IPV6 (i.e. RSS hash for IPv4 or IPv6
252+
* non-fragmented packets). But they may support the hash functions
253+
* ETH_RSS_NONFRAG_IPV4_TCP, ETH_RSS_NONFRAG_IPV4_UDP,
254+
* ETH_RSS_NONFRAG_IPV6_TCP, and ETH_RSS_NONFRAG_IPV6_UDP, and
255+
* setting the input set of the hash these hash functions.
256+
* An example of this behavior is the PMD i40e.
257+
*
258+
* Enabling the parameter below, Gatekeeper will try the alternative
259+
* RSS hash.
260+
*
261+
* Currently, this parameter only works for PMD i40e.
262+
*
263+
* If the interface is bonded, all ports in the bond must either
264+
* need this parameter disabled or enabled.
265+
*/
266+
bool alternative_rss_hash;
267+
249268
/*
250269
* The fields below are for internal use.
251270
* Configuration files should not refer to them.

lib/net.c

+150-36
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <rte_ethdev.h>
3333
#include <rte_eth_bond.h>
3434
#include <rte_malloc.h>
35+
#include <rte_pmd_i40e.h>
3536

3637
#include "gatekeeper_acl.h"
3738
#include "gatekeeper_main.h"
@@ -902,6 +903,105 @@ get_if_back(struct net_config *net_conf)
902903
return net_conf->back_iface_enabled ? &net_conf->back : NULL;
903904
}
904905

906+
static int
907+
i40e_clear_inset_field(struct rte_pmd_i40e_inset *inset, uint8_t field_idx)
908+
{
909+
int ret = rte_pmd_i40e_inset_field_clear(&inset->inset, field_idx);
910+
if (unlikely(ret < 0)) {
911+
G_LOG(ERR, "%s(): cannot clear field %i\n",
912+
__func__, field_idx);
913+
}
914+
return ret;
915+
}
916+
917+
static int
918+
i40e_disable_ports_from_inset(uint16_t port_id,
919+
uint8_t pctype_id)
920+
{
921+
struct rte_pmd_i40e_inset inset;
922+
923+
/* Obtain the current RSS hash inset for @pctype_id. */
924+
int ret = rte_pmd_i40e_inset_get(port_id, pctype_id, &inset,
925+
INSET_HASH);
926+
if (unlikely(ret < 0)) {
927+
G_LOG(ERR, "%s(port_id=%i, pctype=%i): cannot get inset (errno=%i): %s\n",
928+
__func__, port_id, pctype_id, -ret, rte_strerror(-ret));
929+
return ret;
930+
}
931+
932+
/*
933+
* Remove source port (i.e. first two bytes) of @pctype_id.
934+
*
935+
* Field index obtained at "Table 7-12. Default field vector table"
936+
* of "Intel Ethernet Controller X710/XXV710/XL710 Datasheet".
937+
*
938+
* The field index below works for @pctype_id equals to TCP or UDP.
939+
*/
940+
ret = i40e_clear_inset_field(&inset, 29);
941+
if (unlikely(ret < 0))
942+
return ret;
943+
944+
/*
945+
* Remove destination port (i.e. third and forth bytes) of
946+
* @pctype_id.
947+
*/
948+
ret = i40e_clear_inset_field(&inset, 30);
949+
if (unlikely(ret < 0))
950+
return ret;
951+
952+
ret = rte_pmd_i40e_inset_set(port_id, pctype_id, &inset, INSET_HASH);
953+
if (unlikely(ret < 0)) {
954+
G_LOG(ERR, "%s(port_id=%i, pctype=%i): cannot set inset (errno=%i): %s\n",
955+
__func__, port_id, pctype_id, -ret, rte_strerror(-ret));
956+
}
957+
return ret;
958+
}
959+
960+
static int
961+
i40e_disable_pctypes_ports_from_inset(uint16_t port_id, uint8_t *pctypes,
962+
uint8_t n)
963+
{
964+
int i;
965+
for (i = 0; i < n; i++) {
966+
int ret = i40e_disable_ports_from_inset(port_id, pctypes[i]);
967+
if (unlikely(ret < 0))
968+
return ret;
969+
}
970+
return 0;
971+
}
972+
973+
static int
974+
i40e_disable_ipv4_tcp_udp_ports_from_inset(uint16_t port_id)
975+
{
976+
/*
977+
* PCTYPES obtained at "Table 7-5. Packet classifier types and
978+
* its input sets" of "Intel Ethernet Controller X710/XXV710/XL710
979+
* Datasheet".
980+
*/
981+
uint8_t pctypes[] = {
982+
31, /* Non-fragmented IPv4, UDP. */
983+
33, /* Non-fragmented IPv4, TCP. */
984+
};
985+
return i40e_disable_pctypes_ports_from_inset(port_id, pctypes,
986+
RTE_DIM(pctypes));
987+
}
988+
989+
static int
990+
i40e_disable_ipv6_tcp_udp_ports_from_inset(uint16_t port_id)
991+
{
992+
/*
993+
* PCTYPES obtained at "Table 7-5. Packet classifier types and
994+
* its input sets" of "Intel Ethernet Controller X710/XXV710/XL710
995+
* Datasheet".
996+
*/
997+
uint8_t pctypes[] = {
998+
41, /* Non-fragmented IPv6, UDP. */
999+
43, /* Non-fragmented IPv6, TCP. */
1000+
};
1001+
return i40e_disable_pctypes_ports_from_inset(port_id, pctypes,
1002+
RTE_DIM(pctypes));
1003+
}
1004+
9051005
/*
9061006
* Split up ETH_RSS_IP into IPv4-related and IPv6-related hash functions.
9071007
* For each type of IP being used in Gatekeeper, check the supported
@@ -934,21 +1034,21 @@ check_port_rss(struct gatekeeper_if *iface, unsigned int port_idx,
9341034
.rss_key_len = sizeof(rss_hash_key),
9351035
};
9361036
uint64_t rss_off = dev_info->flow_type_rss_offloads;
937-
int ret = rte_eth_dev_rss_hash_conf_get(
938-
iface->ports[port_idx], &__rss_conf);
1037+
uint16_t port_id = iface->ports[port_idx];
1038+
int ret = rte_eth_dev_rss_hash_conf_get(port_id, &__rss_conf);
9391039
if (ret == -ENOTSUP) {
9401040
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support to get RSS configuration, disable RSS\n",
941-
__func__, iface->name,
942-
iface->ports[port_idx], iface->pci_addrs[port_idx]);
1041+
__func__, iface->name, port_id,
1042+
iface->pci_addrs[port_idx]);
9431043
goto disable_rss;
9441044
}
9451045

946-
/* Do not use @rss_conf from now on. See issue #624 for details. */
1046+
/* Do not use @__rss_conf from now on. See issue #624 for details. */
9471047

9481048
if (ret < 0) {
9491049
G_LOG(ERR, "%s(%s): failed to get RSS hash configuration at port %hu (%s) (errno=%i): %s\n",
950-
__func__, iface->name,
951-
iface->ports[port_idx], iface->pci_addrs[port_idx],
1050+
__func__, iface->name, port_id,
1051+
iface->pci_addrs[port_idx],
9521052
-ret, rte_strerror(-ret));
9531053
return ret;
9541054
}
@@ -957,8 +1057,8 @@ check_port_rss(struct gatekeeper_if *iface, unsigned int port_idx,
9571057
/* This port doesn't support RSS, so disable RSS. */
9581058
if (rss_off == 0) {
9591059
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support RSS\n",
960-
__func__, iface->name,
961-
iface->ports[port_idx], iface->pci_addrs[port_idx]);
1060+
__func__, iface->name, port_id,
1061+
iface->pci_addrs[port_idx]);
9621062
goto disable_rss;
9631063
}
9641064

@@ -967,8 +1067,8 @@ check_port_rss(struct gatekeeper_if *iface, unsigned int port_idx,
9671067
dev_info->hash_key_size > GATEKEEPER_RSS_MAX_KEY_LEN ||
9681068
dev_info->hash_key_size % 4 != 0) {
9691069
G_LOG(WARNING, "%s(%s): port %hu (%s) requires a RSS hash key of %i bytes; Gatekeeper only supports keys of [%i, %i] bytes long that are multiple of 4\n",
970-
__func__, iface->name,
971-
iface->ports[port_idx], iface->pci_addrs[port_idx],
1070+
__func__, iface->name, port_id,
1071+
iface->pci_addrs[port_idx],
9721072
dev_info->hash_key_size, GATEKEEPER_RSS_MIN_KEY_LEN,
9731073
GATEKEEPER_RSS_MAX_KEY_LEN);
9741074
goto disable_rss;
@@ -983,8 +1083,8 @@ check_port_rss(struct gatekeeper_if *iface, unsigned int port_idx,
9831083
if (iface->rss_key_len <= GATEKEEPER_RSS_MAX_KEY_LEN &&
9841084
iface->rss_key_len != dev_info->hash_key_size) {
9851085
G_LOG(WARNING, "%s(%s): port %hu (%s) requires a RSS hash key of %i bytes, but another port requires a key of %i bytes; all ports of the same interface must have the same key length\n",
986-
__func__, iface->name,
987-
iface->ports[port_idx], iface->pci_addrs[port_idx],
1086+
__func__, iface->name, port_id,
1087+
iface->pci_addrs[port_idx],
9881088
dev_info->hash_key_size, iface->rss_key_len);
9891089
goto disable_rss;
9901090
}
@@ -995,20 +1095,23 @@ check_port_rss(struct gatekeeper_if *iface, unsigned int port_idx,
9951095
/* No IPv4 hashes are supported, so disable RSS. */
9961096
if ((rss_off & GATEKEEPER_IPV4_RSS_HF) == 0) {
9971097
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support any IPv4 related RSS hashes\n",
998-
__func__, iface->name,
999-
iface->ports[port_idx],
1098+
__func__, iface->name, port_id,
10001099
iface->pci_addrs[port_idx]);
10011100
goto disable_rss;
10021101
}
10031102

1004-
/*
1005-
* The IPv4 hash that we think is typically
1006-
* used is not supported, so warn the user.
1007-
*/
1008-
if ((rss_off & ETH_RSS_IPV4) == 0) {
1009-
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support the ETH_RSS_IPV4 hash function; the device may not hash packets to the correct queues\n",
1010-
__func__, iface->name,
1011-
iface->ports[port_idx],
1103+
if (iface->alternative_rss_hash) {
1104+
ret = i40e_disable_ipv4_tcp_udp_ports_from_inset(
1105+
port_id);
1106+
if (ret < 0)
1107+
goto disable_rss;
1108+
} else if ((rss_off & ETH_RSS_IPV4) == 0) {
1109+
/*
1110+
* The IPv4 hash that we think is typically
1111+
* used is not supported, so warn the user.
1112+
*/
1113+
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support the ETH_RSS_IPV4 hash function. The device may not hash packets to the correct queues. You may try parameter alternative_rss_hash.\n",
1114+
__func__, iface->name, port_id,
10121115
iface->pci_addrs[port_idx]);
10131116
}
10141117
}
@@ -1018,20 +1121,23 @@ check_port_rss(struct gatekeeper_if *iface, unsigned int port_idx,
10181121
/* No IPv6 hashes are supported, so disable RSS. */
10191122
if ((rss_off & GATEKEEPER_IPV6_RSS_HF) == 0) {
10201123
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support any IPv6 related RSS hashes\n",
1021-
__func__, iface->name,
1022-
iface->ports[port_idx],
1124+
__func__, iface->name, port_id,
10231125
iface->pci_addrs[port_idx]);
10241126
goto disable_rss;
10251127
}
10261128

1027-
/*
1028-
* The IPv6 hash that we think is typically
1029-
* used is not supported, so warn the user.
1030-
*/
1031-
if ((rss_off & ETH_RSS_IPV6) == 0) {
1032-
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support the ETH_RSS_IPV6 hash function; the device may not hash packets to the correct queues\n",
1033-
__func__, iface->name,
1034-
iface->ports[port_idx],
1129+
if (iface->alternative_rss_hash) {
1130+
ret = i40e_disable_ipv6_tcp_udp_ports_from_inset(
1131+
port_id);
1132+
if (ret < 0)
1133+
goto disable_rss;
1134+
} else if ((rss_off & ETH_RSS_IPV6) == 0) {
1135+
/*
1136+
* The IPv6 hash that we think is typically
1137+
* used is not supported, so warn the user.
1138+
*/
1139+
G_LOG(WARNING, "%s(%s): port %hu (%s) does not support the ETH_RSS_IPV6 hash function. The device may not hash packets to the correct queues. You may try parameter alternative_rss_hash.\n",
1140+
__func__, iface->name, port_id,
10351141
iface->pci_addrs[port_idx]);
10361142
}
10371143
}
@@ -1045,9 +1151,9 @@ check_port_rss(struct gatekeeper_if *iface, unsigned int port_idx,
10451151
if ((rss_off & port_conf->rx_adv_conf.rss_conf.rss_hf) !=
10461152
port_conf->rx_adv_conf.rss_conf.rss_hf) {
10471153
G_LOG(WARNING, "%s(%s): port %hu (%s) only supports RSS hash functions 0x%"PRIx64", but Gatekeeper asks for 0x%"PRIx64"\n",
1048-
__func__, iface->name,
1049-
iface->ports[port_idx], iface->pci_addrs[port_idx],
1050-
rss_off, port_conf->rx_adv_conf.rss_conf.rss_hf);
1154+
__func__, iface->name, port_id,
1155+
iface->pci_addrs[port_idx], rss_off,
1156+
port_conf->rx_adv_conf.rss_conf.rss_hf);
10511157
}
10521158

10531159
port_conf->rx_adv_conf.rss_conf.rss_hf &= rss_off;
@@ -1195,10 +1301,18 @@ check_port_offloads(struct gatekeeper_if *iface,
11951301
if (ipv4_if_configured(iface)) {
11961302
port_conf->rx_adv_conf.rss_conf.rss_hf |=
11971303
GATEKEEPER_IPV4_RSS_HF;
1304+
if (iface->alternative_rss_hash)
1305+
port_conf->rx_adv_conf.rss_conf.rss_hf |=
1306+
ETH_RSS_NONFRAG_IPV4_TCP |
1307+
ETH_RSS_NONFRAG_IPV4_UDP;
11981308
}
11991309
if (ipv6_if_configured(iface)) {
12001310
port_conf->rx_adv_conf.rss_conf.rss_hf |=
12011311
GATEKEEPER_IPV6_RSS_HF;
1312+
if (iface->alternative_rss_hash)
1313+
port_conf->rx_adv_conf.rss_conf.rss_hf |=
1314+
ETH_RSS_NONFRAG_IPV6_TCP |
1315+
ETH_RSS_NONFRAG_IPV6_UDP;
12021316
}
12031317

12041318
/*

lua/gatekeeper/staticlib.lua

+1
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ struct gatekeeper_if {
284284
bool ipv6_hw_udp_cksum;
285285
bool ipv4_hw_cksum;
286286
bool guarantee_random_entropy;
287+
bool alternative_rss_hash;
287288
/* This struct has hidden fields. */
288289
};
289290

lua/net.lua

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ return function (gatekeeper_server)
4747
local back_ipv6_hw_udp_cksum = true
4848
local front_ipv4_hw_cksum = true
4949
local back_ipv4_hw_cksum = true
50+
local front_alternative_rss_hash = false
51+
local back_alternative_rss_hash = false
5052

5153
--
5254
-- End configuration of the network.
@@ -76,6 +78,7 @@ return function (gatekeeper_server)
7678
front_iface.ipv6_hw_udp_cksum = front_ipv6_hw_udp_cksum
7779
front_iface.ipv4_hw_cksum = front_ipv4_hw_cksum
7880
front_iface.guarantee_random_entropy = guarantee_random_entropy
81+
front_iface.alternative_rss_hash = front_alternative_rss_hash
7982
local ret = staticlib.init_iface(front_iface, "front",
8083
front_ports, front_ips, front_ipv4_vlan_tag,
8184
front_ipv6_vlan_tag)
@@ -99,6 +102,7 @@ return function (gatekeeper_server)
99102
back_iface.ipv6_hw_udp_cksum = back_ipv6_hw_udp_cksum
100103
back_iface.ipv4_hw_cksum = back_ipv4_hw_cksum
101104
back_iface.guarantee_random_entropy = guarantee_random_entropy
105+
back_iface.alternative_rss_hash = back_alternative_rss_hash
102106
ret = staticlib.init_iface(back_iface, "back",
103107
back_ports, back_ips, back_ipv4_vlan_tag,
104108
back_ipv6_vlan_tag)

0 commit comments

Comments
 (0)