Changeset 662 for trunk/kernel/kern/ksocket.c
- Timestamp:
- Oct 10, 2020, 4:50:41 PM (4 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/kern/ksocket.c
r657 r662 1 1 /* 2 * socket.h - socket descriptor and API definition.3 * 4 * Authors Alain Greiner 2 * ksocket.c - kernel socket API implementation. 3 * 4 * Authors Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites 7 7 * 8 * This file is part of ALMOS-MKH 8 * This file is part of ALMOS-MKH. 9 9 * 10 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it … … 18 18 * 19 19 * You should have received a copy of the GNU General Public License 20 * along with ALMOS-MKH ; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation, 21 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 22 */ 23 23 24 #ifndef _SOCKET_H_25 #define _SOCKET_H_26 27 24 #include <kernel_config.h> 28 25 #include <hal_kernel_types.h> 29 #include <xlist.h> 26 #include <hal_remote.h> 27 #include <hal_uspace.h> 28 #include <shared_socket.h> 29 #include <process.h> 30 30 #include <remote_buf.h> 31 #include <remote_busylock.h> 32 33 /**************************************************************************************** 34 * This defines the three commands that can be requested by a client thread to 35 * a TX server thread. These commands are registered in the socket descriptor. 36 ****************************************************************************************/ 37 38 typedef enum sock_cmd_e 39 { 40 SOCKET_TX_CONNECT = 20, /*! request 3 steps handshake (TCP socket only) */ 41 SOCKET_TX_SEND = 21, /*! request to send data (TCP or UDP socket) */ 42 SOCKET_TX_CLOSE = 22, /*! request 3 steps handshake (TCP socket only) */ 31 #include <bits.h> 32 #include <printk.h> 33 #include <kmem.h> 34 #include <thread.h> 35 #include <vfs.h> 36 #include <ksocket.h> 37 #include <dev_nic.h> 38 39 ////////////////////////////////////////////////////////////////////////////////////// 40 // Extern global variables 41 ////////////////////////////////////////////////////////////////////////////////////// 42 43 extern chdev_directory_t chdev_dir; // allocated in kernel_init.c 44 45 /////////////////////////////////////////// 46 char * socket_domain_str( uint32_t domain ) 47 { 48 switch( domain ) 49 { 50 case AF_INET : return "INET"; 51 case AF_LOCAL : return "LOCAL"; 52 53 default : return "undefined"; 54 } 43 55 } 44 sock_cmd_t; 45 46 /***************************************************************************************** 47 * This structure defines a socket descriptor. In order to parallelize the transfers, 48 * the set of all registered sockets is split in several subsets. 49 * The number of subsets is the number of NIC channels. 50 * The distribution key is computed from the (remote_addr/remote_port) couple. 51 * This computation is done by the NIC hardware for RX packets, 52 * and by the dev_nic_connect() function for the TX packets. 53 * 54 * A socket is attached to the NIC_TX[channel] & NIC_RX[channel] chdevs. 55 * Each socket descriptor allows the TX and TX server threads to access various buffers: 56 * - the user "send" buffer contains the data to be send by the TX server thread. 57 * - the kernel "receive" buffer contains the data received by the RX server thread. 58 * - the kernel "r2t" buffer allows the RX server thread to make direct requests 59 * to the associated TX server (to implement the TCP 3 steps handshake). 60 * 61 * The synchronisation mechanism between the clients threads and the servers threads 62 * is different for TX and RX transfers: 63 * 64 * 1) For a TX transfer, it can exist only one client thread for a given socket, 65 * the transfer is always initiated by the local process, and all TX commands 66 * (CONNECT/SEND/CLOSE) are blocking for the client thread. The user buffer is 67 * used by TCP to handle retransmissions when required.in case of re 68 * The client thread registers the command in the thread descriptor, registers itself 69 * in the socket descriptor, unblocks the TX server thread from the BLOCKED_CLIENT 70 * condition, blocks itself on the BLOCKED_IO condition, and deschedules. 71 * When the command is completed, the TX server thread unblocks the client thread. 72 * The TX server blocks itself on the BLOCKED_CLIENT condition, when there is no 73 * pending commands and the R2T queue is empty. It is unblocked when a client 74 * register a new command, or when the TX server thread register a mew request 75 * in the R2T queue. 76 * The tx_valid flip-flop is SET by the client thread to signal a valid command. 77 * It is RESET by the server thread when the command is completed: For a SEND, 78 * all bytes have been sent (UDP) or acknowledged (TCP). 79 * 80 * 2) For an RX transfer, it can exist only one client thread for a given socket, 81 * but the transfer is initiated by the remote process, and the RECV command 82 * is not really blocking: the data can arrive before the local RECV command is 83 * executed, and the server thread does not wait to receive all requested data 84 * to deliver data to client thread. Therefore each socket contains a receive 85 * buffer (rx_buf) handled as a single-writer/single-reader fifo. 86 * The client thread consumes data from the rx_buf when possible. It blocks on the 87 * BLOCKED_IO condition and deschedules when the rx_buf is empty. 88 * It is unblocked by the RX server thread when new data is available in the rx_buf. 89 * The RX server blocks itself on the BLOCKED_ISR condition When the NIC_RX packets 90 * queue is empty. It is unblocked by the hardware when new packets are available. 91 * 92 * Note : the socket domains and types are defined in the "shared_socket.h" file. 93 ****************************************************************************************/ 94 95 typedef enum udp_socket_state_e 96 { 97 UDP_STATE_UNBOUND = 0, 98 UDP_STATE_BOUND = 1, 99 UDP_STATE_CONNECT = 2, 56 57 /////////////////////////////////////// 58 char * socket_type_str( uint32_t type ) 59 { 60 switch( type ) 61 { 62 case SOCK_DGRAM : return "UDP"; 63 case SOCK_STREAM : return "TCP"; 64 65 default : return "undefined"; 66 } 100 67 } 101 udp_socket_state_t; 102 103 typedef enum tcp_socket_state_e 104 { 105 TCP_STATE_UNBOUND = 10, 106 TCP_STATE_BOUND = 11, 107 TCP_STATE_LISTEN = 12, 108 TCP_STATE_SYN_SENT = 13, 109 TCP_STATE_SYN_RCVD = 14, 110 TCP_STATE_ESTAB = 15, 111 TCP_STATE_FIN_WAIT1 = 16, 112 TCP_STATE_FIN_WAIT2 = 17, 113 TCP_STATE_CLOSING = 18, 114 TCP_STATE_TIME_WAIT = 19, 115 TCP_STATE_CLOSE_WAIT = 20, 116 TCP_STATE_LAST_ACK = 21, 68 69 ///////////////////////////////////////// 70 char * socket_state_str( uint32_t state ) 71 { 72 switch( state ) 73 { 74 case UDP_STATE_UNBOUND : return "UDP_UNBOUND"; 75 case UDP_STATE_BOUND : return "UDP_BOUND"; 76 case UDP_STATE_ESTAB : return "UDP_ESTAB"; 77 78 case TCP_STATE_UNBOUND : return "TCP_UNBOUND"; 79 case TCP_STATE_BOUND : return "TCP_BOUND"; 80 case TCP_STATE_LISTEN : return "TCP_LISTEN"; 81 case TCP_STATE_SYN_SENT : return "TCP_SYN_SENT"; 82 case TCP_STATE_SYN_RCVD : return "TCP_SYN_RCVD"; 83 case TCP_STATE_ESTAB : return "TCP_ESTAB"; 84 case TCP_STATE_FIN_WAIT1 : return "TCP_FIN_WAIT1"; 85 case TCP_STATE_FIN_WAIT2 : return "TCP_FIN_WAIT2"; 86 case TCP_STATE_CLOSING : return "TCP_CLOSING"; 87 case TCP_STATE_TIME_WAIT : return "TCP_TIME_WAIT"; 88 case TCP_STATE_CLOSE_WAIT : return "TCP_CLOSE_WAIT"; 89 case TCP_STATE_LAST_ACK : return "TCP_LAST_ACK"; 90 case TCP_STATE_CLOSED : return "TCP_CLOSED"; 91 92 default : return "undefined"; 93 } 117 94 } 118 tcp_socket_state_t; 119 120 typedef struct socket_s 121 { 122 remote_busylock_t lock; /*! lock protecting socket state */ 123 uint32_t domain; /*! domain : AF_LOCAL / AF_INET */ 124 uint32_t type; /*! type : SOCK_DGRAM / SOCK_STREAM */ 125 pid_t pid; /*! owner process identifier */ 126 uint32_t state; /*! see above */ 127 uint32_t local_addr; /*! local socket IP address */ 128 uint32_t remote_addr; /*! remote socket IP address */ 129 uint32_t local_port; /*! local socket port number */ 130 uint32_t remote_port; /*! remote socket port number */ 131 uint32_t nic_channel; /*! derived from (remote_addr,remote_port) */ 132 133 xlist_entry_t tx_list; /*! sockets attached to same NIC_TX chdev */ 134 xptr_t tx_client; /*! extended pointer on TX client thread */ 135 sock_cmd_t tx_cmd; /*! command type (CONNECT/SEND/CLOSE) */ 136 uint8_t * tx_buf; /*! pointer on user buffer in user space */ 137 uint32_t tx_len; /*! number of bytes to be sent in command */ 138 uint32_t tx_todo; /*! number of bytes not yet sent */ 139 uint32_t tx_error; /*! signal a TX command error */ 140 141 xlist_entry_t rx_list; /*! sockets attached to same NIC_RX chdev */ 142 xptr_t rx_client; /*! extended pointer on RX client thread */ 143 remote_buf_t rx_buf; /*! embedded receive buffer descriptor */ 144 145 remote_buf_t r2tq; /*! RX_to_TX requests queue descriptor */ 146 147 remote_buf_t crqq; /*! connection requests queue descriptor */ 148 /* the following fields defines the TCB used for a TCP connection */ 149 150 uint32_t tx_una; /*! first unack byte in TX_data stream */ 151 uint32_t tx_nxt; /*! next byte to send in TX_data stream */ 152 uint32_t tx_wnd; /*! number of acceptable bytes in TX_data stream */ 153 154 uint32_t rx_nxt; /*! next expected byte in RX_data stream */ 155 uint32_t rx_wnd; /*! number of acceptable bytes in RX_data stream */ 156 uint32_t rx_irs; /*! initial sequence number in RX_data stream */ 95 96 /////////////////////////////////////////// 97 char * socket_cmd_type_str( uint32_t type ) 98 { 99 switch( type ) 100 { 101 case CMD_TX_CONNECT : return "TX_CONNECT"; 102 case CMD_TX_ACCEPT : return "TX_ACCEPT"; 103 case CMD_TX_CLOSE : return "TX_CLOSE"; 104 case CMD_TX_SEND : return "TX_SEND"; 105 106 case CMD_RX_ACCEPT : return "RX_ACCEPT"; 107 case CMD_RX_RECV : return "RX_RECV"; 108 109 default : return "undefined"; 110 } 157 111 } 158 socket_t; 159 160 /**************************************************************************************** 161 * This function returns a printable string for a client_to_tx_server command type. 162 **************************************************************************************** 163 * type : SOCKET_TX_CONNECT / SOCKET_TX_SEND / SOCKET_TX_CLOSE 164 ***************************************************************************************/ 165 char * socket_cmd_str( uint32_t type ); 166 167 /**************************************************************************************** 168 * This function returns a printable string for an UDP or TCP socket state. 169 **************************************************************************************** 170 * state : UDP_STATE_*** / TCP_STATE*** 171 ***************************************************************************************/ 172 char * socket_state_str( uint32_t state ); 173 174 /**************************************************************************************** 175 * This function allocates memory in the cluster defined by the <cxy> argument for a 176 * socket descriptor defined by the <domain> and <type> aruments, for the associated 177 * file descriptor, and for the various kernel buffers descriptors contained in the 178 * socket descriptor : "rx_buf" (receive buffer), "r2tq" (RX to RX requests queue), and 179 * "crqq" (connect requests queue). It initialises the socket desccriptor static fields, 180 * (other than local_addr, local_port, remote_addr, remote_port). 181 * It registers the file descriptor in the reference process fd_array[], set the socket 182 * the socket state to UNBOUND, and returns the file identifier in the <fdid> argument. 183 **************************************************************************************** 184 * @ cxy : [in] target cluster identifier. 185 * @ domain : [in] socket protocol family (must be AF_INET). 186 * @ type : [in] socket type (SOCK_DGRAM / SOCK_STREAM). 187 * @ socket : [out] buffer for a local pointer on created socket. 188 * @ fdid : [out] buffer for file identifier. 189 * @ return 0 if success / return -1 if failure (no memory). 190 ***************************************************************************************/ 191 error_t socket_create( cxy_t cxy, 192 uint32_t domain, 193 uint32_t type, 194 struct socket_s ** socket, 195 uint32_t * fdid ); 196 197 /**************************************************************************************** 198 * This functions releases all memory allocated to a socket identified by the <fdid> 199 * argument. This include the file descriptor, the socket descriptor, and all buffers 200 * referenced by the socket descriptor. 201 **************************************************************************************** 202 * @ fdid : [in] file descriptor index. 203 ***************************************************************************************/ 204 void socket_destroy( uint32_t fdid ); 205 206 /**************************************************************************************** 207 * This functions registers the socket defined by the <socket_xp> argument into the 208 * lists of sockets attached to the NIC_TX and NIC_TX chdevs identified by the 209 * <nic_channel> argument. 210 **************************************************************************************** 211 * @ socket_xp : [in] extended pointer on socket descriptor 212 * @ nic_channel : [in] NIC channel index. 213 ***************************************************************************************/ 214 void socket_link_to_servers( xptr_t socket_xp, 215 uint32_t nic_channel ); 112 113 /////////////////////////////////////////// 114 char * socket_cmd_sts_str( uint32_t sts ) 115 { 116 switch( sts ) 117 { 118 case CMD_STS_SUCCESS : return "TX_CONNECT"; 119 case CMD_STS_EOF : return "EOF"; 120 case CMD_STS_RST : return "RST"; 121 case CMD_STS_BADACK : return "BADACK"; 122 case CMD_STS_BADSTATE : return "BADSTATE"; 123 case CMD_STS_BADCMD : return "BADCMD"; 124 125 default : return "undefined"; 126 } 127 } 128 129 ///////////////////////////////////////////////////////////////////////////////////////// 130 // This static function registers the socket defined by the <socket_xp> argument into 131 // the lists of sockets attached to the relevant NIC_TX and NIC_TX chdevs identified 132 // by the <channel> argument, and update the channel field in socket descriptor. 133 ///////////////////////////////////////////////////////////////////////////////////////// 134 // @ socket_xp : [in] extended pointer on socket descriptor. 135 // @ channel : [in] NIC channel index. 136 ///////////////////////////////////////////////////////////////////////////////////////// 137 static void socket_link_to_servers( xptr_t socket_xp, 138 uint32_t channel ) 139 { 140 cxy_t socket_cxy = GET_CXY( socket_xp ); 141 socket_t * socket_ptr = GET_PTR( socket_xp ); 142 143 #if DEBUG_SOCKET_LINK 144 thread_t * this = CURRENT_THREAD; 145 process_t * process = this->process; 146 pid_t socket_pid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid )); 147 fdid_t socket_fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid )); 148 uint32_t cycle = (uint32_t)hal_get_cycles(); 149 if( DEBUG_SOCKET_LINK < cycle ) 150 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / cycle %d\n", 151 __FUNCTION__, process->pid, this->trdid, socket_pid, socket_fdid, cycle ); 152 #endif 153 154 // get pointers on NIC_TX[channel] chdev 155 xptr_t tx_chdev_xp = chdev_dir.nic_tx[channel]; 156 chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp ); 157 cxy_t tx_chdev_cxy = GET_CXY( tx_chdev_xp ); 158 159 // build various TX extended pointers 160 xptr_t tx_root_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_root ); 161 xptr_t tx_lock_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_lock ); 162 xptr_t tx_list_xp = XPTR( socket_cxy , &socket_ptr->tx_list ); 163 164 // get pointers on NIC_RX[channel] chdev 165 xptr_t rx_chdev_xp = chdev_dir.nic_rx[channel]; 166 chdev_t * rx_chdev_ptr = GET_PTR( rx_chdev_xp ); 167 cxy_t rx_chdev_cxy = GET_CXY( rx_chdev_xp ); 168 169 // build various RX extended pointers 170 xptr_t rx_root_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_root ); 171 xptr_t rx_lock_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_lock ); 172 xptr_t rx_list_xp = XPTR( socket_cxy , &socket_ptr->rx_list ); 173 174 // register socket in the NIC_TX[channel] chdev clients queue 175 remote_busylock_acquire( tx_lock_xp ); 176 xlist_add_last( tx_root_xp , tx_list_xp ); 177 remote_busylock_release( tx_lock_xp ); 178 179 // register socket in the NIC_RX[channel] chdev clients queue 180 remote_busylock_acquire( rx_lock_xp ); 181 xlist_add_last( rx_root_xp , rx_list_xp ); 182 remote_busylock_release( rx_lock_xp ); 183 184 #if DEBUG_SOCKET_LINK 185 cycle = (uint32_t)hal_get_cycles(); 186 if( DEBUG_SOCKET_LINK < cycle ) 187 printk("\n[%s] thread[%x,%x] linked socket[%x,%d] to channel %d / cycle %d\n", 188 __FUNCTION__, process->pid, this->trdid, process->pid, socket_pid, socket_fdid, channel, cycle ); 189 #endif 190 191 } // end socket_link_to_servers() 192 193 ///////////////////////////////////////////////////////////////////////////////////////// 194 // This function removes the socket defined by the <socket_xp> argument from the 195 // lists of sockets attached to the relevant NIC_TX and NIC_TX chdevs. 196 ///////////////////////////////////////////////////////////////////////////////////////// 197 // @ socket_xp : [in] extended pointer on socket descriptor 198 ///////////////////////////////////////////////////////////////////////////////////////// 199 static void socket_unlink_from_servers( xptr_t socket_xp ) 200 { 201 cxy_t socket_cxy = GET_CXY( socket_xp ); 202 socket_t * socket_ptr = GET_PTR( socket_xp ); 203 204 #if DEBUG_SOCKET_LINK 205 thread_t * this = CURRENT_THREAD; 206 process_t * process = this->process; 207 pid_t socket_pid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid )); 208 fdid_t socket_fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid )); 209 uint32_t cycle = (uint32_t)hal_get_cycles(); 210 if( DEBUG_SOCKET_LINK < cycle ) 211 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / cycle %d\n", 212 __FUNCTION__, process->pid, this->trdid, socket_pid, socket_fdid, cycle ); 213 #endif 214 215 // get NIC channel 216 uint32_t channel = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->nic_channel )); 217 218 // get pointers on NIC_TX[channel] chdev 219 xptr_t tx_chdev_xp = chdev_dir.nic_tx[channel]; 220 chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp ); 221 cxy_t tx_chdev_cxy = GET_CXY( tx_chdev_xp ); 222 223 // build various TX extended pointers 224 xptr_t tx_lock_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_lock ); 225 xptr_t tx_list_xp = XPTR( socket_cxy , &socket_ptr->tx_list ); 226 227 // get pointers on NIC_RX[channel] chdev 228 xptr_t rx_chdev_xp = chdev_dir.nic_rx[channel]; 229 chdev_t * rx_chdev_ptr = GET_PTR( rx_chdev_xp ); 230 cxy_t rx_chdev_cxy = GET_CXY( rx_chdev_xp ); 231 232 // build various RX extended pointers 233 xptr_t rx_lock_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_lock ); 234 xptr_t rx_list_xp = XPTR( socket_cxy , &socket_ptr->rx_list ); 235 236 // remove socket from the NIC_TX[channel] chdev clients queue 237 remote_busylock_acquire( tx_lock_xp ); 238 xlist_unlink( tx_list_xp ); 239 remote_busylock_release( tx_lock_xp ); 240 241 // remove socket from the NIC_RX[channel] chdev clients queue 242 remote_busylock_acquire( rx_lock_xp ); 243 xlist_unlink( rx_list_xp ); 244 remote_busylock_release( rx_lock_xp ); 245 246 #if DEBUG_SOCKET_LINK 247 cycle = (uint32_t)hal_get_cycles(); 248 if( DEBUG_SOCKET_LINK < cycle ) 249 printk("\n[%s] thread[%x,%x] unlinked socket [%x,%d] / cycle %d\n", 250 __FUNCTION__, process->pid, this->trdid, socket_pid, socket_fdid, cycle ); 251 #endif 252 253 } // end socket_unlink_from_servers() 254 255 ///////////////////////////////////////////////////////////////////////////////////////// 256 // This static function is called by the socket_build() and socket_accept() functions. 257 // It allocates memory in cluster defined by the <cxy> argument for all structures 258 // associated to a socket: file descriptor, socket descriptor, RX buffer, R2T queue, 259 // and CRQ queue. It allocates an fdid, and register it in the process fd_array. 260 // It initialise the the socket desccriptor static fields, other than local_addr, 261 // local_port, remote_addr, remote_port), and set the socket state to UNBOUND. 262 // It returns the local pointer on socket descriptor and the fdid value in buffers 263 // defined by the <socket_ptr> & <fdid_ptr> arguments. 264 ///////////////////////////////////////////////////////////////////////////////////////// 265 // @ cxy : [in] target cluster fo socket & file descriptors. 266 // @ domain : [in] socket domain. 267 // @ type : [in] socket type. 268 // @ socket_ptr : [out] local pointer on buffer for socket pointer. 269 // @ fdid_ptr : [out] local pointer on buffer for fdid value. 270 // # return 0 if success / return -1 if no memory. 271 ///////////////////////////////////////////////////////////////////////////////////////// 272 static error_t socket_create( cxy_t cxy, 273 uint32_t domain, 274 uint32_t type, 275 socket_t ** socket_ptr, 276 uint32_t * fdid_ptr ) 277 { 278 uint32_t fdid; 279 280 thread_t * this = CURRENT_THREAD; 281 process_t * process = this->process; 282 283 kmem_req_t req; 284 socket_t * socket; 285 vfs_file_t * file; 286 uint32_t state; 287 error_t error; 288 289 #if DEBUG_SOCKET_CREATE 290 uint32_t cycle = (uint32_t)hal_get_cycles(); 291 if( DEBUG_SOCKET_CREATE < cycle ) 292 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 293 __FUNCTION__, process->pid, this->trdid, cycle ); 294 #endif 295 296 // allocate memory for socket descriptor 297 req.type = KMEM_KCM; 298 req.order = bits_log2( sizeof(socket_t) ); 299 req.flags = AF_ZERO; 300 socket = kmem_remote_alloc( cxy , &req ); 301 302 if( socket == NULL ) 303 { 304 printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x]\n", 305 __FUNCTION__, process->pid, this->trdid ); 306 return -1; 307 } 308 309 // allocate memory for rx_buf buffer 310 error = remote_buf_init( XPTR( cxy , &socket->rx_buf ), 311 NIC_RX_BUF_SIZE ); 312 313 if( error ) 314 { 315 printk("\n[ERROR] in %s : cannot allocate rx_buf / thread[%x,%x]\n", 316 __FUNCTION__, process->pid, this->trdid ); 317 req.type = KMEM_KCM; 318 req.ptr = socket; 319 kmem_remote_free( cxy , &req ); 320 return -1; 321 } 322 323 // allocate memory for r2tq queue 324 error = remote_buf_init( XPTR( cxy , &socket->r2tq ), 325 NIC_R2T_QUEUE_SIZE ); 326 if( error ) 327 { 328 printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x]\n", 329 __FUNCTION__, process->pid, this->trdid ); 330 remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) ); 331 req.type = KMEM_KCM; 332 req.ptr = socket; 333 kmem_remote_free( cxy , &req ); 334 return -1; 335 } 336 337 // don't allocate memory for crqq queue, as it is done by the socket_listen function 338 339 // allocate memory for file descriptor 340 req.type = KMEM_KCM; 341 req.order = bits_log2( sizeof(vfs_file_t) ); 342 req.flags = AF_ZERO; 343 file = kmem_remote_alloc( cxy , &req ); 344 345 if( file == NULL ) 346 { 347 printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x]\n", 348 __FUNCTION__, process->pid, this->trdid ); 349 remote_buf_destroy( XPTR( cxy , &socket->r2tq ) ); 350 remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) ); 351 req.type = KMEM_KCM; 352 req.ptr = socket; 353 kmem_remote_free( cxy , &req ); 354 return -1; 355 } 356 357 // get an fdid value, and register file descriptor in fd_array[] 358 error = process_fd_register( process->ref_xp, 359 XPTR( cxy , file ), 360 &fdid ); 361 if ( error ) 362 { 363 printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x]\n", 364 __FUNCTION__, process->pid, this->trdid ); 365 req.type = KMEM_KCM; 366 req.ptr = file; 367 kmem_free( &req ); 368 remote_buf_destroy( XPTR( cxy , &socket->r2tq ) ); 369 remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) ); 370 req.ptr = socket; 371 kmem_free( &req ); 372 return -1; 373 } 374 375 state = (type == SOCK_STREAM) ? TCP_STATE_UNBOUND : UDP_STATE_UNBOUND; 376 377 // initialise socket descriptor 378 hal_remote_s32( XPTR( cxy , &socket->pid ) , process->pid ); 379 hal_remote_s32( XPTR( cxy , &socket->fdid ) , fdid ); 380 hal_remote_s32( XPTR( cxy , &socket->domain ) , domain ); 381 hal_remote_s32( XPTR( cxy , &socket->type ) , type ); 382 hal_remote_s32( XPTR( cxy , &socket->state ) , state ); 383 hal_remote_s64( XPTR( cxy , &socket->tx_client ) , XPTR_NULL ); 384 hal_remote_s64( XPTR( cxy , &socket->rx_client ) , XPTR_NULL ); 385 hal_remote_s32( XPTR( cxy , &socket->tx_valid ) , false ); 386 hal_remote_s32( XPTR( cxy , &socket->rx_valid ) , false ); 387 hal_remote_s32( XPTR( cxy , &socket->nic_channel ) , 0 ); 388 389 // initialize file descriptor 390 hal_remote_s32( XPTR( cxy , &file->type ) , INODE_TYPE_SOCK ); 391 hal_remote_spt( XPTR( cxy , &file->socket ) , socket ); 392 hal_remote_s32( XPTR( cxy , &file->refcount ) , 1 ); 393 394 // initialize socket lock 395 remote_queuelock_init( XPTR( cxy , &socket->lock ) , LOCK_SOCKET_STATE ); 396 397 #if DEBUG_SOCKET_CREATE 398 if( DEBUG_SOCKET_CREATE < cycle ) 399 printk("\n[%s] thread[%x,%x] exit / socket[%x,%d] / xptr[%x,%x] / cycle %d\n", 400 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cxy, socket, cycle ); 401 #endif 402 403 // return success 404 *socket_ptr = socket; 405 *fdid_ptr = fdid; 406 407 return 0; 408 409 } // end socket_create 410 411 ///////////////////////////////////////////////////////////////////////////////////////// 412 // This static function is called by the socket_close() function to destroy a socket 413 // identified by the <file_xp> argument. 414 // It remove the associated file from the reference process fd_array. It unlink the 415 // socket from the NIC_TX [k] and NIC_RX[k] chdevs. It release all memory allocated 416 // for the structures associated to the target socket socket : file descriptor, 417 // socket descriptor, RX buffer, R2T queue, CRQ queue. 418 ///////////////////////////////////////////////////////////////////////////////////////// 419 // @ file_xp : extended pointer on the file descriptor. 420 ///////////////////////////////////////////////////////////////////////////////////////// 421 static void socket_destroy( xptr_t file_xp ) 422 { 423 kmem_req_t req; 424 425 thread_t * this = CURRENT_THREAD; 426 process_t * process = this->process; 427 428 // check file_xp argument 429 assert( (file_xp != XPTR_NULL), "illegal argument\n" ); 430 431 // get cluster & local pointer for file descriptor 432 vfs_file_t * file_ptr = GET_PTR( file_xp ); 433 cxy_t file_cxy = GET_CXY( file_xp ); 434 435 #if DEBUG_SOCKET_DESTROY 436 uint32_t cycle = (uint32_t)hal_get_cycles(); 437 if( DEBUG_SOCKET_DESTROY < cycle ) 438 printk("\n[%s] thread[%x,%x] enter / file[%x,%x] / cycle %d\n", 439 __FUNCTION__, process->pid, this->trdid, file_cxy, file_ptr, cycle ); 440 #endif 441 442 // get local pointer for socket and file type 443 socket_t * socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 444 uint32_t file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 445 446 // check file descriptor type 447 assert( (file_type == INODE_TYPE_SOCK), "illegal file type\n" ); 448 449 // get socket nic_channel and fdid 450 uint32_t channel = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel )); 451 uint32_t fdid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid )); 452 453 // remove socket from NIC_TX & NIC_RX chdev queues when socket is connected 454 if( channel < LOCAL_CLUSTER->nb_nic_channels ) 455 { 456 socket_unlink_from_servers( XPTR( file_cxy , socket_ptr ) ); 457 } 458 459 // remove the file descriptor from the fd_array 460 process_fd_remove( process->owner_xp , fdid ); 461 462 // release memory allocated for file descriptor 463 req.type = KMEM_KCM; 464 req.ptr = file_ptr; 465 kmem_remote_free( file_cxy , &req ); 466 467 // release memory allocated for buffers attached to socket descriptor 468 remote_buf_destroy( XPTR( file_cxy , &socket_ptr->crqq ) ); 469 remote_buf_destroy( XPTR( file_cxy , &socket_ptr->r2tq ) ); 470 remote_buf_destroy( XPTR( file_cxy , &socket_ptr->rx_buf ) ); 471 472 // release memory allocated for socket descriptor 473 req.type = KMEM_KCM; 474 req.ptr = socket_ptr; 475 kmem_remote_free( file_cxy , &req ); 476 477 #if DEBUG_SOCKET_DESTROY 478 cycle = (uint32_t)hal_get_cycles(); 479 if( DEBUG_SOCKET_DESTROY < cycle ) 480 printk("\n[%s] thread[%x,%x] exit / cycle %d\n", 481 __FUNCTION__, process->pid, this->trdid, cycle ); 482 #endif 483 484 } // end socket_destroy() 485 486 //////////////////////////////////////////////// 487 void socket_put_r2t_request( xptr_t queue_xp, 488 uint32_t flags, 489 uint32_t channel ) 490 { 491 xptr_t chdev_xp; 492 cxy_t chdev_cxy; 493 chdev_t * chdev_ptr; 494 thread_t * server_ptr; 495 xptr_t server_xp; 496 497 while( 1 ) 498 { 499 // try to register R2T request 500 error_t error = remote_buf_put_from_kernel( queue_xp, 501 (uint8_t *)(&flags), 502 1 ); 503 if( error ) 504 { 505 // queue full => wait and retry 506 sched_yield( "waiting R2T queue" ); 507 } 508 else 509 { 510 // get NIC_TX chdev pointers 511 chdev_xp = chdev_dir.nic_tx[channel]; 512 chdev_cxy = GET_CXY( chdev_xp ); 513 chdev_ptr = GET_PTR( chdev_xp ); 216 514 217 #endif /* _SOCKET_H_ */ 515 // get NIC_TX server thread pointers 516 server_ptr = hal_remote_lpt( XPTR( chdev_cxy , &chdev_ptr->server ) ); 517 server_xp = XPTR( chdev_cxy , server_ptr ); 518 519 // unblocks NIC_TX server thread 520 thread_unblock( server_xp , THREAD_BLOCKED_CLIENT ); 521 522 return; 523 } 524 } 525 } // end socket_put_r2t_request() 526 527 /////////////////////////////////////////////////// 528 error_t socket_put_crq_request( xptr_t queue_xp, 529 uint32_t remote_addr, 530 uint32_t remote_port, 531 uint32_t remote_iss, 532 uint32_t remote_window ) 533 { 534 connect_request_t req; 535 536 // build request 537 req.addr = remote_addr; 538 req.port = remote_port; 539 req.iss = remote_iss; 540 req.window = remote_window; 541 542 // try to register request in CRQ 543 return remote_buf_put_from_kernel( queue_xp, 544 (uint8_t *)(&req), 545 sizeof(connect_request_t) ); 546 } // end socket_put_crq_request() 547 548 //////////////////////////////////////////////////// 549 error_t socket_get_crq_request( xptr_t queue_xp, 550 uint32_t * remote_addr, 551 uint32_t * remote_port, 552 uint32_t * remote_iss, 553 uint32_t * remote_window ) 554 { 555 connect_request_t req; 556 error_t error; 557 558 // get request from CRQ 559 error = remote_buf_get_to_kernel( queue_xp, 560 (uint8_t *)(&req), 561 sizeof(connect_request_t) ); 562 // extract request arguments 563 *remote_addr = req.addr; 564 *remote_port = req.port; 565 *remote_iss = req.iss; 566 *remote_window = req.window; 567 568 return error; 569 570 } // end socket_get_crq_request() 571 572 573 ///////////////////////////////////////////////////////////////////////////////////////// 574 // Functions implementing the SOCKET related syscalls 575 ///////////////////////////////////////////////////////////////////////////////////////// 576 577 ////////////////////////////////////// 578 int socket_build( uint32_t domain, 579 uint32_t type ) 580 { 581 uint32_t fdid; 582 socket_t * socket; 583 error_t error; 584 585 #if DEBUG_SOCKET_BUILD 586 uint32_t cycle = (uint32_t)hal_get_cycles(); 587 thread_t * this = CURRENT_THREAD; 588 process_t * process = this->process; 589 if( DEBUG_SOCKET_BUILD < cycle ) 590 printk("\n[%s] thread[%x,%x] enter / %s / %s / cycle %d\n", 591 __FUNCTION__, process->pid, this->trdid, 592 socket_domain_str(domain), socket_type_str(type), cycle ); 593 #endif 594 595 596 // allocate memory for the file descriptor and for the socket 597 error = socket_create( local_cxy, 598 domain, 599 type, 600 &socket, 601 &fdid ); 602 603 #if DEBUG_SOCKET_BUILD 604 cycle = (uint32_t)hal_get_cycles(); 605 if( DEBUG_SOCKET_BUILD < cycle ) 606 printk("\n[%s] thread[%x,%x] exit / socket %x / fdid %d / %s / cycle %d\n", 607 __FUNCTION__, process->pid, this->trdid, socket, fdid, 608 socket_state_str(hal_remote_l32(XPTR(local_cxy , &socket->state))), 609 cycle ); 610 #endif 611 612 if( error ) return -1; 613 return fdid; 614 } 615 616 //////////////////////////////// 617 int socket_bind( uint32_t fdid, 618 uint32_t addr, 619 uint16_t port ) 620 { 621 vfs_inode_type_t file_type; 622 socket_t * socket; 623 uint32_t socket_type; 624 uint32_t socket_state; 625 626 thread_t * this = CURRENT_THREAD; 627 process_t * process = this->process; 628 629 #if DEBUG_SOCKET_BIND 630 uint32_t cycle = (uint32_t)hal_get_cycles(); 631 if( DEBUG_SOCKET_BIND < cycle ) 632 printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / addr %x / port %x / cycle %d\n", 633 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, addr, port, cycle ); 634 #endif 635 636 // get pointers on file descriptor 637 xptr_t file_xp = process_fd_get_xptr_from_local( process , fdid ); 638 vfs_file_t * file_ptr = GET_PTR( file_xp ); 639 cxy_t file_cxy = GET_CXY( file_xp ); 640 641 // check file_xp 642 if( file_xp == XPTR_NULL ) 643 { 644 printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n", 645 __FUNCTION__, fdid, process->pid, this->trdid ); 646 return -1; 647 } 648 649 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 650 socket = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 651 652 // check file descriptor type 653 if( file_type != INODE_TYPE_SOCK ) 654 { 655 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]", 656 __FUNCTION__, vfs_inode_type_str( file_type ), process->pid, this->trdid ); 657 return -1; 658 } 659 660 // get socket type 661 socket_type = hal_remote_l32(XPTR( file_cxy , &socket->type )); 662 663 // compute socket state 664 socket_state = (socket_type == SOCK_STREAM) ? TCP_STATE_BOUND : UDP_STATE_BOUND; 665 666 // update the socket descriptor 667 hal_remote_s32( XPTR( file_cxy , &socket->local_addr ) , addr ); 668 hal_remote_s32( XPTR( file_cxy , &socket->local_port ) , port ); 669 hal_remote_s32( XPTR( file_cxy , &socket->state ) , socket_state ); 670 671 #if DEBUG_SOCKET_BIND 672 cycle = (uint32_t)hal_get_cycles(); 673 if( DEBUG_SOCKET_BIND < cycle ) 674 printk("\n[%s] thread[%x,%x] exit / socket[%x,%d] / %s / addr %x / port %x / cycle %d\n", 675 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, 676 socket_state_str(hal_remote_l32( XPTR( file_cxy , &socket->state ))), 677 hal_remote_l32( XPTR( file_cxy , &socket->local_addr )), 678 hal_remote_l32( XPTR( file_cxy , &socket->local_port )), 679 cycle ); 680 #endif 681 682 return 0; 683 684 } // end socket_bind() 685 686 ////////////////////////////////// 687 int socket_listen( uint32_t fdid, 688 uint32_t crq_depth ) 689 { 690 xptr_t file_xp; 691 vfs_file_t * file_ptr; 692 cxy_t file_cxy; 693 vfs_inode_type_t file_type; 694 socket_t * socket_ptr; 695 uint32_t socket_type; 696 uint32_t socket_state; 697 uint32_t socket_local_addr; 698 uint32_t socket_local_port; 699 error_t error; 700 701 thread_t * this = CURRENT_THREAD; 702 process_t * process = this->process; 703 704 #if DEBUG_SOCKET_LISTEN 705 uint32_t cycle = (uint32_t)hal_get_cycles(); 706 if( DEBUG_SOCKET_LISTEN < cycle ) 707 printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / crq_depth %x / cycle %d\n", 708 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, crq_depth, cycle ); 709 #endif 710 711 // get pointers on file descriptor 712 file_xp = process_fd_get_xptr_from_local( process , fdid ); 713 file_ptr = GET_PTR( file_xp ); 714 file_cxy = GET_CXY( file_xp ); 715 716 // check file_xp 717 if( file_xp == XPTR_NULL ) 718 { 719 printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n", 720 __FUNCTION__, fdid, process->pid, this->trdid ); 721 return -1; 722 } 723 724 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 725 socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 726 727 // check file descriptor type 728 if( file_type != INODE_TYPE_SOCK ) 729 { 730 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n", 731 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid ); 732 return -1; 733 } 734 735 // get relevant infos from <fdid> socket descriptor 736 socket_type = hal_remote_l32( XPTR( file_cxy , &socket_ptr->type )); 737 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); 738 socket_local_addr = hal_remote_l32( XPTR( file_cxy , &socket_ptr->local_addr )); 739 socket_local_port = hal_remote_l32( XPTR( file_cxy , &socket_ptr->local_port )); 740 741 // check socket type 742 if( socket_type != SOCK_STREAM ) 743 { 744 printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n", 745 __FUNCTION__, socket_type_str(socket_type), process->pid, this->trdid ); 746 return -1; 747 } 748 749 // check socket state 750 if( socket_state != TCP_STATE_BOUND ) 751 { 752 printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n", 753 __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid ); 754 return -1; 755 } 756 757 // compute CRQ queue depth : max( crq_depth , NIC_CRQ_QUEUE_SIZE ) 758 uint32_t depth = ( crq_depth > NIC_CRQ_QUEUE_SIZE ) ? crq_depth : NIC_CRQ_QUEUE_SIZE; 759 760 // allocate memory for the CRQ queue 761 error = remote_buf_init( XPTR( file_cxy , &socket_ptr->crqq ), 762 depth * sizeof(connect_request_t) ); 763 if( error ) 764 { 765 printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x]\n", 766 __FUNCTION__, process->pid, this->trdid ); 767 return -1; 768 } 769 770 // update socket.state 771 hal_remote_s32( XPTR( file_cxy , &socket_ptr->state ) , TCP_STATE_LISTEN ); 772 773 // get pointers on NIC_RX[0] chdev 774 xptr_t rx0_chdev_xp = chdev_dir.nic_rx[0]; 775 chdev_t * rx0_chdev_ptr = GET_PTR( rx0_chdev_xp ); 776 cxy_t rx0_chdev_cxy = GET_CXY( rx0_chdev_xp ); 777 778 // build extended pointers on list of listening sockets 779 xptr_t rx0_root_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.root ); 780 xptr_t rx0_lock_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.lock ); 781 782 // build extended pointer on socket rx_list field 783 xptr_t list_entry_xp = XPTR( file_cxy , &socket_ptr->rx_list ); 784 785 // register <fdid> socket in listening sockets list 786 remote_busylock_acquire( rx0_lock_xp ); 787 xlist_add_last( rx0_root_xp , list_entry_xp ); 788 remote_busylock_release( rx0_lock_xp ); 789 790 #if DEBUG_SOCKET_LISTEN 791 cycle = (uint32_t)hal_get_cycles(); 792 if( DEBUG_SOCKET_LISTEN < cycle ) 793 printk("\n[%s] thread[%x,%x] exit / socket[%x,%d] / %s / cycle %d\n", 794 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, 795 socket_state_str(socket_state), cycle ); 796 #endif 797 798 return 0; 799 800 } // end socket_listen() 801 802 /////////////////////////////////// 803 int socket_accept( uint32_t fdid, 804 uint32_t * remote_addr, 805 uint16_t * remote_port ) 806 { 807 xptr_t file_xp; // extended pointer on remote file 808 vfs_file_t * file_ptr; 809 cxy_t file_cxy; 810 vfs_inode_type_t file_type; // file descriptor type 811 socket_t * socket_ptr; // local pointer on remote waiting socket 812 uint32_t socket_type; // listening socket type 813 uint32_t socket_state; // listening socket state 814 uint32_t socket_domain; // listening socket domain 815 uint32_t socket_local_addr; // listening socket local IP address 816 uint32_t socket_local_port; // listening socket local port 817 uint32_t socket_tx_nxt; // listening socket tx_nxt 818 bool_t socket_tx_valid; // listening socket tx_valid 819 xptr_t socket_tx_client; // listening socket tx_client thread 820 bool_t socket_rx_valid; // listening socket rx_valid 821 xptr_t socket_rx_client; // listening socket rx_client thread 822 xptr_t socket_lock_xp; // listening socket lock 823 xptr_t crq_xp; // listening socket CRQ queue 824 uint32_t crq_status; // number of bytes in CRQ 825 cxy_t new_socket_cxy; // new socket cluster identifier 826 socket_t * new_socket_ptr; // local pointer on new socket 827 xptr_t new_socket_xp; // extended pointer on new socket 828 volatile uint32_t new_state; // new socket state (modified by NIC_RX thread) 829 uint32_t new_fdid; // new socket file descriptor index 830 uint32_t new_remote_addr; // new socket remote IP address 831 uint32_t new_remote_port; // new socket remote port 832 uint32_t new_remote_iss; // new socket remote iss 833 uint32_t new_remote_window; // new socket receive window 834 xptr_t tx_server_xp; // extended pointer on TX server thread 835 thread_t * tx_server_ptr; // local pointer on TX server thread 836 uint32_t cmd_status; // command status (rx_sts or tx_sts) 837 bool_t cmd_valid; // valid command (rx_valid or tx_valid) 838 error_t error; 839 840 thread_t * this = CURRENT_THREAD; 841 xptr_t client_xp = XPTR( local_cxy , this ); 842 process_t * process = this->process; 843 844 #if DEBUG_SOCKET_ACCEPT 845 uint32_t cycle = (uint32_t)hal_get_cycles(); 846 if( DEBUG_SOCKET_ACCEPT < cycle ) 847 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / cycle %d\n", 848 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 849 #endif 850 851 // 1) get pointers on file descriptor 852 file_xp = process_fd_get_xptr_from_local( process , fdid ); 853 file_ptr = GET_PTR( file_xp ); 854 file_cxy = GET_CXY( file_xp ); 855 856 // check file_xp 857 if( file_xp == XPTR_NULL ) 858 { 859 printk("\n[ERROR] in %s : undefined fdid %d", 860 __FUNCTION__, fdid ); 861 return -1; 862 } 863 864 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 865 socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 866 867 // check file descriptor type 868 if( file_type != INODE_TYPE_SOCK ) 869 { 870 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n", 871 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid ); 872 return -1; 873 } 874 875 // build extended pointer on listening socket lock 876 socket_lock_xp = XPTR( file_cxy , &socket_ptr->lock ); 877 878 // acquire listening socket lock 879 remote_queuelock_acquire( socket_lock_xp ); 880 881 // get listening socket type, domain, state, local_addr, local_port & tx_nxt 882 socket_type = hal_remote_l32( XPTR( file_cxy , &socket_ptr->type )); 883 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); 884 socket_domain = hal_remote_l32( XPTR( file_cxy , &socket_ptr->domain )); 885 socket_local_addr = hal_remote_l32( XPTR( file_cxy , &socket_ptr->local_addr )); 886 socket_local_port = hal_remote_l32( XPTR( file_cxy , &socket_ptr->local_port )); 887 socket_tx_nxt = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_nxt )); 888 socket_tx_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )); 889 socket_tx_client = hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client )); 890 socket_rx_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )); 891 socket_rx_client = hal_remote_l64( XPTR( file_cxy , &socket_ptr->rx_client )); 892 893 // check socket type 894 if( socket_type != SOCK_STREAM ) 895 { 896 // release listening socket lock 897 remote_queuelock_release( socket_lock_xp ); 898 899 printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n", 900 __FUNCTION__, socket_type_str(socket_type), process->pid , this->trdid ); 901 return -1; 902 } 903 904 // check socket state 905 if( socket_state != TCP_STATE_LISTEN ) 906 { 907 // release listening socket lock 908 remote_queuelock_release( socket_lock_xp ); 909 910 printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n", 911 __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid ); 912 return -1; 913 } 914 915 // check no previous RX command 916 if( (socket_rx_valid == true) || (socket_rx_client != XPTR_NULL) ) 917 { 918 // release listening socket lock 919 remote_queuelock_release( socket_lock_xp ); 920 921 printk("\n[ERROR] in %s : previous RX cmd on socket[%x,%d] / thread[%x,%x]\n", 922 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 923 return -1; 924 } 925 926 // check no previous TX command 927 if( (socket_tx_valid == true) || (socket_tx_client != XPTR_NULL) ) 928 { 929 // release socket lock 930 remote_queuelock_release( socket_lock_xp ); 931 932 printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n", 933 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 934 return -1; 935 } 936 937 // 2) build extended pointer on listening socket.crq 938 crq_xp = XPTR( file_cxy , &socket_ptr->crqq ); 939 940 // get CRQ status 941 crq_status = remote_buf_status( crq_xp ); 942 943 // block & deschedule when CRQ empty 944 if( crq_status == 0 ) 945 { 946 // register command arguments in listening socket 947 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_cmd ), CMD_RX_ACCEPT ); 948 hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client ), client_xp ); 949 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_valid ), true ); 950 951 // release listening socket lock 952 remote_queuelock_release( socket_lock_xp ); 953 954 #if DEBUG_SOCKET_ACCEPT 955 cycle = (uint32_t)hal_get_cycles(); 956 if( DEBUG_SOCKET_ACCEPT < cycle ) 957 printk("\n[%s] thread[%x,%x] socket[%x,%d] / CRQ empty => blocks on <IO> / cycle %d\n", 958 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 959 #endif 960 // block & deschedule when CRQQ empty 961 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_IO ); 962 sched_yield( "CRQ queue empty"); 963 964 #if DEBUG_SOCKET_ACCEPT 965 cycle = (uint32_t)hal_get_cycles(); 966 if( DEBUG_SOCKET_ACCEPT < cycle ) 967 printk("\n[%s] thread[%x,%x] socket[%x,%d] / resumes / cycle %d\n", 968 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 969 #endif 970 // take listening socket lock 971 remote_queuelock_acquire( socket_lock_xp ); 972 973 // get CRQ status & command status 974 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid ) ); 975 cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts ) ); 976 crq_status = remote_buf_status( crq_xp ); 977 978 assert( (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)), 979 "illegal socket state when client thread resumes after RX_ACCEPT" ); 980 981 // reset socket.rx_client 982 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_client ) , XPTR_NULL ); 983 984 if( cmd_status != CMD_STS_SUCCESS ) 985 { 986 // release socket lock 987 remote_queuelock_release( socket_lock_xp ); 988 989 printk("\n[ERROR] in %s for RX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n", 990 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 991 return -1; 992 } 993 994 // extract first request from the listening socket CRQ 995 error = socket_get_crq_request( crq_xp, 996 &new_remote_addr, 997 &new_remote_port, 998 &new_remote_iss, 999 &new_remote_window ); 1000 1001 assert( (error == 0), 1002 "cannot get a connection request from a non-empty CRQ" ); 1003 1004 // reset listening socket rx_client 1005 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_client ) , XPTR_NULL ); 1006 1007 // release socket lock 1008 remote_queuelock_release( socket_lock_xp ); 1009 1010 } // end blocking on CRQ status 1011 1012 // from this point, we can create a new socket 1013 // and ask the NIC_TX to send a SYN-ACK segment 1014 1015 #if DEBUG_SOCKET_ACCEPT 1016 cycle = (uint32_t)hal_get_cycles(); 1017 if( DEBUG_SOCKET_ACCEPT < cycle ) 1018 printk("\n[%s] thread[%x,%x] socket[%x,%d] / got a CRQ request / cycle %d\n", 1019 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1020 #endif 1021 1022 // 3) select a cluster for the new socket 1023 new_socket_cxy = cluster_random_select(); 1024 1025 // allocate memory for the new socket descriptor 1026 error = socket_create( new_socket_cxy, 1027 socket_domain, 1028 socket_type, 1029 &new_socket_ptr, 1030 &new_fdid ); 1031 if( error ) 1032 { 1033 printk("\n[ERROR] in %s : cannot allocate new socket / thread[%x,%x]\n", 1034 __FUNCTION__, process->pid, this->trdid ); 1035 return -1; 1036 } 1037 1038 // build extended poiner on new socket 1039 new_socket_xp = XPTR( new_socket_cxy , new_socket_ptr ); 1040 1041 #if DEBUG_SOCKET_ACCEPT 1042 cycle = (uint32_t)hal_get_cycles(); 1043 if( DEBUG_SOCKET_ACCEPT < cycle ) 1044 printk("\n[%s] thread[%x,%x] created new socket[%x,%d] / cycle %d\n", 1045 __FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle ); 1046 #endif 1047 1048 // compute NIC channel index from remote_addr and remote_port 1049 uint32_t new_nic_channel = dev_nic_get_key( new_remote_addr , new_remote_port ); 1050 1051 // update new socket descriptor 1052 hal_remote_s32(XPTR(new_socket_cxy , &new_socket_ptr->local_addr ) , socket_local_addr ); 1053 hal_remote_s32(XPTR(new_socket_cxy , &new_socket_ptr->local_port ) , socket_local_port ); 1054 hal_remote_s32(XPTR(new_socket_cxy , &new_socket_ptr->remote_addr) , new_remote_addr ); 1055 hal_remote_s32(XPTR(new_socket_cxy , &new_socket_ptr->remote_port) , new_remote_port ); 1056 hal_remote_s32(XPTR(new_socket_cxy , &new_socket_ptr->nic_channel) , new_nic_channel ); 1057 hal_remote_s32(XPTR(new_socket_cxy , &new_socket_ptr->state ) , TCP_STATE_SYN_RCVD ); 1058 1059 // set new socket TCB : increment tx_nxt / initialize rx_nxt, rx_irs, rx_wnd 1060 hal_remote_s32( XPTR( new_socket_cxy , &new_socket_ptr->tx_nxt ), socket_tx_nxt + 1 ); 1061 hal_remote_s32( XPTR( new_socket_cxy , &new_socket_ptr->rx_nxt ), new_remote_iss + 1 ); 1062 hal_remote_s32( XPTR( new_socket_cxy , &new_socket_ptr->rx_irs ), new_remote_iss ); 1063 hal_remote_s32( XPTR( new_socket_cxy , &new_socket_ptr->rx_wnd ), new_remote_window ); 1064 1065 // link new socket to chdev servers 1066 socket_link_to_servers( new_socket_xp , new_nic_channel ); 1067 1068 // 3) get pointers on NIC_TX[channel] chdev 1069 xptr_t tx_chdev_xp = chdev_dir.nic_tx[new_nic_channel]; 1070 chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp ); 1071 cxy_t tx_chdev_cxy = GET_CXY( tx_chdev_xp ); 1072 1073 // get pointers on NIC_TX[channel] server thread 1074 tx_server_ptr = hal_remote_lpt( XPTR( tx_chdev_cxy , &tx_chdev_ptr->server )); 1075 tx_server_xp = XPTR( tx_chdev_cxy , tx_server_ptr ); 1076 1077 // register command arguments in new socket to request a SYN_ACK segment 1078 hal_remote_s32( XPTR( new_socket_cxy , &new_socket_ptr->tx_cmd ), CMD_TX_ACCEPT ); 1079 hal_remote_s64( XPTR( new_socket_cxy , &new_socket_ptr->tx_client ), client_xp ); 1080 hal_remote_s32( XPTR( new_socket_cxy , &new_socket_ptr->tx_valid ), true ); 1081 1082 // unblock NIC_TX server thread 1083 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 1084 1085 #if DEBUG_SOCKET_ACCEPT 1086 cycle = (uint32_t)hal_get_cycles(); 1087 if( DEBUG_SOCKET_ACCEPT < cycle ) 1088 printk("\n[%s] thread[%x,%x] new_socket[%x,%d] blocks on <IO> waiting ESTAB / cycle %d\n", 1089 __FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle ); 1090 #endif 1091 1092 // client thread blocks & deschedules 1093 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_IO ); 1094 sched_yield( "waiting new socket connection"); 1095 1096 #if DEBUG_SOCKET_ACCEPT 1097 cycle = (uint32_t)hal_get_cycles(); 1098 if( DEBUG_SOCKET_ACCEPT < cycle ) 1099 printk("\n[%s] thread[%x,%x] new_socket[%x,%d] resumes / cycle %d\n", 1100 __FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle ); 1101 #endif 1102 1103 // get new socket state, tx_valid and tx_sts 1104 new_state = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->state )); 1105 cmd_valid = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->tx_valid )); 1106 cmd_status = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->tx_sts )); 1107 1108 assert( (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS)) 1109 && (cmd_valid == false)), 1110 "illegal socket state when client thread resumes after TX_ACCEPT" ); 1111 1112 // reset socket.tx_client 1113 hal_remote_s64( XPTR( new_socket_cxy , &new_socket_ptr->tx_client ) , XPTR_NULL ); 1114 1115 if( cmd_status != CMD_STS_SUCCESS ) 1116 { 1117 printk("\n[ERROR] in %s for TX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n", 1118 __FUNCTION__, process->pid, new_fdid, process->pid, this->trdid ); 1119 return -1; 1120 } 1121 else 1122 { 1123 1124 #if DEBUG_SOCKET_ACCEPT 1125 cycle = (uint32_t)hal_get_cycles(); 1126 if( DEBUG_SOCKET_ACCEPT < cycle ) 1127 printk("\n[%s] thread[%x,%x] new_socket[%x,%d] / state %s / addr %x / port %x / cycle %d\n", 1128 __FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, 1129 socket_state_str(new_state), new_remote_addr, new_remote_port, cycle ); 1130 #endif 1131 1132 // return success 1133 *remote_addr = new_remote_addr; 1134 *remote_port = new_remote_port; 1135 return new_fdid; 1136 } 1137 1138 } // end socket_accept() 1139 1140 ////////////////////////////////// 1141 int socket_connect( uint32_t fdid, 1142 uint32_t remote_addr, 1143 uint16_t remote_port ) 1144 { 1145 vfs_inode_type_t file_type; 1146 socket_t * socket_ptr; // local pointer on thread descriptor 1147 volatile uint32_t socket_state; // socket state (modified by the NIC_TX thread) 1148 uint32_t socket_type; // socket type 1149 uint32_t local_addr; // local IP address 1150 uint32_t local_port; // local port 1151 xptr_t tx_server_xp; // extended pointer on TX server thread 1152 thread_t * tx_server_ptr; // local pointer on TX server thread 1153 uint32_t nic_channel; // NIC channel index 1154 uint32_t cmd_status; // command status (tx_sts field) 1155 bool_t cmd_valid; // command valid (tx_valid field) 1156 1157 thread_t * this = CURRENT_THREAD; 1158 xptr_t client_xp = XPTR( local_cxy , this ); 1159 1160 // get pointers on file descriptor 1161 xptr_t file_xp = process_fd_get_xptr_from_local( this->process , fdid ); 1162 vfs_file_t * file_ptr = GET_PTR( file_xp ); 1163 cxy_t file_cxy = GET_CXY( file_xp ); 1164 1165 // check file_xp 1166 if( file_xp == XPTR_NULL ) 1167 { 1168 printk("\n[ERROR] in %s : undefined fdid %d", 1169 __FUNCTION__, fdid ); 1170 return -1; 1171 } 1172 1173 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 1174 socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 1175 1176 #if DEBUG_SOCKET_CONNECT 1177 uint32_t cycle = (uint32_t)hal_get_cycles(); 1178 pid_t pid = this->process->pid; 1179 trdid_t trdid = this->trdid; 1180 if( DEBUG_SOCKET_CONNECT < cycle ) 1181 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / addr %x / port %d / cycle %d\n", 1182 __FUNCTION__, pid, trdid, pid, fdid, remote_addr, remote_port, cycle ); 1183 #endif 1184 1185 // check file descriptor type 1186 if( file_type != INODE_TYPE_SOCK ) 1187 { 1188 printk("\n[ERROR] in %s : illegal file type %s", 1189 __FUNCTION__, vfs_inode_type_str( file_type ) ); 1190 return -1; 1191 } 1192 1193 // get relevant socket infos 1194 socket_type = hal_remote_l32( XPTR( file_cxy , &socket_ptr->type ) ); 1195 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state ) ); 1196 local_addr = hal_remote_l32( XPTR( file_cxy , &socket_ptr->local_addr ) ); 1197 local_port = hal_remote_l32( XPTR( file_cxy , &socket_ptr->local_port ) ); 1198 1199 if( socket_type == SOCK_DGRAM ) // UDP 1200 { 1201 if( socket_state != UDP_STATE_BOUND ) 1202 { 1203 printk("\n[ERROR] in %s : illegal socket state %s for type %s", 1204 __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) ); 1205 return -1; 1206 } 1207 } 1208 else if( socket_type == SOCK_STREAM ) // TCP 1209 { 1210 if( socket_state != TCP_STATE_BOUND ) 1211 { 1212 printk("\n[ERROR] in %s : illegal socket state %s for type %s", 1213 __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) ); 1214 return -1; 1215 } 1216 } 1217 else 1218 { 1219 printk("\n[ERROR] in %s : illegal socket type %s", 1220 __FUNCTION__, socket_type_str(socket_type) ); 1221 return -1; 1222 } 1223 1224 // compute nic_channel index from remote_addr and remote_port 1225 nic_channel = dev_nic_get_key( remote_addr , remote_port ); 1226 1227 // link socket to chdev servers 1228 socket_link_to_servers( XPTR( file_cxy , socket_ptr ), nic_channel ); 1229 1230 // update the socket descriptor 1231 hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_addr ) , remote_addr ); 1232 hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_port ) , remote_port ); 1233 hal_remote_s32( XPTR( file_cxy , &socket_ptr->nic_channel ) , nic_channel ); 1234 1235 // the actual connection mechanism depends on socket type 1236 // UDP : client thread updates the local socket state without blocking 1237 // TCP : client thread request TX server thread to start the 3 steps handshake 1238 1239 if( socket_type == SOCK_DGRAM ) // UDP 1240 { 1241 // directly update the local socket state 1242 hal_remote_s32( XPTR( file_cxy , &socket_ptr->state ) , UDP_STATE_ESTAB ); 1243 1244 return 0; 1245 } 1246 else // TCP 1247 { 1248 // get pointers on NIC_TX[channel] chdev 1249 xptr_t tx_chdev_xp = chdev_dir.nic_tx[nic_channel]; 1250 chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp ); 1251 cxy_t tx_chdev_cxy = GET_CXY( tx_chdev_xp ); 1252 1253 // get pointers on NIC_TX[channel] server thread 1254 tx_server_ptr = hal_remote_lpt( XPTR( tx_chdev_cxy , &tx_chdev_ptr->server )); 1255 tx_server_xp = XPTR( tx_chdev_cxy , tx_server_ptr ); 1256 1257 // register command arguments in socket descriptor for a SYN segment 1258 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_cmd ), CMD_TX_CONNECT ); 1259 hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ), client_xp ); 1260 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid ), true ); 1261 1262 // unblock NIC_TX server thread 1263 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 1264 1265 #if DEBUG_SOCKET_CONNECT 1266 cycle = (uint32_t)hal_get_cycles(); 1267 if( DEBUG_SOCKET_CONNECT < cycle ) 1268 printk("\n[%s] thread[%x,%x] socket[%x,%d] blocks on <IO> waiting connexion / cycle %d \n", 1269 __FUNCTION__, pid, trdid, pid, fdid, cycle ); 1270 #endif 1271 // block itself and deschedule 1272 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_IO ); 1273 sched_yield( "waiting connection" ); 1274 1275 #if DEBUG_SOCKET_CONNECT 1276 cycle = (uint32_t)hal_get_cycles(); 1277 if( DEBUG_SOCKET_CONNECT < cycle ) 1278 printk("\n[%s] thread[%x,%x] socket[%x,%d] / resumes / cycle %d \n", 1279 __FUNCTION__, pid, trdid, pid, fdid, cycle ); 1280 #endif 1281 1282 // get socket state, tx_valid and tx_sts 1283 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )); 1284 cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts )); 1285 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); 1286 1287 assert( (((socket_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS)) 1288 && (cmd_valid == false)), 1289 "illegal socket state when client thread resumes after TX_CONNECT" ); 1290 1291 // reset socket.tx_client 1292 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL ); 1293 1294 if( cmd_status != CMD_STS_SUCCESS ) 1295 { 1296 printk("\n[ERROR] in %s : for command TX_CONNECT / socket[%x,%d] / thread[%x,%x]\n", 1297 __FUNCTION__, pid, fdid, pid, trdid ); 1298 return -1; 1299 } 1300 else 1301 { 1302 1303 #if DEBUG_SOCKET_CONNECT 1304 cycle = (uint32_t)hal_get_cycles(); 1305 if( DEBUG_SOCKET_CONNECT < cycle ) 1306 printk("\n[%s] thread[%x,%x] exit for socket[%x,%d] / %s / cycle %d \n", 1307 __FUNCTION__, pid, trdid, pid, fdid, socket_state_str(socket_state),cycle ); 1308 #endif 1309 return 0; 1310 } 1311 } // end TCP 1312 1313 } // end socket_connect() 1314 1315 /////////////////////////////////// 1316 int socket_close( xptr_t file_xp, 1317 uint32_t fdid ) 1318 { 1319 uint32_t socket_type; 1320 uint32_t socket_state; 1321 uint32_t nic_channel; 1322 uint32_t cmd_status; // socket.tx_sts 1323 bool_t cmd_valid; // socket.tx_valid 1324 thread_t * tx_server_ptr; // local pointer on NIC_TX server thread 1325 xptr_t tx_server_xp; // extended pointer on NIC_TX server thread 1326 xptr_t socket_lock_xp; // extended pointer on socket lock 1327 1328 thread_t * this = CURRENT_THREAD; 1329 xptr_t client_xp = XPTR( local_cxy , this ); 1330 process_t * process = this->process; 1331 1332 // get pointer on socket descriptor 1333 cxy_t file_cxy = GET_CXY( file_xp ); 1334 vfs_file_t * file_ptr = GET_PTR( file_xp ); 1335 socket_t * socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 1336 1337 assert( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid )) == fdid), 1338 "unconsistent file_xp & fdid arguments"); 1339 1340 #if DEBUG_SOCKET_CLOSE 1341 uint32_t cycle = (uint32_t)hal_get_cycles(); 1342 pid_t pid = this->process->pid; 1343 if (DEBUG_SOCKET_CLOSE < cycle ) 1344 printk("\n[%s] thread[%x,%x] enters for socket[%x,%d] / cycle %d\n", 1345 __FUNCTION__, pid, this->trdid, pid, fdid, cycle ); 1346 #endif 1347 1348 // build extended pointer on lock protecting socket 1349 socket_lock_xp = XPTR( file_cxy , &socket_ptr->lock ); 1350 1351 // take socket lock 1352 remote_queuelock_acquire( socket_lock_xp ); 1353 1354 // check no previous TX command 1355 if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true) || 1356 (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) ) 1357 { 1358 // release socket lock 1359 remote_queuelock_release( socket_lock_xp ); 1360 1361 printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n", 1362 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 1363 return -1; 1364 } 1365 1366 // get relevant socket infos 1367 socket_type = hal_remote_l32( XPTR( file_cxy , &socket_ptr->type )); 1368 nic_channel = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel )); 1369 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); 1370 1371 1372 // the actual close mechanism depends on socket type and state: 1373 // UDP or TCP not connected : client thread directly destroy the socket descriptor 1374 // TCP connected : client thread request TX server thread to make the TCP close handshake 1375 1376 if( socket_type == SOCK_DGRAM ) // UDP 1377 { 1378 1379 #if DEBUG_SOCKET_CLOSE 1380 cycle = (uint32_t)hal_get_cycles(); 1381 if( cycle > DEBUG_DEV_NIC_TX ) 1382 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / destroy socket / cycle %d\n", 1383 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, 1384 socket_state_str( socket_state ), cycle ); 1385 #endif 1386 // directly destroy socket 1387 socket_destroy( file_xp ); 1388 1389 return 0; 1390 } 1391 else if( (socket_state == TCP_STATE_BOUND) || 1392 (socket_state == TCP_STATE_LISTEN) || 1393 (socket_state == TCP_STATE_SYN_SENT) ) // TCP not connected 1394 { 1395 1396 #if DEBUG_SOCKET_CLOSE 1397 cycle = (uint32_t)hal_get_cycles(); 1398 if( cycle > DEBUG_DEV_NIC_TX ) 1399 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / destroy socket / cycle %d\n", 1400 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, 1401 socket_state_str( socket_state ), cycle ); 1402 #endif 1403 // directly destroy socket 1404 socket_destroy( file_xp ); 1405 1406 return 0; 1407 } 1408 else // TCP connected 1409 { 1410 // get pointers on NIC_TX[index] chdev 1411 xptr_t tx_chdev_xp = chdev_dir.nic_tx[nic_channel]; 1412 chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp ); 1413 cxy_t tx_chdev_cxy = GET_CXY( tx_chdev_xp ); 1414 1415 // get pointers on NIC_TX[channel] server thread 1416 tx_server_ptr = hal_remote_lpt( XPTR( tx_chdev_cxy , &tx_chdev_ptr->server )); 1417 tx_server_xp = XPTR( tx_chdev_cxy , tx_server_ptr ); 1418 1419 // register command arguments in socket descriptor 1420 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_cmd ), CMD_TX_CLOSE ); 1421 hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ), client_xp ); 1422 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid ), true ); 1423 1424 // unblock NIC_TX server thread 1425 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 1426 1427 // release socket lock 1428 remote_queuelock_release( socket_lock_xp ); 1429 1430 #if DEBUG_SOCKET_CLOSE 1431 cycle = (uint32_t)hal_get_cycles(); 1432 if( DEBUG_SOCKET_CLOSE < cycle ) 1433 printk("\n[%s] thread[%x,%x] socket[%x,%d] blocks on <IO> waiting close / cycle %d \n", 1434 __FUNCTION__, pid, this->trdid, pid, fdid, cycle ); 1435 #endif 1436 // block itself and deschedule 1437 thread_block( client_xp , THREAD_BLOCKED_IO ); 1438 sched_yield( "blocked in close" ); 1439 1440 #if DEBUG_SOCKET_CLOSE 1441 cycle = (uint32_t)hal_get_cycles(); 1442 if( DEBUG_SOCKET_CLOSE < cycle ) 1443 printk("\n[%s] thread[%x,%x] socket[%x,%d] / resumes / cycle %d \n", 1444 __FUNCTION__, pid, this->trdid, pid, fdid, cycle ); 1445 #endif 1446 // take socket lock 1447 remote_queuelock_acquire( socket_lock_xp ); 1448 1449 // get socket state & command status 1450 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state ) ); 1451 cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts) ); 1452 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ) ); 1453 1454 assert( (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS)) 1455 && (cmd_valid == false)), 1456 "illegal socket state when client thread resumes after TX_CLOSE\n" 1457 " socket_state = %s / cmd_status = %d / cmd_valid = %d\n", 1458 socket_state_str(socket_state), cmd_status, cmd_valid ); 1459 1460 // reset socket.tx_client 1461 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL ); 1462 1463 if( cmd_status != CMD_STS_SUCCESS ) // error reported 1464 { 1465 printk("\n[ERROR] in %s for command TX_CLOSE / socket[%x,%d] / thread[%x,%x]\n", 1466 __FUNCTION__, pid, fdid, pid, this->trdid ); 1467 return -1; 1468 } 1469 else // success 1470 { 1471 1472 #if DEBUG_SOCKET_CLOSE 1473 cycle = (uint32_t)hal_get_cycles(); 1474 if( DEBUG_SOCKET_CLOSE < cycle ) 1475 printk("\n[%s] thread[%x,%x] socket[%x,%d] / destroy socket / cycle %d\n", 1476 __FUNCTION__, pid, this->trdid, pid, fdid, socket_state_str(socket_state) , cycle ); 1477 #endif 1478 // destroy socket 1479 socket_destroy( file_xp ); 1480 1481 return 0; 1482 } 1483 } // end if TCP 1484 } // end socket_close() 1485 1486 //////////////////////////////////////////////////////////////////////////////////////// 1487 // This static and blocking function is executed by an user thread calling one of the 1488 // four functions: socket_send() / socket_recv() / socket_sendto() / socket_recvfrom() 1489 // It can be used for both UDP and TCP sockets. 1490 //////////////////////////////////////////////////////////////////////////////////////// 1491 // @ is_send : send when true / receive when false. 1492 // @ fdid : socket identifier. 1493 // @ u_buf : pointer on user buffer in user space. 1494 // @ length : number of bytes. 1495 // @ explicit : explicit remote IP address and port when true. 1496 //////////////////////////////////////////////////////////////////////////////////////// 1497 // Implementation note : The behavior is different for SEND & RECV 1498 // - For a SEND, the client thread checks that there is no TX command registered 1499 // in the socket. It registers the command arguments in the socket descriptor 1500 // (tx_client, tx_cmd, tx_buf, tx_len). Then the client thread unblocks the 1501 // TX server thread from the BLOCKED_CLIENT condition, blocks itself on the 1502 // BLOCKED_IO condition, and deschedules. It is unblocked by the TX server thread 1503 // when the last byte has been sent (for UDP) or acknowledged (for TCP). 1504 // When the client thread resumes, it reset the command in socket, and returns. 1505 // - For a RECV, the client thread checks that there is no RX command registered 1506 // in the socket. It registers itself in socket (rx_client). It checks the status 1507 // of the receive buffer. It the rx_buf is empty, it blocks on the BLOCKED_IO 1508 // condition, and deschedules. It is unblocked by the RX server thread when an UDP 1509 // packet or TCP segment has been writen in the rx_buf. When it resumes, it moves 1510 // the available data from the rx_buf to the user buffer, reset its registration 1511 // in socket (reset the rx_buf for an UDP socket), and returns. 1512 //////////////////////////////////////////////////////////////////////////////////////// 1513 int socket_move_data( bool_t is_send, 1514 uint32_t fdid, 1515 uint8_t * u_buf, 1516 uint32_t length, 1517 bool_t explicit, 1518 uint32_t explicit_addr, 1519 uint32_t explicit_port ) 1520 { 1521 vfs_inode_type_t file_type; // file descriptor type 1522 socket_t * socket_ptr; // local pointer on socket descriptor 1523 uint32_t socket_state; // current socket state 1524 uint32_t socket_type; // socket type (UDP/TCP) 1525 uint32_t nic_channel; // NIC channel for this socket 1526 xptr_t socket_lock_xp; // extended pointer on socket lock 1527 xptr_t file_xp; // extended pointer on file descriptor 1528 vfs_file_t * file_ptr; 1529 cxy_t file_cxy; 1530 xptr_t chdev_xp; // extended pointer on NIC_TX[channel] chdev 1531 chdev_t * chdev_ptr; 1532 cxy_t chdev_cxy; 1533 uint32_t remote_addr; 1534 uint32_t remote_port; 1535 uint32_t buf_status; // number of bytes in rx_buf 1536 int32_t moved_bytes; // total number of moved bytes (fot return) 1537 xptr_t server_xp; // extended pointer on NIC_TX / NIC_RX server thread 1538 thread_t * server_ptr; // local pointer on NIC_TX / NIC_RX server thread 1539 kmem_req_t req; // KCM request for TX kernel buffer 1540 uint8_t * tx_buf; // kernel buffer for TX transfer 1541 bool_t cmd_valid; // from socket descriptor 1542 uint32_t cmd_status; // from socket descriptor 1543 uint32_t tx_todo; // from socket descriptor 1544 1545 thread_t * this = CURRENT_THREAD; 1546 process_t * process = this->process; 1547 1548 // build extended pointer on client thread 1549 xptr_t client_xp = XPTR( local_cxy , this ); 1550 1551 // get pointers on file descriptor identifying the socket 1552 file_xp = process_fd_get_xptr_from_local( process , fdid ); 1553 file_ptr = GET_PTR( file_xp ); 1554 file_cxy = GET_CXY( file_xp ); 1555 1556 if( file_xp == XPTR_NULL ) 1557 { 1558 printk("\n[ERROR] in %s : undefined fdid %d / thread%x,%x]\n", 1559 __FUNCTION__, fdid , process->pid, this->trdid ); 1560 return -1; 1561 } 1562 1563 // get file type and socket pointer 1564 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 1565 1566 // get local pointer on socket 1567 socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 1568 1569 // check file descriptor type 1570 if( file_type != INODE_TYPE_SOCK ) 1571 { 1572 printk("\n[ERROR] in %s : illegal file type %s / socket[%x,%d]\n", 1573 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, fdid ); 1574 return -1; 1575 } 1576 1577 // build extended pointer on lock protecting socket 1578 socket_lock_xp = XPTR( file_cxy , &socket_ptr->lock ); 1579 1580 // take the socket lock 1581 remote_queuelock_acquire( socket_lock_xp ); 1582 1583 // get socket type, state, and channel 1584 socket_type = hal_remote_l32( XPTR( file_cxy , &socket_ptr->type )); 1585 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); 1586 nic_channel = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel )); 1587 1588 // handle the explicit remote address and port 1589 if( socket_type == SOCK_DGRAM ) // UDP socket 1590 { 1591 if( socket_state == UDP_STATE_UNBOUND ) 1592 { 1593 // release socket lock 1594 remote_queuelock_release( socket_lock_xp ); 1595 1596 printk("\n[ERROR] in %s : SEND/RECV for socket[%x,%d] in state %s\n", 1597 __FUNCTION__, process->pid, fdid, socket_state_str(socket_state) ); 1598 return -1; 1599 } 1600 1601 if( explicit ) 1602 { 1603 // update remote IP address and port into socket descriptor 1604 hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_addr ), explicit_addr ); 1605 hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_port ), explicit_port ); 1606 1607 // update socket state if required 1608 if( socket_state == UDP_STATE_BOUND ) 1609 { 1610 hal_remote_s32( XPTR( file_cxy , &socket_ptr->state ), UDP_STATE_ESTAB ); 1611 } 1612 } 1613 } 1614 else // TCP socket 1615 { 1616 if( explicit ) 1617 { 1618 // get remote IP address and port from socket descriptor 1619 remote_addr = hal_remote_l32( XPTR( file_cxy , &socket_ptr->remote_addr )); 1620 remote_port = hal_remote_l32( XPTR( file_cxy , &socket_ptr->remote_port )); 1621 1622 if( (remote_addr != explicit_addr) || (remote_port != explicit_port) ) 1623 { 1624 // release socket lock 1625 remote_queuelock_release( socket_lock_xp ); 1626 1627 printk("\n[ERROR] in %s : wrong expliciy access for socket[%x,%d]\n", 1628 __FUNCTION__, process->pid, fdid ); 1629 return -1; 1630 } 1631 } 1632 } 1633 1634 /////////////////////////////////////////////////////// 1635 if( is_send ) // TX_SEND command 1636 { 1637 1638 #if DEBUG_SOCKET_SEND 1639 uint32_t cycle = (uint32_t)hal_get_cycles(); 1640 if (DEBUG_SOCKET_SEND < cycle ) 1641 printk("\n[%s] thread[%x,%x] received SEND command for socket[%x,%d] / length %d / cycle %d\n", 1642 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle ); 1643 #endif 1644 // check no previous TX command 1645 if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true) || 1646 (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) ) 1647 { 1648 // release socket lock 1649 remote_queuelock_release( socket_lock_xp ); 1650 1651 printk("\n[ERROR] in %s : previous TX command / socket[%x,%d] / thread[%x,%x]\n", 1652 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 1653 return -1; 1654 } 1655 1656 // allocate a temporary kernel buffer 1657 req.type = KMEM_KCM; 1658 req.order = bits_log2( length ); 1659 req.flags = AF_NONE; 1660 tx_buf = kmem_alloc( &req ); 1661 1662 if( tx_buf == NULL ) 1663 { 1664 // release socket lock 1665 remote_queuelock_release( socket_lock_xp ); 1666 1667 printk("\n[ERROR] in %s : no memory for tx_buf / socket[%x,%d] / thread[%x,%x]\n", 1668 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 1669 return -1; 1670 } 1671 1672 // copy data from user u_buf to kernel tx_buf 1673 hal_copy_from_uspace( XPTR( local_cxy , tx_buf ), 1674 u_buf, 1675 length ); 1676 1677 // register command in socket descriptor 1678 hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , client_xp ); 1679 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_cmd ) , CMD_TX_SEND ); 1680 hal_remote_spt( XPTR( file_cxy , &socket_ptr->tx_buf ) , tx_buf ); 1681 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_len ) , length ); 1682 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_todo ) , length ); 1683 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid ) , true ); 1684 1685 // release socket lock 1686 remote_queuelock_release( socket_lock_xp ); 1687 1688 // get pointers on relevant chdev 1689 chdev_xp = chdev_dir.nic_tx[nic_channel]; 1690 chdev_ptr = GET_PTR( chdev_xp ); 1691 chdev_cxy = GET_CXY( chdev_xp ); 1692 1693 // get pointers on NIC_TX[channel] server thread 1694 server_ptr = hal_remote_lpt( XPTR( chdev_cxy , &chdev_ptr->server )); 1695 server_xp = XPTR( chdev_cxy , server_ptr ); 1696 1697 // unblocks the NIC_TX server thread 1698 thread_unblock( server_xp , THREAD_BLOCKED_CLIENT ); 1699 1700 #if DEBUG_SOCKET_SEND 1701 cycle = (uint32_t)hal_get_cycles(); 1702 if( DEBUG_SOCKET_SEND < cycle ) 1703 printk("\n[%s] thread[%x,%x] socket[%x,%d] register SEND => blocks on <IO> / cycle %d\n", 1704 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1705 #endif 1706 // client thread blocks itself and deschedules 1707 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_IO ); 1708 sched_yield( "blocked in nic_io" ); 1709 1710 #if DEBUG_SOCKET_SEND 1711 cycle = (uint32_t)hal_get_cycles(); 1712 if( DEBUG_SOCKET_SEND < cycle ) 1713 printk("\n[%s] thread[%x,%x] socket[%x,%d] for SEND resumes / cycle %d\n", 1714 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1715 #endif 1716 // take socket lock 1717 remote_queuelock_acquire( socket_lock_xp ); 1718 1719 // get tx_valid, tx_todo, and tx_sts 1720 tx_todo = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_todo )); 1721 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )); 1722 cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts )); 1723 1724 // reset tx_client in socket descriptor 1725 hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL ); 1726 1727 // release socket lock 1728 remote_queuelock_release( socket_lock_xp ); 1729 1730 // check SEND command completed when TX client thread resumes 1731 assert( (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 1732 "illegal socket state when client thread resumes after TX_SEND\n" 1733 " tx_todo = %d / tx_status = %d / tx_valid = %d\n", 1734 tx_todo, cmd_status, cmd_valid ); 1735 1736 // release the tx_buf 1737 req.ptr = tx_buf; 1738 kmem_free( &req ); 1739 1740 if( cmd_status != CMD_STS_SUCCESS ) 1741 { 1742 1743 #if DEBUG_SOCKET_SEND 1744 cycle = (uint32_t)hal_get_cycles(); 1745 if( DEBUG_SOCKET_RECV < cycle ) 1746 printk("\n[%s] error %s for TX_SEND / socket[%x,%d] / thread[%x,%x]\n", 1747 __FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid ); 1748 #endif 1749 return -1; 1750 } 1751 else 1752 { 1753 1754 #if DEBUG_SOCKET_SEND 1755 cycle = (uint32_t)hal_get_cycles(); 1756 if (DEBUG_SOCKET_SEND < cycle ) 1757 printk("\n[%s] thread[%x,%x] success for SEND / socket[%x,%d] / length %d / cycle %d\n", 1758 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle ); 1759 #endif 1760 return length; 1761 } 1762 1763 } // end TX_SEND command 1764 1765 //////////////////////////////////////////////////////// 1766 else // RX_RECV command 1767 { 1768 1769 #if DEBUG_SOCKET_RECV 1770 uint32_t cycle = (uint32_t)hal_get_cycles(); 1771 if (DEBUG_SOCKET_SEND < cycle ) 1772 printk("\n[%s] thread[%x,%x] received RECV command for socket[%x,%d] / length %d / cycle %d\n", 1773 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle ); 1774 #endif 1775 // check no previous RX command 1776 if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )) == true) || 1777 (hal_remote_l64( XPTR( file_cxy , &socket_ptr->rx_client)) != XPTR_NULL) ) 1778 { 1779 // release socket lock 1780 remote_queuelock_release( socket_lock_xp ); 1781 1782 printk("\n[ERROR] in %s : previous RX command on socket[%x,%d] / thread[%x,%x]\n", 1783 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 1784 return -1; 1785 } 1786 1787 // return EOF for a TCP socket not in ESTAB state 1788 if( (socket_type == SOCK_STREAM ) && (socket_state != TCP_STATE_ESTAB) ) 1789 { 1790 // release socket lock 1791 remote_queuelock_release( socket_lock_xp ); 1792 1793 #if DEBUG_SOCKET_RECV 1794 uint32_t cycle = (uint32_t)hal_get_cycles(); 1795 if( DEBUG_SOCKET_RECV < cycle ) 1796 printk("\n[%s] thread[%x,%x] socket[%x,%d] TCP connection closed / cycle %d\n", 1797 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1798 #endif 1799 return 0; 1800 } 1801 // build extended pointer on socket.rx_buf 1802 xptr_t rx_buf_xp = XPTR( file_cxy , &socket_ptr->rx_buf ); 1803 1804 // get rx_buf status 1805 buf_status = remote_buf_status( rx_buf_xp ); 1806 1807 if( buf_status == 0 ) 1808 { 1809 // registers RX_RECV command in socket descriptor 1810 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_cmd ) , CMD_RX_RECV ); 1811 hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client ) , client_xp ); 1812 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_valid ) , true ); 1813 1814 // release socket lock 1815 remote_queuelock_release( socket_lock_xp ); 1816 1817 #if DEBUG_SOCKET_RECV 1818 uint32_t cycle = (uint32_t)hal_get_cycles(); 1819 if( DEBUG_SOCKET_RECV < cycle ) 1820 printk("\n[%s] thread[%x,%x] socket[%x,%d] rx_buf empty => blocks on <IO> / cycle %d\n", 1821 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1822 #endif 1823 // client thread blocks itself and deschedules 1824 thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_IO ); 1825 sched_yield( "blocked in nic_io" ); 1826 1827 #if DEBUG_SOCKET_RECV 1828 cycle = (uint32_t)hal_get_cycles(); 1829 if( DEBUG_SOCKET_RECV < cycle ) 1830 printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV resumes / cycle %d\n", 1831 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1832 #endif 1833 // take socket lock 1834 remote_queuelock_acquire( socket_lock_xp ); 1835 1836 // get rx_sts and rx_buf status 1837 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )); 1838 cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts )); 1839 buf_status = remote_buf_status( rx_buf_xp ); 1840 1841 assert( (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 1842 "illegal socket state when client thread resumes after RX_RECV\n" 1843 " buf_status = %d / rx_sts = %d / rx_valid = %d\n", 1844 buf_status , cmd_status , cmd_valid ); 1845 1846 // reset rx_client in socket descriptor 1847 hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client ) , XPTR_NULL ); 1848 1849 // reset rx_buf for an UDP socket 1850 if( socket_type == SOCK_DGRAM ) remote_buf_reset( rx_buf_xp ); 1851 1852 // release socket lock 1853 remote_queuelock_release( socket_lock_xp ); 1854 1855 if( cmd_status == CMD_STS_EOF ) // EOF (remote close) reported 1856 { 1857 1858 #if DEBUG_SOCKET_RECV 1859 cycle = (uint32_t)hal_get_cycles(); 1860 if( DEBUG_SOCKET_RECV < cycle ) 1861 printk("\n[%s] EOF for RX_RECV / socket[%x,%d] / thread[%x,%x]\n", 1862 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 1863 #endif 1864 return 0; 1865 } 1866 else if( cmd_status != CMD_STS_SUCCESS ) // other error reported 1867 { 1868 1869 #if DEBUG_SOCKET_RECV 1870 cycle = (uint32_t)hal_get_cycles(); 1871 if( DEBUG_SOCKET_RECV < cycle ) 1872 printk("\n[%s] error %s for RX_RECV / socket[%x,%d] / thread[%x,%x]\n", 1873 __FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid ); 1874 #endif 1875 return -1; 1876 } 1877 1878 } 1879 1880 // number of bytes extracted from rx_buf cannot be larger than u_buf size 1881 moved_bytes = ( length < buf_status ) ? length : buf_status; 1882 1883 // move data from kernel rx_buf to user u_buf 1884 remote_buf_get_to_user( rx_buf_xp, 1885 u_buf, 1886 moved_bytes ); 1887 #if DEBUG_SOCKET_SEND 1888 cycle = (uint32_t)hal_get_cycles(); 1889 if (DEBUG_SOCKET_SEND < cycle ) 1890 printk("\n[%s] thread[%x,%x] success for RECV / socket[%x,%d] / length %d / cycle %d\n", 1891 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, moved_bytes, cycle ); 1892 #endif 1893 return moved_bytes; 1894 1895 } // end RX_RECV command 1896 } // end socket_move_data() 1897 1898 1899 /////////////////////////////////// 1900 int socket_send( uint32_t fdid, 1901 uint8_t * u_buf, 1902 uint32_t length ) 1903 { 1904 int nbytes = socket_move_data( true, // SEND 1905 fdid, 1906 u_buf, 1907 length, 1908 false, 0, 0 ); // no explicit remote socket 1909 return nbytes; 1910 1911 } // end socket_send() 1912 1913 ///////////////////////////////////// 1914 int socket_sendto( uint32_t fdid, 1915 uint8_t * u_buf, 1916 uint32_t length, 1917 uint32_t remote_addr, 1918 uint32_t remote_port ) 1919 { 1920 int nbytes = socket_move_data( true, // SEND 1921 fdid, 1922 u_buf, 1923 length, 1924 true, // explicit remote socket 1925 remote_addr, 1926 remote_port ); 1927 return nbytes; 1928 1929 } // end socket_sendto() 1930 1931 /////////////////////////////////// 1932 int socket_recv( uint32_t fdid, 1933 uint8_t * u_buf, 1934 uint32_t length ) 1935 { 1936 int nbytes = socket_move_data( false, // RECV 1937 fdid, 1938 u_buf, 1939 length, 1940 false, 0, 0 ); // no explicit remote socket 1941 return nbytes; 1942 1943 } // end socket_recv() 1944 1945 1946 /////////////////////////////////////// 1947 int socket_recvfrom( uint32_t fdid, 1948 uint8_t * u_buf, 1949 uint32_t length, 1950 uint32_t remote_addr, 1951 uint32_t remote_port ) 1952 { 1953 int nbytes = socket_move_data( false, // RECV 1954 fdid, 1955 u_buf, 1956 length, 1957 true, // explicit remote socket 1958 remote_addr, 1959 remote_port ); 1960 return nbytes; 1961 1962 } // end socket_recvfrom() 1963 1964 //////////////////////////////////////////// 1965 void socket_display( xptr_t socket_xp, 1966 const char * func_str ) 1967 { 1968 socket_t * socket = GET_PTR( socket_xp ); 1969 cxy_t cxy = GET_CXY( socket_xp ); 1970 1971 pid_t pid = hal_remote_l32( XPTR( cxy , &socket->pid )); 1972 fdid_t fdid = hal_remote_l32( XPTR( cxy , &socket->fdid )); 1973 uint32_t state = hal_remote_l32( XPTR( cxy , &socket->state )); 1974 uint32_t channel = hal_remote_l32( XPTR( cxy , &socket->nic_channel )); 1975 uint32_t local_addr = hal_remote_l32( XPTR( cxy , &socket->local_addr )); 1976 uint32_t local_port = hal_remote_l32( XPTR( cxy , &socket->local_port )); 1977 uint32_t remote_addr = hal_remote_l32( XPTR( cxy , &socket->remote_addr )); 1978 uint32_t remote_port = hal_remote_l32( XPTR( cxy , &socket->remote_port )); 1979 uint32_t tx_valid = hal_remote_l32( XPTR( cxy , &socket->tx_valid )); 1980 uint32_t tx_cmd = hal_remote_l32( XPTR( cxy , &socket->tx_cmd )); 1981 uint32_t tx_sts = hal_remote_l32( XPTR( cxy , &socket->tx_sts )); 1982 uint32_t tx_len = hal_remote_l32( XPTR( cxy , &socket->tx_len )); 1983 uint32_t tx_todo = hal_remote_l32( XPTR( cxy , &socket->tx_todo )); 1984 uint32_t tx_una = hal_remote_l32( XPTR( cxy , &socket->tx_una )); 1985 uint32_t tx_nxt = hal_remote_l32( XPTR( cxy , &socket->tx_nxt )); 1986 uint32_t tx_wnd = hal_remote_l32( XPTR( cxy , &socket->tx_wnd )); 1987 uint32_t rx_valid = hal_remote_l32( XPTR( cxy , &socket->rx_valid )); 1988 uint32_t rx_cmd = hal_remote_l32( XPTR( cxy , &socket->rx_cmd )); 1989 uint32_t rx_sts = hal_remote_l32( XPTR( cxy , &socket->rx_sts )); 1990 uint32_t rx_nxt = hal_remote_l32( XPTR( cxy , &socket->rx_nxt )); 1991 uint32_t rx_wnd = hal_remote_l32( XPTR( cxy , &socket->rx_wnd )); 1992 uint32_t rx_irs = hal_remote_l32( XPTR( cxy , &socket->rx_irs )); 1993 1994 if( func_str == NULL ) 1995 { 1996 printk("\n****** socket[%x,%d] / xptr[%x,%x]*****\n", 1997 pid, fdid, cxy, socket ); 1998 } 1999 else 2000 { 2001 printk("\n***** socket[%x,%d] / xptr[%x,%x] / from %s *****\n", 2002 pid, fdid, cxy, socket, func_str ); 2003 } 2004 printk(" - state %s / channel %d\n" 2005 " - local_addr %x / local_port %x\n" 2006 " - remote_addr %x / remote_port %x\n" 2007 " - tx_valid %d (%s) / tx_sts %d / tx_len %x / tx_todo %x\n" 2008 " - tx_una %x / tx_nxt %x / tx_wnd %x\n" 2009 " - rx_valid %d (%s) / rx_sts %d\n" 2010 " - rx_nxt %x / rx_wnd %x / rx_irs %x\n", 2011 socket_state_str(state), channel , 2012 local_addr, local_port, 2013 remote_addr, remote_port, 2014 tx_valid, socket_cmd_type_str(tx_cmd), tx_sts, tx_len, tx_todo, 2015 tx_una, tx_nxt, tx_wnd, 2016 rx_valid, socket_cmd_type_str(rx_cmd), rx_sts, 2017 rx_nxt, rx_wnd, rx_irs ); 2018 2019 } // end socket_display() 2020 2021 2022 2023 2024
Note: See TracChangeset
for help on using the changeset viewer.