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 | (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 | (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 | (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_udp_hdr - fill the UDP RSS protocol header |
61 | * @hdr: the virtchnl message protocol header data structure |
62 | * @hash_flds: the RSS configuration protocol hash fields |
63 | */ |
64 | static void |
65 | (struct virtchnl_proto_hdr *hdr, u64 hash_flds) |
66 | { |
67 | VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, UDP); |
68 | |
69 | if (hash_flds & IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT) |
70 | VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, SRC_PORT); |
71 | |
72 | if (hash_flds & IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT) |
73 | VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, UDP, DST_PORT); |
74 | } |
75 | |
76 | /** |
77 | * iavf_fill_adv_rss_sctp_hdr - fill the SCTP RSS protocol header |
78 | * @hdr: the virtchnl message protocol header data structure |
79 | * @hash_flds: the RSS configuration protocol hash fields |
80 | */ |
81 | static void |
82 | (struct virtchnl_proto_hdr *hdr, u64 hash_flds) |
83 | { |
84 | VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, SCTP); |
85 | |
86 | if (hash_flds & IAVF_ADV_RSS_HASH_FLD_SCTP_SRC_PORT) |
87 | VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, SRC_PORT); |
88 | |
89 | if (hash_flds & IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT) |
90 | VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, SCTP, DST_PORT); |
91 | } |
92 | |
93 | /** |
94 | * iavf_fill_adv_rss_cfg_msg - fill the RSS configuration into virtchnl message |
95 | * @rss_cfg: the virtchnl message to be filled with RSS configuration setting |
96 | * @packet_hdrs: the RSS configuration protocol header types |
97 | * @hash_flds: the RSS configuration protocol hash fields |
98 | * |
99 | * Returns 0 if the RSS configuration virtchnl message is filled successfully |
100 | */ |
101 | int |
102 | (struct virtchnl_rss_cfg *, |
103 | u32 packet_hdrs, u64 hash_flds) |
104 | { |
105 | struct virtchnl_proto_hdrs *proto_hdrs = &rss_cfg->proto_hdrs; |
106 | struct virtchnl_proto_hdr *hdr; |
107 | |
108 | rss_cfg->rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC; |
109 | |
110 | proto_hdrs->tunnel_level = 0; /* always outer layer */ |
111 | |
112 | hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; |
113 | switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L3) { |
114 | case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4: |
115 | iavf_fill_adv_rss_ip4_hdr(hdr, hash_flds); |
116 | break; |
117 | case IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6: |
118 | iavf_fill_adv_rss_ip6_hdr(hdr, hash_flds); |
119 | break; |
120 | default: |
121 | return -EINVAL; |
122 | } |
123 | |
124 | hdr = &proto_hdrs->proto_hdr[proto_hdrs->count++]; |
125 | switch (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_L4) { |
126 | case IAVF_ADV_RSS_FLOW_SEG_HDR_TCP: |
127 | iavf_fill_adv_rss_tcp_hdr(hdr, hash_flds); |
128 | break; |
129 | case IAVF_ADV_RSS_FLOW_SEG_HDR_UDP: |
130 | iavf_fill_adv_rss_udp_hdr(hdr, hash_flds); |
131 | break; |
132 | case IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP: |
133 | iavf_fill_adv_rss_sctp_hdr(hdr, hash_flds); |
134 | break; |
135 | default: |
136 | return -EINVAL; |
137 | } |
138 | |
139 | return 0; |
140 | } |
141 | |
142 | /** |
143 | * iavf_find_adv_rss_cfg_by_hdrs - find RSS configuration with header type |
144 | * @adapter: pointer to the VF adapter structure |
145 | * @packet_hdrs: protocol header type to find. |
146 | * |
147 | * Returns pointer to advance RSS configuration if found or null |
148 | */ |
149 | struct iavf_adv_rss * |
150 | (struct iavf_adapter *adapter, u32 packet_hdrs) |
151 | { |
152 | struct iavf_adv_rss *; |
153 | |
154 | list_for_each_entry(rss, &adapter->adv_rss_list_head, list) |
155 | if (rss->packet_hdrs == packet_hdrs) |
156 | return rss; |
157 | |
158 | return NULL; |
159 | } |
160 | |
161 | /** |
162 | * iavf_print_adv_rss_cfg |
163 | * @adapter: pointer to the VF adapter structure |
164 | * @rss: pointer to the advance RSS configuration to print |
165 | * @action: the string description about how to handle the RSS |
166 | * @result: the string description about the virtchnl result |
167 | * |
168 | * Print the advance RSS configuration |
169 | **/ |
170 | void |
171 | (struct iavf_adapter *adapter, struct iavf_adv_rss *, |
172 | const char *action, const char *result) |
173 | { |
174 | u32 packet_hdrs = rss->packet_hdrs; |
175 | u64 hash_flds = rss->hash_flds; |
176 | static char hash_opt[300]; |
177 | const char *proto; |
178 | |
179 | if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_TCP) |
180 | proto = "TCP" ; |
181 | else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_UDP) |
182 | proto = "UDP" ; |
183 | else if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP) |
184 | proto = "SCTP" ; |
185 | else |
186 | return; |
187 | |
188 | memset(hash_opt, 0, sizeof(hash_opt)); |
189 | |
190 | strcat(p: hash_opt, q: proto); |
191 | if (packet_hdrs & IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4) |
192 | strcat(p: hash_opt, q: "v4 " ); |
193 | else |
194 | strcat(p: hash_opt, q: "v6 " ); |
195 | |
196 | if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_SA | |
197 | IAVF_ADV_RSS_HASH_FLD_IPV6_SA)) |
198 | strcat(p: hash_opt, q: "IP SA," ); |
199 | if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_DA | |
200 | IAVF_ADV_RSS_HASH_FLD_IPV6_DA)) |
201 | strcat(p: hash_opt, q: "IP DA," ); |
202 | if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT | |
203 | IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT | |
204 | IAVF_ADV_RSS_HASH_FLD_SCTP_SRC_PORT)) |
205 | strcat(p: hash_opt, q: "src port," ); |
206 | if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT | |
207 | IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT | |
208 | IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT)) |
209 | strcat(p: hash_opt, q: "dst port," ); |
210 | |
211 | if (!action) |
212 | action = "" ; |
213 | |
214 | if (!result) |
215 | result = "" ; |
216 | |
217 | dev_info(&adapter->pdev->dev, "%s %s %s\n" , action, hash_opt, result); |
218 | } |
219 | |