1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef PLATFORMS_NEMORA_PORTABLE_NCSI_CLIENT_H_
18 #define PLATFORMS_NEMORA_PORTABLE_NCSI_CLIENT_H_
19 
20 /*
21  * Client module for interacting with NC-SI capable network cards.
22  *
23  * DMTF v1.0.0 NC-SI specification:
24  * http://www.dmtf.org/sites/default/files/standards/documents/DSP0222_1.0.0.pdf
25  */
26 
27 #include <stdbool.h>
28 #include <stdint.h>
29 
30 #include "platforms/nemora/portable/ncsi.h"
31 #include "platforms/nemora/portable/net_types.h"
32 
33 #define CHANNEL_0_ID 0
34 #define CHANNEL_1_ID 1
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 /*
41  * Return the state of our connection to the NIC. Does not map to NC-SI spec.
42  * TODO remove this function from here. It is neither defined nor used
43  * in ncsi_client.c.
44  */
45 ncsi_connection_state_t ncsi_connection_state(void);
46 
47 /*
48  * Return the expected length for the response to a given NC-SI comamnds
49  *
50  * Args:
51  *  cmd_type: id for the given commands as defined in the NC-SI spec
52  *
53  * Caveat: returns 0 for commands that have not been implemented yet or for
54  *         NCSI_OEM_COMMAND.
55  */
56 uint32_t ncsi_get_response_size(uint8_t cmd_type);
57 
58 /*
59  * Return the expected length for the response to a given OEM NC-SI comamnds
60  *
61  * Args:
62  *  oem_cmd_type: id for the given OEM command as defined in the
63  *                ncsi_oem_extension_header_t (and not to be confused with the
64  *                id of standard commands)
65  */
66 uint32_t ncsi_oem_get_response_size(uint8_t oem_cmd_type);
67 
68 /*
69  * The following commands write the message to the buffer provided.
70  * The length of the message (including the ethernet header and padding) is
71  * returned.
72  */
73 
74 /* Standard NC-SI commands */
75 
76 /*
77  * Construct MAC address filtering command. 8.4.15
78  *
79  * Args:
80  *  buf: buffer of length >= sizeof(ncsi_set_mac_command_t) where command will
81  *       be placed.
82  *  channel: NC-SI channel to filter on (corresponds to a physical port).
83  *  mac_filter: MAC address to match against incoming traffic.
84  */
85 uint32_t ncsi_cmd_set_mac(uint8_t* buf, uint8_t channel,
86                           mac_addr_t* mac_filter);
87 
88 /*
89  * Construct clear initial state command. 8.4.3
90  *
91  * Args:
92  *  buf: buffer of length >= sizeof(ncsi_simple_command_t) where command will be
93  *       placed.
94  *  channel: NC-SI channel targeted (corresponds to a physical port).
95  */
96 uint32_t ncsi_cmd_clear_initial_state(uint8_t* buf, uint8_t channel);
97 
98 /*
99  * Construct enable broadcast filter command. 8.4.33
100  *
101  * Args:
102  *  filter_settings: filter mask (host order).
103  */
104 uint32_t ncsi_cmd_enable_broadcast_filter(uint8_t* buf, uint8_t channel,
105                                           uint32_t filter_settings);
106 /*
107  * Construct disable broadcast filter command. 8.4.35
108  *
109  * Note: disable filtering == allow forwarding of broadcast traffic
110  *
111  * Args:
112  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
113  *  channel: NC-SI channel targeted (corresponds to a physical port).
114  */
115 uint32_t ncsi_cmd_disable_broadcast_filter(uint8_t* buf, uint8_t channel);
116 
117 /*
118  * Construct enable channel command. 8.4.9
119  *
120  * Required before any NC-SI passthrough traffic will go in or out of that
121  * channel.
122  *
123  * Args:
124  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
125  *  channel: NC-SI channel targeted (corresponds to a physical port).
126  */
127 uint32_t ncsi_cmd_enable_channel(uint8_t* buf, uint8_t channel);
128 
129 /*
130  * Construct reset channel command. 8.4.13
131  *
132  * Put channel into its initial state
133  *
134  * Args:
135  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
136  *  channel: NC-SI channel targeted (corresponds to a physical port).
137  */
138 uint32_t ncsi_cmd_reset_channel(uint8_t* buf, uint8_t channel);
139 
140 /*
141  * Construct enable TX command. 8.4.15
142  *
143  * Args:
144  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
145  *  channel: NC-SI channel targeted (corresponds to a physical port).
146  */
147 uint32_t ncsi_cmd_enable_tx(uint8_t* buf, uint8_t channel);
148 
149 /*
150  * Construct get link status command. 8.4.23
151  *
152  * Args:
153  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
154  *  channel: NC-SI channel targeted (corresponds to a physical port).
155  */
156 uint32_t ncsi_cmd_get_link_status(uint8_t* buf, uint8_t channel);
157 
158 /*
159  * Construct get capabilities command. 8.4.44
160  *
161  * Args:
162  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
163  *  channel: NC-SI channel targeted (corresponds to a physical port).
164  */
165 uint32_t ncsi_cmd_get_version(uint8_t* buf, uint8_t channel);
166 
167 /*
168  * Construct get capabilities command. 8.4.45
169  *
170  * Args:
171  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
172  *  channel: NC-SI channel targeted (corresponds to a physical port).
173  */
174 uint32_t ncsi_cmd_get_capabilities(uint8_t* buf, uint8_t channel);
175 
176 /*
177  * Construct get parameters command. 8.4.47
178  *
179  * Args:
180  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
181  *  channel: NC-SI channel targeted (corresponds to a physical port).
182  */
183 uint32_t ncsi_cmd_get_parameters(uint8_t* buf, uint8_t channel);
184 
185 /*
186  * Construct get pass-through statistics. 8.4.53
187  *
188  * Args:
189  *  buf: buffer of length >= sizeof(ncsi_simple_command_t)
190  *  channel: NC-SI channel targeted (corresponds to a physical port).
191  */
192 uint32_t ncsi_cmd_get_passthrough_stats(uint8_t* buf, uint8_t channel);
193 
194 /* OEM commands */
195 // TODO: Move OEM commands to another file.
196 
197 /*
198  * Get Host MAC address. Query the NIC for its MAC address(es).
199  *
200  * Args:
201  *  buf: buffer of length >= sizeof(ncsi_oem_simple_cmd_t)
202  *  channel: NC-SI channel targeted (corresponds to a physical port).
203  */
204 uint32_t ncsi_oem_cmd_get_host_mac(uint8_t* buf, uint8_t channel);
205 
206 /*
207  * Get filter used for RX traffic.
208  */
209 uint32_t ncsi_oem_cmd_get_filter(uint8_t* buf, uint8_t channel);
210 
211 /*
212  * Set filter for RX traffic. Incoming packets that match all the fields
213  * specified here will be forwarded over the NC-SI link.
214  *
215  * Args:
216  *  buf: buffer of length >= sizeof(ncsi_oem_set_filter_cmd_t)
217  *  channel: NC-SI channel targeted (corresponds to a physical port).
218  *  mac: mac address to filter on (byte array in network order)
219  *  ip: IPv4 address to filter on (little-endian)
220  *  port: TCP/UDP port number to filter on (little-endian)
221  *  flags: bitfield of options.
222  */
223 uint32_t ncsi_oem_cmd_set_filter(uint8_t* buf, uint8_t channel, mac_addr_t* mac,
224                                  uint32_t ip, uint16_t port, uint8_t flags);
225 
226 /*
227  * Send NC-SI packet to test connectivity with NIC.
228  *
229  * Args:
230  *  buf: buffer of length >= sizeof(ncsi_oem_echo_cmd_t)
231  *  channel: NC-SI channel targeted (corresponds to a physical port).
232  *  pattern: echo payload.
233  */
234 uint32_t ncsi_oem_cmd_echo(uint8_t* buf, uint8_t channel,
235                            uint8_t pattern[NCSI_OEM_ECHO_PATTERN_SIZE]);
236 
237 /*
238  * Validate NC-SI response in the buffer and return validation result.
239  * Exposes "expected_size" as part of interface to handle legacy NICs. Avoid
240  * using this function directly, use ncsi_validate_std_response or
241  * ncsi_validate_oem_response instead.
242  *
243  * Args:
244  *  buf: buffer containint NC-SI response.
245  *  len: size of the response in the buffer.
246  *  cmd_type: Id of the command *that was sent* to NIC.
247  *  is_eom: true if the response in the buffer is OEM response.
248  *  expected_size: expected size of the response.
249  */
250 ncsi_response_type_t ncsi_validate_response(uint8_t* buf, uint32_t len,
251                                             uint8_t cmd_type, bool is_oem,
252                                             uint32_t expected_size);
253 /*
254  * Validate NC-SI response in the buffer and return validation result.
255  *
256  * Args:
257  *  buf: buffer containint NC-SI response.
258  *  len: size of the response in the buffer.
259  *  cmd_type: Id of the command *that was sent* to NIC.
260  */
261 ncsi_response_type_t ncsi_validate_std_response(uint8_t* buf, uint32_t len,
262                                                 uint8_t cmd_type);
263 
264 /*
265  * Validate NC-SI OEM response in the buffer and return validation result.
266  *
267  * Args:
268  *  buf: buffer containint NC-SI response.
269  *  len: size of the response in the buffer.
270  *  cmd_type: Id of the OEM command *that was sent* to NIC.
271  */
272 ncsi_response_type_t ncsi_validate_oem_response(uint8_t* buf, uint32_t len,
273                                                 uint8_t cmd_type);
274 
275 #ifdef __cplusplus
276 }  /* extern "C" */
277 #endif
278 
279 #endif  // PLATFORMS_NEMORA_PORTABLE_NCSI_CLIENT_H_
280