From 418ae6fe5f5a5f27bd6cd6a2c886c434db571839 Mon Sep 17 00:00:00 2001 From: Radek Matejka Date: Mon, 13 Aug 2012 10:17:50 +0200 Subject: [PATCH] reworking kernel canethgw The header file canethgw.h was refactored and cleaned. Thread synchronization was remade. --- kernel/canethgw.c | 344 +++++++++++++++++++----------------- kernel/canethgw.h | 49 ++--- utils/cegw/cegw.c | 41 +++-- utils/cegwbench/cegwbench.c | 52 ++++-- 4 files changed, 255 insertions(+), 231 deletions(-) diff --git a/kernel/canethgw.c b/kernel/canethgw.c index 020f79e..3a9b966 100644 --- a/kernel/canethgw.c +++ b/kernel/canethgw.c @@ -1,3 +1,5 @@ +#define DEBUG 1 + #include #include #include @@ -29,26 +31,25 @@ MODULE_LICENSE( "GPL" ); -static int gw_udp_recv( void* data ); -static void gw_udp_send( struct can_frame* cf, struct in_addr ipaddr, u16 port ); -static int gw_can_recv( void* data ); -static void gw_can_send( struct can_frame* cf, int ifidx ); +static int cegw_udp_can( void* data ); +inline static void cegw_udp_send( struct socket* udp_sock, struct can_frame* cf, struct in_addr ipaddr, u16 port ); +static int cegw_can_udp( void* data ); +inline static void cegw_can_send( struct socket* can_sock, struct can_frame* cf, int ifindex ); static void cegw_thread_start( void ); static void cegw_thread_stop( void ); -static int cegw_thread_restart( void* arg ); +static int cegw_thread_restart( void* arg ); #define CEGW_STOPPED 0 #define CEGW_RUNNING 1 +static struct socket* can_sock, * udp_sock; static struct task_struct* eth_to_can, * can_to_eth; -static struct socket* udp_sock = NULL; -static struct socket* can_sock = NULL; /* ToDo: protect with mutex */ -static int gw_state = CEGW_STOPPED; +static int cegw_state = CEGW_STOPPED; struct can_eth_gw { - int src_if_idx; + int src_ifindex; struct in_addr dst_addr; unsigned short dst_port; struct hlist_node list; @@ -72,14 +73,58 @@ struct unsigned short eth_port; } cegw_setting; -DECLARE_COMPLETION( udp_compl ); -DECLARE_COMPLETION( can_compl ); -DECLARE_COMPLETION( udp_fin ); -DECLARE_COMPLETION( can_fin ); +DECLARE_COMPLETION( cegw_compl_init ); +DECLARE_COMPLETION( cegw_compl_exit ); DEFINE_MUTEX( cegw_setting_mutex ); -/**/ -static int gw_udp_recv( void* data ) +inline static void cegw_udp_send( struct socket* udp_sock, struct can_frame* cf, struct in_addr ipaddr, u16 port ) +{ + struct msghdr mh; + struct sockaddr_in addr; + struct kvec vec; + + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + addr.sin_addr = ipaddr; + + mh.msg_name = &addr; + mh.msg_namelen = sizeof( addr ); + mh.msg_control = NULL; + mh.msg_controllen = 0; + mh.msg_flags = 0; + + vec.iov_base = cf; + vec.iov_len = sizeof( *cf ); + + kernel_sendmsg( udp_sock, &mh, &vec, 1, sizeof( *cf ) ); +} + +inline static void cegw_can_send( struct socket* can_sock, struct can_frame* cf, int ifindex ) +{ + struct msghdr mh; + struct kvec vec; + struct sockaddr_can addr; + + addr.can_family = AF_CAN; + addr.can_ifindex = ifindex; + + mh.msg_name = &addr; + mh.msg_namelen = sizeof( addr ); + mh.msg_control = NULL; + mh.msg_controllen = 0; + mh.msg_flags = 0; + + vec.iov_base = cf; + vec.iov_len = sizeof( *cf ); + + kernel_sendmsg( can_sock, &mh, &vec, 1, sizeof( *cf ) ); /* ToDo: handle error */ +} + +/** + * cegw_udp_can - performs udp->can routing + * This function is run as a thread. + */ +static int cegw_udp_can( void* data ) { struct can_frame cf; struct kvec vec; @@ -89,6 +134,16 @@ static int gw_udp_recv( void* data ) int can_ifidx; int recv_size; struct sockaddr_in udp_addr; + struct sockaddr_can can_addr; + + can_addr.can_family = AF_CAN; + can_addr.can_ifindex = 0; + + udp_addr.sin_family = AF_INET; + mutex_lock( &cegw_setting_mutex ); + udp_addr.sin_port = htons( cegw_setting.eth_port ); + udp_addr.sin_addr = cegw_setting.eth_addr; + mutex_unlock( &cegw_setting_mutex ); mh.msg_name = NULL; mh.msg_namelen = 0; @@ -98,84 +153,72 @@ static int gw_udp_recv( void* data ) mh.msg_controllen = 0; mh.msg_flags = 0; - mutex_lock( &cegw_setting_mutex ); - udp_addr.sin_family = AF_INET; - udp_addr.sin_port = htons( cegw_setting.eth_port ); - udp_addr.sin_addr = cegw_setting.eth_addr; - mutex_unlock( &cegw_setting_mutex ); - if( sock_create_kern( PF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp_sock) != 0 ) { - printk( KERN_ERR "error: can_sock creation failed\n" ); + printk( KERN_ERR "canethgw: udp socket creation failed\n" ); return -1; } - - if( kernel_bind( udp_sock, (struct sockaddr*)&udp_addr, sizeof( udp_addr ) ) != 0 ) /* ref impl ?!? */ + + if( sock_create_kern( PF_CAN, SOCK_RAW, CAN_RAW, &can_sock) != 0 ) { - printk( "error: binding failed\n" ); + printk( KERN_ERR "canethgw: can socket creation failed\n" ); + return -1; + } + + if( kernel_bind( udp_sock, (struct sockaddr*)&udp_addr, sizeof( udp_addr ) ) != 0 ) + { + printk( KERN_ERR "canethgw: udp socket binding failed\n" ); sock_release( udp_sock ); + sock_release( can_sock ); return -1; } - printk( "gw_udp_recv is complete\n" ); - complete_all( &udp_compl ); /* ToDo: why _all? */ - wait_for_completion( &can_compl ); - printk( "gw_udp_recv continues\n" ); + if( kernel_bind( can_sock, (struct sockaddr*) &can_addr, sizeof(can_addr) ) != 0 ) + { + printk( KERN_ERR "canethgw: can socket binding failed\n" ); + sock_release( udp_sock ); + sock_release( can_sock ); + return -1; + } + + pr_devel( "canethgw: cegw_udp_can init complete\n" ); + complete_all( &cegw_compl_init ); /* ToDo: why _all? */ + pr_devel( "canethgw: cegw_udp_can is entering working cycle\n" ); while( 1 ) { - if( gw_state == CEGW_STOPPED ) + if( cegw_state == CEGW_STOPPED ) break; vec.iov_base = &cf; vec.iov_len = sizeof(cf); - recv_size = kernel_recvmsg( udp_sock, &mh, &vec, 1, sizeof(cf), 0 ); /* ToDo: handle error */ + recv_size = kernel_recvmsg( udp_sock, &mh, &vec, 1, sizeof(cf), 0 ); /* ToDo: handle error, size check */ if( recv_size == 0 ) { continue; } - printk( "yes" ); - printk( "received udp msg_id:%d\n", cf.can_id ); hlist_for_each_entry_rcu( job, pos, ð_can_job, list ) { rcu_read_lock(); /**/ can_ifidx = job->dst_if_idx; rcu_read_unlock(); /* ToDo: from filter */ - gw_can_send( &cf, can_ifidx ); + cegw_can_send( can_sock, &cf, can_ifidx ); } } + pr_devel( "canethgw: cegw_udp_can is ready for termination\n" ); + wait_for_completion( &cegw_compl_exit ); sock_release( udp_sock ); - complete_all( &udp_fin ); - printk( "udp terminates\n" ); + sock_release( can_sock ); + cegw_state = CEGW_STOPPED; /* ToDo */ + pr_devel( "canethgw: cegw_udp_can terminates\n" ); return 0; } -inline static void gw_udp_send( struct can_frame* cf, struct in_addr ipaddr, u16 port ) -{ - struct msghdr mh; - struct sockaddr_in addr; - struct kvec vec; - - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - addr.sin_addr = ipaddr; - - mh.msg_name = &addr; - mh.msg_namelen = sizeof( addr ); - mh.msg_control = NULL; - mh.msg_controllen = 0; - mh.msg_flags = 0; - - vec.iov_base = cf; - vec.iov_len = sizeof( *cf ); - - kernel_sendmsg( udp_sock, &mh, &vec, 1, sizeof( *cf ) ); -} - -/**/ - -static int gw_can_recv( void* data ) +/** + * cegw_can_udp - performs can->udp routing + */ +static int cegw_can_udp( void* data ) { struct msghdr mh; struct kvec vec; @@ -186,7 +229,6 @@ static int gw_can_recv( void* data ) struct in_addr eth_addr; u16 eth_port; int recv_size; - struct sockaddr_can can_addr; mh.msg_name = &ca; mh.msg_namelen = sizeof( ca ); @@ -194,30 +236,12 @@ static int gw_can_recv( void* data ) mh.msg_controllen = 0; mh.msg_flags = 0; - can_addr.can_family = AF_CAN; - can_addr.can_ifindex = 0; - - if( sock_create_kern( PF_CAN, SOCK_RAW, CAN_RAW, &can_sock) != 0 ) - { - printk( KERN_ERR "error: can_sock creation failed\n" ); - return -1; - } - - if( kernel_bind( can_sock, (struct sockaddr*) &can_addr, sizeof(can_addr) ) != 0 ) - { - printk( KERN_ERR "can_sock bind failed\n" ); - sock_release( can_sock ); - return -1; - } - - printk( "gw_can_recv is complete\n" ); - complete_all( &can_compl ); - wait_for_completion( &udp_compl ); - printk( "gw_can_recv continues\n" ); + wait_for_completion( &cegw_compl_init ); + pr_devel( "canethgw: cegw_can_udp is entering working cycle\n" ); while( 1 ) { - if( gw_state == CEGW_STOPPED ) /**/ + if( cegw_state == CEGW_STOPPED ) /**/ break; vec.iov_base = &cf; vec.iov_len = sizeof( cf ); @@ -227,54 +251,32 @@ static int gw_can_recv( void* data ) { continue; } - printk( "received can msg_id:%d, from:%d\n", cf.can_id, ca.can_ifindex ); hlist_for_each_entry_rcu( job, pos, &can_eth_job, list ) { rcu_read_lock(); eth_addr = job->dst_addr; eth_port = job->dst_port; rcu_read_unlock(); - printk( KERN_INFO "%x\n", eth_addr.s_addr ); - if( job->src_if_idx == ca.can_ifindex ) - gw_udp_send( &cf, eth_addr, eth_port ); + if( job->src_ifindex == ca.can_ifindex ) + cegw_udp_send( udp_sock, &cf, eth_addr, eth_port ); } } - sock_release( can_sock ); - complete_all( &can_fin ); - printk( "can terminates\n" ); + complete_all( &cegw_compl_exit ); + pr_devel( "canethgw: cegw_can_udp terminates\n" ); return 0; } -inline static void gw_can_send( struct can_frame* cf, int ifidx ) -{ - struct msghdr mh; - struct kvec vec; - struct sockaddr_can ca = - { - .can_family = AF_CAN, - .can_ifindex = ifidx - }; - - mh.msg_name = &ca; - mh.msg_namelen = sizeof( ca ); - mh.msg_control = NULL; - mh.msg_controllen = 0; - mh.msg_flags = 0; - - vec.iov_base = cf; - vec.iov_len = sizeof( *cf ); - - kernel_sendmsg( can_sock, &mh, &vec, 1, sizeof( *cf ) ); -} - /* NetLink */ static int cegw_create_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg ) { - struct nlattr* tb[ CGW_MAX+1 ]; + struct nlattr* tb[ CEGW_MAX+1 ]; struct can_eth_gw* cethgw = NULL; struct eth_can_gw* ecangw = NULL; + int ifindex; + u32 ip; + u16 port; int err = 0; /* ToDo: size check @@ -282,67 +284,69 @@ static int cegw_create_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg return -EINVAL; */ - err = nlmsg_parse( nlh, sizeof( struct rtmsg ), tb, CGW_MAX, NULL ); + err = nlmsg_parse( nlh, sizeof( struct rtmsg ), tb, CEGW_MAX, NULL ); if( err < 0 ) { - printk( KERN_ERR "error: nlmsg_parse\n" ); + printk( KERN_ERR "canethgw: nlmsg_parse error\n" ); return err; } - if( tb[CGW_CMD_INFO] == NULL ) + if( tb[CEGW_CMD_INFO] == NULL ) { - printk( "error: bad cmd\n" ); + printk( KERN_ERR "canethgw: bad cmd error\n" ); return -EINVAL; } - switch( *(int*)nla_data( tb[CGW_CMD_INFO] ) ) + switch( *(int*)nla_data( tb[CEGW_CMD_INFO] ) ) { case CEGW_LISTEN: - if( gw_state == CEGW_RUNNING ) + if( cegw_state == CEGW_RUNNING ) { mutex_lock( &cegw_setting_mutex ); - cegw_setting.eth_addr = *(struct in_addr*)nla_data( tb[CGW_LISTEN_IP] ); - cegw_setting.eth_port = *(u16*)nla_data( tb[CGW_LISTEN_PORT] ); + cegw_setting.eth_addr = *(struct in_addr*)nla_data( tb[CEGW_ETH_IP] ); + cegw_setting.eth_port = *(u16*)nla_data( tb[CEGW_ETH_PORT] ); mutex_unlock( &cegw_setting_mutex ); kthread_run( cegw_thread_restart, NULL, "canethgw" ); } else { mutex_lock( &cegw_setting_mutex ); - cegw_setting.eth_addr = *(struct in_addr*)nla_data( tb[CGW_LISTEN_IP] ); - cegw_setting.eth_port = *(u16*)nla_data( tb[CGW_LISTEN_PORT] ); + cegw_setting.eth_addr = *(struct in_addr*)nla_data( tb[CEGW_ETH_IP] ); + cegw_setting.eth_port = *(u16*)nla_data( tb[CEGW_ETH_PORT] ); mutex_unlock( &cegw_setting_mutex ); cegw_thread_start(); } break; - case CGW_TYPE_CAN_ETH_UDP: - printk( KERN_INFO "can:%d\n", *(int*)nla_data( tb[CGW_CAN_IF] ) ); - printk( KERN_INFO "eth addr:%x\n", *(u32*)nla_data( tb[CGW_ETH_IP] ) ); - printk( KERN_INFO "eth port:%hu\n", *(u16*)nla_data( tb[CGW_ETH_PORT] ) ); + case CEGW_RULE_CAN_ETH: /* new can->eth rule */ + { + ifindex = *(int*)nla_data( tb[CEGW_CAN_IFINDEX] ); + ip = *(u32*)nla_data( tb[CEGW_ETH_IP] ); + port = *(u16*)nla_data( tb[CEGW_ETH_PORT] ); + pr_devel( "canethgw: new can->eth rule - (%d)->(%x:%hu)\n", ifindex, ip, port ); + cethgw = kmalloc( sizeof(struct can_eth_gw), GFP_KERNEL ); if( cethgw == NULL ) { - printk( KERN_ERR "error: kmalloc\n" ); break; } - cethgw->src_if_idx = *(int*)nla_data( tb[CGW_CAN_IF] ); - cethgw->dst_addr = *(struct in_addr*)nla_data( tb[CGW_ETH_IP] ); - cethgw->dst_port = *(u16*)nla_data( tb[CGW_ETH_PORT] ); + cethgw->src_ifindex = ifindex; + cethgw->dst_addr = *(struct in_addr*)nla_data( tb[CEGW_ETH_IP] ); + cethgw->dst_port = *(u16*)nla_data( tb[CEGW_ETH_PORT] ); hlist_add_head_rcu( &cethgw->list, &can_eth_job ); - break; - case CGW_TYPE_ETH_CAN_UDP: - printk( KERN_INFO "can:%d\n", *(int*)nla_data( tb[CGW_CAN_IF] ) ); + } + break; + case CEGW_RULE_ETH_CAN: /* new eth->can rule */ + printk( KERN_INFO "can:%d\n", *(int*)nla_data( tb[CEGW_CAN_IFINDEX] ) ); ecangw = kmalloc( sizeof(struct eth_can_gw), GFP_KERNEL ); if( ecangw == NULL ) { - printk( KERN_ERR "error: kmalloc\n" ); break; } - ecangw->dst_if_idx = *(int*)nla_data( tb[CGW_CAN_IF] ); + ecangw->dst_if_idx = *(int*)nla_data( tb[CEGW_CAN_IFINDEX] ); hlist_add_head_rcu( &ecangw->list, ð_can_job ); break; default: - printk( "default" ); + pr_devel( "canethgw: unknown CEGW_CMD_INFO\n" ); /* ToDo undef operation */ break; } @@ -353,7 +357,7 @@ static int cegw_create_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg static int cegw_remove_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg ) { struct rtmsg* r; - struct nlattr* tb[ CGW_MAX+1 ]; + struct nlattr* tb[ CEGW_MAX+1 ]; struct hlist_node* pos,* n; struct can_eth_gw* ceth; struct eth_can_gw* ecan; @@ -374,14 +378,14 @@ static int cegw_remove_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg */ printk( "attrsize=%d\n", nlmsg_attrlen(nlh, sizeof(struct rtmsg)) ); - err = nlmsg_parse( nlh, sizeof(struct rtmsg), tb, CGW_MAX, NULL ); + err = nlmsg_parse( nlh, sizeof(struct rtmsg), tb, CEGW_MAX, NULL ); if( err != 0 ) return -EINVAL; - if( tb[CGW_CMD_INFO] == NULL ) + if( tb[CEGW_CMD_INFO] == NULL ) return -EINVAL; - if( *(int*)nla_data( tb[CGW_CMD_INFO] ) == CEGW_FLUSH ) + if( *(int*)nla_data( tb[CEGW_CMD_INFO] ) == CEGW_FLUSH ) { hlist_for_each_entry_safe( ceth, pos, n, &can_eth_job, list ) { @@ -420,11 +424,11 @@ static int cegw_dump_job( struct sk_buff* skb, struct netlink_callback* cb ) nlh = nlmsg_put( skb, 0, 0, 0, 0, 0 ); ifidx = ecan->dst_if_idx; - type = CGW_TYPE_ETH_CAN_UDP; - nla_put( skb, CGW_TYPE, sizeof(type), &type ); + type = CEGW_RULE_ETH_CAN; + nla_put( skb, CEGW_TYPE, sizeof(type), &type ); nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(type) ); - nla_put( skb, CGW_CAN_IF, sizeof(ifidx), &ifidx ); /* ToDo return */ + nla_put( skb, CEGW_CAN_IFINDEX, sizeof(ifidx), &ifidx ); /* ToDo return */ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(ifidx) ); cont1: idx++; @@ -439,21 +443,21 @@ cont1: nlh = nlmsg_put( skb, 0, 0, 0, 0, 0 ); - ifidx = ceth->src_if_idx; - type = CGW_TYPE_CAN_ETH_UDP; + ifidx = ceth->src_ifindex; + type = CEGW_RULE_CAN_ETH; dst_ip = ceth->dst_addr; dst_port = ceth->dst_port; - nla_put( skb, CGW_TYPE, sizeof(type), &type ); + nla_put( skb, CEGW_TYPE, sizeof(type), &type ); nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(type) ); - nla_put( skb, CGW_CAN_IF, sizeof(ifidx), &ifidx ); /* ToDo return */ + nla_put( skb, CEGW_CAN_IFINDEX, sizeof(ifidx), &ifidx ); /* ToDo return */ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(ifidx) ); - nla_put( skb, CGW_ETH_IP, sizeof(dst_ip), &dst_ip ); /* ToDo return */ + nla_put( skb, CEGW_ETH_IP, sizeof(dst_ip), &dst_ip ); /* ToDo return */ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(dst_ip) ); - nla_put( skb, CGW_ETH_PORT, sizeof(dst_port), &dst_port ); /* ToDo return */ + nla_put( skb, CEGW_ETH_PORT, sizeof(dst_port), &dst_port ); /* ToDo return */ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN( sizeof(dst_port) ); //nla_put( skb, CGW_ETH_IP, sizeof() IP_ADDR ) @@ -470,16 +474,25 @@ cont2: static void cegw_thread_start( void ) { - gw_state = CEGW_RUNNING; + cegw_state = CEGW_RUNNING; - INIT_COMPLETION( udp_compl ); - INIT_COMPLETION( can_compl ); - INIT_COMPLETION( udp_fin ); - INIT_COMPLETION( can_fin ); + INIT_COMPLETION( cegw_compl_init ); + INIT_COMPLETION( cegw_compl_exit ); - eth_to_can = kthread_run( gw_udp_recv, NULL, "canethgw" ); - can_to_eth = kthread_run( gw_can_recv, NULL, "canethgw" ); + eth_to_can = kthread_create( cegw_udp_can, NULL, "canethgw" ); + if( !IS_ERR( eth_to_can ) ) + { + get_task_struct( eth_to_can ); + wake_up_process( eth_to_can ); + } + can_to_eth = kthread_run( cegw_can_udp, NULL, "canethgw" ); + if( !IS_ERR( can_to_eth ) ) + { + get_task_struct( can_to_eth ); + wake_up_process( can_to_eth ); + } + /* ToDo: kthread creation fail */ printk( KERN_INFO "threads are running\n" ); } @@ -490,10 +503,10 @@ static void cegw_thread_stop( void ) struct sock* sk = NULL; /* be sure sockets exist */ - wait_for_completion( &can_compl ); - wait_for_completion( &udp_compl ); - gw_state = CEGW_STOPPED; + wait_for_completion( &cegw_compl_init ); + cegw_state = CEGW_STOPPED; + /* shut down socket */ sk = can_sock->sk; how++; lock_sock( sk ); @@ -503,11 +516,14 @@ static void cegw_thread_stop( void ) kernel_sock_shutdown( udp_sock, SHUT_RDWR ); - /* wait for shutdown to be able to reuse port */ - wait_for_completion( &udp_fin ); - wait_for_completion( &can_fin ); + /* wait for return to reuse port if restart */ + kthread_stop( eth_to_can ); + kthread_stop( can_to_eth ); } +/** + * cegw_thread_restart + */ static int cegw_thread_restart( void* data ) { printk( "restart\n" ); @@ -538,7 +554,7 @@ static int __init cangw_init( void ) static void __exit cangw_exit( void ) { - if( gw_state == CEGW_RUNNING ) + if( cegw_state == CEGW_RUNNING ) { cegw_thread_stop(); /* ToDo: frees mem_cache? */ diff --git a/kernel/canethgw.h b/kernel/canethgw.h index 3da136a..85061e5 100644 --- a/kernel/canethgw.h +++ b/kernel/canethgw.h @@ -11,43 +11,32 @@ struct rtcanmsg { __u16 flags; }; +/* CEGW_CMD_INFO values */ enum { - CGW_TYPE_UNSPEC, - CGW_TYPE_CAN_CAN, /* CAN->CAN routing */ - CGW_TYPE_CAN_ETH_UDP, /* CAN->ETH udp */ - CGW_TYPE_ETH_CAN_UDP, /* ETH->CAN udp */ - CGW_TYPE_CAN_ETH_TCP, - CGW_TYPE_CONFIG, - CEGW_FLUSH, + CEGW_RULE_CAN_ETH, + CEGW_RULE_ETH_CAN, CEGW_LISTEN, - __CGW_TYPE_MAX + CEGW_FLUSH, + __CEGW_CMD_MAX }; - -#define CGW_TYPE_MAX (__CGW_TYPE_MAX - 1) +#define CEGW_CMD_MAX (__CEGW_CMD_MAX - 1) /* rtnetlink attributes */ enum { - CGW_UNSPEC, - CGW_MOD_AND, /* CAN frame modification binary AND */ - CGW_MOD_OR, /* CAN frame modification binary OR */ - CGW_MOD_XOR, /* CAN frame modification binary XOR */ - CGW_MOD_SET, /* CAN frame modification set alternate values */ - CGW_CS_XOR, /* set data[] XOR checksum into data[index] */ - CGW_CS_CRC8, /* set data[] CRC8 checksum into data[index] */ - CGW_HANDLED, /* number of handled CAN frames */ - CGW_DROPPED, /* number of dropped CAN frames */ - CGW_CAN_IF, /* ifindex of source network interface */ - CGW_LISTEN_IP, - CGW_LISTEN_PORT, - CGW_TYPE, - CGW_CMD_INFO, - CGW_ETH_IP, - CGW_ETH_PORT, - CGW_ETH_PROTO, - CGW_FILTER, /* specify struct can_filter on source CAN device */ - __CGW_MAX + CEGW_TYPE, + CEGW_CAN_IFINDEX, + CEGW_ETH_IP, + CEGW_ETH_PORT, + CEGW_CMD_INFO, + __CEGW_MAX }; +#define CEGW_MAX (__CEGW_MAX - 1) + +/* ToDo: + * CEGW_HANDLED + * CEGW_DROPPED + * CEGW_ETH_PROTO + */ -#define CGW_MAX (__CGW_MAX - 1) #endif /* CANETHGW_H */ diff --git a/utils/cegw/cegw.c b/utils/cegw/cegw.c index dceb5a0..42b6a0a 100644 --- a/utils/cegw/cegw.c +++ b/utils/cegw/cegw.c @@ -241,22 +241,22 @@ inline static int cegw_add( struct cegw_nlmsg* req, struct cegw_data* d ) return -cegw_errno; } - gwtype = (d->src_if == IF_CAN) ? CGW_TYPE_CAN_ETH_UDP : CGW_TYPE_ETH_CAN_UDP; - addattr_l( &req->nh, sizeof(*req), CGW_CAN_IF, &d->can_ifidx, sizeof(d->can_ifidx) ); + gwtype = (d->src_if == IF_CAN) ? CEGW_RULE_CAN_ETH : CEGW_RULE_ETH_CAN; + addattr_l( &req->nh, sizeof(*req), CEGW_CAN_IFINDEX, &d->can_ifidx, sizeof(d->can_ifidx) ); switch( gwtype ) { - case CGW_TYPE_CAN_ETH_UDP: - addattr_l( &req->nh, sizeof(*req), CGW_ETH_IP, &d->eth_addr, sizeof(d->eth_addr) ); - addattr_l( &req->nh, sizeof(*req), CGW_ETH_PORT, &d->eth_port, sizeof(d->eth_port) ); + case CEGW_RULE_CAN_ETH: + addattr_l( &req->nh, sizeof(*req), CEGW_ETH_IP, &d->eth_addr, sizeof(d->eth_addr) ); + addattr_l( &req->nh, sizeof(*req), CEGW_ETH_PORT, &d->eth_port, sizeof(d->eth_port) ); break; - case CGW_TYPE_ETH_CAN_UDP: + case CEGW_RULE_ETH_CAN: break; default: break; } - addattr32( &req->nh, sizeof(*req), CGW_CMD_INFO, gwtype ); + addattr32( &req->nh, sizeof(*req), CEGW_CMD_INFO, gwtype ); return 0; } @@ -264,9 +264,9 @@ inline static int cegw_add( struct cegw_nlmsg* req, struct cegw_data* d ) inline static int cegw_listen( struct cegw_nlmsg* req, struct cegw_data* d ) { req->nh.nlmsg_type = RTM_NEWROUTE; - addattr32( &req->nh, sizeof(*req), CGW_CMD_INFO, CEGW_LISTEN ); - addattr_l( &req->nh, sizeof(*req), CGW_LISTEN_IP, &d->eth_listen_addr, sizeof(d->eth_listen_addr) ); - addattr_l( &req->nh, sizeof(*req), CGW_LISTEN_PORT, &d->eth_listen_port, sizeof(d->eth_listen_port) ); + addattr32( &req->nh, sizeof(*req), CEGW_CMD_INFO, CEGW_LISTEN ); + addattr_l( &req->nh, sizeof(*req), CEGW_ETH_IP, &d->eth_listen_addr, sizeof(d->eth_listen_addr) ); + addattr_l( &req->nh, sizeof(*req), CEGW_ETH_PORT, &d->eth_listen_port, sizeof(d->eth_listen_port) ); printf( "listen at: %x, %hu\n", d->eth_listen_addr.s_addr, d->eth_listen_port ); return 0; @@ -282,7 +282,7 @@ inline static int cegw_list( struct cegw_nlmsg* req, struct cegw_data* d ) inline static int cegw_flush( struct cegw_nlmsg* req, struct cegw_data* d ) { - addattr32( &req->nh, sizeof(*req), CGW_CMD_INFO, CEGW_FLUSH ); + addattr32( &req->nh, sizeof(*req), CEGW_CMD_INFO, CEGW_FLUSH ); req->nh.nlmsg_type = RTM_DELROUTE; return 0; } @@ -291,6 +291,8 @@ void print_list_item( struct list_item* li ) { char ifname[IF_NAMESIZE]; const char src_width = 21; + char* dotaddr; + int tmp; if( if_indextoname( li->can, ifname ) == NULL ) { @@ -300,12 +302,15 @@ void print_list_item( struct list_item* li ) /* ToDo listening at */ switch( li->type ) { - case CGW_TYPE_CAN_ETH_UDP: + case CEGW_RULE_CAN_ETH: printf( "can@%-*s -> udp@%s:%hu\n", src_width, ifname, \ inet_ntoa(li->ip), li->port ); break; - case CGW_TYPE_ETH_CAN_UDP: - printf( "udp@%-*s -> can@%s\n", src_width, "*:*", ifname ); + case CEGW_RULE_ETH_CAN: + dotaddr = inet_ntoa(li->ip); + tmp = src_width - strlen(dotaddr) - 1; + printf( "udp@%s:%-*hu -> can@%s\n", inet_ntoa(li->ip), \ + tmp, li->port, ifname ); break; } } @@ -495,16 +500,16 @@ int main( int argc, char* argv[] ) { switch( rta->rta_type ) { - case CGW_TYPE: + case CEGW_TYPE: li.type = *(int*)RTA_DATA(rta); break; - case CGW_CAN_IF: + case CEGW_CAN_IFINDEX: li.can = *(int*)RTA_DATA(rta); break; - case CGW_ETH_IP: + case CEGW_ETH_IP: li.ip = *(struct in_addr*)RTA_DATA(rta); break; - case CGW_ETH_PORT: + case CEGW_ETH_PORT: li.port = *(unsigned short*)RTA_DATA(rta); break; /* case CGW_ETH_PROTO */ diff --git a/utils/cegwbench/cegwbench.c b/utils/cegwbench/cegwbench.c index 7a93708..bc74a38 100644 --- a/utils/cegwbench/cegwbench.c +++ b/utils/cegwbench/cegwbench.c @@ -19,6 +19,13 @@ * [ ] consider can timestamp */ +//#define BENCH_DEBUG +#ifdef BENCH_DEBUG +#define printdbg(...) printf( __VA_ARGS__ ) +#else +#define printdbg(...) +#endif + #define BENCH_FLAG_N 1 #define BENCH_FLAG_SRC 2 #define BENCH_FLAG_DST 4 @@ -50,6 +57,7 @@ void* thr_recv( void* arg ) int sock; struct can_frame cf; int i; + int seq; if( d.ceif[1].type == IF_CAN ) sock = can_sock_create( d.ceif[1].can.ifindex ); @@ -64,8 +72,9 @@ void* thr_recv( void* arg ) for( i=0; itv_nsec < y->tv_nsec ) { int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1; @@ -154,6 +163,18 @@ int can_sock_create( int ifindex ) return can_sock; } +void dump_arg( int argc, char* argv[] ) +{ + int i; + + putchar( '#' ); + for( i=0; i