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