2 * vcan.c - Virtual CAN interface
4 * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Volkswagen nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * Alternatively, provided that this notice is retained in full, this
20 * software may be distributed under the terms of the GNU General
21 * Public License ("GPL") version 2, in which case the provisions of the
22 * GPL apply INSTEAD OF those given above.
24 * The provided data structures and external interfaces from this code
25 * are not restricted to be used by modules with a GPL compatible license.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
40 * Send feedback to <socketcan-users@lists.berlios.de>
44 #include <linux/module.h>
45 #include <linux/init.h>
46 #include <linux/version.h>
47 #include <linux/netdevice.h>
48 #include <linux/if_arp.h>
49 #include <linux/if_ether.h>
50 #include <socketcan/can.h>
51 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
52 #include <net/rtnetlink.h>
55 #include <socketcan/can/version.h> /* for RCSID. Removed by mkpatch script */
58 static __initdata const char banner[] =
59 KERN_INFO "vcan: Virtual CAN interface driver\n";
61 MODULE_DESCRIPTION("virtual CAN interface");
62 MODULE_LICENSE("Dual BSD/GPL");
63 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
65 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
66 static void *kzalloc(size_t size, unsigned int __nocast flags)
68 void *ret = kmalloc(size, flags);
77 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
78 static int numdev = 4; /* default number of virtual CAN interfaces */
79 module_param(numdev, int, S_IRUGO);
80 MODULE_PARM_DESC(numdev, "Number of virtual CAN devices");
85 * Enable the echo on driver level for testing the CAN core echo modes.
86 * See Documentation/networking/can.txt for details.
89 static int echo; /* echo testing. Default: 0 (Off) */
90 module_param(echo, bool, S_IRUGO);
91 MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");
93 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
94 static struct net_device **vcan_devs; /* root pointer to netdevice structs */
97 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
98 #define PRIVSIZE sizeof(struct net_device_stats)
99 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
103 static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
105 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
106 struct net_device_stats *stats = &dev->stats;
108 struct net_device_stats *stats = netdev_priv(dev);
112 stats->rx_bytes += skb->len;
114 skb->protocol = htons(ETH_P_CAN);
115 skb->pkt_type = PACKET_BROADCAST;
117 skb->ip_summed = CHECKSUM_UNNECESSARY;
122 static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
124 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
125 struct net_device_stats *stats = &dev->stats;
127 struct net_device_stats *stats = netdev_priv(dev);
132 stats->tx_bytes += skb->len;
134 /* set flag whether this packet has to be looped back */
135 loop = skb->pkt_type == PACKET_LOOPBACK;
138 /* no echo handling available inside this driver */
142 * only count the packets here, because the
143 * CAN core already did the echo for us
146 stats->rx_bytes += skb->len;
152 /* perform standard echo handling for CAN network interfaces */
155 struct sock *srcsk = skb->sk;
157 skb = skb_share_check(skb, GFP_ATOMIC);
161 /* receive with packet counting */
165 /* no looped packets => no counting */
171 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
172 static struct net_device_stats *vcan_get_stats(struct net_device *dev)
174 struct net_device_stats *stats = netdev_priv(dev);
179 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
180 static const struct net_device_ops vcan_netdev_ops = {
181 .ndo_start_xmit = vcan_tx,
185 static void vcan_setup(struct net_device *dev)
187 dev->type = ARPHRD_CAN;
188 dev->mtu = sizeof(struct can_frame);
189 dev->hard_header_len = 0;
191 dev->tx_queue_len = 0;
192 dev->flags = IFF_NOARP;
194 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
195 #define IFF_ECHO IFF_LOOPBACK
197 /* set flags according to driver capabilities */
199 dev->flags |= IFF_ECHO;
201 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
202 dev->netdev_ops = &vcan_netdev_ops;
204 dev->hard_start_xmit = vcan_tx;
206 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
207 dev->destructor = free_netdev;
209 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
210 dev->get_stats = vcan_get_stats;
214 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
215 static struct rtnl_link_ops vcan_link_ops __read_mostly = {
220 static __init int vcan_init_module(void)
225 printk(KERN_INFO "vcan: enabled echo on driver level.\n");
227 return rtnl_link_register(&vcan_link_ops);
230 static __exit void vcan_cleanup_module(void)
232 rtnl_link_unregister(&vcan_link_ops);
235 static __init int vcan_init_module(void)
241 /* register at least one interface */
246 "vcan: registering %d virtual CAN interfaces. (echo %s)\n",
247 numdev, echo ? "enabled" : "disabled");
249 vcan_devs = kzalloc(numdev * sizeof(struct net_device *), GFP_KERNEL);
251 printk(KERN_ERR "vcan: Can't allocate vcan devices array!\n");
255 for (i = 0; i < numdev; i++) {
256 vcan_devs[i] = alloc_netdev(PRIVSIZE, "vcan%d", vcan_setup);
258 printk(KERN_ERR "vcan: error allocating net_device\n");
263 result = register_netdev(vcan_devs[i]);
266 "vcan: error %d registering interface %s\n",
267 result, vcan_devs[i]->name);
268 free_netdev(vcan_devs[i]);
277 for (i = 0; i < numdev; i++) {
279 unregister_netdev(vcan_devs[i]);
280 free_netdev(vcan_devs[i]);
289 static __exit void vcan_cleanup_module(void)
293 for (i = 0; i < numdev; i++) {
295 unregister_netdev(vcan_devs[i]);
296 free_netdev(vcan_devs[i]);
304 module_init(vcan_init_module);
305 module_exit(vcan_cleanup_module);