mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
6.3 KiB
218 lines
6.3 KiB
// 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); |
|
}
|
|
|