Skip to content

Commit 28f50eb

Browse files
committed
Merge branch 'hv_netvsc-TCP-hash-level'
Haiyang Zhang says: ==================== hv_netvsc: support changing TCP hash level The patch set simplifies the existing hash level switching code for UDP. It also adds the support for changing TCP hash level. So users can switch between L3 an L4 hash levels for TCP and UDP. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents c1b85a1 + 78005d9 commit 28f50eb

File tree

3 files changed

+86
-29
lines changed

3 files changed

+86
-29
lines changed

Documentation/networking/netvsc.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ Features
1919

2020
Receive Side Scaling
2121
--------------------
22-
Hyper-V supports receive side scaling. For TCP, packets are
23-
distributed among available queues based on IP address and port
22+
Hyper-V supports receive side scaling. For TCP & UDP, packets can
23+
be distributed among available queues based on IP address and port
2424
number.
2525

26-
For UDP, we can switch UDP hash level between L3 and L4 by ethtool
27-
command. UDP over IPv4 and v6 can be set differently. The default
26+
For TCP & UDP, we can switch hash level between L3 and L4 by ethtool
27+
command. TCP/UDP over IPv4 and v6 can be set differently. The default
2828
hash level is L4. We currently only allow switching TX hash level
2929
from within the guests.
3030

drivers/net/hyperv/hyperv_net.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,14 @@ struct netvsc_reconfig {
704704
u32 event;
705705
};
706706

707+
/* L4 hash bits for different protocols */
708+
#define HV_TCP4_L4HASH 1
709+
#define HV_TCP6_L4HASH 2
710+
#define HV_UDP4_L4HASH 4
711+
#define HV_UDP6_L4HASH 8
712+
#define HV_DEFAULT_L4HASH (HV_TCP4_L4HASH | HV_TCP6_L4HASH | HV_UDP4_L4HASH | \
713+
HV_UDP6_L4HASH)
714+
707715
/* The context of the netvsc device */
708716
struct net_device_context {
709717
/* point back to our device context */
@@ -726,10 +734,9 @@ struct net_device_context {
726734
u32 tx_send_table[VRSS_SEND_TAB_SIZE];
727735

728736
/* Ethtool settings */
729-
bool udp4_l4_hash;
730-
bool udp6_l4_hash;
731737
u8 duplex;
732738
u32 speed;
739+
u32 l4_hash; /* L4 hash settings */
733740
struct netvsc_ethtool_stats eth_stats;
734741

735742
/* State to manage the associated VF interface. */

drivers/net/hyperv/netvsc_drv.c

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,33 @@ static inline u32 netvsc_get_hash(
203203
const struct net_device_context *ndc)
204204
{
205205
struct flow_keys flow;
206-
u32 hash;
206+
u32 hash, pkt_proto = 0;
207207
static u32 hashrnd __read_mostly;
208208

209209
net_get_random_once(&hashrnd, sizeof(hashrnd));
210210

211211
if (!skb_flow_dissect_flow_keys(skb, &flow, 0))
212212
return 0;
213213

214-
if (flow.basic.ip_proto == IPPROTO_TCP ||
215-
(flow.basic.ip_proto == IPPROTO_UDP &&
216-
((flow.basic.n_proto == htons(ETH_P_IP) && ndc->udp4_l4_hash) ||
217-
(flow.basic.n_proto == htons(ETH_P_IPV6) &&
218-
ndc->udp6_l4_hash)))) {
214+
switch (flow.basic.ip_proto) {
215+
case IPPROTO_TCP:
216+
if (flow.basic.n_proto == htons(ETH_P_IP))
217+
pkt_proto = HV_TCP4_L4HASH;
218+
else if (flow.basic.n_proto == htons(ETH_P_IPV6))
219+
pkt_proto = HV_TCP6_L4HASH;
220+
221+
break;
222+
223+
case IPPROTO_UDP:
224+
if (flow.basic.n_proto == htons(ETH_P_IP))
225+
pkt_proto = HV_UDP4_L4HASH;
226+
else if (flow.basic.n_proto == htons(ETH_P_IPV6))
227+
pkt_proto = HV_UDP6_L4HASH;
228+
229+
break;
230+
}
231+
232+
if (pkt_proto & ndc->l4_hash) {
219233
return skb_get_hash(skb);
220234
} else {
221235
if (flow.basic.n_proto == htons(ETH_P_IP))
@@ -898,8 +912,7 @@ static void netvsc_init_settings(struct net_device *dev)
898912
{
899913
struct net_device_context *ndc = netdev_priv(dev);
900914

901-
ndc->udp4_l4_hash = true;
902-
ndc->udp6_l4_hash = true;
915+
ndc->l4_hash = HV_DEFAULT_L4HASH;
903916

904917
ndc->speed = SPEED_UNKNOWN;
905918
ndc->duplex = DUPLEX_FULL;
@@ -1245,23 +1258,32 @@ static int
12451258
netvsc_get_rss_hash_opts(struct net_device_context *ndc,
12461259
struct ethtool_rxnfc *info)
12471260
{
1261+
const u32 l4_flag = RXH_L4_B_0_1 | RXH_L4_B_2_3;
1262+
12481263
info->data = RXH_IP_SRC | RXH_IP_DST;
12491264

12501265
switch (info->flow_type) {
12511266
case TCP_V4_FLOW:
1267+
if (ndc->l4_hash & HV_TCP4_L4HASH)
1268+
info->data |= l4_flag;
1269+
1270+
break;
1271+
12521272
case TCP_V6_FLOW:
1253-
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1273+
if (ndc->l4_hash & HV_TCP6_L4HASH)
1274+
info->data |= l4_flag;
1275+
12541276
break;
12551277

12561278
case UDP_V4_FLOW:
1257-
if (ndc->udp4_l4_hash)
1258-
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1279+
if (ndc->l4_hash & HV_UDP4_L4HASH)
1280+
info->data |= l4_flag;
12591281

12601282
break;
12611283

12621284
case UDP_V6_FLOW:
1263-
if (ndc->udp6_l4_hash)
1264-
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1285+
if (ndc->l4_hash & HV_UDP6_L4HASH)
1286+
info->data |= l4_flag;
12651287

12661288
break;
12671289

@@ -1302,23 +1324,51 @@ static int netvsc_set_rss_hash_opts(struct net_device_context *ndc,
13021324
{
13031325
if (info->data == (RXH_IP_SRC | RXH_IP_DST |
13041326
RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1305-
if (info->flow_type == UDP_V4_FLOW)
1306-
ndc->udp4_l4_hash = true;
1307-
else if (info->flow_type == UDP_V6_FLOW)
1308-
ndc->udp6_l4_hash = true;
1309-
else
1327+
switch (info->flow_type) {
1328+
case TCP_V4_FLOW:
1329+
ndc->l4_hash |= HV_TCP4_L4HASH;
1330+
break;
1331+
1332+
case TCP_V6_FLOW:
1333+
ndc->l4_hash |= HV_TCP6_L4HASH;
1334+
break;
1335+
1336+
case UDP_V4_FLOW:
1337+
ndc->l4_hash |= HV_UDP4_L4HASH;
1338+
break;
1339+
1340+
case UDP_V6_FLOW:
1341+
ndc->l4_hash |= HV_UDP6_L4HASH;
1342+
break;
1343+
1344+
default:
13101345
return -EOPNOTSUPP;
1346+
}
13111347

13121348
return 0;
13131349
}
13141350

13151351
if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
1316-
if (info->flow_type == UDP_V4_FLOW)
1317-
ndc->udp4_l4_hash = false;
1318-
else if (info->flow_type == UDP_V6_FLOW)
1319-
ndc->udp6_l4_hash = false;
1320-
else
1352+
switch (info->flow_type) {
1353+
case TCP_V4_FLOW:
1354+
ndc->l4_hash &= ~HV_TCP4_L4HASH;
1355+
break;
1356+
1357+
case TCP_V6_FLOW:
1358+
ndc->l4_hash &= ~HV_TCP6_L4HASH;
1359+
break;
1360+
1361+
case UDP_V4_FLOW:
1362+
ndc->l4_hash &= ~HV_UDP4_L4HASH;
1363+
break;
1364+
1365+
case UDP_V6_FLOW:
1366+
ndc->l4_hash &= ~HV_UDP6_L4HASH;
1367+
break;
1368+
1369+
default:
13211370
return -EOPNOTSUPP;
1371+
}
13221372

13231373
return 0;
13241374
}

0 commit comments

Comments
 (0)