Subversion Repositories HelenOS

Rev

Rev 4163 | Rev 4243 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4163 Rev 4192
Line 35... Line 35...
35
 *  @see eth.h
35
 *  @see eth.h
36
 */
36
 */
37
 
37
 
38
#include <async.h>
38
#include <async.h>
39
#include <malloc.h>
39
#include <malloc.h>
-
 
40
#include <mem.h>
40
#include <stdio.h>
41
#include <stdio.h>
41
#include <string.h>
-
 
42
 
42
 
43
#include <ipc/ipc.h>
43
#include <ipc/ipc.h>
44
#include <ipc/services.h>
44
#include <ipc/services.h>
45
 
45
 
46
#include "../../err.h"
46
#include "../../err.h"
Line 74... Line 74...
74
 
74
 
75
/** Returns the packet identifier message parameter.
75
/** Returns the packet identifier message parameter.
76
 */
76
 */
77
#define IPC_GET_PACKET( call )      ( packet_id_t ) IPC_GET_ARG2( * call )
77
#define IPC_GET_PACKET( call )      ( packet_id_t ) IPC_GET_ARG2( * call )
78
 
78
 
-
 
79
#define IPC_GET_STATE( call )       ( device_state_t ) IPC_GET_ARG2( * call )
-
 
80
 
79
/** Returns the protocol service message parameter.
81
/** Returns the protocol service message parameter.
80
 */
82
 */
81
#define IPC_GET_PROTO( call )       ( services_t ) IPC_GET_ARG1( * call )
83
#define IPC_GET_PROTO( call )       ( services_t ) IPC_GET_ARG2( * call )
82
 
84
 
83
/** Returns the device driver service message parameter.
85
/** Returns the device driver service message parameter.
84
 */
86
 */
85
#define IPC_GET_SERVICE( call )     ( services_t ) IPC_GET_ARG2( * call )
87
#define IPC_GET_SERVICE( call )     ( services_t ) IPC_GET_ARG2( * call )
86
 
88
 
Line 121... Line 123...
121
int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address );
123
int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address );
122
int eth_register_message( services_t service, int phone );
124
int eth_register_message( services_t service, int phone );
123
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender );
125
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender );
124
int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
126
int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
125
void    eth_receiver( ipc_callid_t iid, ipc_call_t * icall );
127
void    eth_receiver( ipc_callid_t iid, ipc_call_t * icall );
126
eth_proto_ref   eth_proccess_packet( int dummy, packet_t packet );
128
eth_proto_ref   eth_process_packet( int dummy, packet_t packet );
127
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype );
129
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype );
128
 
130
 
129
int eth_initialize( void ){
131
int eth_initialize( void ){
130
    ERROR_DECLARE;
132
    ERROR_DECLARE;
131
 
133
 
Line 149... Line 151...
149
    ERROR_DECLARE;
151
    ERROR_DECLARE;
150
 
152
 
151
    aid_t           message;
153
    aid_t           message;
152
    ipc_call_t      answer;
154
    ipc_call_t      answer;
153
    eth_device_ref  device;
155
    eth_device_ref  device;
-
 
156
    ipcarg_t        result;
154
    int             result;
157
    int             index;
155
 
158
 
156
    rwlock_write_lock( & eth_globals.devices_lock );
159
    rwlock_write_lock( & eth_globals.devices_lock );
157
    // an existing device?
160
    // an existing device?
158
    device = eth_devices_find( & eth_globals.devices, device_id );
161
    device = eth_devices_find( & eth_globals.devices, device_id );
159
    if( device ){
162
    if( device ){
Line 188... Line 191...
188
            rwlock_write_unlock( & eth_globals.devices_lock );
191
            rwlock_write_unlock( & eth_globals.devices_lock );
189
            free( device );
192
            free( device );
190
            async_wait_for( message, NULL );
193
            async_wait_for( message, NULL );
191
            return ERROR_CODE;
194
            return ERROR_CODE;
192
        }
195
        }
193
        async_wait_for( message, ( ipcarg_t * ) & result );
196
        async_wait_for( message, & result );
194
        if( ERROR_OCCURRED( result )){
197
        if( ERROR_OCCURRED( result )){
195
            rwlock_write_unlock( & eth_globals.devices_lock );
198
            rwlock_write_unlock( & eth_globals.devices_lock );
196
            free( device->addr );
199
            free( device->addr );
197
            free( device->addr_data );
200
            free( device->addr_data );
198
            free( device );
201
            free( device );
199
            return ERROR_CODE;
202
            return ERROR_CODE;
200
        }
203
        }
201
        // add to the cache
204
        // add to the cache
202
        if( ERROR_OCCURRED( eth_devices_add( & eth_globals.devices, device->device_id, device ))){
205
        index = eth_devices_add( & eth_globals.devices, device->device_id, device );
-
 
206
        if( index < 0 ){
203
            rwlock_write_unlock( & eth_globals.devices_lock );
207
            rwlock_write_unlock( & eth_globals.devices_lock );
204
            free( device->addr );
208
            free( device->addr );
205
            free( device->addr_data );
209
            free( device->addr_data );
206
            free( device );
210
            free( device );
207
            return ERROR_CODE;
211
            return index;
208
        }
212
        }
209
        printf( "\nNew device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n\taddress\t= %X:%X:%X:%X:%X:%X", device->device_id, device->service, device->mtu, device->addr_data[ 0 ], device->addr_data[ 1 ], device->addr_data[ 2 ], device->addr_data[ 3 ], device->addr_data[ 4 ], device->addr_data[ 5 ] );
213
        printf( "\nNew device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n\taddress\t= %X:%X:%X:%X:%X:%X", device->device_id, device->service, device->mtu, device->addr_data[ 0 ], device->addr_data[ 1 ], device->addr_data[ 2 ], device->addr_data[ 3 ], device->addr_data[ 4 ], device->addr_data[ 5 ] );
210
    }
214
    }
211
    rwlock_write_unlock( & eth_globals.devices_lock );
215
    rwlock_write_unlock( & eth_globals.devices_lock );
212
    return EOK;
216
    return EOK;
213
}
217
}
214
 
218
 
215
eth_proto_ref eth_proccess_packet( int dummy, packet_t packet ){
219
eth_proto_ref eth_process_packet( int dummy, packet_t packet ){
216
    ERROR_DECLARE;
220
    ERROR_DECLARE;
217
 
221
 
218
    eth_header_ex_ref   header;
222
    eth_header_ex_ref   header;
219
    size_t              length;
223
    size_t              length;
220
    int                 type;
224
    int                 type;
Line 284... Line 288...
284
    dummy = device->dummy;
288
    dummy = device->dummy;
285
    rwlock_read_unlock( & eth_globals.devices_lock );
289
    rwlock_read_unlock( & eth_globals.devices_lock );
286
    rwlock_read_lock( & eth_globals.protos_lock );
290
    rwlock_read_lock( & eth_globals.protos_lock );
287
    do{
291
    do{
288
        next = pq_detach( packet );
292
        next = pq_detach( packet );
289
        proto = eth_proccess_packet( dummy, packet );
293
        proto = eth_process_packet( dummy, packet );
290
        if( proto ){
294
        if( proto ){
291
            async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet ));
295
            async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet ));
292
        }else{
296
        }else{
293
            // drop invalid/unknown
297
            // drop invalid/unknown
294
            packet_release( eth_globals.networking_phone, packet_get_id( packet ));
298
            pq_release( eth_globals.networking_phone, packet_get_id( packet ));
295
        }
299
        }
296
        packet = next;
300
        packet = next;
297
    }while( packet );
301
    }while( packet );
298
    rwlock_read_unlock( & eth_globals.protos_lock );
302
    rwlock_read_unlock( & eth_globals.protos_lock );
299
    return EOK;
303
    return EOK;
Line 301... Line 305...
301
 
305
 
302
int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
306
int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
303
    eth_device_ref  device;
307
    eth_device_ref  device;
304
 
308
 
305
    if( !( addr_len && prefix && content && suffix )) return EINVAL;
309
    if( !( addr_len && prefix && content && suffix )) return EINVAL;
306
    rwlock_write_lock( & eth_globals.devices_lock );
310
    rwlock_read_lock( & eth_globals.devices_lock );
307
    device = eth_devices_find( & eth_globals.devices, device_id );
311
    device = eth_devices_find( & eth_globals.devices, device_id );
308
    if( ! device ){
312
    if( ! device ){
309
        rwlock_write_unlock( & eth_globals.devices_lock );
313
        rwlock_read_unlock( & eth_globals.devices_lock );
310
        return ENOENT;
314
        return ENOENT;
311
    }
315
    }
312
    * content = ( ETH_MAX_CONTENT > device->mtu ) ? device->mtu : ETH_MAX_CONTENT;
316
    * content = ( ETH_MAX_CONTENT > device->mtu ) ? device->mtu : ETH_MAX_CONTENT;
313
    rwlock_write_unlock( & eth_globals.devices_lock );
317
    rwlock_read_unlock( & eth_globals.devices_lock );
314
    * addr_len = ETH_ADDR;
318
    * addr_len = ETH_ADDR;
315
    * prefix = ETH_PREFIX;
319
    * prefix = ETH_PREFIX;
316
    * suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
320
    * suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
317
    return EOK;
321
    return EOK;
318
}
322
}
Line 322... Line 326...
322
 
326
 
323
    if( ! address ) return EINVAL;
327
    if( ! address ) return EINVAL;
324
    if( type == ETH_BROADCAST_ADDR ){
328
    if( type == ETH_BROADCAST_ADDR ){
325
        * address = eth_globals.broadcast_addr;
329
        * address = eth_globals.broadcast_addr;
326
    }else{
330
    }else{
327
        rwlock_write_lock( & eth_globals.devices_lock );
331
        rwlock_read_lock( & eth_globals.devices_lock );
328
        device = eth_devices_find( & eth_globals.devices, device_id );
332
        device = eth_devices_find( & eth_globals.devices, device_id );
329
        if( ! device ){
333
        if( ! device ){
330
            rwlock_write_unlock( & eth_globals.devices_lock );
334
            rwlock_read_unlock( & eth_globals.devices_lock );
331
            return ENOENT;
335
            return ENOENT;
332
        }
336
        }
333
        * address = device->addr;
337
        * address = device->addr;
334
        rwlock_write_unlock( & eth_globals.devices_lock );
338
        rwlock_read_unlock( & eth_globals.devices_lock );
335
    }
339
    }
336
    return ( * address ) ? EOK : ENOENT;
340
    return ( * address ) ? EOK : ENOENT;
337
}
341
}
338
 
342
 
339
int eth_register_message( services_t service, int phone ){
343
int eth_register_message( services_t service, int phone ){
340
    ERROR_DECLARE;
-
 
341
 
-
 
342
    eth_proto_ref   proto;
344
    eth_proto_ref   proto;
343
    int             protocol;
345
    int             protocol;
-
 
346
    int             index;
344
 
347
 
345
    protocol = protocol_map( SERVICE_ETHERNET, service );
348
    protocol = protocol_map( SERVICE_ETHERNET, service );
346
    if( ! protocol ) return ENOENT;
349
    if( ! protocol ) return ENOENT;
347
    rwlock_write_lock( & eth_globals.protos_lock );
350
    rwlock_write_lock( & eth_globals.protos_lock );
348
    proto = eth_protos_find( & eth_globals.protos, protocol );
351
    proto = eth_protos_find( & eth_globals.protos, protocol );
Line 357... Line 360...
357
            return ENOMEM;
360
            return ENOMEM;
358
        }
361
        }
359
        proto->service = service;
362
        proto->service = service;
360
        proto->protocol = protocol;
363
        proto->protocol = protocol;
361
        proto->phone = phone;
364
        proto->phone = phone;
362
        if( ERROR_OCCURRED( eth_protos_add( & eth_globals.protos, protocol, proto ))){
365
        index = eth_protos_add( & eth_globals.protos, protocol, proto );
-
 
366
        if( index < 0 ){
363
            rwlock_write_unlock( & eth_globals.protos_lock );
367
            rwlock_write_unlock( & eth_globals.protos_lock );
364
            free( proto );
368
            free( proto );
365
            return ERROR_CODE;
369
            return index;
366
        }
370
        }
367
    }
371
    }
368
    printf( "\nNew protocol registered:\n\tprotocol\t= %d\n\tservice\t= %d\n\tphone\t= %d", proto->protocol, proto->service, proto->phone );
372
    printf( "\nNew protocol registered:\n\tprotocol\t= 0x%x\n\tservice\t= %d\n\tphone\t= %d", proto->protocol, proto->service, proto->phone );
369
    rwlock_write_unlock( & eth_globals.protos_lock );
373
    rwlock_write_unlock( & eth_globals.protos_lock );
370
    return EOK;
374
    return EOK;
371
}
375
}
372
 
376
 
373
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ){
377
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ){
Line 396... Line 400...
396
    length = packet_get_data_length( packet );
400
    length = packet_get_data_length( packet );
397
    if( length > ETH_MAX_CONTENT ) return EINVAL;
401
    if( length > ETH_MAX_CONTENT ) return EINVAL;
398
    if( length < ETH_MIN_CONTENT ){
402
    if( length < ETH_MIN_CONTENT ){
399
        padding = packet_suffix( packet, ETH_MIN_CONTENT - length );
403
        padding = packet_suffix( packet, ETH_MIN_CONTENT - length );
400
        if( ! padding ) return ENOMEM;
404
        if( ! padding ) return ENOMEM;
401
        memset( padding, 0, ETH_MIN_CONTENT - length );
405
        bzero( padding, ETH_MIN_CONTENT - length );
402
    }
406
    }
403
    header->header.ethertype = htons( length );
407
    header->header.ethertype = htons( length );
404
    header->lsap.dsap = 0xAA;
408
    header->lsap.dsap = 0xAA;
405
    header->lsap.ssap = header->lsap.dsap;
409
    header->lsap.ssap = header->lsap.dsap;
406
    header->lsap.ctrl = 0;
410
    header->lsap.ctrl = 0;
Line 422... Line 426...
422
    packet_t            tmp;
426
    packet_t            tmp;
423
    int                 ethertype;
427
    int                 ethertype;
424
 
428
 
425
    ethertype = htons( protocol_map( SERVICE_ETHERNET, sender ));
429
    ethertype = htons( protocol_map( SERVICE_ETHERNET, sender ));
426
    if( ! ethertype ){
430
    if( ! ethertype ){
427
        packet_release( eth_globals.networking_phone, packet_get_id( packet ));
431
        pq_release( eth_globals.networking_phone, packet_get_id( packet ));
428
        return EINVAL;
432
        return EINVAL;
429
    }
433
    }
430
    rwlock_read_lock( & eth_globals.devices_lock );
434
    rwlock_read_lock( & eth_globals.devices_lock );
431
    device = eth_devices_find( & eth_globals.devices, device_id );
435
    device = eth_devices_find( & eth_globals.devices, device_id );
432
    if( ! device ){
436
    if( ! device ){
433
        rwlock_read_unlock( & eth_globals.devices_lock );
437
        rwlock_read_unlock( & eth_globals.devices_lock );
434
        return ENOENT;
438
        return ENOENT;
435
    }
439
    }
436
    // proccess packet queue
440
    // process packet queue
437
    next = packet;
441
    next = packet;
438
    do{
442
    do{
439
        if( ERROR_OCCURRED( eth_prepare_packet( device->dummy, next, ( uint8_t * ) device->addr->value, ethertype ))){
443
        if( ERROR_OCCURRED( eth_prepare_packet( device->dummy, next, ( uint8_t * ) device->addr->value, ethertype ))){
440
            // release invalid packet
444
            // release invalid packet
441
            tmp = pq_detach( next );
445
            tmp = pq_detach( next );
442
            packet_release( eth_globals.networking_phone, packet_get_id( next ));
446
            pq_release( eth_globals.networking_phone, packet_get_id( next ));
443
            next = tmp;
447
            next = tmp;
444
        }else{
448
        }else{
445
            next = pq_next( next );
449
            next = pq_next( next );
446
        }
450
        }
447
    }while( next );
451
    }while( next );
Line 469... Line 473...
469
        case NET_NIL_PACKET_SPACE:
473
        case NET_NIL_PACKET_SPACE:
470
            ERROR_PROPAGATE( eth_packet_space_message( IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
474
            ERROR_PROPAGATE( eth_packet_space_message( IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
471
            * answer_count = 3;
475
            * answer_count = 3;
472
            return EOK;
476
            return EOK;
473
        case NET_NIL_ADDR:
477
        case NET_NIL_ADDR:
474
            rwlock_read_lock( & eth_globals.devices_lock );
-
 
475
            if( ! ERROR_OCCURRED( eth_addr_message( IPC_GET_DEVICE( call ), ETH_LOCAL_ADDR, & address ))){
478
            ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_LOCAL_ADDR, & address ));
476
                 ERROR_CODE = measured_strings_reply( address, 1 );
479
            return measured_strings_reply( address, 1 );
477
            }
-
 
478
            rwlock_read_unlock( & eth_globals.devices_lock );
-
 
479
            return ERROR_CODE;
-
 
480
        case NET_NIL_BROADCAST_ADDR:
480
        case NET_NIL_BROADCAST_ADDR:
481
            rwlock_read_lock( & eth_globals.devices_lock );
-
 
482
            if( ! ERROR_OCCURRED( eth_addr_message( IPC_GET_DEVICE( call ), ETH_BROADCAST_ADDR, & address ))){
481
            ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_BROADCAST_ADDR, & address ));
483
                 ERROR_CODE = measured_strings_reply( address, 1 );
482
            return measured_strings_reply( address, 1 );
484
            }
-
 
485
            rwlock_read_unlock( & eth_globals.devices_lock );
-
 
486
            return ERROR_CODE;
483
            return ERROR_CODE;
487
        case IPC_M_CONNECT_TO_ME:
484
        case IPC_M_CONNECT_TO_ME:
488
            return eth_register_message( IPC_GET_PROTO( call ), IPC_GET_PHONE( call ));
485
            return eth_register_message( IPC_GET_PROTO( call ), IPC_GET_PHONE( call ));
489
    }
486
    }
490
    return ENOTSUP;
487
    return ENOTSUP;
Line 492... Line 489...
492
 
489
 
493
void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ){
490
void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ){
494
    ERROR_DECLARE;
491
    ERROR_DECLARE;
495
 
492
 
496
    packet_t        packet;
493
    packet_t        packet;
-
 
494
    int             index;
-
 
495
    eth_proto_ref   proto;
497
 
496
 
498
    while( true ){
497
    while( true ){
499
        switch( IPC_GET_METHOD( * icall )){
498
        switch( IPC_GET_METHOD( * icall )){
500
            case NET_NIL_DEVICE_STATE:
499
            case NET_NIL_DEVICE_STATE:
501
                //TODO clear device if off?
500
                //TODO clear device if off?
-
 
501
                rwlock_read_lock( & eth_globals.protos_lock );
-
 
502
                for( index = eth_protos_count( & eth_globals.protos ) - 1; index >= 0; -- index ){
-
 
503
                    proto = eth_protos_get_index( & eth_globals.protos, index );
-
 
504
                    if( proto && proto->phone ) async_msg_2( proto->phone, NET_IL_DEVICE_STATE, IPC_GET_DEVICE( icall ), IPC_GET_STATE( icall ));
-
 
505
                }
-
 
506
                rwlock_read_unlock( & eth_globals.protos_lock );
-
 
507
                ipc_answer_0( iid, EOK );
502
                break;
508
                break;
503
            case NET_NIL_RECEIVED:
509
            case NET_NIL_RECEIVED:
504
                if( ! ERROR_OCCURRED( packet_translate( eth_globals.networking_phone, & packet, IPC_GET_PACKET( icall )))){
510
                if( ! ERROR_OCCURRED( packet_translate( eth_globals.networking_phone, & packet, IPC_GET_PACKET( icall )))){
505
                    ERROR_CODE = eth_receive_message( IPC_GET_DEVICE( icall ), packet );
511
                    ERROR_CODE = eth_receive_message( IPC_GET_DEVICE( icall ), packet );
506
                }
512
                }