can_eth_gw Gateway Module  0.1
A bidirectional CAN to Ethernet Gateway (Kernel Module)
 All Data Structures Files Functions Variables Enumerations Enumerator Macros Groups Pages
ce_gw_main.c File Reference

Control Area Network - Ethernet - Gateway - Device. More...

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include "ce_gw_dev.h"
#include "ce_gw_netlink.h"
#include <uapi/linux/can.h>
#include <uapi/linux/if_arp.h>
#include <linux/can/core.h>
#include <linux/can/error.h>
#include <linux/slab.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/crc32.h>
#include "ce_gw_main.h"
#include <net/ip.h>
#include <asm-generic/errno-base.h>
#include <asm-generic/errno.h>
#include <linux/can/dev.h>
Include dependency graph for ce_gw_main.c:

Go to the source code of this file.

static struct kmem_cache
*ce_gw_job_cache 
__read_mostly
 
static int job_count = 1
 
 MODULE_DESCRIPTION ("Control Area Network - Ethernet - Gateway")
 
 MODULE_LICENSE ("GPL")
 
 MODULE_AUTHOR ("Fabian Raab <fabian.raab@tum.de>, ""Stefan Smarzly <stefan.smarzly@in.tum.de>")
 
 MODULE_ALIAS ("can_eth_gateway")
 
 HLIST_HEAD (ce_gw_job_list)
 
static void list_jobs ()
 Some helper tools for testing. More...
 
static void test_send_can_to_eth (struct net_device *ethdev)
 Keep these files only during development. More...
 
static void test_get_vcan_netdev (void)
 Keep these files only during development. More...
 
static void test_hash_list (void)
 Keep these files only during development. More...
 
struct hlist_head * ce_gw_get_job_list (void)
 getter for HLIST_HEAD(ce_gw_job_list) More...
 
struct can_frame * ce_gw_alloc_can_frame (void)
 allocates memory for the can frame More...
 
void ce_gw_free_can_frame (struct can_frame *memory)
 frees memory allocated for can_frame More...
 
struct canfd_frame * ce_gw_alloc_canfd_frame (void)
 allocates memory for a canfd frame More...
 
void ce_gw_free_canfd_frame (struct canfd_frame *memory)
 frees memory allocated for can_frame More...
 
struct can_frame * ce_gw_get_header_can (canid_t can_id, __u8 can_dlc, __u8 *payload)
 builds a can header in SFF (standart frame format) or EFF (extended frame formate) with the given information More...
 
struct canfd_frame * ce_gw_get_header_canfd (canid_t id, __u8 len, __u8 flags, __u8 res0, __u8 res1, __u8 *data)
 
void ce_gw_can2net (struct sk_buff *eth_skb, struct sk_buff *can_skb, struct net_device *eth_dev, struct net_device *can_dev, unsigned char *mac_dst, unsigned char *mac_src)
 for CE_GW_TYPE_NET: copy CAN-Frame into ethernet payload More...
 
struct sk_buff * ce_gw_can2net_alloc (struct sk_buff *can_skb, struct net_device *eth_dev, struct net_device *can_dev, unsigned char *mac_dst, unsigned char *mac_src)
 for CE_GW_TYPE_NET: copy CAN-Frame into ethernet payload and allocate More...
 
struct sk_buff * ce_gw_net2can_alloc (struct sk_buff *eth_skb, struct net_device *can_dev)
 for CE_GW_TYPE_NET: Copy the can-frame from eth_skb to a new can skb. More...
 
void ce_gw_canfd2net (struct sk_buff *eth_skb, struct sk_buff *can_skb, struct net_device *eth_dev, struct net_device *can_dev, unsigned char *mac_dst, unsigned char *mac_src)
 for CE_GW_TYPE_NET: copy CAN-Frame into ethernet payload More...
 
struct sk_buff * ce_gw_canfd2net_alloc (struct sk_buff *can_skb, struct net_device *eth_dev, struct net_device *can_dev, unsigned char *mac_dst, unsigned char *mac_src)
 for CE_GW_TYPE_NET: copy canfd-Frame into ethernet payload and allocate More...
 
struct sk_buff * ce_gw_net2canfd_alloc (struct sk_buff *eth_skb, struct net_device *can_dev, struct net_device *eth_dev)
 for CE_GW_TYPE_NET: Copy the canfd-frame from eth_skb to a new can skb. More...
 
struct sk_buff * ce_gw_can_to_eth (unsigned char *dest, unsigned char *source, __be16 type, struct sk_buff *can_buffer, struct net_device *dev)
 converts sk buffer including can frame into sk buffer including ethernet_frame More...
 
struct sk_buff * ce_gw_canfd_to_eth (unsigned char *dest, unsigned char *source, __be16 type, struct sk_buff *canfd_skb, struct net_device *dev)
 converts sk buffer including canfd frame into sk buffer including ethernet frame More...
 
struct sk_buff * ce_gw_eth_to_can (canid_t id, struct sk_buff *eth_buff, struct net_device *dev)
 converst sk_buffer including an ethernet frame to sk_buffer including a can_frame More...
 
struct sk_buff * ce_gw_eth_to_canfd (canid_t id, __u8 flags, __u8 res0, __u8 res1, struct sk_buff *eth_skb, struct net_device *dev)
 converst sk buffer including an ethernet frame to sk buffer including a canfd frame More...
 
static __u8 ce_gw_get_ip_version (void *payload)
 Reads the first 4 bytes of IP-Header and detects the version. More...
 
void ce_gw_can_rcv (struct sk_buff *can_skb, void *data)
 The gateway function for incoming CAN frames Receive CAN frame –> process –> send to ETH dev (skbuffer, struct receiver->data) More...
 
void ce_gw_eth_rcv (struct sk_buff *eth_skb, void *data)
 The gateway function for incoming ETH frames Receive skb from ETH dev –> process –> send to CAN bus. More...
 
static int ce_gw_register_can_src (struct ce_gw_job *gwj)
 
static void ce_gw_unregister_can_src (struct ce_gw_job *gwj)
 
static int ce_gw_register_eth_src (struct ce_gw_job *gwj)
 
static void ce_gw_unregister_eth_src (struct ce_gw_job *gwj)
 
int ce_gw_create_route (int src_ifindex, int dst_ifindex, enum ce_gw_type rt_type, u32 flags)
 
int ce_gw_remove_route (u32 id)
 
static int __init ce_gw_init_module (void)
 Will be automatic called at module init. More...
 
static void __exit ce_gw_cleanup (void)
 Will be automatically called on module remove. More...
 
 module_init (ce_gw_init_module)
 
 module_exit (ce_gw_cleanup)
 

Detailed Description

Control Area Network - Ethernet - Gateway - Device.

Author
Stefan Smarzly (stefa.nosp@m.n.sm.nosp@m.arzly.nosp@m.@in..nosp@m.tum.d.nosp@m.e)
Fabian Raab (fabia.nosp@m.n.ra.nosp@m.ab@tu.nosp@m.m.de)
Date
May, 2013

Definition in file ce_gw_main.c.

Function Documentation

int ce_gw_create_route ( int  src_ifindex,
int  dst_ifindex,
enum ce_gw_type  rt_type,
u32  flags 
)

Definition at line 916 of file ce_gw_main.c.

References ce_gw_job::can_rcv_filter, ce_gw_has_min_mtu(), ce_gw_is_registered_dev(), ce_gw_register_can_src(), ce_gw_register_eth_src(), ce_gw_job::dev, ce_gw_job::dropped_frames, ce_gw_job::dst, ce_gw_job::flags, ce_gw_job::handled_frames, ce_gw_job::id, job_count, ce_gw_job::list, ce_gw_job::src, and ce_gw_job::type.

Referenced by ce_gw_netlink_add().

918 {
919  int err = 0;
920 
921  struct ce_gw_job *gwj;
922  gwj = kmem_cache_alloc(ce_gw_job_cache, GFP_KERNEL);
923 
924  gwj->id = job_count++;
925  gwj->handled_frames = 0;
926  gwj->dropped_frames = 0;
927 
928  err = -ENODEV;
929  gwj->src.dev = dev_get_by_index(&init_net, src_ifindex);
930  gwj->dst.dev = dev_get_by_index(&init_net, dst_ifindex);
931  if (!gwj->src.dev || !gwj->dst.dev)
932  goto clean_exit;
933 
934  if (ce_gw_has_min_mtu(gwj->src.dev, rt_type, flags) == false ||
935  ce_gw_has_min_mtu(gwj->dst.dev, rt_type, flags) == false) {
936  err = -EOPNOTSUPP;
937  goto clean_exit;
938  }
939 
940  gwj->type = rt_type;
941  gwj->flags = flags;
942 
943  /* TEST: pre-filled values */
944  gwj->can_rcv_filter.can_id = 0x42A;
945  gwj->can_rcv_filter.can_mask = 0; /* allow all frames */
946 
947  /*
948  * Depending on routing direction: register at source device
949  */
950  if (gwj->src.dev->type == ARPHRD_CAN &&
951  ce_gw_is_registered_dev(gwj->dst.dev) == 0) {
952  /* && gwj->dst.dev->type == ARPHRD_ETHER) {*/
953  /* CAN source --> ETH destination (cegw virtual dev) */
954  err = ce_gw_register_can_src(gwj);
955  } else if (ce_gw_is_registered_dev(gwj->src.dev) == 0 &&
956  gwj->dst.dev->type == ARPHRD_CAN) {
957  /* ETH source (cegw virtual dev) --> CAN destination */
958  err = ce_gw_register_eth_src(gwj);
959  } else {
960  /* Undefined routing setup */
961  goto clean_exit;
962  }
963 
964  if (!err)
965  hlist_add_head_rcu(&gwj->list, &ce_gw_job_list);
966 
967 clean_exit:
968  if (err) {
969  printk(KERN_ERR "ce_gw: Src or dst device not found or "
970  "not compatible (CAN<->CEGW ETH), exit.\n");
971  if (gwj->src.dev)
972  dev_put(gwj->src.dev);
973  if (gwj->dst.dev)
974  dev_put(gwj->dst.dev);
975  kmem_cache_free(ce_gw_job_cache, gwj);
976  }
977 
978  return err;
979 }

Here is the call graph for this function:

Here is the caller graph for this function:

struct canfd_frame* ce_gw_get_header_canfd ( canid_t  id,
__u8  len,
__u8  flags,
__u8  res0,
__u8  res1,
__u8 *  data 
)
read

Definition at line 201 of file ce_gw_main.c.

References ce_gw_alloc_canfd_frame().

202  {
203  struct canfd_frame *canfd = ce_gw_alloc_canfd_frame();
204  if (canfd == NULL) {
205  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
206  "ce_gw_get_header_canfd\n");
207  return NULL;
208  }
209 
210  canfd->can_id = id;
211  canfd->len = len;
212  canfd->flags = flags;
213  canfd->__res0 = res0;
214  canfd->__res1 = res1;
215  *(u64 *)canfd->data = *(u64 *)data;
216 
217  return canfd;
218 }

Here is the call graph for this function:

struct hlist_head * ce_gw_get_job_list ( void  )
read

getter for HLIST_HEAD(ce_gw_job_list)

Returns
Pointer to ce_gw_job_list.

Definition at line 157 of file ce_gw_main.c.

Referenced by ce_gw_netlink_list().

157  {
158  return &ce_gw_job_list;
159 }

Here is the caller graph for this function:

static int ce_gw_register_can_src ( struct ce_gw_job gwj)
inlinestatic

Definition at line 888 of file ce_gw_main.c.

References ce_gw_job::can_rcv_filter, ce_gw_can_rcv(), ce_gw_job::dev, and ce_gw_job::src.

Referenced by ce_gw_create_route().

889 {
890  return can_rx_register(gwj->src.dev, gwj->can_rcv_filter.can_id,
891  gwj->can_rcv_filter.can_mask, ce_gw_can_rcv,
892  gwj, "ce_gw");
893 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int ce_gw_register_eth_src ( struct ce_gw_job gwj)
inlinestatic

Definition at line 903 of file ce_gw_main.c.

References ce_gw_dev_job_src_add().

Referenced by ce_gw_create_route().

904 {
906  return 0;
907 }

Here is the call graph for this function:

Here is the caller graph for this function:

int ce_gw_remove_route ( u32  id)

Definition at line 982 of file ce_gw_main.c.

References ce_gw_job::can_rcv_filter, ce_gw_unregister_can_src(), ce_gw_unregister_eth_src(), ce_gw_job::dev, ce_gw_job::dst, ce_gw_job::id, ce_gw_job::list, and ce_gw_job::src.

Referenced by ce_gw_cleanup(), ce_gw_dev_unregister(), and ce_gw_netlink_del().

983 {
984  pr_info("ce_gw: unregister CAN ETH GW routes\n");
985  struct ce_gw_job *gwj = NULL;
986  struct hlist_node *n, *nx;
987 
988  hlist_for_each_entry_safe(gwj, n, nx, &ce_gw_job_list, list) {
989  if (gwj->id != id && id)
990  continue;
991 
992  pr_debug("Removing routing src device: %s, id %x, mask %x\n",
993  gwj->src.dev->name, gwj->can_rcv_filter.can_id,
994  gwj->can_rcv_filter.can_mask);
995  hlist_del(&gwj->list);
996  /* TODO: Unregister destination device (only for cegw eth) */
997  if (gwj->src.dev->type == ARPHRD_CAN)
999  else
1001  dev_put(gwj->src.dev);
1002  dev_put(gwj->dst.dev);
1003  kmem_cache_free(ce_gw_job_cache, gwj);
1004  }
1005 
1006  return 0; /* TODO: error, when no suitable entry was found */
1007 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void ce_gw_unregister_can_src ( struct ce_gw_job gwj)
inlinestatic

Definition at line 895 of file ce_gw_main.c.

References ce_gw_job::can_rcv_filter, ce_gw_can_rcv(), ce_gw_job::dev, and ce_gw_job::src.

Referenced by ce_gw_remove_route().

896 {
897  return can_rx_unregister(gwj->src.dev, gwj->can_rcv_filter.can_id,
898  gwj->can_rcv_filter.can_mask,
899  ce_gw_can_rcv, gwj);
900 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void ce_gw_unregister_eth_src ( struct ce_gw_job gwj)
inlinestatic

Definition at line 910 of file ce_gw_main.c.

References ce_gw_dev_job_remove().

Referenced by ce_gw_remove_route().

911 {
913 }

Here is the call graph for this function:

Here is the caller graph for this function:

HLIST_HEAD ( ce_gw_job_list  )
static void list_jobs ( void  )
static

Some helper tools for testing.

Definition at line 1069 of file ce_gw_main.c.

References ce_gw_job::dev, ce_gw_job::dst, ce_gw_job::id, and ce_gw_job::src.

Referenced by ce_gw_init_module().

1070 {
1071  struct ce_gw_job *gwj = NULL;
1072  struct hlist_node *n, *nx;
1073 
1074  pr_info("Routing jobs\n"
1075  "------------\n");
1076  hlist_for_each_entry_safe(gwj, n, nx, &ce_gw_job_list, list) {
1077  pr_info("ID: %i, input dev: %s, output dev: %s\n",
1078  gwj->id, gwj->src.dev->name, gwj->dst.dev->name);
1079  }
1080  if (!gwj)
1081  pr_info("No ce_gw routing jobs found!\n");
1082 }

Here is the caller graph for this function:

MODULE_ALIAS ( "can_eth_gateway"  )
MODULE_AUTHOR ( "Fabian Raab <fabian.raab@tum.de>  ,
""Stefan Smarzly< stefan.smarzly @in.tum.de >"   
)
MODULE_DESCRIPTION ( "Control Area Network - Ethernet - Gateway"  )
_______________________________________________________
| |
| CAN Ethernet Gateway Kernel Module (ce_gw) |
|_______________________________________________________|
| |
| Ethernet Frame +----------------------+ | CAN Frame
| +-----o---------->|CAN - Ethernet Gateway|<-+-------o----+
| | | ce_gw_main.c | | |
| | +----------------------+ | v
| v | +----------+
| +--------------------+ | |CAN Device|
| |virtual Ethernet dev| | | can.c |
| |('cegw#' Interface) | +---------------+ | +----------+
| | ce_gw_dev.c | |Netlink Server | | ^
| +--------------------+ |ce_gw_netlink.c| | |
| ^ +---------------+ | v
| | ^ | +----------+
|___________|____________________________|______________| |CAN Driver|
| o Netlink Frame +----------+
v Kernelspace | ^
+----+ __________________|_____________ |
| OS | Userspace | v
+----+ v +-------+
+------------------+ |CAN NIC|
| Netlink Client | +-------+
| netlink.c |
|(can-eth-gw-utils)|
+------------------+

Diagramm witch shows the relation and Packet transmission between the components of this kernel module (ce_gw) and others of the OS.

+------------------+ /--------------------------------------\
| <<Ethernet>> | |ce_gw_job has Ethernet as dest and CAN|
|struct net_device | |as source OR has Ethernet as src and |
+------------------+ |CAN as dst. hlist_node annotations are|
+-->| .... | |Members of the structs where the arrow|
| +------------------+ |points to. The hlist structs are not |
| | |directly represented here and are so |
| |void *priv |simplyfied. |
| | \--------------------------------------/
| v
| +---------------------+ struct hlist_head ce_gw_job_list
| |struct ce_gw_job_info| |
| +---------------------+ |
| | | struct hlist_node |
| +---------------------+ list \ |
| | | struct \|
| struct | |hlist_head | +------------------+
| hlist_head| | job_src | | <<CAN>> |
| job_dst | | | |struct net_device |
| | |\ | +------------------+
| | | struct hlist_node | | .... |
| | |/ list_dev | +------------------+
| | / | ^
| |/| |0...* |
| struct | | 0...* v | struct
|net_device | +--------->+----------------------+ |net_device
| *dev +----------->| struct ce_gw_job | | *dev
| 0...* +----------------------+ |
| +-------------+ |struct rcu_head rcu | +-------------+
| | union | |u32 id | | union |
+--------+-------------+ |enum ce_gw_type type | +-------------+
| |<>-----|u32 flags |----<>| |
+-------------+ dst/ |u32 handled_frames | src/ +-------------+
src |u32 dropped_frames | dst
|union { struct can_ |
|filter can_rcv_filter}|
+----------------------+

This is an UML Klass Diagramm witch shows the main routing Management lists.

module_exit ( ce_gw_cleanup  )
module_init ( ce_gw_init_module  )
MODULE_LICENSE ( "GPL"  )
static void test_get_vcan_netdev ( void  )
static

Keep these files only during development.

Definition at line 1100 of file ce_gw_main.c.

1101 {
1102  struct net_device *dev;
1103  char vcandev[] = "vcan1";
1104 
1105  pr_debug("cegw testing: Try finding vcan0 net_device.\n");
1106  /* use dev_get_by_index for ifindex */
1107  if ((dev = __dev_get_by_name(&init_net, vcandev)) == NULL) {
1108  pr_debug("cegw testing: %s not found.\n", vcandev);
1109  return;
1110  }
1111  /* Getting infos from vcan device */
1112  pr_debug("cegw testing: %s found!\n", vcandev);
1113  pr_debug("type: %i, ifindex: %i\n", dev->type, dev->ifindex);
1114 
1115 }
static void test_hash_list ( void  )
static

Keep these files only during development.

Definition at line 1120 of file ce_gw_main.c.

References ce_gw_job::dropped_frames, and ce_gw_job::list.

1121 {
1122  struct ce_gw_job *gwj1 = kmem_cache_alloc(ce_gw_job_cache, GFP_KERNEL);
1123  gwj1->dropped_frames = 25;
1124  struct ce_gw_job *gwj2 = kmem_cache_alloc(ce_gw_job_cache, GFP_KERNEL);
1125  gwj2->dropped_frames = 250;
1126  /* dynamic alloc, dangerous when out of scope*/
1127  struct ce_gw_job gwj3 = {
1128  .dropped_frames = 555
1129  };
1130 
1131  hlist_add_head(&gwj1->list, &ce_gw_job_list);
1132  hlist_add_head(&gwj2->list, &ce_gw_job_list);
1133  hlist_add_head(&gwj3.list, &ce_gw_job_list);
1134 
1135  struct ce_gw_job *gwj = NULL;
1136  struct hlist_node *n, *nx;
1137 
1138  hlist_for_each_entry(gwj, n, &ce_gw_job_list, list) {
1139  pr_debug("cegw hashtest: List entry %i\n", gwj->dropped_frames);
1140  }
1141 
1142 }
static void test_send_can_to_eth ( struct net_device *  ethdev)
static

Keep these files only during development.

Definition at line 1087 of file ce_gw_main.c.

1088 {
1089  struct sk_buff *skb;
1090 
1091  skb = netdev_alloc_skb(ethdev, sizeof(struct ethhdr) +
1092  sizeof(struct can_frame));
1093  skb_reserve(skb, sizeof(struct ethhdr));
1094 
1095 }

Variable Documentation

struct kmem_cache* ce_gw_job_cache __read_mostly
static

Definition at line 148 of file ce_gw_main.c.

int job_count = 1
static

Definition at line 149 of file ce_gw_main.c.

Referenced by ce_gw_create_route().