xref: /openbmc/google-misc/subprojects/ncsid/src/platforms/nemora/portable/ncsi.h (revision 1285115c16180bd28a3cfe79d9db8d10c84fe2ed)
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_H_
18  #define PLATFORMS_NEMORA_PORTABLE_NCSI_H_
19  
20  /*
21   * 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/net_types.h"
31  
32  #ifdef __cplusplus
33  extern "C" {
34  #endif
35  
36  #ifndef __packed
37  #define __packed __attribute__((packed))
38  #endif
39  
40  // Define states for our NC-SI connection to the NIC.
41  // There is no mapping to the NC-SI specification for these states, but they
42  // reflect the outcome of NC-SI commands used in our configuration state
43  // machine.
44  //
45  // 'DOWN' - while in this state, periodically restart the configuration state
46  //   machine until it succeeds.
47  // 'LOOPBACK' - the response to the first NC-SI command of the configuration
48  //   state machine was identical to the command: from this we infer we are in
49  //   loopback. While in this state, periodically restart the configuration state
50  //   machine.
51  // 'UP' - all commands were responded successfully, but need DHCP configuration
52  //   to go to the next state. While in this state, the connection is tested
53  //   periodically for failures, which can bring back to 'DOWN'.
54  // 'UP_AND_CONFIGURED' - NC-SI OEM commands for L3/L4 configuration (which
55  //   depend on DHCP configuration) were responded successfully. While in this
56  //   state, the connection and configuration are tested periodically for
57  //   failures, which can bring back to 'DOWN'.
58  // 'DISABLED' - reset default state. As soon as network is enabled (which
59  //   noticeably means that ProdID must be disabled), the state goes to DOWN.
60  // TODO: connection state has nothing to do with ncsi protocol and needs
61  // to be moved to ncsi_fsm.h. The main problem with the move is that
62  // ncsi_client.h defines an extern function with this return type, that is used
63  // in a lot of places that have no business including ncsi_fsm.h
64  typedef enum {
65    NCSI_CONNECTION_DOWN,
66    NCSI_CONNECTION_LOOPBACK,
67    NCSI_CONNECTION_UP,
68    NCSI_CONNECTION_UP_AND_CONFIGURED,
69    NCSI_CONNECTION_DISABLED,
70  } ncsi_connection_state_t;
71  
72  typedef enum {
73    NCSI_RESPONSE_NONE,
74    NCSI_RESPONSE_ACK,
75    NCSI_RESPONSE_NACK,
76    NCSI_RESPONSE_UNDERSIZED,
77    NCSI_RESPONSE_UNEXPECTED_TYPE,
78    NCSI_RESPONSE_UNEXPECTED_SIZE,
79    NCSI_RESPONSE_OEM_FORMAT_ERROR,
80    NCSI_RESPONSE_TIMEOUT,
81    NCSI_RESPONSE_UNEXPECTED_PARAMS,
82  } ncsi_response_type_t;
83  
84  // For NC-SI Rev 1.0.0, the management controller ID (mc_id) is 0.
85  #define NCSI_MC_ID 0
86  // For NC-SI Rev 1.0.0, the header revision is 0x01.
87  #define NCSI_HEADER_REV 1
88  #define NCSI_ETHERTYPE 0x88F8
89  #define NCSI_RESPONSE 0x80
90  
91  // Command IDs
92  enum {
93    NCSI_CLEAR_INITIAL_STATE,
94    NCSI_SELECT_PACKAGE,
95    NCSI_DESELECT_PACKAGE,
96    NCSI_ENABLE_CHANNEL,
97    NCSI_DISABLE_CHANNEL,
98    NCSI_RESET_CHANNEL,
99    NCSI_ENABLE_CHANNEL_NETWORK_TX,
100    NCSI_DISABLE_CHANNEL_NETWORK_TX,
101    NCSI_AEN_ENABLE,
102    NCSI_SET_LINK,
103    NCSI_GET_LINK_STATUS,
104    NCSI_SET_VLAN_FILTER,
105    NCSI_ENABLE_VLAN,
106    NCSI_DISABLE_VLAN,
107    NCSI_SET_MAC_ADDRESS,
108    // 0x0F is not a valid command
109    NCSI_ENABLE_BROADCAST_FILTER = 0x10,
110    NCSI_DISABLE_BROADCAST_FILTER,
111    NCSI_ENABLE_GLOBAL_MULTICAST_FILTER,
112    NCSI_DISABLE_GLOBAL_MULTICAST_FILTER,
113    NCSI_SET_NCSI_FLOW_CONTROL,
114    NCSI_GET_VERSION_ID,
115    NCSI_GET_CAPABILITIES,
116    NCSI_GET_PARAMETERS,
117    NCSI_GET_CONTROLLER_PACKET_STATISTICS,
118    NCSI_GET_NCSI_STATISTICS,
119    NCSI_GET_PASSTHROUGH_STATISTICS,
120    // 0x1B-0x4F are not valid commands
121    NCSI_OEM_COMMAND = 0x50,
122  };
123  // OEM Command IDs (subtypes of NCSI_OEM_COMMAND)
124  #define NCSI_OEM_COMMAND_GET_HOST_MAC 0x00
125  #define NCSI_OEM_COMMAND_SET_FILTER 0x01
126  #define NCSI_OEM_COMMAND_GET_FILTER 0x02
127  #define NCSI_OEM_COMMAND_ECHO 0x03
128  
129  #define NCSI_OEM_MANUFACTURER_ID 11129  // IANA Enterprise Number for Google.
130  #define NCSI_OEM_ECHO_PATTERN_SIZE 64
131  
132  /*
133   * NCSI command frame with packet header as described in section 8.2.1.
134   * Prepended with an ethernet header.
135   */
136  typedef struct __packed {
137    eth_hdr_t ethhdr;
138    uint8_t mc_id;
139    uint8_t header_revision;
140    uint8_t reserved_00;
141    uint8_t instance_id;          // Destinguish retried commands from new ones.
142    uint8_t control_packet_type;  // See section 8.3, and Table 17.
143    uint8_t channel_id;
144    uint16_t payload_length;  // In Bytes. Excludes header, checksum, padding.
145    uint16_t reserved_01[4];
146  } ncsi_header_t;
147  
148  /*
149   * Simple NCSI response packet.
150   */
151  typedef struct __packed {
152    ncsi_header_t hdr;
153    uint16_t response_code;
154    uint16_t reason_code;
155  } ncsi_simple_response_t;
156  
157  /*
158   * Simple NCSI command packet.
159   */
160  typedef struct {
161    ncsi_header_t hdr;
162  } ncsi_simple_command_t;
163  
164  /*
165   * Get Link Status Response. 8.4.24
166   */
167  typedef struct __packed {
168    uint32_t link_status;
169    uint32_t other_indications;
170    uint32_t oem_link_status;
171  } ncsi_link_status_t;
172  
173  typedef struct __packed {
174    ncsi_header_t hdr;
175    uint16_t response_code;
176    uint16_t reason_code;
177    ncsi_link_status_t link_status;
178  } ncsi_link_status_response_t;
179  
180  #define NCSI_LINK_STATUS_UP (1 << 0)
181  
182  /*
183   * Set MAC Address packet. 8.4.31
184   */
185  typedef struct __packed {
186    ncsi_header_t hdr;
187    mac_addr_t mac_addr;
188    uint8_t mac_addr_num;
189    uint8_t misc;
190  } ncsi_set_mac_command_t;
191  
192  /*
193   * Enable Broadcast Filter packet. 8.4.33
194   */
195  typedef struct __packed {
196    ncsi_header_t hdr;
197    uint32_t filter_settings;
198  } ncsi_enable_broadcast_filter_command_t;
199  
200  #define NCSI_BROADCAST_FILTER_MASK_ARP         (1 << 0)
201  #define NCSI_BROADCAST_FILTER_MASK_DHCP_CLIENT (1 << 1)
202  #define NCSI_BROADCAST_FILTER_MASK_DHCP_SERVER (1 << 2)
203  #define NCSI_BROADCAST_FILTER_MASK_NETBIOS     (1 << 3)
204  
205  /*
206   * Get Version ID Response. 8.4.44
207   */
208  typedef struct __packed {
209    struct {
210      uint8_t major;
211      uint8_t minor;
212      uint8_t update;
213      uint8_t alpha1;
214      uint8_t reserved[3];
215      uint8_t alpha2;
216    } ncsi_version;
217    uint8_t firmware_name_string[12];
218    uint32_t firmware_version;
219    uint16_t pci_did;
220    uint16_t pci_vid;
221    uint16_t pci_ssid;
222    uint16_t pci_svid;
223    uint32_t manufacturer_id;
224  } ncsi_version_id_t;
225  
226  typedef struct __packed {
227    ncsi_header_t hdr;
228    uint16_t response_code;
229    uint16_t reason_code;
230    ncsi_version_id_t version;
231  } ncsi_version_id_response_t;
232  
233  /*
234   * Get Capabilities Response 8.4.46
235   */
236  typedef struct __packed {
237    ncsi_header_t hdr;
238    uint16_t response_code;
239    uint16_t reason_code;
240    uint32_t capabilities_flags;
241    uint32_t broadcast_packet_filter_capabilties;
242    uint32_t multicast_packet_filter_capabilties;
243    uint32_t buffering_capability;
244    uint32_t aen_control_support;
245    uint8_t vlan_filter_count;
246    uint8_t mixed_filter_count;
247    uint8_t multicast_filter_count;
248    uint8_t unicast_filter_count;
249    uint16_t reserved;
250    uint8_t vlan_mode_support;
251    uint8_t channel_count;
252  } ncsi_capabilities_response_t;
253  
254  /*
255   * Get Parameters Response 8.4.48
256   */
257  typedef struct __packed {
258    ncsi_header_t hdr;
259    uint16_t response_code;
260    uint16_t reason_code;
261    // TODO: Note: Mellanox 1.4 FW has mac count swapped with mac flags.
262    uint8_t mac_address_count;
263    uint16_t reserved_01;
264    uint8_t mac_address_flags;
265    uint8_t vlan_tag_count;
266    uint8_t reserved_02;
267    uint16_t vlan_tag_flags;
268    uint32_t link_settings;
269    uint32_t broadcast_settings;
270    uint32_t configuration_flags;
271    uint8_t vlan_mode;
272    uint8_t flow_control_enable;
273    uint16_t reserved_03;
274    uint32_t aen_control;
275    mac_addr_t mac_address[2];
276    // TODO: Variable number of mac address filters (max 8. See 8.4.48)
277    uint16_t vlan_tags[2];
278    // TODO: Variable of vlan filters (up to 15 based on 8.4.48)
279  } ncsi_parameters_response_t;
280  
281  /*
282   * Get Passthrough statistics response. 8.4.54
283   *
284   * The legacy data structure matches MLX implementation up to vX
285   * (Google vX), however the standard requires the first field to be
286   * 64bits and MLX fixed it in vX (Google vX).
287   *
288   */
289  typedef struct __packed {
290    uint32_t tx_packets_received;  // EC -> NIC
291    uint32_t tx_packets_dropped;
292    uint32_t tx_channel_errors;
293    uint32_t tx_undersized_errors;
294    uint32_t tx_oversized_errors;
295    uint32_t rx_packets_received;  // Network -> NIC
296    uint32_t rx_packets_dropped;
297    uint32_t rx_channel_errors;
298    uint32_t rx_undersized_errors;
299    uint32_t rx_oversized_errors;
300  } ncsi_passthrough_stats_legacy_t;
301  
302  typedef struct __packed {
303    uint32_t tx_packets_received_hi;  // EC -> NIC (higher 32bit)
304    uint32_t tx_packets_received_lo;  // EC -> NIC (lower 32bit)
305    uint32_t tx_packets_dropped;
306    uint32_t tx_channel_errors;
307    uint32_t tx_undersized_errors;
308    uint32_t tx_oversized_errors;
309    uint32_t rx_packets_received;  // Network -> NIC
310    uint32_t rx_packets_dropped;
311    uint32_t rx_channel_errors;
312    uint32_t rx_undersized_errors;
313    uint32_t rx_oversized_errors;
314  } ncsi_passthrough_stats_t;
315  
316  typedef struct __packed {
317    ncsi_header_t hdr;
318    uint16_t response_code;
319    uint16_t reason_code;
320    ncsi_passthrough_stats_legacy_t stats;
321  } ncsi_passthrough_stats_legacy_response_t;
322  
323  typedef struct __packed {
324    ncsi_header_t hdr;
325    uint16_t response_code;
326    uint16_t reason_code;
327    ncsi_passthrough_stats_t stats;
328  } ncsi_passthrough_stats_response_t;
329  
330  /*
331   * OEM extension header for custom commands.
332   */
333  typedef struct __packed {
334    uint32_t manufacturer_id;
335    uint8_t reserved[3];
336    uint8_t oem_cmd;
337  } ncsi_oem_extension_header_t;
338  
339  /*
340   * Response format for simple OEM command.
341   */
342  typedef struct __packed {
343    ncsi_header_t hdr;
344    uint16_t response_code;
345    uint16_t reason_code;
346    ncsi_oem_extension_header_t oem_header;
347  } ncsi_oem_simple_response_t;
348  
349  /*
350   * Response format for OEM get MAC command.
351   */
352  typedef struct __packed {
353    ncsi_header_t hdr;
354    uint16_t response_code;
355    uint16_t reason_code;
356    ncsi_oem_extension_header_t oem_header;
357    uint16_t reserved0;
358    uint8_t mac[6];
359  } ncsi_host_mac_response_t;
360  
361  /*
362   * Format for OEM filter.
363   */
364  typedef struct __packed {
365    uint16_t reserved0;
366    uint8_t mac[6];
367    // If ip is set to zero, the filter will match any IP address, including any
368    // IPv6 address.
369    uint32_t ip;  // Network order
370    uint16_t port;  // Network order
371    uint8_t reserved1;
372    uint8_t flags;
373    uint8_t regid[8];
374  } ncsi_oem_filter_t;
375  
376  // Set flags
377  #define NCSI_OEM_FILTER_FLAGS_ENABLE      (0x01)
378  
379  // Get flags
380  #define NCSI_OEM_FILTER_FLAGS_ENABLED     (0x01)
381  #define NCSI_OEM_FILTER_FLAGS_REGISTERED  (0x02)
382  #define NCSI_OEM_FILTER_FLAGS_HOSTLESS    (0x04)
383  
384  /*
385   * Command format for simple OEM command.
386   */
387  typedef struct __packed {
388    ncsi_header_t hdr;
389    ncsi_oem_extension_header_t oem_header;
390  } ncsi_oem_simple_cmd_t;
391  
392  /*
393   * Response format for OEM get filter command.
394   */
395  typedef struct __packed {
396    ncsi_header_t hdr;
397    uint16_t response_code;
398    uint16_t reason_code;
399    ncsi_oem_extension_header_t oem_header;
400    ncsi_oem_filter_t filter;
401  } ncsi_oem_get_filter_response_t;
402  
403  /*
404   * Command format for OEM set filter command.
405   */
406  typedef struct __packed {
407    ncsi_header_t hdr;
408    ncsi_oem_extension_header_t oem_header;
409    ncsi_oem_filter_t filter;
410  } ncsi_oem_set_filter_cmd_t;
411  
412  /*
413   * Command format for OEM echo command.
414   */
415  typedef struct __packed {
416    ncsi_header_t hdr;
417    ncsi_oem_extension_header_t oem_header;
418    uint8_t pattern[NCSI_OEM_ECHO_PATTERN_SIZE];
419  } ncsi_oem_echo_cmd_t;
420  
421  /*
422   * Response format for OEM echo command.
423   */
424  typedef struct __packed {
425    ncsi_header_t hdr;
426    uint16_t response_code;
427    uint16_t reason_code;
428    ncsi_oem_extension_header_t oem_header;
429    uint8_t pattern[NCSI_OEM_ECHO_PATTERN_SIZE];
430  } ncsi_oem_echo_response_t;
431  
432  #ifdef __cplusplus
433  }  /* extern "C" */
434  #endif
435  
436  #endif  // PLATFORMS_NEMORA_PORTABLE_NCSI_H_
437