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
Go to the documentation of this file.
1 
19 /*****************************************************************************
20  * (C) Copyright 2013 Fabian Raab, Stefan Smarzly
21  *
22  * This file is part of CAN-Eth-GW.
23  *
24  * CAN-Eth-GW is free software: you can redistribute it and/or modify
25  * it under the terms of the GNU General Public License as published by
26  * the Free Software Foundation, either version 3 of the License, or
27  * (at your option) any later version.
28  *
29  * CAN-Eth-GW is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32  * GNU General Public License for more details.
33  *
34  * You should have received a copy of the GNU General Public License
35  * along with CAN-Eth-GW. If not, see <http://www.gnu.org/licenses/>.
36  *****************************************************************************/
37 
118 #include <linux/module.h>
119 #include <linux/kernel.h>
120 #include <linux/list.h>
121 #include <linux/types.h> /* ce_gw_job */
122 #include <linux/skbuff.h> /* sk_buff for receive */
123 #include "ce_gw_dev.h"
124 #include "ce_gw_netlink.h"
125 #include <uapi/linux/can.h> /* since kernel 3.7 in uapi/linux/ */
126 #include <uapi/linux/if_arp.h> /* Net_device types */
127 #include <linux/can/core.h> /* for can_rx_register and can_send */
128 #include <linux/can/error.h>
129 #include <linux/slab.h> /* for using kmalloc/kfree */
130 #include <linux/if_ether.h> /* for using ethernet header */
131 #include <linux/netdevice.h>
132 #include <linux/crc32.h> /* for calculating crc checksum */
133 #include "ce_gw_main.h"
134 #include <net/ip.h>
135 #include <asm-generic/errno-base.h>
136 #include <asm-generic/errno.h>
137 
138 #include <linux/can/dev.h>
139 
140 MODULE_DESCRIPTION("Control Area Network - Ethernet - Gateway");
141 MODULE_LICENSE("GPL");
142 MODULE_AUTHOR("Fabian Raab <fabian.raab@tum.de>, "
143  "Stefan Smarzly <stefan.smarzly@in.tum.de>");
144 MODULE_ALIAS("can_eth_gateway");
145 
146 /* List for managing CAN <-> ETH gateway jobs */
147 HLIST_HEAD(ce_gw_job_list);
148 static struct kmem_cache *ce_gw_job_cache __read_mostly;
149 static int job_count = 1; /* reserve 0 for removing all routes */
150 
151 /* Prototypes for testing */
152 static void list_jobs(void);
153 static void test_send_can_to_eth(struct net_device *ethdev);
154 static void test_get_vcan_netdev(void);
155 static void test_hash_list(void);
156 
157 struct hlist_head *ce_gw_get_job_list(void) {
158  return &ce_gw_job_list;
159 }
160 
161 struct can_frame *ce_gw_alloc_can_frame(void) {
162  struct can_frame *memory;
163  memory = kmalloc(sizeof(struct can_frame),GFP_KERNEL);
164  return memory;
165 }
166 
167 void ce_gw_free_can_frame(struct can_frame *memory)
168 {
169  kfree (memory);
170 }
171 
172 
173 struct canfd_frame *ce_gw_alloc_canfd_frame(void) {
174  struct canfd_frame *memory;
175  memory = kmalloc(sizeof(struct canfd_frame), GFP_KERNEL);
176  return memory;
177 }
178 
179 
180 void ce_gw_free_canfd_frame(struct canfd_frame *memory)
181 {
182  kfree (memory);
183 }
184 
185 
186 struct can_frame *ce_gw_get_header_can(canid_t can_id, __u8 can_dlc, __u8
187  *payload) {
188  struct can_frame *new_can_frame = ce_gw_alloc_can_frame();
189  if (new_can_frame == NULL) {
190  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
191  "ce_gw_get_header_can \n");
192  return NULL;
193  }
194  new_can_frame->can_id = can_id;
195  new_can_frame->can_dlc = can_dlc;
196  *(u64 *)new_can_frame->data = *(u64 *)payload;
197  return new_can_frame;
198 }
199 
200 
201 struct canfd_frame *ce_gw_get_header_canfd(canid_t id, __u8 len, __u8 flags,
202  __u8 res0, __u8 res1, __u8 *data) {
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 }
219 
240 void ce_gw_can2net(struct sk_buff *eth_skb, struct sk_buff *can_skb,
241  struct net_device *eth_dev, struct net_device *can_dev,
242  unsigned char *mac_dst, unsigned char *mac_src)
243 {
244 # ifdef NET_SKBUFF_DATA_USES_OFFSET
245 # else /* NET_SKBUFF_DATA_USES_OFFSET */
246 # endif /* NET_SKBUFF_DATA_USES_OFFSET */
247 
248  /* set transport to data. if data == tail (what normally should be)
249  * that means there is no transport layer */
250  skb_set_transport_header(eth_skb, 0);
251 
252  /* network layer */
253  struct can_frame *eth_canf;
254  eth_canf = (struct can_frame *)skb_push(
255  eth_skb, sizeof(struct can_frame));
256  skb_set_network_header(eth_skb, 0);
257 
258  struct can_frame *can_canf;
259  can_canf = (struct can_frame *) can_skb->data;
260 
261  memcpy(eth_canf, can_canf, sizeof(struct can_frame));
262 
263  /* hardware layer */
264  struct ethhdr *eth_ethh;
265  eth_ethh = (struct ethhdr *)skb_push(eth_skb, sizeof(struct ethhdr));
266  skb_set_mac_header(eth_skb, 0);
267 
268  memcpy(eth_ethh->h_dest, mac_dst , ETH_ALEN);
269  memcpy(eth_ethh->h_source, mac_src, ETH_ALEN);
270  eth_ethh->h_proto = htons(ETH_P_CAN);
271 }
272 
295 struct sk_buff *ce_gw_can2net_alloc(struct sk_buff *can_skb,
296  struct net_device *eth_dev,
297  struct net_device *can_dev,
298  unsigned char *mac_dst,
299  unsigned char *mac_src) {
300  int err;
301  struct sk_buff *eth_skb;
302  eth_skb = netdev_alloc_skb(eth_dev, sizeof(struct ethhdr) +
303  sizeof(struct can_frame));
304  if (eth_skb == NULL) {
305  err = -ENOMEM;
306  pr_err("ce_gw: Error during ce_gw_can2net_alloc: %d\n", err);
307  return NULL;
308  }
309 
310  skb_reserve(eth_skb, sizeof(struct ethhdr) + sizeof(struct can_frame));
311  /* On CAN only broatcast possible */
312  eth_skb->pkt_type = PACKET_BROADCAST;
313  ce_gw_can2net(eth_skb, can_skb, eth_dev, can_dev, mac_dst, mac_src);
314 
315  return eth_skb;
316 
317 ce_gw_can2net_alloc_error:
318  kfree_skb(eth_skb);
319  return NULL;
320 }
321 
338 struct sk_buff *ce_gw_net2can_alloc(struct sk_buff *eth_skb,
339  struct net_device *can_dev) {
340  int err;
341 
342  /* No transport layer */
343  /* No network layer */
344 
345  /* hardware (mac) layer */
346  struct sk_buff *can_skb;
347  /* canf is the pointer where you can later copy the data to buffer */
348  struct can_frame *canf;
349  can_skb = alloc_can_skb(can_dev, &canf);
350  if (!can_skb) {
351  err = -ENOMEM;
352  pr_err("ce_gw: Allocation failed: %d\n", err);
353  goto ce_gw_net2can_alloc_error;
354  }
355 
356  /* Get Can frame at network layer start */
357  memcpy(canf, skb_network_header(eth_skb), sizeof(struct can_frame));
358 
359  return can_skb;
360 
361 ce_gw_net2can_alloc_error:
362  kfree_skb(can_skb);
363  return NULL;
364 }
365 
387 void ce_gw_canfd2net(struct sk_buff *eth_skb, struct sk_buff *can_skb,
388  struct net_device *eth_dev, struct net_device *can_dev,
389  unsigned char *mac_dst, unsigned char *mac_src)
390 {
391 # ifdef NET_SKBUFF_DATA_USES_OFFSET
392 # else /* NET_SKBUFF_DATA_USES_OFFSET */
393 # endif /* NET_SKBUFF_DATA_USES_OFFSET */
394 
395  /* set transport to data. if data == tail (what normally should be)
396  * that means there is no transport layer */
397  skb_set_transport_header(eth_skb, 0);
398 
399  /* network layer */
400  struct canfd_frame *eth_canf;
401  eth_canf = (struct canfd_frame *)skb_push(
402  eth_skb, sizeof(struct canfd_frame));
403  skb_set_network_header(eth_skb, 0);
404 
405  struct canfd_frame *can_canf;
406  can_canf = (struct canfd_frame *) can_skb->data;
407 
408  memcpy(eth_canf, can_canf, sizeof(struct canfd_frame));
409 
410  /* hardware layer */
411  struct ethhdr *eth_ethh;
412  eth_ethh = (struct ethhdr *)skb_push(eth_skb, sizeof(struct ethhdr));
413  skb_set_mac_header(eth_skb, 0);
414 
415  memcpy(eth_ethh->h_dest, mac_dst, ETH_ALEN);
416  memcpy(eth_ethh->h_source, mac_src, ETH_ALEN);
417  eth_ethh->h_proto = htons(ETH_P_CANFD);
418 }
419 
444 struct sk_buff *ce_gw_canfd2net_alloc(struct sk_buff *can_skb,
445  struct net_device *eth_dev,
446  struct net_device *can_dev,
447  unsigned char *mac_dst,
448  unsigned char *mac_src) {
449  int err;
450  struct sk_buff *eth_skb;
451  eth_skb = netdev_alloc_skb(eth_dev, sizeof(struct ethhdr) +
452  sizeof(struct canfd_frame));
453  if (eth_skb == NULL) {
454  err = -ENOMEM;
455  pr_err("ce_gw: Allocation failed: %d\n", err);
456  return NULL;
457  }
458 
459  skb_reserve(eth_skb, sizeof(struct ethhdr) +
460  sizeof(struct canfd_frame));
461  eth_skb->pkt_type = PACKET_BROADCAST;
462 
463  ce_gw_can2net(eth_skb, can_skb, eth_dev, can_dev, mac_dst, mac_src);
464  return eth_skb;
465 
466 ce_gw_can2net_alloc_error:
467  kfree_skb(eth_skb);
468  return NULL;
469 }
470 
490 struct sk_buff *ce_gw_net2canfd_alloc(struct sk_buff *eth_skb,
491  struct net_device *can_dev,
492  struct net_device *eth_dev) {
493  int err;
494 
495  /* No transport layer */
496  /* No network layer */
497 
498  /* hardware layer */
499  struct sk_buff *can_skb;
500  /* canf is the pointer where you can later copy the data to buffer */
501  struct can_frame *canf;
502  can_skb = alloc_can_skb(can_dev, &canf);
503  if (can_skb == NULL) {
504  err = -ENOMEM;
505  pr_err("ce_gw: Allocation failed: %d\n", err);
506  goto ce_gw_net2can_alloc_error;
507  }
508 
509  /* expand the sk_buff because alloc_can_skb only allocates space for
510  * an can_frame and not the larger canfd_frame. So it will be
511  * expanded by the difference
512  * TODO This is quite a bad idea but there is no alloc_can_skb function
513  * for canfd_frame. Anyway there might exist a better way */
514  skb_copy_expand(can_skb, 0, sizeof(struct canfd_frame) -
515  sizeof(struct can_frame), GFP_ATOMIC);
516  skb_put(can_skb, sizeof(struct canfd_frame) - sizeof(struct can_frame));
517  can_skb->protocol = htons(ETH_P_CANFD);
518 
519  struct canfd_frame *canfdf;
520  canfdf = (struct canfd_frame *) canf;
521 
522  /* copy canfd_frame */
523  memcpy(canfdf, skb_network_header(eth_skb), sizeof(struct canfd_frame));
524 
525  return can_skb;
526 
527 ce_gw_net2can_alloc_error:
528  kfree_skb(can_skb);
529  return NULL;
530 }
531 
532 
533 struct sk_buff *ce_gw_can_to_eth(unsigned char *dest, unsigned char *source,
534  __be16 type, struct sk_buff *can_buffer, struct
535  net_device *dev) {
536  struct can_frame *can_frame_skb = (struct can_frame *)
537  can_buffer->data;
538  struct ethhdr *ethhdr;
539  u8 canlen = can_dlc2len(can_frame_skb->can_dlc);
540  struct sk_buff *eth_skb = dev_alloc_skb(sizeof(struct ethhdr) + sizeof
541  (struct can_frame) + 64);
542  if (eth_skb == NULL) {
543  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
544  "ce_gw_can_to_eth \n");
545  return NULL;
546  }
547  eth_skb->dev = dev;
548 
549  /*updates data pointer to tail */
550  skb_reserve(eth_skb, sizeof(struct ethhdr) + sizeof(struct can_frame) +
551  64);
552  /*updates data pointer to start of network header*/
553  eth_skb->data = skb_push(eth_skb, (const int) canlen);
554 
555  /*copys data from can sk buffer into ethernet sk buffer */
556  memcpy(eth_skb->data, can_buffer->data + sizeof(struct can_frame) -
557  - canlen, canlen);
558  /*update network_header */
559  skb_set_network_header(eth_skb, 0);
560  /*updates transport header */
561  skb_set_transport_header(eth_skb, (const int) canlen);
562 
563  /*updates data pointer to mac header */
564  eth_skb->data = skb_push(eth_skb, (const int) sizeof(struct ethhdr));
565  /*updates mac_header*/
566  skb_set_mac_header(eth_skb, 0);
567  /*fills ethhdr with data */
568  ethhdr = eth_hdr(eth_skb);
569  memcpy(ethhdr->h_dest, dest, ETH_ALEN);
570  memcpy(ethhdr->h_source, source, ETH_ALEN);
571  ethhdr->h_proto = type;
572 
573  return eth_skb;
574 }
575 
576 
577 struct sk_buff *ce_gw_canfd_to_eth(unsigned char *dest, unsigned char *source,
578  __be16 type, struct sk_buff *canfd_skb,
579  struct net_device *dev) {
580  struct sk_buff *eth_skb = dev_alloc_skb(sizeof(struct ethhdr) +
581  sizeof(struct canfd_frame) + 64);
582  if (eth_skb == NULL) {
583  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
584  "ce_gw_canfd_to_eth \n");
585  return NULL;
586  }
587  struct ethhdr *ethhdr;
588  struct canfd_frame *canfd_frame_skb = (struct canfd_frame *)
589  canfd_skb->data;
590  u8 canlen = can_dlc2len(canfd_frame_skb->len);
591  unsigned int iplen = ip_hdrlen(canfd_skb);
592  eth_skb->dev = dev;
593 
594  /*updates data pointer to tail */
595  skb_reserve(eth_skb, sizeof(struct ethhdr) + sizeof(struct canfd_frame)
596  + 64);
597  /*updates data pointer to start of network header*/
598  eth_skb->data = skb_push(eth_skb, (const int) canlen);
599 
600  /*copys data from canfd sk buffer into ethernet sk buffer */
601  memcpy(eth_skb->data, canfd_skb->data + sizeof(struct canfd_frame) -
602  sizeof(__u8)*64, canlen);
603  /*update network_header */
604  skb_set_network_header(eth_skb, 0);
605  /*updates transport header */
606  if (canlen >= iplen) {
607  skb_set_transport_header(eth_skb, (const int) iplen);
608  } else {
609  skb_set_transport_header(eth_skb, (const int) sizeof(__u8)*64);
610  }
611  /*updates data pointer to start of mac header*/
612  eth_skb->data = skb_push(eth_skb, (const int) sizeof(struct ethhdr));
613  /*updates mac_header*/
614  skb_set_mac_header(eth_skb, 0);
615  /*fills eth_skb with data*/
616  ethhdr = eth_hdr(eth_skb);
617  memcpy(ethhdr->h_dest, &dest, ETH_ALEN);
618  memcpy(ethhdr->h_source, &source, ETH_ALEN);
619  ethhdr->h_proto = type;
620 
621  return eth_skb;
622 }
623 
624 
625 struct sk_buff *ce_gw_eth_to_can(canid_t id, struct sk_buff *eth_buff, struct
626  net_device *dev) {
627  struct sk_buff *can_buff;
628  struct can_frame *can = ce_gw_alloc_can_frame();
629  if (can == NULL) {
630  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
631  "ce_gw_eth_to_can \n");
632  return NULL;
633  }
634  unsigned int ethdatalen = (skb_tail_pointer(eth_buff) - (eth_buff->data
635  + sizeof(struct ethhdr)));
636  /* unsigned int iplen = ip_hdrlen(eth_buff); */
637 
638  /*fills can header */
639  can->can_id = id;
640  can->can_dlc = (__u8) eth_buff->data_len - sizeof(struct ethhdr);
641 
642  can_buff = dev_alloc_skb(sizeof(struct can_frame) + ethdatalen + 64);
643  if (can_buff == NULL) {
644  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
645  "ce_gw_eth_to_can \n");
646  return NULL;
647  }
648  can_buff->dev = dev;
649 
650  /*updates data pointer to tail */
651  skb_reserve(can_buff, sizeof(struct can_frame) + ethdatalen + 64);
652  /*updates data pointer to start of network header*/
653  can_buff->data = skb_push(can_buff, (const int) ethdatalen);
654 
655  /*copys data from ethernet sk buffer into can buffer */
656  memcpy(can_buff->data, eth_buff->data + sizeof(struct ethhdr),
657  sizeof(u64));
658  /*update network_header */
659  skb_set_network_header(can_buff, 0);
660  /*updates transport header */
661  skb_set_transport_header(can_buff, (const int) sizeof(u64));
662 
663  /*updates data pointer to start of mac header */
664  can_buff->data = skb_push(can_buff, (const int) sizeof(__u32) +
665  sizeof(__u8));
666  /*updates mac header */
667  skb_set_mac_header(can_buff, 0);
668  /*copys can header at the beginning of sk buffer */
669  memcpy(skb_mac_header(can_buff), &can->can_id, sizeof(__u32) +
670  sizeof(__u8));
671 
673 
674  return can_buff;
675 }
676 
677 
678 struct sk_buff *ce_gw_eth_to_canfd(canid_t id, __u8 flags, __u8 res0, __u8
679  res1, struct sk_buff *eth_skb, struct
680  net_device *dev) {
681  struct sk_buff *canfd_skb;
682  struct canfd_frame *canfd = ce_gw_alloc_canfd_frame();
683  if (canfd == NULL) {
684  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
685  "ce_gw_eth_to_canfd \n");
686  return NULL;
687  }
688  /* unsigned int ethdatalen = (skb_tail_pointer(eth_skb) - (eth_skb->data
689  + sizeof(struct ethhdr))); */
690  unsigned int iplen = ip_hdrlen(eth_skb);
691 
692  /*fills canfd header */
693  canfd->can_id = id;
694  canfd->flags = flags;
695  canfd->__res0 = res0;
696  canfd->__res1 = res1;
697  canfd->len = (__u8) eth_skb->data_len - sizeof(struct ethhdr);
698 
699  canfd_skb = dev_alloc_skb(sizeof(struct canfd_frame) + 64);
700  if (canfd_skb == NULL) {
701  printk (KERN_ERR "ce_gw_main.c: kmalloc failed in function"
702  "ce_gw_eth_to_canfd \n");
703  return NULL;
704  }
705  canfd_skb->dev = dev;
706 
707  /*updates data pointer to tail */
708  skb_reserve(canfd_skb, sizeof(struct canfd_frame) + 64);
709  /*updates data pointer to start of network header*/
710  canfd_skb->data = skb_push(canfd_skb, (const int) sizeof(__u8)*64);
711 
712  /*copys data from ethernet sk buffer into canfd sk buffer */
713  memcpy(canfd_skb->data, eth_skb->data + sizeof(struct ethhdr),
714  sizeof(__u8)*64);
715  /*update network_header */
716  skb_set_network_header(canfd_skb, 0);
717  /*checks if can data length >= iplen*/
718  /*updates transport header */
719  if (sizeof(__u8)*64 >= iplen) {
720  skb_set_transport_header(canfd_skb, (const int) iplen);
721  } else {
722  skb_set_transport_header(canfd_skb, sizeof(__u8)*64);
723  }
724  /*updates data pointer to start of mac header */
725  canfd_skb->data = skb_push(canfd_skb, (const int) sizeof(struct
726  canfd_frame) - sizeof(__u8)*64);
727  /*updates mac header */
728  skb_set_mac_header(canfd_skb, 0);
729  /*copys canfd header into sk buffer */
730  memcpy(skb_mac_header(canfd_skb), &canfd->can_id, sizeof(struct
731  canfd_frame) - sizeof(__u8)*64);
732  ce_gw_free_canfd_frame(canfd);
733 
734  return canfd_skb;
735 }
736 
746 static __u8 ce_gw_get_ip_version(void *payload)
747 {
748  __u8 version = *(__u8 *)payload & 0xF0;
749  if (version == 0x40) {
750  return 4;
751  } else if (version == 0x60) {
752  return 6;
753  } else {
754  return 0;
755  }
756 }
757 
758 
759 void ce_gw_can_rcv(struct sk_buff *can_skb, void *data)
760 {
761  int err = 0;
762  struct can_frame *cf;
763  /* CAN frame (id, dlc, data)*/
764  cf = (struct can_frame *)can_skb->data;
765  pr_debug("Incoming msg from can dev: can_id %x, len %i, can_msg %x\n",
766  cf->can_id, cf->can_dlc, cf->data[0]);
767 
768  struct ce_gw_job *cgj = (struct ce_gw_job *)data;
769  struct sk_buff *eth_skb = NULL;
770 
771  long long dmac = 0xffffffffffff;
772  long long smac = 0x000000000000;
773 
774  switch (cgj->type) {
775 
776  case CE_GW_TYPE_ETH:
777  pr_info("Translation ETH not implemented yet.");
778  break;
779 
780  case CE_GW_TYPE_NET:
781  eth_skb = ce_gw_can2net_alloc(can_skb,
782  cgj->dst.dev,
783  cgj->src.dev,
784  (unsigned char *) &dmac,
785  (unsigned char *) &smac);
786  break;
787 
788  case CE_GW_TYPE_TCP:
789  pr_info("Translation IP TCP not implemented yet.");
790  break;
791 
792  case CE_GW_TYPE_UDP:
793  pr_info("Translation IP UDP not implemented yet.");
794  break;
795 
796  default:
797  pr_err("ce_gw: Translation type of ce_gw_job not "
798  "implemented. BUG: Some module inserted an invalid "
799  "type. Use enum ce_gw_type instead.");
800  goto drop_frame;
801  break;
802  }
803 
804  err = netif_rx_ni(eth_skb);
805  if (err != 0) {
806  pr_err("ce_gw: send to kernel failed");
807  cgj->dropped_frames++;
808  goto exit_error;
809  }
810  cgj->handled_frames++;
811 
812  /* TODO If you use kfree_skb(can_skb) the system hang up completely
813  * without printing stack trace. But a few packets normally passed
814  * before sytem hang up. But <linux/can/dev.h> uses kfree_skb(). There
815  * is no refdata count left. The reason why hang up is completely
816  * unknown. */
817 exit_error:
818  pr_info("ce_gw: WARNING can skb will not be freed");
819  /*kfree_skb(can_skb);*/
820  return;
821 
822 drop_frame:
823  cgj->dropped_frames++;
824  dev_kfree_skb(eth_skb);
825  return;
826 }
827 
828 
829 void ce_gw_eth_rcv(struct sk_buff *eth_skb, void *data)
830 {
831  struct ce_gw_job *gwj = (struct ce_gw_job *)data;
832 
833  /* Create Can skb and convert incoming Eth sk buffer depending on
834  * type (ce_gw_type in gwj)
835  */
836  struct sk_buff *can_skb = NULL;
837 
838  switch (gwj->type) {
839 
840  case CE_GW_TYPE_ETH:
841  pr_info("Translation ETH not implemented yet.");
842  break;
843 
844  case CE_GW_TYPE_NET:
845  can_skb = ce_gw_net2can_alloc(eth_skb, gwj->dst.dev);
846  break;
847 
848  case CE_GW_TYPE_TCP:
849  pr_info("Translation IP TCP not implemented yet.");
850  break;
851 
852  case CE_GW_TYPE_UDP:
853  pr_info("Translation IP UDP not implemented yet.");
854  break;
855 
856  default:
857  printk(KERN_ERR "ce_gw: Translation type of ce_gw_job not "
858  "implemented. BUG: Some module inserted an invalid "
859  "type. Use enum ce_gw_type instead.");
860  goto drop_frame;
861  break;
862  }
863 
864  /* Memory allocation or translation ETH -> CAN failed */
865  if (!can_skb)
866  goto drop_frame;
867 
868  struct can_frame *cf;
869  cf = (struct can_frame *)can_skb->data;
870  pr_debug("Incoming msg from eth dev (gwj %i): "
871  "can_id %x, len %i, can_msg(1) %x\n",
872  gwj->id, cf->can_id, cf->can_dlc, cf->data[0]);
873 
874  /* send to CAN netdevice (with echo flag for loopback devices) */
875  if (can_send(can_skb, 0x01))
876  goto drop_frame;
877  else
878  gwj->handled_frames++;
879 
880  return; /* Receive + process + send to CAN successful */
881 
882 drop_frame:
883  gwj->dropped_frames++;
884  dev_kfree_skb(can_skb);
885  return;
886 }
887 
888 static inline int ce_gw_register_can_src(struct ce_gw_job *gwj)
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 }
894 
895 static inline void ce_gw_unregister_can_src(struct ce_gw_job *gwj)
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 }
901 
902 /* TODO: register at eth device for receiving data frames */
903 static inline int ce_gw_register_eth_src(struct ce_gw_job *gwj)
904 {
906  return 0;
907 }
908 
909 /* TODO: unregister at eth device */
910 static inline void ce_gw_unregister_eth_src(struct ce_gw_job *gwj)
911 {
913 }
914 
915 
916 int ce_gw_create_route(int src_ifindex, int dst_ifindex,
917  enum ce_gw_type rt_type, u32 flags)
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 }
980 
981 
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 }
1008 
1016 static int __init ce_gw_init_module(void)
1017 {
1018  int err = 0;
1019  printk(KERN_INFO "ce_gw: Module started.\n");
1020 
1021  ce_gw_job_cache = kmem_cache_create("can_eth_gw",
1022  sizeof(struct ce_gw_job), 0, 0, NULL);
1023  if (!ce_gw_job_cache)
1024  return ENOMEM;
1025 
1029  list_jobs();
1034  err = ce_gw_netlink_init();
1035  err += ce_gw_dev_init_module();
1036 
1037  if (err != 0)
1038  return 1;
1039  else
1040  return 0;
1041 }
1042 
1048 static void __exit ce_gw_cleanup(void)
1049 {
1050  printk(KERN_INFO "ce_gw: Cleaning up the module\n");
1051 
1052  pr_debug("ce_gw: Unregister netlink server.\n");
1054 
1055  /* Unregister all routes */
1056  pr_info("ce_gw: unregister all CAN ETH GW routes\n");
1057  ce_gw_remove_route(0);
1058 
1059  pr_debug("ce_gw: Unregister virtual net devices.\n");
1061 
1062  /* Mem cleanup */
1063  kmem_cache_destroy(ce_gw_job_cache);
1064 }
1065 
1069 static void list_jobs()
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 }
1083 
1087 static void test_send_can_to_eth(struct net_device *ethdev)
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 }
1096 
1100 static void test_get_vcan_netdev(void)
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 }
1116 
1120 static void test_hash_list(void)
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 }
1143 
1146