1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021, Intel Corporation. */
3 
4 /* advanced RSS configuration ethtool support for iavf */
5 
6 #include "iavf.h"
7 
8 /**
9  * iavf_fill_adv_rss_ip4_hdr - fill the IPv4 RSS protocol header
10  * @hdr: the virtchnl message protocol header data structure
11  * @hash_flds: the RSS configuration protocol hash fields
12  */
13 static void
14 iavf_fill_adv_rss_ip4_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
15 {
16 	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV4);
17 
18 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV4_SA)
19 		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, SRC);
20 
21 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV4_DA)
22 		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
23 }
24 
25 /**
26  * iavf_fill_adv_rss_ip6_hdr - fill the IPv6 RSS protocol header
27  * @hdr: the virtchnl message protocol header data structure
28  * @hash_flds: the RSS configuration protocol hash fields
29  */
30 static void
31 iavf_fill_adv_rss_ip6_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
32 {
33 	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, IPV6);
34 
35 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV6_SA)
36 		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, SRC);
37 
38 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_IPV6_DA)
39 		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
40 }
41 
42 /**
43  * iavf_fill_adv_rss_tcp_hdr - fill the TCP RSS protocol header
44  * @hdr: the virtchnl message protocol header data structure
45  * @hash_flds: the RSS configuration protocol hash fields
46  */
47 static void
48 iavf_fill_adv_rss_tcp_hdr(struct virtchnl_proto_hdr *hdr, u64 hash_flds)
49 {
50 	VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, TCP);
51 
52 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT)
53 		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, SRC_PORT);
54 
55 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT)
56 		VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, TCP, DST_PORT);
57 }
58 
59 /**
60  * iavf_fill_adv_rss_cfg_msg - fill the RSS configuration into virtchnl message
61  * @rss_cfg: the virtchnl message to be filled with RSS configuration setting
62  * @packet_hdrs: the RSS configuration protocol header types
63  * @hash_flds: the RSS configuration protocol hash fields
64  *
65  * Returns 0 if the RSS configuration virtchnl message is filled successfully
66  */
67 int
68 iavf_fill_adv_rss_cfg_msg(struct virtchnl_rss_cfg *rss_cfg,
69 			  u32 packet_hdrs, u64 hash_flds)
70 {
71 	struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs;
72 	struct virtchnl_proto_hdr *hdr;
73 
74 	rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
75 
76 	proto_hdrs->tunnel_level = 0;	/* always outer layer */
77 
78 	hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
79 	switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L3) {
80 	case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4:
81 		iavf_fill_adv_rss_ip4_hdr(hdr, hash_flds);
82 		break;
83 	case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6:
84 		iavf_fill_adv_rss_ip6_hdr(hdr, hash_flds);
85 		break;
86 	default:
87 		return -EINVAL;
88 	}
89 
90 	hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
91 	switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L4) {
92 	case IAVF_ADV_RSS_FLOW_SEG_HDR_TCP:
93 		iavf_fill_adv_rss_tcp_hdr(hdr, hash_flds);
94 		break;
95 	default:
96 		return -EINVAL;
97 	}
98 
99 	return 0;
100 }
101 
102 /**
103  * iavf_find_adv_rss_cfg_by_hdrs - find RSS configuration with header type
104  * @adapter: pointer to the VF adapter structure
105  * @packet_hdrs: protocol header type to find.
106  *
107  * Returns pointer to advance RSS configuration if found or null
108  */
109 struct iavf_adv_rss *
110 iavf_find_adv_rss_cfg_by_hdrs(struct iavf_adapter *adapter, u32 packet_hdrs)
111 {
112 	struct iavf_adv_rss *rss;
113 
114 	list_for_each_entry(rss, &adapter->adv_rss_list_head, list)
115 		if (rss->packet_hdrs == packet_hdrs)
116 			return rss;
117 
118 	return NULL;
119 }
120 
121 /**
122  * iavf_print_adv_rss_cfg
123  * @adapter: pointer to the VF adapter structure
124  * @rss: pointer to the advance RSS configuration to print
125  * @action: the string description about how to handle the RSS
126  * @result: the string description about the virtchnl result
127  *
128  * Print the advance RSS configuration
129  **/
130 void
131 iavf_print_adv_rss_cfg(struct iavf_adapter *adapter, struct iavf_adv_rss *rss,
132 		       const char *action, const char *result)
133 {
134 	u32 packet_hdrs = rss->packet_hdrs;
135 	u64 hash_flds = rss->hash_flds;
136 	static char hash_opt[300];
137 	const char *proto;
138 
139 	if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_TCP)
140 		proto = "TCP";
141 	else
142 		return;
143 
144 	memset(hash_opt, 0, sizeof(hash_opt));
145 
146 	strcat(hash_opt, proto);
147 	if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4)
148 		strcat(hash_opt, "v4 ");
149 	else
150 		strcat(hash_opt, "v6 ");
151 
152 	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_SA |
153 			 IAVF_ADV_RSS_HASH_FLD_IPV6_SA))
154 		strcat(hash_opt, "IP SA,");
155 	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_DA |
156 			 IAVF_ADV_RSS_HASH_FLD_IPV6_DA))
157 		strcat(hash_opt, "IP DA,");
158 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT)
159 		strcat(hash_opt, "src port,");
160 	if (hash_flds & IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT)
161 		strcat(hash_opt, "dst port,");
162 
163 	if (!action)
164 		action = "";
165 
166 	if (!result)
167 		result = "";
168 
169 	dev_info(&adapter->pdev->dev, "%s %s %s\n", action, hash_opt, result);
170 }
171