Commit ccb29637991fa6b8321a80c2320a71e379aea962
Committed by
David S. Miller
1 parent
ffd980f976
Exists in
master
and in
39 other branches
[CAN]: Add virtual CAN netdevice driver
This patch adds the virtual CAN bus (vcan) network driver. The vcan device is just a loopback device for CAN frames, no real CAN hardware is involved. Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de> Signed-off-by: Urs Thuermann <urs.thuermann@volkswagen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 5 changed files with 203 additions and 0 deletions Side-by-side Diff
drivers/net/Makefile
drivers/net/can/Kconfig
1 | +menu "CAN Device Drivers" | |
2 | + depends on CAN | |
3 | + | |
4 | +config CAN_VCAN | |
5 | + tristate "Virtual Local CAN Interface (vcan)" | |
6 | + depends on CAN | |
7 | + default N | |
8 | + ---help--- | |
9 | + Similar to the network loopback devices, vcan offers a | |
10 | + virtual local CAN interface. | |
11 | + | |
12 | + This driver can also be built as a module. If so, the module | |
13 | + will be called vcan. | |
14 | + | |
15 | +config CAN_DEBUG_DEVICES | |
16 | + bool "CAN devices debugging messages" | |
17 | + depends on CAN | |
18 | + default N | |
19 | + ---help--- | |
20 | + Say Y here if you want the CAN device drivers to produce a bunch of | |
21 | + debug messages to the system log. Select this if you are having | |
22 | + a problem with CAN support and want to see more of what is going | |
23 | + on. | |
24 | + | |
25 | +endmenu |
drivers/net/can/Makefile
drivers/net/can/vcan.c
1 | +/* | |
2 | + * vcan.c - Virtual CAN interface | |
3 | + * | |
4 | + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research | |
5 | + * All rights reserved. | |
6 | + * | |
7 | + * Redistribution and use in source and binary forms, with or without | |
8 | + * modification, are permitted provided that the following conditions | |
9 | + * are met: | |
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. | |
18 | + * | |
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. | |
23 | + * | |
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. | |
26 | + * | |
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 | |
38 | + * DAMAGE. | |
39 | + * | |
40 | + * Send feedback to <socketcan-users@lists.berlios.de> | |
41 | + * | |
42 | + */ | |
43 | + | |
44 | +#include <linux/module.h> | |
45 | +#include <linux/init.h> | |
46 | +#include <linux/netdevice.h> | |
47 | +#include <linux/if_arp.h> | |
48 | +#include <linux/if_ether.h> | |
49 | +#include <linux/can.h> | |
50 | +#include <net/rtnetlink.h> | |
51 | + | |
52 | +static __initdata const char banner[] = | |
53 | + KERN_INFO "vcan: Virtual CAN interface driver\n"; | |
54 | + | |
55 | +MODULE_DESCRIPTION("virtual CAN interface"); | |
56 | +MODULE_LICENSE("Dual BSD/GPL"); | |
57 | +MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); | |
58 | + | |
59 | + | |
60 | +/* | |
61 | + * CAN test feature: | |
62 | + * Enable the echo on driver level for testing the CAN core echo modes. | |
63 | + * See Documentation/networking/can.txt for details. | |
64 | + */ | |
65 | + | |
66 | +static int echo; /* echo testing. Default: 0 (Off) */ | |
67 | +module_param(echo, bool, S_IRUGO); | |
68 | +MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)"); | |
69 | + | |
70 | + | |
71 | +static void vcan_rx(struct sk_buff *skb, struct net_device *dev) | |
72 | +{ | |
73 | + struct net_device_stats *stats = &dev->stats; | |
74 | + | |
75 | + stats->rx_packets++; | |
76 | + stats->rx_bytes += skb->len; | |
77 | + | |
78 | + skb->protocol = htons(ETH_P_CAN); | |
79 | + skb->pkt_type = PACKET_BROADCAST; | |
80 | + skb->dev = dev; | |
81 | + skb->ip_summed = CHECKSUM_UNNECESSARY; | |
82 | + | |
83 | + netif_rx(skb); | |
84 | +} | |
85 | + | |
86 | +static int vcan_tx(struct sk_buff *skb, struct net_device *dev) | |
87 | +{ | |
88 | + struct net_device_stats *stats = &dev->stats; | |
89 | + int loop; | |
90 | + | |
91 | + stats->tx_packets++; | |
92 | + stats->tx_bytes += skb->len; | |
93 | + | |
94 | + /* set flag whether this packet has to be looped back */ | |
95 | + loop = skb->pkt_type == PACKET_LOOPBACK; | |
96 | + | |
97 | + if (!echo) { | |
98 | + /* no echo handling available inside this driver */ | |
99 | + | |
100 | + if (loop) { | |
101 | + /* | |
102 | + * only count the packets here, because the | |
103 | + * CAN core already did the echo for us | |
104 | + */ | |
105 | + stats->rx_packets++; | |
106 | + stats->rx_bytes += skb->len; | |
107 | + } | |
108 | + kfree_skb(skb); | |
109 | + return NETDEV_TX_OK; | |
110 | + } | |
111 | + | |
112 | + /* perform standard echo handling for CAN network interfaces */ | |
113 | + | |
114 | + if (loop) { | |
115 | + struct sock *srcsk = skb->sk; | |
116 | + | |
117 | + skb = skb_share_check(skb, GFP_ATOMIC); | |
118 | + if (!skb) | |
119 | + return NETDEV_TX_OK; | |
120 | + | |
121 | + /* receive with packet counting */ | |
122 | + skb->sk = srcsk; | |
123 | + vcan_rx(skb, dev); | |
124 | + } else { | |
125 | + /* no looped packets => no counting */ | |
126 | + kfree_skb(skb); | |
127 | + } | |
128 | + return NETDEV_TX_OK; | |
129 | +} | |
130 | + | |
131 | +static void vcan_setup(struct net_device *dev) | |
132 | +{ | |
133 | + dev->type = ARPHRD_CAN; | |
134 | + dev->mtu = sizeof(struct can_frame); | |
135 | + dev->hard_header_len = 0; | |
136 | + dev->addr_len = 0; | |
137 | + dev->tx_queue_len = 0; | |
138 | + dev->flags = IFF_NOARP; | |
139 | + | |
140 | + /* set flags according to driver capabilities */ | |
141 | + if (echo) | |
142 | + dev->flags |= IFF_ECHO; | |
143 | + | |
144 | + dev->hard_start_xmit = vcan_tx; | |
145 | + dev->destructor = free_netdev; | |
146 | +} | |
147 | + | |
148 | +static struct rtnl_link_ops vcan_link_ops __read_mostly = { | |
149 | + .kind = "vcan", | |
150 | + .setup = vcan_setup, | |
151 | +}; | |
152 | + | |
153 | +static __init int vcan_init_module(void) | |
154 | +{ | |
155 | + printk(banner); | |
156 | + | |
157 | + if (echo) | |
158 | + printk(KERN_INFO "vcan: enabled echo on driver level.\n"); | |
159 | + | |
160 | + return rtnl_link_register(&vcan_link_ops); | |
161 | +} | |
162 | + | |
163 | +static __exit void vcan_cleanup_module(void) | |
164 | +{ | |
165 | + rtnl_link_unregister(&vcan_link_ops); | |
166 | +} | |
167 | + | |
168 | +module_init(vcan_init_module); | |
169 | +module_exit(vcan_cleanup_module); |
net/can/Kconfig