mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-29 05:55:02 +08:00
e41985f0fe
Provide the ability to enable SCTP RSS hashing by ethtool. It gives users option of generating RSS hash based on the SCTP source and destination ports numbers, IPv4 or IPv6 source and destination addresses. Signed-off-by: Haiyue Wang <haiyue.wang@intel.com> Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
219 lines
6.3 KiB
C
219 lines
6.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) 2021, Intel Corporation. */
|
|
|
|
/* advanced RSS configuration ethtool support for iavf */
|
|
|
|
#include "iavf.h"
|
|
|
|
/**
|
|
* iavf_fill_adv_rss_ip4_hdr - fill the IPv4 RSS protocol header
|
|
* @hdr: the virtchnl message protocol header data structure
|
|
* @hash_flds: the RSS configuration protocol hash fields
|
|
*/
|
|
static void
|
|
iavf_fill_adv_rss_ip4_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
|
|
{
|
|
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV4);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV4_SA)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, SRC);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV4_DA)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
|
|
}
|
|
|
|
/**
|
|
* iavf_fill_adv_rss_ip6_hdr - fill the IPv6 RSS protocol header
|
|
* @hdr: the virtchnl message protocol header data structure
|
|
* @hash_flds: the RSS configuration protocol hash fields
|
|
*/
|
|
static void
|
|
iavf_fill_adv_rss_ip6_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
|
|
{
|
|
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV6);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV6_SA)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, SRC);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV6_DA)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
|
|
}
|
|
|
|
/**
|
|
* iavf_fill_adv_rss_tcp_hdr - fill the TCP RSS protocol header
|
|
* @hdr: the virtchnl message protocol header data structure
|
|
* @hash_flds: the RSS configuration protocol hash fields
|
|
*/
|
|
static void
|
|
iavf_fill_adv_rss_tcp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
|
|
{
|
|
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, TCP);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, SRC_PORT);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, DST_PORT);
|
|
}
|
|
|
|
/**
|
|
* iavf_fill_adv_rss_udp_hdr - fill the UDP RSS protocol header
|
|
* @hdr: the virtchnl message protocol header data structure
|
|
* @hash_flds: the RSS configuration protocol hash fields
|
|
*/
|
|
static void
|
|
iavf_fill_adv_rss_udp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
|
|
{
|
|
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, UDP);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, SRC_PORT);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, DST_PORT);
|
|
}
|
|
|
|
/**
|
|
* iavf_fill_adv_rss_sctp_hdr - fill the SCTP RSS protocol header
|
|
* @hdr: the virtchnl message protocol header data structure
|
|
* @hash_flds: the RSS configuration protocol hash fields
|
|
*/
|
|
static void
|
|
iavf_fill_adv_rss_sctp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
|
|
{
|
|
VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, SCTP);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_SCTP_SRC_PORT)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, SRC_PORT);
|
|
|
|
if (hash_flds & IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT)
|
|
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, DST_PORT);
|
|
}
|
|
|
|
/**
|
|
* iavf_fill_adv_rss_cfg_msg - fill the RSS configuration into virtchnl message
|
|
* @rss_cfg: the virtchnl message to be filled with RSS configuration setting
|
|
* @packet_hdrs: the RSS configuration protocol header types
|
|
* @hash_flds: the RSS configuration protocol hash fields
|
|
*
|
|
* Returns 0 if the RSS configuration virtchnl message is filled successfully
|
|
*/
|
|
int
|
|
iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
|
|
u32 packet_hdrs, u64 hash_flds)
|
|
{
|
|
struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs;
|
|
struct virtchnl_proto_hdr *hdr;
|
|
|
|
rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
|
|
|
|
proto_hdrs->tunnel_level = 0; /* always outer layer */
|
|
|
|
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
|
|
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L3) {
|
|
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4:
|
|
iavf_fill_adv_rss_ip4_hdr(hdr, hash_flds);
|
|
break;
|
|
case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6:
|
|
iavf_fill_adv_rss_ip6_hdr(hdr, hash_flds);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
|
|
switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L4) {
|
|
case IAVF_ADV_RSS_FLOW_SEG_HDR_TCP:
|
|
iavf_fill_adv_rss_tcp_hdr(hdr, hash_flds);
|
|
break;
|
|
case IAVF_ADV_RSS_FLOW_SEG_HDR_UDP:
|
|
iavf_fill_adv_rss_udp_hdr(hdr, hash_flds);
|
|
break;
|
|
case IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP:
|
|
iavf_fill_adv_rss_sctp_hdr(hdr, hash_flds);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* iavf_find_adv_rss_cfg_by_hdrs - find RSS configuration with header type
|
|
* @adapter: pointer to the VF adapter structure
|
|
* @packet_hdrs: protocol header type to find.
|
|
*
|
|
* Returns pointer to advance RSS configuration if found or null
|
|
*/
|
|
struct iavf_adv_rss *
|
|
iavf_find_adv_rss_cfg_by_hdrs(struct iavf_adapter *adapter, u32 packet_hdrs)
|
|
{
|
|
struct iavf_adv_rss *rss;
|
|
|
|
list_for_each_entry(rss, &adapter->adv_rss_list_head, list)
|
|
if (rss->packet_hdrs == packet_hdrs)
|
|
return rss;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* iavf_print_adv_rss_cfg
|
|
* @adapter: pointer to the VF adapter structure
|
|
* @rss: pointer to the advance RSS configuration to print
|
|
* @action: the string description about how to handle the RSS
|
|
* @result: the string description about the virtchnl result
|
|
*
|
|
* Print the advance RSS configuration
|
|
**/
|
|
void
|
|
iavf_print_adv_rss_cfg(struct iavf_adapter *adapter, struct iavf_adv_rss *rss,
|
|
const char *action, const char *result)
|
|
{
|
|
u32 packet_hdrs = rss->packet_hdrs;
|
|
u64 hash_flds = rss->hash_flds;
|
|
static char hash_opt[300];
|
|
const char *proto;
|
|
|
|
if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_TCP)
|
|
proto = "TCP";
|
|
else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_UDP)
|
|
proto = "UDP";
|
|
else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP)
|
|
proto = "SCTP";
|
|
else
|
|
return;
|
|
|
|
memset(hash_opt, 0, sizeof(hash_opt));
|
|
|
|
strcat(hash_opt, proto);
|
|
if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4)
|
|
strcat(hash_opt, "v4 ");
|
|
else
|
|
strcat(hash_opt, "v6 ");
|
|
|
|
if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_SA |
|
|
IAVF_ADV_RSS_HASH_FLD_IPV6_SA))
|
|
strcat(hash_opt, "IP SA,");
|
|
if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_DA |
|
|
IAVF_ADV_RSS_HASH_FLD_IPV6_DA))
|
|
strcat(hash_opt, "IP DA,");
|
|
if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT |
|
|
IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT |
|
|
IAVF_ADV_RSS_HASH_FLD_SCTP_SRC_PORT))
|
|
strcat(hash_opt, "src port,");
|
|
if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT |
|
|
IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT |
|
|
IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT))
|
|
strcat(hash_opt, "dst port,");
|
|
|
|
if (!action)
|
|
action = "";
|
|
|
|
if (!result)
|
|
result = "";
|
|
|
|
dev_info(&adapter->pdev->dev, "%s %s %s\n", action, hash_opt, result);
|
|
}
|