Line data Source code
1 : #ifndef HEADER_fd_src_discof_admin_fd_adminctl_h 2 : #define HEADER_fd_src_discof_admin_fd_adminctl_h 3 : 4 : #include "../../util/fd_util_base.h" 5 : 6 : /* fd_adminctl_t provides APIs for out-of-band command-and-control 7 : signals to the firedancer process via the admin tile. It provides a 8 : ring of shared-memory command slots between command processes and the 9 : admin tile. 10 : 11 : Each slot is owned by one CAS word that packs state, process pid, 12 : request sequence number, and reservation timestamp. Command 13 : processes send commands to the main app process via a reserve and 14 : publish scheme. A call to fd_adminctl_reserve claims a command slot; 15 : the command process then has exclusive write access to writing the 16 : command payload. The fd_adminctl_publish publishes the command to 17 : the app process and effectively transfers ownership of the slot to 18 : the app process. The app process will poll for a command via 19 : fd_adminctl_poll, process the command, and send back a result via 20 : fd_adminctl_complete. The command process receives the result via 21 : fd_adminctl_wait which blocks on the result. At this point, the slot 22 : is free again and is free to be claimed by another command process. 23 : 24 : If a command process dies while it has ownership of a slot (after 25 : a reservation has been made, but before a publish OR while a command 26 : result is available but not consumed), then other command processes 27 : are free to claim the slot. If for some reason the command process 28 : is hung, the caller will be responsible for cleaning up and killing 29 : the process. 30 : 31 : All input into fd_adminctl_t must be trusted. If the adminctl memory 32 : layout changes, adminctl magic must be updated. */ 33 : 34 0 : #define FD_ADMINCTL_CMD_IDLE (0UL) 35 0 : #define FD_ADMINCTL_CMD_ADD_AUTH_VOTER (1UL) 36 0 : #define FD_ADMINCTL_CMD_SET_IDENTITY (2UL) 37 0 : #define FD_ADMINCTL_CMD_GET_IDENTITY (3UL) 38 0 : #define FD_ADMINCTL_CMD_REMOVE_ALL_AUTH_VOTERS (4UL) 39 0 : #define FD_ADMINCTL_CMD_SNAP_CREATE (5UL) 40 : 41 0 : #define FD_ADMINCTL_ALIGN (8UL) 42 0 : #define FD_ADMINCTL_PAYLOAD_MAX (32768UL) 43 0 : #define FD_ADMINCTL_SLOT_CNT (4UL) 44 : 45 : /* Shared command result codes. */ 46 0 : #define FD_ADMINCTL_RESULT_SUCCESS (0UL) 47 0 : #define FD_ADMINCTL_RESULT_UNKNOWN_COMMAND (1UL) 48 0 : #define FD_ADMINCTL_RESULT_ABI_VERSION_MISMATCH (2UL) 49 0 : #define FD_ADMINCTL_RESULT_ABI_SIZE_MISMATCH (3UL) 50 0 : #define FD_ADMINCTL_RESULT_UNSUPPORTED (4UL) 51 : 52 : /* App-specific command result codes. 53 : NOTE: It is important these codes start at least 5UL. */ 54 : 55 0 : #define FD_ADD_AUTHORIZED_VOTER_RESULT_KEYPAIR_MISMATCH (0x1001UL) 56 0 : #define FD_ADD_AUTHORIZED_VOTER_RESULT_MAX_AUTH_VOTERS (0x1002UL) 57 0 : #define FD_ADD_AUTHORIZED_VOTER_RESULT_DUPLICATE_AUTH_VOTER (0x1003UL) 58 : 59 0 : #define FD_SNAPSHOT_CREATE_RESULT_BUSY (0x2001UL) 60 0 : #define FD_SNAPSHOT_CREATE_RESULT_NOT_READY (0x2003UL) 61 0 : #define FD_SNAPSHOT_CREATE_RESULT_SLOT_IN_PAST (0x2004UL) 62 : 63 0 : #define FD_SET_IDENTITY_RESULT_KEYPAIR_MISMATCH (0x3001UL) 64 0 : #define FD_SET_IDENTITY_RESULT_INVALID_VOTE_HISTORY (0x3002UL) 65 0 : #define FD_SET_IDENTITY_RESULT_SAME_IDENTITY (0x3003UL) 66 : 67 : struct fd_adminctl_add_auth_voter_v1 { 68 : ulong version; /* ==FD_ADMINCTL_ADD_AUTH_VOTER_PAYLOAD_VERSION */ 69 : uchar keypair[ 64UL ]; 70 : }; 71 : typedef struct fd_adminctl_add_auth_voter_v1 fd_adminctl_add_auth_voter_t; 72 0 : #define FD_ADMINCTL_ADD_AUTH_VOTER_PAYLOAD_VERSION (1UL) 73 : 74 : struct fd_adminctl_snap_create_v1 { 75 : ulong version; /* ==FD_ADMINCTL_SNAP_CREATE_PAYLOAD_VERSION */ 76 : ulong slot; /* 0 to create a snapshot of the published root 77 : immediately, else stop rooting at the first rooted 78 : slot >= this slot and snapshot it */ 79 : }; 80 : typedef struct fd_adminctl_snap_create_v1 fd_adminctl_snap_create_t; 81 0 : #define FD_ADMINCTL_SNAP_CREATE_PAYLOAD_VERSION (1UL) 82 : 83 : struct fd_adminctl_set_identity_v4 { 84 : ulong version; /* ==FD_ADMINCTL_SET_IDENTITY_PAYLOAD_VERSION */ 85 : uchar keypair[ 64UL ]; 86 : ulong vote_history_slot; /* scanned by the command from the vote history file, 0 if none was provided */ 87 : }; 88 : typedef struct fd_adminctl_set_identity_v4 fd_adminctl_set_identity_t; 89 : FD_STATIC_ASSERT( sizeof(fd_adminctl_set_identity_t)<=FD_ADMINCTL_PAYLOAD_MAX, set_identity ); 90 0 : #define FD_ADMINCTL_SET_IDENTITY_PAYLOAD_VERSION (4UL) 91 : 92 : struct fd_adminctl_get_identity_req_v1 { 93 : ulong version; /* ==FD_ADMINCTL_GET_IDENTITY_PAYLOAD_VERSION */ 94 : }; 95 : typedef struct fd_adminctl_get_identity_req_v1 fd_adminctl_get_identity_req_t; 96 : 97 : struct fd_adminctl_get_identity_resp_v1 { 98 : ulong version; /* ==FD_ADMINCTL_GET_IDENTITY_PAYLOAD_VERSION */ 99 : uchar identity_pubkey[ 32UL ]; 100 : }; 101 : typedef struct fd_adminctl_get_identity_resp_v1 fd_adminctl_get_identity_resp_t; 102 0 : #define FD_ADMINCTL_GET_IDENTITY_PAYLOAD_VERSION (1UL) 103 : 104 : struct fd_adminctl_remove_all_auth_voters_v1 { 105 : ulong version; /* ==FD_ADMINCTL_REMOVE_ALL_AUTH_VOTERS_PAYLOAD_VERSION */ 106 : }; 107 : typedef struct fd_adminctl_remove_all_auth_voters_v1 fd_adminctl_remove_all_auth_voters_t; 108 0 : #define FD_ADMINCTL_REMOVE_ALL_AUTH_VOTERS_PAYLOAD_VERSION (1UL) 109 : 110 : typedef struct fd_adminctl_private fd_adminctl_t; 111 : 112 : FD_PROTOTYPES_BEGIN 113 : 114 : FD_FN_CONST ulong 115 : fd_adminctl_align( void ); 116 : 117 : FD_FN_CONST ulong 118 : fd_adminctl_footprint( void ); 119 : 120 : void * 121 : fd_adminctl_new( void * shmem ); 122 : 123 : fd_adminctl_t * 124 : fd_adminctl_join( void * shadminctl ); 125 : 126 : /* fd_adminctl_reserve claims a command slot and returns an identifier 127 : for the command reservation (index into the command buffer). Returns 128 : ULONG_MAX if every slot is busy or reserved. If a reservation is 129 : successful, payload_out receives a pointer into shared memory valid 130 : until publish completes or the reservation is abandoned by process 131 : death. */ 132 : 133 : ulong 134 : fd_adminctl_reserve( fd_adminctl_t * adminctl, 135 : void ** payload_out, 136 : ulong * payload_max_out ); 137 : 138 : /* fd_adminctl_publish validates the reservation and publishes the 139 : command to the admin tile. This should only be called by a command 140 : process after a successful reservation. After this function is 141 : called, the ownership of the slot is transferred to the app process. 142 : If a publish is made after a reservation, it will always succeed. */ 143 : 144 : void 145 : fd_adminctl_publish( fd_adminctl_t * adminctl, 146 : ulong slot_id, 147 : ulong cmd_id, 148 : ulong payload_sz ); 149 : 150 : /* fd_adminctl_wait waits for the command identified by slot_id to 151 : complete and returns the command result. This command should only be 152 : called by a command process after a successful publish. After the 153 : function returns, the command slot will be reclaimed. The command 154 : process result is returned. */ 155 : 156 : ulong 157 : fd_adminctl_wait( fd_adminctl_t * adminctl, 158 : ulong slot_id ); 159 : 160 : /* fd_adminctl_wait_response is fd_adminctl_wait for commands that also 161 : return a response payload. Before the slot is reclaimed, up to 162 : resp_max bytes of the response payload are copied into resp and the 163 : response payload size is stored in resp_sz_out. */ 164 : 165 : ulong 166 : fd_adminctl_wait_response( fd_adminctl_t * adminctl, 167 : ulong slot_id, 168 : void * resp, 169 : ulong resp_max, 170 : ulong * resp_sz_out ); 171 : 172 : /* fd_adminctl_poll checks a command slot at a time and returns the 173 : command id and payload if a command is available. The command is now 174 : ready to be processed by the app process. If no command is 175 : available, the function returns FD_ADMINCTL_CMD_IDLE. Under the 176 : hood, it checks one slot at a time and advances the poll cursor. 177 : This function should be called repeatedly by only the main app 178 : process. */ 179 : 180 : ulong 181 : fd_adminctl_poll( fd_adminctl_t * adminctl, 182 : ulong * slot_id_out, 183 : void ** payload_out, 184 : ulong * payload_sz_out ); 185 : 186 : /* fd_adminctl_complete publishes the result for the command that has 187 : finished being processed. It should only be called by the app 188 : process after the command has been processed. */ 189 : 190 : void 191 : fd_adminctl_complete( fd_adminctl_t * adminctl, 192 : ulong slot_id, 193 : ulong result ); 194 : 195 : /* fd_adminctl_complete_response is fd_adminctl_complete for commands 196 : that also return a response payload. The request payload is zeroed 197 : and replaced with the resp_sz bytes at resp before the result is 198 : published. */ 199 : 200 : void 201 : fd_adminctl_complete_response( fd_adminctl_t * adminctl, 202 : ulong slot_id, 203 : ulong result, 204 : void const * resp, 205 : ulong resp_sz ); 206 : 207 : FD_PROTOTYPES_END 208 : 209 : #endif /* HEADER_fd_src_discof_admin_fd_adminctl_h */