54,6 → 54,7 |
#include "../../include/protocol_map.h" |
#include "../../include/device.h" |
#include "../../include/netif_interface.h" |
#include "../../include/net_interface.h" |
#include "../../include/nil_interface.h" |
#include "../../include/il_interface.h" |
|
69,9 → 70,31 |
#define ETH_SUFFIX sizeof( eth_fcs_t ) |
#define ETH_MAX_CONTENT 1500 |
#define ETH_MIN_CONTENT 46 |
#define ETH_MAX_TAGGED_CONTENT ( ETH_MAX_CONTENT - sizeof( eth_header_lsap_t ) - sizeof( eth_header_snap_t )) |
#define ETH_MIN_TAGGED_CONTENT ( ETH_MIN_CONTENT - sizeof( eth_header_lsap_t ) - sizeof( eth_header_snap_t )) |
#define ETH_MAX_TAGGED_CONTENT( flags ) ( ETH_MAX_CONTENT - (( IS_8023_2_LSAP( flags ) || IS_8023_2_SNAP( flags )) ? sizeof( eth_header_lsap_t ) : 0 ) - ( IS_8023_2_SNAP( flags ) ? sizeof( eth_header_snap_t ) : 0 )) |
#define ETH_MIN_TAGGED_CONTENT( flags ) ( ETH_MIN_CONTENT - (( IS_8023_2_LSAP( flags ) || IS_8023_2_SNAP( flags )) ? sizeof( eth_header_lsap_t ) : 0 ) - ( IS_8023_2_SNAP( flags ) ? sizeof( eth_header_snap_t ) : 0 )) |
|
#define ETH_DUMMY_SHIFT 0 |
#define ETH_MODE_SHIFT 1 |
|
/** Dummy device flag. |
* Preamble and FCS are mandatory part of the packets. |
*/ |
#define ETH_DUMMY ( 1 << ETH_DUMMY_SHIFT ) |
#define IS_DUMMY( flags ) (( flags ) & ETH_DUMMY ) |
|
/** Device mode flags. |
* @see ETH_DIX |
* @see ETH_8023_2_LSAP |
* @see ETH_8023_2_SNAP |
*/ |
#define ETH_MODE_MASK ( 3 << ETH_MODE_SHIFT ) |
#define ETH_DIX ( 1 << ETH_MODE_SHIFT ) |
#define IS_DIX( flags ) ((( flags ) & ETH_MODE_MASK ) == ETH_DIX ) |
#define ETH_8023_2_LSAP ( 2 << ETH_MODE_SHIFT ) |
#define IS_8023_2_LSAP( flags ) ((( flags ) & ETH_MODE_MASK ) == ETH_8023_2_LSAP ) |
#define ETH_8023_2_SNAP ( 3 << ETH_MODE_SHIFT ) |
#define IS_8023_2_SNAP( flags ) ((( flags ) & ETH_MODE_MASK ) == ETH_8023_2_SNAP ) |
|
typedef enum eth_addr_type eth_addr_type_t; |
typedef eth_addr_type_t * eth_addr_type_ref; |
|
100,8 → 123,8 |
int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ); |
int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ); |
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ); |
eth_proto_ref eth_process_packet( int dummy, packet_t packet ); |
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ); |
eth_proto_ref eth_process_packet( int flags, packet_t packet ); |
int eth_prepare_packet( int flags, packet_t packet, uint8_t * src_addr, int ethertype ); |
|
int nil_device_state_msg( int nil_phone, device_id_t device_id, int state ){ |
int index; |
142,6 → 165,10 |
|
eth_device_ref device; |
int index; |
measured_string_t names[ 2 ] = {{ "ETH_MODE", 8 }, { "ETH_DUMMY", 9 }}; |
measured_string_ref configuration; |
int count = 2; |
char * data; |
|
rwlock_write_lock( & eth_globals.devices_lock ); |
// an existing device? |
162,9 → 189,29 |
if( ! device ) return ENOMEM; |
device->device_id = device_id; |
device->service = service; |
device->mtu = (( mtu > 0 ) && ( mtu <= ETH_MAX_TAGGED_CONTENT )) ? mtu : ETH_MAX_TAGGED_CONTENT; |
// TODO get dummy setting |
device->dummy = 0; |
device->flags = 0; |
device->mtu = (( mtu > 0 ) && ( mtu <= ETH_MAX_TAGGED_CONTENT( device->flags ))) ? mtu : ETH_MAX_TAGGED_CONTENT( device->flags ); |
configuration = & names[ 0 ]; |
if( ERROR_OCCURRED( net_get_device_conf_req( eth_globals.net_phone, device->device_id, & configuration, count, & data ))){ |
rwlock_write_unlock( & eth_globals.devices_lock ); |
free( device ); |
return ERROR_CODE; |
} |
if( configuration ){ |
if( ! str_lcmp( configuration[ 0 ].value, "DIX", configuration[ 0 ].length )){ |
device->flags |= ETH_DIX; |
}else if( ! str_lcmp( configuration[ 0 ].value, "8023_2_LSAP", configuration[ 0 ].length )){ |
// TODO 8023_2_LSAP |
printf( "8023_2_LSAP is not supported (yet?), DIX used instead\n" ); |
device->flags |= ETH_DIX; |
}else device->flags |= ETH_8023_2_SNAP; |
if(( configuration[ 1 ].value ) && ( configuration[ 1 ].value[ 0 ] == 'y' )){ |
device->flags |= ETH_DUMMY; |
} |
net_free_settings( configuration, data ); |
}else{ |
device->flags |= ETH_8023_2_SNAP; |
} |
// bind the device driver |
device->phone = netif_bind_service( device->service, device->device_id, SERVICE_ETHERNET, eth_receiver ); |
if( device->phone < 0 ){ |
187,13 → 234,13 |
free( device ); |
return index; |
} |
printf( "New device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n\taddress\t= %X:%X:%X:%X:%X:%X\n", 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 ] ); |
printf( "New device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n\taddress\t= %X:%X:%X:%X:%X:%X\n\tflags\t= 0x%x\n", 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 ], device->flags ); |
} |
rwlock_write_unlock( & eth_globals.devices_lock ); |
return EOK; |
} |
|
eth_proto_ref eth_process_packet( int dummy, packet_t packet ){ |
eth_proto_ref eth_process_packet( int flags, packet_t packet ){ |
ERROR_DECLARE; |
|
eth_header_ex_ref header; |
204,17 → 251,17 |
eth_fcs_ref fcs; |
|
length = packet_get_data_length( packet ); |
if( dummy ){ |
if( IS_DUMMY( flags )){ |
packet_trim( packet, sizeof( eth_preamble_t ), 0 ); |
} |
if( length <= sizeof( eth_header_t ) + ETH_MIN_CONTENT + ETH_SUFFIX ) return NULL; |
if( length < sizeof( eth_header_t ) + ETH_MIN_CONTENT + ( IS_DUMMY( flags ) ? ETH_SUFFIX : 0 )) return NULL; |
header = ( eth_header_ex_ref ) packet_get_data( packet ); |
type = ntohs( header->header.ethertype ); |
if( type >= ETH_MIN_PROTO ){ |
// DIX Ethernet |
prefix = sizeof( eth_header_t ); |
suffix = sizeof( eth_fcs_t ); |
fcs = (( void * ) header ) + length - suffix; |
suffix = 0; |
fcs = (( void * ) header ) + length - sizeof( eth_fcs_t ); |
}else if( type <= ETH_MAX_CONTENT ){ |
// translate "LSAP" values |
if(( header->lsap.dsap == ETH_LSAP_GLSAP ) && ( header->lsap.ssap == ETH_LSAP_GLSAP )){ |
238,10 → 285,11 |
// invalid length/type, should not occurr |
return NULL; |
} |
if( dummy ){ |
if( IS_DUMMY( flags )){ |
if(( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 )) != ntohl( * fcs )){ |
return NULL; |
} |
suffix += sizeof( eth_fcs_t ); |
} |
if( ERROR_OCCURRED( packet_set_addr( packet, header->header.src, header->header.dest, ETH_ADDR )) |
|| ERROR_OCCURRED( packet_trim( packet, prefix, suffix ))){ |
254,7 → 302,7 |
eth_proto_ref proto; |
packet_t next; |
eth_device_ref device; |
int dummy; |
int flags; |
|
rwlock_read_lock( & eth_globals.devices_lock ); |
device = eth_devices_find( & eth_globals.devices, device_id ); |
262,12 → 310,12 |
rwlock_read_unlock( & eth_globals.devices_lock ); |
return ENOENT; |
} |
dummy = device->dummy; |
flags = device->flags; |
rwlock_read_unlock( & eth_globals.devices_lock ); |
rwlock_read_lock( & eth_globals.protos_lock ); |
do{ |
next = pq_detach( packet ); |
proto = eth_process_packet( dummy, packet ); |
proto = eth_process_packet( flags, packet ); |
if( proto ){ |
il_received_msg( proto->phone, device_id, packet, proto->service ); |
}else{ |
351,8 → 399,9 |
return EOK; |
} |
|
int eth_prepare_packet( int dummy, packet_t packet, uint8_t * src_addr, int ethertype ){ |
int eth_prepare_packet( int flags, packet_t packet, uint8_t * src_addr, int ethertype ){ |
eth_header_ex_ref header; |
eth_header_ref header_dix; |
eth_fcs_ref fcs; |
uint8_t * src; |
uint8_t * dest; |
361,36 → 410,46 |
void * padding; |
eth_preamble_ref preamble; |
|
length = packet_get_addr( packet, & src, & dest ); |
if( length < 0 ) return length; |
if( length < ETH_ADDR ) return EINVAL; |
length = packet_get_data_length( packet ); |
if( length > ETH_MAX_TAGGED_CONTENT ) return EINVAL; |
if( length < ETH_MIN_TAGGED_CONTENT ){ |
padding = packet_suffix( packet, ETH_MIN_TAGGED_CONTENT - length ); |
if( length > ETH_MAX_TAGGED_CONTENT( flags )) return EINVAL; |
if( length < ETH_MIN_TAGGED_CONTENT( flags )){ |
padding = packet_suffix( packet, ETH_MIN_TAGGED_CONTENT( flags ) - length ); |
if( ! padding ) return ENOMEM; |
bzero( padding, ETH_MIN_TAGGED_CONTENT - length ); |
bzero( padding, ETH_MIN_TAGGED_CONTENT( flags ) - length ); |
} |
if( dummy ){ |
if( IS_DUMMY( flags )){ |
preamble = PACKET_PREFIX( packet, eth_preamble_t ); |
if( ! preamble ) return ENOMEM; |
for( i = 0; i < 7; ++ i ) preamble->preamble[ i ] = ETH_PREAMBLE; |
preamble->sfd = ETH_SFD; |
} |
header = PACKET_PREFIX( packet, eth_header_ex_t ); |
if( ! header ) return ENOMEM; |
header->header.ethertype = htons( length + sizeof( eth_header_lsap_t ) + sizeof( eth_header_snap_t )); |
header->lsap.dsap = ( uint16_t ) ETH_LSAP_SNAP; |
header->lsap.ssap = header->lsap.dsap; |
header->lsap.ctrl = 0; |
for( i = 0; i < 3; ++ i ) header->snap.proto[ i ] = 0; |
header->snap.ethertype = ( uint16_t ) ethertype; |
length = packet_get_addr( packet, & src, & dest ); |
if( length < 0 ) return length; |
if( length < ETH_ADDR ) return EINVAL; |
memcpy( header->header.src, src_addr, ETH_ADDR ); |
memcpy( header->header.dest, dest, ETH_ADDR ); |
if( dummy ){ |
// TODO LSAP only device |
if( IS_DIX( flags ) || IS_8023_2_LSAP( flags )){ |
header_dix = PACKET_PREFIX( packet, eth_header_t ); |
header_dix->ethertype = ( uint16_t ) ethertype; |
memcpy( header_dix->src, src_addr, ETH_ADDR ); |
memcpy( header_dix->dest, dest, ETH_ADDR ); |
src = & header_dix->dest[ 0 ]; |
}else if( IS_8023_2_SNAP( flags )){ |
header = PACKET_PREFIX( packet, eth_header_ex_t ); |
if( ! header ) return ENOMEM; |
header->header.ethertype = htons( length + sizeof( eth_header_lsap_t ) + sizeof( eth_header_snap_t )); |
header->lsap.dsap = ( uint16_t ) ETH_LSAP_SNAP; |
header->lsap.ssap = header->lsap.dsap; |
header->lsap.ctrl = 0; |
for( i = 0; i < 3; ++ i ) header->snap.proto[ i ] = 0; |
header->snap.ethertype = ( uint16_t ) ethertype; |
memcpy( header->header.src, src_addr, ETH_ADDR ); |
memcpy( header->header.dest, dest, ETH_ADDR ); |
src = & header->header.dest[ 0 ]; |
} |
if( IS_DUMMY( flags )){ |
fcs = PACKET_SUFFIX( packet, eth_fcs_t ); |
if( ! fcs ) return ENOMEM; |
* fcs = htonl( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 )); |
* fcs = htonl( ~ compute_crc32( ~ 0, src, ((( void * ) fcs ) - (( void * ) src )) * 8 )); |
} |
return EOK; |
} |
417,7 → 476,7 |
// process packet queue |
next = packet; |
do{ |
if( ERROR_OCCURRED( eth_prepare_packet( device->dummy, next, ( uint8_t * ) device->addr->value, ethertype ))){ |
if( ERROR_OCCURRED( eth_prepare_packet( device->flags, next, ( uint8_t * ) device->addr->value, ethertype ))){ |
// release invalid packet |
tmp = pq_detach( next ); |
pq_release( eth_globals.net_phone, packet_get_id( next )); |
470,6 → 529,7 |
packet_t packet; |
|
while( true ){ |
// printf( "message %d - %d\n", IPC_GET_METHOD( * icall ), NET_NIL_FIRST ); |
switch( IPC_GET_METHOD( * icall )){ |
case NET_NIL_DEVICE_STATE: |
nil_device_state_msg( 0, IPC_GET_DEVICE( icall ), IPC_GET_STATE( icall )); |