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