iavf_adv_rss.c 4.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
// 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_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;
	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
		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)
		strcat(hash_opt, "src port,");
	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_TCP_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);
}