/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* */ /* */ /* IBM CONFIDENTIAL */ /* */ /* OBJECT CODE ONLY SOURCE MATERIALS */ /* */ /* (C) COPYRIGHT International Business Machines Corp. 2000,2019 */ /* All Rights Reserved */ /* */ /* The source code for this program is not published or otherwise */ /* divested of its trade secrets, irrespective of what has been */ /* deposited with the U.S. Copyright Office. */ /* */ /* IBM_PROLOG_END_TAG */ /*****************************************************************************/ /* */ /* Topology Services Network Interface Module (NIM) */ /* */ /* nim_interface.h: this file contains the definitions and data */ /* structures that are used in the communication between the */ /* Topology Services daemon and the NIM processes. */ /* */ /* Communication between the daemon and the NIMs occurs through */ /* a Unix-Domain socket. A number of command, responses, and */ /* notifications is defined in this file. */ /* */ /*****************************************************************************/ /* sccsid = "@(#)24 1.21 src/rsct/pts/pam/nim/nim_interface.h, topology.services, rsct_rady, rady2035a 1/18/18 07:18:26" */ #ifndef _NIM_INTERFACE_h #define _NIM_INTERFACE_h #ifdef __cplusplus extern "C" { #endif /* * Includes */ #include /* 64-bit types (in AIX inttypes.h warns against including this file directly, but this file seems to be the only one that is common in AIX and Linux and has 64-bit data type definitions) */ #include /* for ushort */ #include /* needed by if.h */ #include /* for IFNAMSIZ */ #include /* sockaddr_in */ #include #if defined(_AIX) || defined(__sun) /* AIX or SUN */ #pragma pack(4) /* produce 4-byte aligned data structure */ #elif defined(__linux__) || defined(__INTERIX) /* Linux or Interix */ #pragma pack(push) /* to save the previous pack configuration */ #pragma pack(4) /* produce 4-byte aligned data structure */ #endif /* * Return codes of the NIM process * * Values 1--100 are reserved for errno in the exec() call */ #define HA_NIM_EXIT_OK 0 /* OK (NIM was told to exit) */ #define HA_NIM_EXIT_UDS_CONN 101 /* cannot connect to Unix-domain socket */ #define HA_NIM_EXIT_INT_ERR 102 /* NIM internal error */ #define HA_NIM_EXIT_INV_PAR 103 /* invalid parameter to NIM */ /* * Types of messages exchanged between the HATS daemon and the NIM */ typedef enum { /* HATS daemon -> NIM */ HA_NIM_OPEN = 1, /* open connection to local adapter */ HA_NIM_CLOSE, /* close connection with local adapter */ HA_NIM_START_HB, /* start sending heartbeats */ HA_NIM_MONITOR_HB, /* start monitoring heartbeats */ HA_NIM_SEND_MSG, /* send a message to a peer daemon */ HA_NIM_STOP_HB, /* stop sending heartbeats */ HA_NIM_STOP_MONITOR, /* stop monitoring heartbeats */ HA_NIM_ARE_YOU_ALIVE, /* requests response from NIM */ HA_NIM_EXIT, /* exit */ HA_NIM_DMS_START, /* start updating DMS timer */ HA_NIM_DMS_STOP, /* stop updating DMS timer */ HA_NIM_START_THREAD_REPORTS, /* begin reporting thread blockage */ HA_NIM_STOP_THREAD_REPORTS, /* quit reporting thread blockage */ /* NIM -> HATS daemon */ HA_NIM_OPEN_RESPONSE = 30, /* response to open -- need room for expansion */ HA_NIM_ADAPTER_STATUS, /* adapter status */ HA_NIM_INCOMING_MSG, /* a message arrived from peer daemon */ HA_NIM_REMOTE_ADAPTER_STAT, /* information about remote adapter */ HA_NIM_ERROR, /* error in NIM */ HA_NIM_I_AM_ALIVE, /* response to HA_NIM_ARE_YOU_ALIVE */ HA_NIM_INFO, /* NIM returns information */ HA_NIM_REMOTE_NODE_HALT, /* message when NIM sees remote halt */ HA_NIM_THREADS_BLOCKED /* Reports statistics of blocked threads */ } nim_msg_type_t; /* * Size of the interface name used on some platforms for IPv6 socket binding */ #define NIM_IF_LEN 32 /* * Interface version number */ #define NIM_MSG_VERSION_MAJOR (1) #define NIM_MSG_VERSION_MINOR (1) typedef struct { ushort major, minor;} nim_msg_version_t; #define set_nim_msg_version(__major, __minor, ver) ver.major = __major; \ ver.minor = __minor; #define nim_msg_version_is_equal(ver1, ver2) ((ver1.major == ver2.major) && \ (ver1.minor == ver2.minor)) #define nim_msg_version_is_greater_equal(ver1, ver2) ((ver1.major > \ ver2.major) || \ ((ver1.major == ver2.major) &&\ (ver1.minor >= ver2.minor))) #define nim_msg_version_as_int(v) (int)(v.major * 1000 + v.minor) #define NIM_MSG_MAX_SIZE 40000 /* maximum message size for this version */ /* * Message header format */ typedef struct { ct_uint32_t size; /* size of the rest of the message */ nim_msg_type_t type; /* type of the message */ nim_msg_version_t version; /* interface version number */ ct_uint32_t padding[3]; /* room for expansion */ } nim_msg_header_t; /* * Format of an adapter address */ /* Address types */ #define NIM_ADDR_TYPE_IPv4 (ushort) 1 /* IPv4 address (struct sockaddr_in)*/ #define NIM_ADDR_TYPE_IPv6 (ushort) 2 /* IPv6 address (struct sockaddr_in6) */ #define NIM_ADDR_TYPE_DEVNAME (ushort) 3 /* null terminated device name */ #define NIM_ADDR_TYPE_MNDHB (ushort) 4 /* Fake IPv4 address (struct sockaddr_in) */ /* IPv6 */ /* Boosted the following from 100 to 130 as INET6_ADDRSTRLEN is 30 bytes * more than INET_ADDRSTRLEN. */ #define NIM_MAX_ADDR_SIZE 130 /* max size of header + actual address */ typedef struct { ct_uint16_t addrtype; /* type of address */ ct_uint16_t addrlen; /* length of address */ char addr[2]; /* the address: variable size */ } nim_adap_addr_t; #define sizeof_adap_addr_hdr(x) (sizeof(x->addrtype) + sizeof(x->addrlen)) #define sizeof_adap_addr(x) (sizeof(x->addrtype) + sizeof(x->addrlen) + \ (size_t)x->addrlen) #define nim_addr_copy(dest, src) \ memcpy((void *)dest, \ (void *)src, \ sizeof_adap_addr(src)) /* IPv6 */ /* The following expect nim_adap_addr_union_t for the addresses */ /* Compare to adddresses. Returns false if they are not same or not same type. */ #define COMP_ADDR(a,b) (((a).addrtype == NIM_ADDR_TYPE_IPv4) ? \ ((a).addrtype == (b).addrtype) && \ ((a).u.ipv4addr.sin_addr.s_addr == \ (b).u.ipv4addr.sin_addr.s_addr) : \ ((a).addrtype == NIM_ADDR_TYPE_IPv6) ? \ ((a).addrtype == (b).addrtype) && \ IN6_ARE_ADDR_EQUAL(&(a).u.ipv6addr.sin6_addr, \ &(b).u.ipv6addr.sin6_addr) : \ 0) /* Return the Address family for a given type */ #define IP_FAM(a) (((a).addrtype == NIM_ADDR_TYPE_IPv4) ? \ AF_INET : \ ((a).addrtype == NIM_ADDR_TYPE_IPv6) ? \ AF_INET6 : \ 0) /* Return a pointer cast as struck sockaddr* to the address */ #define SOCK_PTR(a) (((a).addrtype == NIM_ADDR_TYPE_IPv4) ? \ (struct sockaddr *)&(a).u.ipv4addr : \ ((a).addrtype == NIM_ADDR_TYPE_IPv6) ? \ (struct sockaddr *)&(a).u.ipv6addr : \ (struct sockaddr *)NULL) /* Return size of socket address for the given type */ #define SOCK_LEN(a) (((a).addrtype == NIM_ADDR_TYPE_IPv4) ? \ sizeof(struct sockaddr_in) : \ ((a).addrtype == NIM_ADDR_TYPE_IPv6) ? \ sizeof(struct sockaddr_in6) : \ 0) #define NIM_MAX_DEVNAME_LEN (NIM_MAX_ADDR_SIZE - 2 * sizeof(ushort)) /* max size of a device name */ /* * Format of a daemon-daemon packet. The NIM needs to have some * minimum information about how a daemon-daemon packet looks like * to be able to do some level of validation and to distinguish * between a heartbeat packet and a non-heartbeat packet. * * The declaration of the "real" packet is in lib/comm_lib.h. */ typedef ct_uint32_t nim_GSgid_t[2]; /* The heartbeat packet is the only one that the NIM needs to worry about */ typedef enum { HA_NIM_HEART_BEAT = 0xA, HA_NIM_PING = 0x15 } nim_daemon_packet_kind_t; typedef struct { int32_t Treceive[2]; nim_daemon_packet_kind_t kind; ct_int32_t len; ct_int32_t fill1[3]; nim_GSgid_t from_group; /* source group of the packet */ ct_int32_t fill2[2]; nim_GSgid_t to_group; /* destination group of the packet */ ct_int32_t fill3[5]; /* Defect 111477 - making fill3[] one smaller so machinesInst can be explicit, since it is now used to determine if heartbeats are valid */ ct_int32_t machinesInst; } nim_daemon_packet_t; /* * Data structures used for the HA_NIM_OPEN command * * Format of packet is: * - header (nim_msg_header_t) * - local address (nim_adap_addr_t - variable size) * - number of other local adapters * - array of other local addresses (nim_adap_addr_t) * - number of remote adapters * - array of remote addresses (nim_adap_addr_t) * - open data (nim_open_data_t) */ #define NIM_OPEN_SPECIAL_DATA 8 /* number of ints passed to NIM */ typedef struct { ct_uint32_t min_packet_size; /* minimum packet size */ ct_uint32_t max_packet_size; /* maximum packet size */ ct_uint32_t num_send_retries; /* number of retries when sending msg */ ct_uint32_t bcast_enabled; /* bcast enabled for this adapter */ ct_uint32_t no_ping; /* do not ping to determine status */ char interface_name[NIM_IF_LEN]; /* Interface name */ ct_int32_t special_data[NIM_OPEN_SPECIAL_DATA]; /* special data passed to NIM */ } nim_open_data_t; /* * Data structures used for the HA_NIM_OPEN_RESPONSE response * * Format of packet is: * - header (nim_msg_header_t) * - status data (nim_open_response_data_t) * - bcast/multicast address (nim_adap_addr_t - variable size) */ /* status of HA_NIM_OPEN request */ typedef enum { HA_NIM_OPEN_OK, /* open request successful */ HA_NIM_ADDRESS_MISSING, /* address not configured in any adapter */ HA_NIM_CANNOT_BIND_UDS, /* cannot bind to UNIX-domain socket */ /* XXX if cannot bind then will not be able to respond via the UDS interface either!!! */ HA_NIM_CANNOT_BIND_SOC, /* cannot bind to IP socket */ HA_NIM_CANNOT_OPEN_DEV, /* cannot open the device (non-IP) */ HA_NIM_SYSCALL_ERROR, /* error in system call */ HA_NIM_NETMON_ERROR, /* error in netmon library */ HA_NIM_BCAST_ADDR_ERROR /* inconsistent broadcast address */ } nim_open_response_status_t; #define HA_NIM_MAX_FCT_NAME 64 /* max function name */ typedef struct { nim_open_response_status_t status;/* status of open request */ ct_int32_t errno_val; /* errno value */ ct_int32_t error_code; /* error given by netmon library */ char fct_name[HA_NIM_MAX_FCT_NAME]; /* function that returned error */ ct_int32_t bcast_flag; /* does adapter support broadcast? */ char ifname[IFNAMSIZ]; /* interface name */ /* XXX missing: MTU, subnet mask, ?? */ } nim_open_response_data_t; /* get open response as a string */ #define get_open_response_status_string(st) \ ((st == HA_NIM_OPEN_OK) ? "HA_NIM_OPEN_OK" : \ (st == HA_NIM_ADDRESS_MISSING) ? "HA_NIM_ADDRESS_MISSING" : \ (st == HA_NIM_CANNOT_BIND_UDS) ? "HA_NIM_CANNOT_BIND_UDS" : \ (st == HA_NIM_CANNOT_BIND_SOC) ? "HA_NIM_CANNOT_BIND_SOC" : \ (st == HA_NIM_CANNOT_OPEN_DEV) ? "HA_NIM_CANNOT_OPEN_DEV" : \ (st == HA_NIM_SYSCALL_ERROR) ? "HA_NIM_SYSCALL_ERROR" : \ (st == HA_NIM_NETMON_ERROR) ? "HA_NIM_NETMON_ERROR" : \ (st == HA_NIM_BCAST_ADDR_ERROR) ? "HA_NIM_BCAST_ADDR_ERROR" : \ "") /* * Data structures used for the HA_NIM_ADAPTER_STATUS status report * * Format of packet is: * - header (nim_msg_header_t) * - adapter status (nim_adapter_status_t) */ typedef enum { HA_NIM_ADAPTER_IS_UP = 1, /* adapter is up */ HA_NIM_ADAPTER_IF_FLAG_DOWN, /* adapter's interface flag is down */ HA_NIM_ADAPTER_IS_DOWN, /* adapter is down (no incoming packets)*/ HA_NIM_ADAPTER_IS_MISCONFIGURED, /* adapter is misconfigured */ HA_NIM_ADAPTER_NETMON_ERROR /* error in netmon library */ } nim_adapter_state_t; typedef struct { nim_adapter_state_t state; /* up/down state of adapter */ ct_int32_t errno_val; /* errno value */ char fct_name[HA_NIM_MAX_FCT_NAME]; /* function that returned error */ ct_int32_t error_code; /* error given by netmon library */ } nim_adapter_status_t; /* get adapter status as a string */ #define get_open_adapter_status_string(st) \ ((st == HA_NIM_ADAPTER_IS_UP) ? "HA_NIM_ADAPTER_IS_UP" : \ (st == HA_NIM_ADAPTER_IF_FLAG_DOWN) ? "HA_NIM_ADAPTER_IF_FLAG_DOWN" : \ (st == HA_NIM_ADAPTER_IS_DOWN) ? "HA_NIM_ADAPTER_IS_DOWN" : \ (st == HA_NIM_ADAPTER_IS_MISCONFIGURED) ? \ "HA_NIM_ADAPTER_IS_MISCONFIGURED" : \ (st == HA_NIM_ADAPTER_NETMON_ERROR) ? "HA_NIM_ADAPTER_NETMON_ERROR" : \ "UNKNOWN_STATUS") /* * Data structures used for the HA_NIM_REMOTE_ADAPTER_STAT status report * * Format of packet is: * - header (nim_msg_header_t) * - address (nim_adap_addr_t - variable size) * - adapter status (nim_adapter_status_t) */ /* * Format of "daemon messages" (for example, heartbeat packet passed in * HA_NIM_START_HB, or the message sent with HA_NIM_SEND_MSG or * received in HA_NIM_INCOMING_MSG) * * - Destination/source address (nim_adap_addr_t) * - message length (int -- 32bits) * - the message itself */ /* * Data structures used for the HA_NIM_START_HB command * * Format of packet is: * - header (nim_msg_header_t) * - daemon message (including destination address) * - heartbeat information (nim_hb_send_info_t) */ typedef struct { ct_uint32_t how_often_msec; /* how often to send the heartbeats (in msec) */ } nim_hb_send_info_t; /* * Data structures used for the HA_NIM_STOP_HB command * * Format of packet is: * - header (nim_msg_header_t) * - neighbor address (nim_adap_addr_t -- variable size) */ /* * Data structures used for the HA_NIM_SEND_MSG command * * Format of packet is: * - header (nim_msg_header_t) * - daemon message (including destination address) */ /* * Data structures used for the HA_NIM_MONITOR_HB command * * Format of packet is: * - header (nim_msg_header_t) * - neighbor address (nim_adap_addr_t) * - heartbeat monitoring info (nim_hb_monitor_info_t) */ /* * Data type to represent a "ping grace period" value that is specified * by the user is passed from the daemon to the NIM */ typedef ct_int32_t nim_ping_grace_period_t; typedef struct { nim_GSgid_t group; /* group id of expected message */ ct_uint32_t how_often_msec; /* how often to expect the heartbeats (in msec) */ ct_uint32_t sensitivity; /* how many heartbeats to miss before telling daemon about it */ /* Defect 111477 - Need the instance number in the NIM so we can handle heartbeats with the wrong instance number correctly */ uint32_t machinesInst; /* Current instance number */ nim_ping_grace_period_t hb_monitor_ping_grace_period_msec; /* grace period value in millisecs */ } nim_hb_monitor_info_t; /* * Default value for the grace period, meaning "NIM will choose grace * period value" */ #define NIM_PING_GRACE_PERIOD_DEFAULT_VALUE ((nim_ping_grace_period_t)-1) /* * Data structures used for the HA_NIM_STOP_MONITOR command * * Format of packet is: * - header (nim_msg_header_t) * - neighbor address (nim_adap_addr_t -- variable size) */ /* * Data structures used for the HA_NIM_DMS_START command * * Format of packet is: * - header (nim_msg_header_t) */ /* * Data structures used for the HA_NIM_DMS_STOP command * * Format of packet is: * - header (nim_msg_header_t) */ /* * Data structures used for the HA_NIM_I_AM_ALIVE response * * Format of packet is: * - header (nim_msg_header_t) * - NIM statistics (nim_statistics_t) * - vendor info (nim_vendor_info_t) */ /* * Format of the statistics block passed back from NIM to daemon */ #define NIM_NUM_GEN_STATS 8 typedef struct { uint64_t packets_sent; /* number of packets sent */ uint64_t icmp_packets_sent; /* number of ICMP packets sent */ uint64_t packets_rcvd; /* number of packets received */ uint64_t icmp_packets_rcvd; /* number of ICMP packets received */ uint64_t send_errors; /* number of errors when sending */ uint64_t no_mbuf_send_errors; /* number of ENOBUFS when sending */ uint64_t dropped; /* number of packets dropped by NIM filters */ uint64_t missed_hbs_current; /* number of missed heartbeats for current group */ uint64_t missed_hbs_total; /* total number of missed heartbeats since device was opened */ uint64_t data[NIM_NUM_GEN_STATS]; /* NIM-specific statistics */ } nim_statistics_t; /* * Format of the vendor information passed from NIM back to daemon */ #define NIM_VENDOR_STRING_SIZE 64 typedef struct { char vendor[NIM_VENDOR_STRING_SIZE]; /* vendor name */ char version[NIM_VENDOR_STRING_SIZE]; /* version string */ char date[NIM_VENDOR_STRING_SIZE]; /* date string */ } nim_vendor_info_t; /* * Data structures used for the HA_NIM_ERROR response * * Format of packet is: * - header (nim_msg_header_t) * - severity level (nim_error_level_t) * - error code (nim_error_code_t) * - generic error values * - error string */ /* error levels */ typedef enum { HA_NIM_ERROR_LEVEL_FATAL = 1, /* fatal error; NIM will exit */ HA_NIM_ERROR_LEVEL_ERROR, /* (possibly) recoverable error */ HA_NIM_ERROR_LEVEL_INFO /* information or non-fatal error */ } nim_error_level_t; /* error codes */ typedef enum { HA_NIM_ERROR_CODE_INTERNAL, /* internal error */ HA_NIM_ERROR_CODE_STUCK, /* a thread was stuck for too long */ HA_NIM_ERROR_CODE_READ, /* read error */ HA_NIM_ERROR_CODE_WRITE, /* write error */ HA_NIM_ERROR_CODE_INVAL_REQ, /* invalid request from daemon */ HA_NIM_ERROR_CODE_VERSION, /* protocol version not supported */ HA_NIM_ERROR_CODE_INPUT_TRAFFIC, /* excessive input msg traffic */ HA_NIM_ERROR_CODE_OUTPUT_TRAFFIC, /* excessive outgoing msg traffic */ HA_NIM_ERROR_CODE_OTHER = 50 /* other error. Must be last */ } nim_error_code_t; #define HA_NIM_MAX_ERROR_STRING 256 /* length of error string */ typedef struct { nim_error_level_t error_level; /* error level */ nim_error_code_t error_code; /* error code */ ct_int32_t value1; /* value 1 */ ct_int32_t value2; /* value 2 */ char error_string[HA_NIM_MAX_ERROR_STRING]; /* NULL-terminated error string */ } nim_error_data_t; // Similar to nim_msg_header_t, but it actually reserves the memory space // for the address. Moved from nim_data.h so this type would be available // to nim_driver typedef struct { ct_uint16_t addrtype; // type of address ct_uint16_t addrlen; // length of address union { struct sockaddr_in ipv4addr; // an IPv4 address struct sockaddr_in6 ipv6addr; // an IPv6 address char dev_name[NIM_MAX_DEVNAME_LEN]; // a device name } u; } nim_adap_addr_union_t; // Details section of HA_NIM_THREADS_BLOCKED message #define NIM_BLOCKED_THREAD_NAME_SZ 16 typedef struct { char thread_name[NIM_BLOCKED_THREAD_NAME_SZ]; ct_int32_t msecs_blocked; // time blocked in milliseconds } nim_blocked_thread_details_t; #if defined(_AIX) || defined(__sun) /* AIX or SUN */ #pragma pack() /* turn off forcing of 4-byte alignment.*/ #elif defined(__linux__) || defined(__INTERIX) /* Linux or Interix */ #pragma pack(pop) /* turn off forcing of 4-byte alignment.*/ #endif #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* _NIM_INTERFACE_h */