source: trunk/kernel/kern/socket.c @ 659

Last change on this file since 659 was 657, checked in by alain, 5 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 10.2 KB
Line 
1/*
2 * socket.c - socket API implementation.
3 *
4 * Authors  Alain Greiner   (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH.is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
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,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_remote.h>
27#include <shared_socket.h>
28#include <process.h>
29#include <remote_buf.h>
30#include <printk.h>
31#include <kmem.h>
32#include <thread.h>
33#include <vfs.h>
34#include <socket.h>
35
36//////////////////////////////////////////////////////////////////////////////////////
37// Extern global variables
38//////////////////////////////////////////////////////////////////////////////////////
39
40extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
41
42//////////////////////////////////////
43char * socket_cmd_str( uint32_t type )
44{
45    switch( type )
46    {
47        case SOCKET_TX_CONNECT  : return "CONNECT";
48        case SOCKET_TX_SEND     : return "SEND";
49        case SOCKET_TX_CLOSE    : return "CLOSE";
50
51        default:                return "undefined";
52    }
53}
54   
55/////////////////////////////////////////
56char * socket_state_str( uint32_t state )
57{
58    switch( state )
59    {
60        case UDP_STATE_UNBOUND    : return "UDP_UNBOUND";
61        case UDP_STATE_BOUND      : return "UDP_BOUND";
62        case UDP_STATE_CONNECT    : return "UDP_CONNECT";
63
64        case TCP_STATE_UNBOUND    : return "TCP_UNBOUND";
65        case TCP_STATE_BOUND      : return "TCP_BOUND";
66        case TCP_STATE_LISTEN     : return "TCP_LISTEN";
67        case TCP_STATE_SYN_SENT   : return "TCP_SYN_SENT";
68        case TCP_STATE_SYN_RCVD   : return "TCP_SYN_RCVD";
69        case TCP_STATE_ESTAB      : return "TCP_ESTAB";
70        case TCP_STATE_FIN_WAIT1  : return "TCP_FIN_WAIT1";
71        case TCP_STATE_FIN_WAIT2  : return "TCP_FIN_WAIT2";
72        case TCP_STATE_CLOSING    : return "TCP_CLOSING";
73        case TCP_STATE_TIME_WAIT  : return "TCP_TIME_WAIT";
74        case TCP_STATE_CLOSE_WAIT : return "TCP_CLOSE_WAIT";
75        case TCP_STATE_LAST_ACK   : return "TCP_LAST_ACK";
76
77        default:                    return "undefined";
78    }
79}
80
81///////////////////////////////////////
82error_t socket_create( cxy_t       cxy,
83                       uint32_t    domain,
84                       uint32_t    type,
85                       socket_t ** socket_ptr,
86                       uint32_t  * fdid_ptr )
87{
88    uint32_t    fdid;
89
90    thread_t  * this    = CURRENT_THREAD;
91    process_t * process = this->process;
92
93    kmem_req_t     req;
94    socket_t     * socket;
95    vfs_file_t   * file;
96    uint32_t       state;
97    error_t        error;
98
99    // allocate memory for socket descriptor
100    req.type   = KMEM_KCM;
101    req.order  = bits_log2( sizeof(socket_t) );
102    req.flags  = AF_ZERO;
103    socket     = kmem_remote_alloc( cxy , &req );
104
105    if( socket == NULL )
106    {
107        printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x]\n",
108        __FUNCTION__, process->pid, this->trdid );
109        return -1;
110    }
111
112    // allocate memory for rx_buf buffer
113    error = remote_buf_create( XPTR( cxy , &socket->rx_buf ),
114                               NIC_RX_BUF_SIZE );
115
116    if( error )
117    {
118        printk("\n[ERROR] in %s : cannot allocate rx_buf / thread[%x,%x]\n",
119        __FUNCTION__, process->pid, this->trdid );
120        req.type = KMEM_KCM;
121        req.ptr  = socket;
122        kmem_remote_free( cxy , &req );
123        return -1;
124    }
125
126    // allocate memory for r2tq queue
127    error = remote_buf_create( XPTR( cxy , &socket->r2tq ),
128                               NIC_R2T_QUEUE_SIZE );
129    if( error )
130    {
131        printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x]\n",
132        __FUNCTION__, process->pid, this->trdid );
133        remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
134        req.type = KMEM_KCM;
135        req.ptr  = socket;
136        kmem_remote_free( cxy , &req );
137        return -1;
138    }
139
140    // allocate memory for crqq queue
141    error = remote_buf_create( XPTR( cxy , &socket->crqq ),
142                               NIC_CRQ_QUEUE_SIZE * sizeof(sockaddr_t) );
143    if( error )
144    {
145        printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x]\n",
146        __FUNCTION__, process->pid, this->trdid );
147        remote_buf_destroy( XPTR( cxy , &socket->r2tq ) );
148        remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
149        req.type = KMEM_KCM;
150        req.ptr  = socket;
151        kmem_remote_free( cxy , &req );
152        return -1;
153    }
154
155    //  allocate memory for file descriptor
156        req.type  = KMEM_KCM;
157        req.order = bits_log2( sizeof(vfs_file_t) );
158    req.flags = AF_ZERO;
159        file      = kmem_remote_alloc( cxy , &req );
160
161    if( file == NULL ) 
162    {
163        printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x]\n",
164        __FUNCTION__, process->pid, this->trdid );
165        remote_buf_destroy( XPTR( cxy , &socket->crqq ) );
166        remote_buf_destroy( XPTR( cxy , &socket->r2tq ) );
167        remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
168        req.type = KMEM_KCM;
169        req.ptr  = socket;
170        kmem_remote_free( cxy , &req );
171        return -1;
172    }
173   
174    // get an fdid value, and register file descriptor in fd_array[]
175    error = process_fd_register( process->ref_xp,
176                                 XPTR( cxy , file ),
177                                 &fdid );
178    if ( error ) 
179    {
180        printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x]\n",
181        __FUNCTION__, process->pid, this->trdid );
182        req.type = KMEM_KCM;
183        req.ptr  = file;
184        kmem_free( &req );
185        remote_buf_destroy( XPTR( cxy , &socket->crqq ) );
186        remote_buf_destroy( XPTR( cxy , &socket->r2tq ) );
187        remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
188        req.ptr  = socket;
189        kmem_free( &req );
190        return -1;
191    }
192    state = (type == SOCK_STREAM) ? TCP_STATE_UNBOUND : UDP_STATE_UNBOUND;
193
194    // initialise socket descriptor
195    hal_remote_s32( XPTR( cxy , &socket->domain    ) , domain );
196    hal_remote_s32( XPTR( cxy , &socket->type      ) , type );
197    hal_remote_s32( XPTR( cxy , &socket->pid       ) , process->pid );
198    hal_remote_s32( XPTR( cxy , &socket->state     ) , state );
199    hal_remote_s64( XPTR( cxy , &socket->tx_client ) , XPTR_NULL );
200    hal_remote_s64( XPTR( cxy , &socket->rx_client ) , XPTR_NULL );
201
202    // initialize file descriptor
203    hal_remote_s32( XPTR( cxy , &file->type        ) , INODE_TYPE_SOCK );
204    hal_remote_spt( XPTR( cxy , &file->socket      ) , socket );
205    hal_remote_s32( XPTR( cxy , &file->refcount    ) , 1 );
206
207    remote_rwlock_init( XPTR( cxy , &file->lock ) , LOCK_VFS_FILE );
208   
209    // return success
210    *socket_ptr = socket;
211    *fdid_ptr   = fdid;
212
213    return 0;
214
215}  // end socket_create
216
217////////////////////////////////////
218void socket_destroy( uint32_t fdid )
219{
220    uint32_t            type;
221    socket_t          * socket;
222    kmem_req_t          req;
223
224    thread_t  * this    = CURRENT_THREAD;
225    process_t * process = this->process;
226
227    // get pointers on file descriptor
228    xptr_t       file_xp  = process_fd_get_xptr( process , fdid );
229    vfs_file_t * file     = GET_PTR( file_xp );
230    cxy_t        cxy      = GET_CXY( file_xp );
231
232    type   = hal_remote_l32( XPTR( cxy , &file->type ) );
233    socket = hal_remote_lpt( XPTR( cxy , &file->socket ) );
234
235// check file descriptor pointer
236assert( (file_xp != XPTR_NULL), "illegal fdid\n" );
237
238// check file descriptor type
239assert( (type == INODE_TYPE_SOCK), "illegal file type\n" );
240
241    // remove the file descriptor from the process
242    process_fd_remove( process->owner_xp , fdid );
243
244    // release memory allocated for file descriptor
245    req.type = KMEM_KCM;
246    req.ptr  = file;
247    kmem_remote_free( cxy , &req );
248
249    // release memory allocated for buffers attached to socket descriptor
250    remote_buf_destroy( XPTR( cxy , &socket->crqq ) );
251    remote_buf_destroy( XPTR( cxy , &socket->r2tq ) );
252    remote_buf_destroy( XPTR( cxy , &socket->rx_buf ) );
253
254    // release memory allocated for socket descriptor
255    req.type = KMEM_KCM;
256    req.ptr  = socket;
257    kmem_remote_free( cxy , &req );
258
259}  // end socket_destroy()
260
261/////////////////////////////////////////////////
262void socket_link_to_servers( xptr_t    socket_xp,
263                             uint32_t  nic_channel ) 
264{
265    cxy_t      socket_cxy = GET_CXY( socket_xp );
266    socket_t * socket_ptr = GET_PTR( socket_xp );
267
268    // get pointers on NIC_TX[index] chdev
269    xptr_t    tx_chdev_xp  = chdev_dir.nic_tx[nic_channel];
270    chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp );
271    cxy_t     tx_chdev_cxy = GET_CXY( tx_chdev_xp );
272
273    // build extended pointers on root of sockets attached to NIC_TX[channel] chdev
274    xptr_t    tx_root_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_root );
275    xptr_t    tx_lock_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_lock );
276
277    // register socket in the NIC_TX[channel] chdev clients queue
278    remote_rwlock_wr_acquire( tx_lock_xp );
279    xlist_add_last( tx_root_xp , XPTR( socket_cxy , &socket_ptr->tx_list ) );
280    remote_rwlock_wr_release( tx_lock_xp );
281
282    // get pointers on NIC_RX[index] chdev
283    xptr_t    rx_chdev_xp  = chdev_dir.nic_rx[nic_channel];
284    chdev_t * rx_chdev_ptr = GET_PTR( rx_chdev_xp );
285    cxy_t     rx_chdev_cxy = GET_CXY( rx_chdev_xp );
286
287    // build extended pointer on root of sockets attached to NIC_TX[channel] chdev
288    xptr_t    rx_root_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_root );
289    xptr_t    rx_lock_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_lock );
290
291    // register socket in the NIC_RX[channel] chdev clients queue
292    remote_rwlock_wr_acquire( rx_lock_xp );
293    xlist_add_last( rx_root_xp , XPTR( socket_cxy , &socket_ptr->rx_list ) );
294    remote_rwlock_wr_release( rx_lock_xp );
295
296}  // end socket_link_to_server()
297
298
Note: See TracBrowser for help on using the repository browser.