iavf_adv_rss.c 6.3 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
// 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);
}

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/**
 * 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);
}

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/**
 * 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);
}

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
/**
 * 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;
129 130 131
	case IAVF_ADV_RSS_FLOW_SEG_HDR_UDP:
		iavf_fill_adv_rss_udp_hdr(hdr, hash_flds);
		break;
132 133 134
	case IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP:
		iavf_fill_adv_rss_sctp_hdr(hdr, hash_flds);
		break;
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 171 172 173 174 175 176 177 178 179 180
	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";
181 182
	else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_UDP)
		proto = "UDP";
183 184
	else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP)
		proto = "SCTP";
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	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,");
202
	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT |
203 204
			 IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT |
			 IAVF_ADV_RSS_HASH_FLD_SCTP_SRC_PORT))
205
		strcat(hash_opt, "src port,");
206
	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT |
207 208
			 IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT |
			 IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT))
209 210 211 212 213 214 215 216 217 218
		strcat(hash_opt, "dst port,");

	if (!action)
		action = "";

	if (!result)
		result = "";

	dev_info(&adapter->pdev->dev, "%s %s %s\n", action, hash_opt, result);
}