Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4075 → Rev 3992

/branches/network/uspace/srv/net/crc.c
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/branches/network/uspace/srv/net/nil/eth/eth.c
48,8 → 48,6
#include "../../modules.h"
 
#include "../../include/byteorder.h"
#include "../../include/crc.h"
#include "../../include/ethernet_lsap.h"
#include "../../include/ethernet_protocols.h"
#include "../../include/protocol_map.h"
#include "../../netif/device.h"
64,9 → 62,10
#include "eth_module.h"
 
#define ETH_PREFIX ( sizeof( eth_header_t ) + sizeof( eth_header_lsap_t ) + sizeof( eth_header_snap_t ))
#define ETH_SUFFIX sizeof( eth_fcs_t )
#define ETH_MAX_CONTENT 1500
#define ETH_SUFFIX 4
#define ETH_MAX_CONTENT ( ETH_MIN_PROTO - 1 )
#define ETH_MIN_CONTENT 46
#define ETH_PADDING ETH_SUFFIX
 
/** Returns the device identifier message parameter.
*/
123,8 → 122,6
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender );
int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
void eth_receiver( ipc_callid_t iid, ipc_call_t * icall );
eth_proto_ref eth_proccess_packet( packet_t packet );
int eth_prepare_packet( packet_t packet, uint8_t * src_addr, int ethertype );
 
int eth_initialize( void ){
ERROR_DECLARE;
204,76 → 201,55
return EOK;
}
 
eth_proto_ref eth_proccess_packet( packet_t packet ){
int eth_receive_message( device_id_t device_id, packet_t packet ){
ERROR_DECLARE;
 
eth_header_ex_ref header;
size_t length;
int type;
size_t prefix;
size_t suffix;
eth_fcs_ref fcs;
eth_proto_ref proto;
size_t size;
 
length = packet_get_data_length( packet );
if( length <= sizeof( eth_header_t ) + ETH_MIN_CONTENT + ETH_SUFFIX ) return NULL;
if( length <= sizeof( eth_header_t ) + ETH_MIN_CONTENT + ETH_PADDING ) return EINVAL;
// TODO check CRC padding?
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;
}else if( type <= ETH_MAX_CONTENT ){
size = sizeof( eth_header_t );
}else{
// TODO check length?
// translate "LSAP" values
if(( header->lsap.dsap == ETH_LSAP_GLSAP ) && ( header->lsap.ssap == ETH_LSAP_GLSAP )){
if(( header->lsap.dsap == ETH_RAW ) && ( header->lsap.ssap == ETH_RAW )){
// raw packet
// discard
return NULL;
return EINVAL;
}else if(( header->lsap.dsap == ETH_LSAP_SNAP ) && ( header->lsap.ssap == ETH_LSAP_SNAP )){
// IEEE 802.3 + 802.2 + LSAP + SNAP
// IEEE 802.3 SNAP
// organization code not supported
type = ntohs( header->snap.ethertype );
prefix = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t) + sizeof( eth_header_snap_t);
size = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t) + sizeof( eth_header_snap_t);
}else{
// IEEE 802.3 + 802.2 LSAP
type = lsap_map( header->lsap.dsap );
prefix = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t);
// TODO lsap numbers
type = header->lsap.dsap;
size = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t);
}
suffix = ( type < ETH_MIN_CONTENT ) ? ETH_MIN_CONTENT - type : 0;
fcs = (( void * ) header ) + prefix + type + suffix;
suffix += length - prefix - type;
}else{
// invalid length/type, should not occurr
return NULL;
}
// TODO compute crc with fcs to erase?
if(( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 )) != ( * fcs )){
return NULL;
rwlock_write_lock( & eth_globals.protos_lock );
proto = eth_protos_find( & eth_globals.protos, type );
if( ! proto ){
rwlock_write_unlock( & eth_globals.protos_lock );
return ENOENT;
}
if( ERROR_OCCURRED( packet_set_addr( packet, header->header.src, header->header.dest, ETH_ADDR ))
|| ERROR_OCCURRED( packet_trim( packet, prefix, suffix ))){
return NULL;
|| ERROR_OCCURRED( packet_trim( packet, size, ETH_PADDING ))){
rwlock_write_unlock( & eth_globals.protos_lock );
return ERROR_CODE;
}
return eth_protos_find( & eth_globals.protos, type );
}
 
int eth_receive_message( device_id_t device_id, packet_t packet ){
eth_proto_ref proto;
packet_t next;
 
rwlock_read_lock( & eth_globals.protos_lock );
do{
next = pq_detach( packet );
proto = eth_proccess_packet( packet );
if( proto ){
async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet ));
}else{
// drop invalid/unknown
packet_release( eth_globals.networking_phone, packet_get_id( packet ));
}
packet = next;
}while( packet );
rwlock_read_unlock( & eth_globals.protos_lock );
async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet ));
rwlock_write_unlock( & eth_globals.protos_lock );
return EOK;
}
 
291,7 → 267,7
rwlock_write_unlock( & eth_globals.devices_lock );
* addr_len = ETH_ADDR;
* prefix = ETH_PREFIX;
* suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
* suffix = ETH_SUFFIX;
return EOK;
}
 
347,14 → 323,15
return EOK;
}
 
int eth_prepare_packet( packet_t packet, uint8_t * src_addr, int ethertype ){
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ){
ERROR_DECLARE;
 
eth_device_ref device;
eth_header_ex_ref header;
eth_fcs_ref fcs;
uint8_t * src;
uint8_t * dest;
int length;
int i;
void * padding;
 
header = PACKET_PREFIX( packet, eth_header_ex_t );
if( ! header ) return ENOMEM;
363,14 → 340,12
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 );
// TODO src set?
// TODO set addresses
length = packet_get_data_length( packet );
if( length > ETH_MAX_CONTENT ) return EINVAL;
if( length < ETH_MIN_CONTENT ){
padding = packet_suffix( packet, ETH_MIN_CONTENT - length );
if( ! padding ) return ENOMEM;
memset( padding, 0, ETH_MIN_CONTENT - length );
// TODO pad zeros
}
header->header.ethertype = htons( length );
header->lsap.dsap = 0xAA;
377,47 → 352,15
header->lsap.ssap = header->lsap.dsap;
header->lsap.ctrl = 0;
for( i = 0; i < 3; ++ i ) header->snap.proto[ i ] = 0;
header->snap.ethertype = ethertype;
fcs = PACKET_SUFFIX( packet, eth_fcs_t );
if( ! fcs ) return ENOMEM;
* fcs = ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 );
return EOK;
}
 
int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ){
ERROR_DECLARE;
 
eth_device_ref device;
packet_t next;
packet_t tmp;
int ethertype;
 
ethertype = htons( protocol_map( SERVICE_ETHERNET, sender ));
if( ! ethertype ){
packet_release( eth_globals.networking_phone, packet_get_id( packet ));
return EINVAL;
header->snap.ethertype = htons( protocol_map( SERVICE_ETHERNET, sender ));
if( ! header ) return ENOENT;
// TODO eth padding
if( ! packet_suffix( packet, ETH_PADDING )){
return ENOMEM;
}
rwlock_read_lock( & eth_globals.devices_lock );
device = eth_devices_find( & eth_globals.devices, device_id );
if( ! device ){
rwlock_read_unlock( & eth_globals.devices_lock );
return ENOENT;
}
// proccess packet queue
next = packet;
do{
if( ERROR_OCCURRED( eth_prepare_packet( next, ( uint8_t * ) device->addr->value, ethertype ))){
// release invalid packet
tmp = pq_detach( next );
packet_release( eth_globals.networking_phone, packet_get_id( next ));
next = tmp;
}else{
next = pq_next( next );
}
}while( next );
// send packet queue
async_msg_2( device->phone, NET_NETIF_SEND, device_id, packet_get_id( packet ));
rwlock_read_unlock( & eth_globals.devices_lock );
rwlock_write_lock( & eth_globals.devices_lock );
rwlock_write_unlock( & eth_globals.devices_lock );
return EOK;
}
 
/branches/network/uspace/srv/net/nil/eth/Makefile
37,7 → 37,6
$(NAME).c \
$(NET_BASE)module.c \
$(NET_BASE)modules.c \
$(NET_BASE)crc.c \
$(STRUCTURES)measured_strings.c \
$(STRUCTURES)packet/packet.c \
$(STRUCTURES)packet/packet_client.c
/branches/network/uspace/srv/net/nil/eth/eth_header.h
44,8 → 44,12
 
#define ETH_PREAMBLE 0x55
 
#define ETH_SFD 0xD5
#define ETH_SFD 0xF5
 
#define ETH_LSAP_SNAP 0xAA
 
#define ETH_RAW 0xFF
 
/** Type definition of the Ethernet header with all the extensions.
* @see eth_header_ex
*/
154,14 → 158,6
eth_header_snap_t snap;
};
 
/** Ethernet Frame Check Sequence.
*/
typedef uint32_t eth_fcs_t;
 
/** Ethernet Frame Check Sequence pointer.
*/
typedef eth_fcs_t * eth_fcs_ref;
 
#endif
 
/** @}
/branches/network/uspace/srv/net/include/ethernet_lsap.h
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/branches/network/uspace/srv/net/include/crc.h
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/branches/network/uspace/srv/net/include/ethernet_protocols.h
39,9 → 39,8
#define __NET_ETHERNET_PROTOCOLS_H__
 
/** Ethernet minimal protocol number.
* According to the IEEE 802.3 specification.
*/
#define ETH_MIN_PROTO 0x0600 /*1536*/
#define ETH_MIN_PROTO 1501
 
/** Ethernet loopback packet protocol type.
*/
/branches/network/uspace/srv/net/include/protocol_map.h
39,7 → 39,6
 
#include <ipc/services.h>
 
#include "ethernet_lsap.h"
#include "ethernet_protocols.h"
 
/** Maps the internetwork layer service to the network interface layer type.
86,22 → 85,6
}
}
 
/** Maps the link service access point identifier to the Ethernet protocol identifier.
* @param lsap Link service access point identifier. Input parameter.
* @returns Ethernet protocol identifier of the link service access point identifier.
* @returns ETH_LSAP_NULL if mapping is not found.
*/
static inline int lsap_map( int lsap ){
switch( lsap ){
case ETH_LSAP_IP:
return ETH_P_IP;
case ETH_LSAP_ARP:
return ETH_P_ARP;
default:
return ETH_LSAP_NULL;
}
}
 
#endif
 
/** @}
/branches/network/uspace/srv/net/networking/startup/Makefile
41,9 → 41,7
$(NAME).c \
$(NET_BASE)modules.c \
$(NET_BASE)self_test.c \
$(STRUCTURES)char_map.c \
$(STRUCTURES)measured_strings.c \
$(NET_BASE)crc.c
$(STRUCTURES)measured_strings.c
 
NET_DEFS += -D NETWORKING_$(NETWORKING)
 
/branches/network/uspace/srv/net/netif/lo/lo.c
167,16 → 167,16
 
ERROR_PROPAGATE( find_device( device_id, & device ));
if( device->state != NETIF_ACTIVE ) return EPERM;
next = packet;
do{
++ device->stats.tx_packets;
++ device->stats.rx_packets;
length = packet_get_data_length( next );
length = packet_get_data_length( packet );
device->stats.tx_bytes += length;
device->stats.rx_bytes += length;
next = pq_next( next );
}while( next );
nil_message( device, NET_NIL_RECEIVED, packet_get_id( packet ), PACKET_SELF );
next = pq_detach( packet );
nil_message( device, NET_NIL_RECEIVED, packet_get_id( packet ), PACKET_SELF );
packet = next;
}while( packet );
return EOK;
}
 
/branches/network/uspace/srv/net/structures/packet/packet.c
250,15 → 250,5
}
}
 
packet_t pq_next( packet_t packet ){
if( ! packet_is_valid( packet )) return NULL;
return pm_find( packet->next );
}
 
packet_t pq_previous( packet_t packet ){
if( ! packet_is_valid( packet )) return NULL;
return pm_find( packet->previous );
}
 
/** @}
*/
/branches/network/uspace/srv/net/structures/packet/packet_client.h
193,10 → 193,9
*/
packet_t packet_get_1( int phone, size_t content );
 
/** Releases the packet queue.
* All packets in the queue are marked as free for use.
* The packet queue may be one packet only.
* The module should not use the packets after this point until they are received or obtained again.
/** Releases the packet.
* The packet is marked as free for use.
* The module should not use the packet after this point until it is received or obtained again.
* @param phone The packet server module phone. Input parameter.
* @param packet_id The packet identifier. Input parameter.
*/
/branches/network/uspace/srv/net/structures/packet/packet.h
129,22 → 129,6
*/
void pq_destroy( packet_t first, void ( * packet_release )( packet_t packet ));
 
/** Returns the next packet in the queue.
* @param packet The packet queue member. Input parameter.
* @returns The next packet in the queue.
* @returns NULL if there is no next packet.
* @returns NULL if the packet is not valid.
*/
packet_t pq_next( packet_t packet );
 
/** Returns the previous packet in the queue.
* @param packet The packet queue member. Input parameter.
* @returns The previous packet in the queue.
* @returns NULL if there is no previous packet.
* @returns NULL if the packet is not valid.
*/
packet_t pq_previous( packet_t packet );
 
#endif
 
/** @}
/branches/network/uspace/srv/net/configuration.h
45,7 → 45,7
* The NET_SELF_TEST has to be activated.
* @see measured_strings.h
*/
#define NET_SELF_TEST_MEASURED_STRINGS 0
#define NET_SELF_TEST_MEASURED_STRINGS 1
 
/** Activate the char map self test.
* The NET_SELF_TEST has to be activated.
71,12 → 71,6
*/
#define NET_SELF_TEST_GENERIC_CHAR_MAP 0
 
/** Activate the CRC computation self test.
* The NET_SELF_TEST has to be activated.
* @see crc.h
*/
#define NET_SELF_TEST_CRC 0
 
#endif
 
/** @}
/branches/network/uspace/srv/net/self_test.c
41,11 → 41,10
#include <malloc.h>
#include <stdio.h>
 
#include "include/crc.h"
#include "structures/int_map.h"
#include "structures/char_map.h"
#include "structures/generic_char_map.h"
#include "structures/measured_strings.h"
#include "int_map.h"
#include "char_map.h"
#include "generic_char_map.h"
#include "measured_strings.h"
 
#include "self_test.h"
 
53,7 → 52,6
printf( "\n\t%s", ( name )); \
if(( function_call ) != ( result )){ \
printf( "\tERROR" ); \
error = 1; \
}else{ \
printf( "\tOK" ); \
} \
84,7 → 82,6
#endif
 
int self_test( void ){
int error = 0;
int * x, * y, * z, * u, * v, * w;
 
#if NET_SELF_TEST_MEASURED_STRINGS
91,7 → 88,7
measured_string_ref string;
 
printf( "\nMeasured strings test" );
string = measured_string_create_bulk( "I am a measured string!", 0 );
string = measured_string_create_bulk( "I am a measured string!", -1 );
printf( "\n%x, %s at %x of %d", string, string->value, string->value, string->length );
printf( "\nOK" );
#endif
135,11 → 132,10
TEST( "update ucho 3 einval", char_map_update( & cm, "ucho", 0, 3 ), EINVAL );
printf( "\nOK" );
 
if( error ) return EINVAL;
 
#endif
 
#if NET_SELF_TEST_INT_MAP
 
int_map_t im;
 
x = ( int * ) malloc( sizeof( int ));
189,11 → 185,10
TEST( "count -1", int_map_count( & im ), -1 );
printf( "\nOK" );
 
if( error ) return EINVAL;
 
#endif
 
#if NET_SELF_TEST_GENERIC_FIELD
 
int_field_t gf;
 
x = ( int * ) malloc( sizeof( int ));
240,11 → 235,10
TEST( "count -1", int_field_count( & gf ), -1 );
printf( "\nOK" );
 
if( error ) return EINVAL;
 
#endif
 
#if NET_SELF_TEST_GENERIC_CHAR_MAP
 
int_char_map_t icm;
 
x = ( int * ) malloc( sizeof( int ));
283,40 → 277,8
TEST( "add ucho z einval", int_char_map_add( & icm, "ucho", 0, z ), EINVAL );
printf( "\nOK" );
 
if( error ) return EINVAL;
 
#endif
 
#if NET_SELF_TEST_CRC
uint32_t value;
 
printf( "\nCRC computation test" );
value = ~ compute_crc32( ~ 0, "123456789", 8 * 9 );
TEST( "123456789", value, 0xCBF43926 );
printf( "\t=> %X", value );
value = ~ compute_crc32( ~ 0, "1", 8 );
TEST( "1", value, 0x83DCEFB7 );
printf( "\t=> %X", value );
value = ~ compute_crc32( ~ 0, "12", 8 * 2 );
TEST( "12", value, 0x4F5344CD );
printf( "\t=> %X", value );
value = ~ compute_crc32( ~ 0, "123", 8 * 3 );
TEST( "123", value, 0x884863D2 );
printf( "\t=> %X", value );
value = ~ compute_crc32( ~ 0, "1234", 8 * 4 );
TEST( "1234", value, 0x9BE3E0A3 );
printf( "\t=> %X", value );
value = ~ compute_crc32( ~ 0, "12345678", 8 * 8 );
TEST( "12345678", value, 0x9AE0DAAF );
printf( "\t=> %X", value );
value = ~ compute_crc32( ~ 0, "ahoj pane", 8 * 9 );
TEST( "ahoj pane", value, 0x5FC3D706 );
printf( "\t=> %X", value );
 
if( error ) return EINVAL;
 
#endif
 
return EOK;
}