1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * vxcan.c - Virtual CAN Tunnel for cross namespace communication |
4 | * |
5 | * This code is derived from drivers/net/can/vcan.c for the virtual CAN |
6 | * specific parts and from drivers/net/veth.c to implement the netlink API |
7 | * for network interface pairs in a common and established way. |
8 | * |
9 | * Copyright (c) 2017 Oliver Hartkopp <socketcan@hartkopp.net> |
10 | */ |
11 | |
12 | #include <linux/ethtool.h> |
13 | #include <linux/module.h> |
14 | #include <linux/init.h> |
15 | #include <linux/netdevice.h> |
16 | #include <linux/if_arp.h> |
17 | #include <linux/if_ether.h> |
18 | #include <linux/can.h> |
19 | #include <linux/can/dev.h> |
20 | #include <linux/can/skb.h> |
21 | #include <linux/can/vxcan.h> |
22 | #include <linux/can/can-ml.h> |
23 | #include <linux/slab.h> |
24 | #include <net/rtnetlink.h> |
25 | |
26 | #define DRV_NAME "vxcan" |
27 | |
28 | MODULE_DESCRIPTION("Virtual CAN Tunnel" ); |
29 | MODULE_LICENSE("GPL" ); |
30 | MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>" ); |
31 | MODULE_ALIAS_RTNL_LINK(DRV_NAME); |
32 | |
33 | struct vxcan_priv { |
34 | struct net_device __rcu *peer; |
35 | }; |
36 | |
37 | static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev) |
38 | { |
39 | struct vxcan_priv *priv = netdev_priv(dev); |
40 | struct net_device *peer; |
41 | struct net_device_stats *peerstats, *srcstats = &dev->stats; |
42 | struct sk_buff *skb; |
43 | unsigned int len; |
44 | |
45 | if (can_dropped_invalid_skb(dev, skb: oskb)) |
46 | return NETDEV_TX_OK; |
47 | |
48 | rcu_read_lock(); |
49 | peer = rcu_dereference(priv->peer); |
50 | if (unlikely(!peer)) { |
51 | kfree_skb(skb: oskb); |
52 | dev->stats.tx_dropped++; |
53 | goto out_unlock; |
54 | } |
55 | |
56 | skb_tx_timestamp(skb: oskb); |
57 | |
58 | skb = skb_clone(skb: oskb, GFP_ATOMIC); |
59 | if (skb) { |
60 | consume_skb(skb: oskb); |
61 | } else { |
62 | kfree_skb(skb: oskb); |
63 | goto out_unlock; |
64 | } |
65 | |
66 | /* reset CAN GW hop counter */ |
67 | skb->csum_start = 0; |
68 | skb->pkt_type = PACKET_BROADCAST; |
69 | skb->dev = peer; |
70 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
71 | |
72 | len = can_skb_get_data_len(skb); |
73 | if (netif_rx(skb) == NET_RX_SUCCESS) { |
74 | srcstats->tx_packets++; |
75 | srcstats->tx_bytes += len; |
76 | peerstats = &peer->stats; |
77 | peerstats->rx_packets++; |
78 | peerstats->rx_bytes += len; |
79 | } |
80 | |
81 | out_unlock: |
82 | rcu_read_unlock(); |
83 | return NETDEV_TX_OK; |
84 | } |
85 | |
86 | |
87 | static int vxcan_open(struct net_device *dev) |
88 | { |
89 | struct vxcan_priv *priv = netdev_priv(dev); |
90 | struct net_device *peer = rtnl_dereference(priv->peer); |
91 | |
92 | if (!peer) |
93 | return -ENOTCONN; |
94 | |
95 | if (peer->flags & IFF_UP) { |
96 | netif_carrier_on(dev); |
97 | netif_carrier_on(dev: peer); |
98 | } |
99 | return 0; |
100 | } |
101 | |
102 | static int vxcan_close(struct net_device *dev) |
103 | { |
104 | struct vxcan_priv *priv = netdev_priv(dev); |
105 | struct net_device *peer = rtnl_dereference(priv->peer); |
106 | |
107 | netif_carrier_off(dev); |
108 | if (peer) |
109 | netif_carrier_off(dev: peer); |
110 | |
111 | return 0; |
112 | } |
113 | |
114 | static int vxcan_get_iflink(const struct net_device *dev) |
115 | { |
116 | struct vxcan_priv *priv = netdev_priv(dev); |
117 | struct net_device *peer; |
118 | int iflink; |
119 | |
120 | rcu_read_lock(); |
121 | peer = rcu_dereference(priv->peer); |
122 | iflink = peer ? peer->ifindex : 0; |
123 | rcu_read_unlock(); |
124 | |
125 | return iflink; |
126 | } |
127 | |
128 | static int vxcan_change_mtu(struct net_device *dev, int new_mtu) |
129 | { |
130 | /* Do not allow changing the MTU while running */ |
131 | if (dev->flags & IFF_UP) |
132 | return -EBUSY; |
133 | |
134 | if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU && |
135 | !can_is_canxl_dev_mtu(mtu: new_mtu)) |
136 | return -EINVAL; |
137 | |
138 | dev->mtu = new_mtu; |
139 | return 0; |
140 | } |
141 | |
142 | static const struct net_device_ops vxcan_netdev_ops = { |
143 | .ndo_open = vxcan_open, |
144 | .ndo_stop = vxcan_close, |
145 | .ndo_start_xmit = vxcan_xmit, |
146 | .ndo_get_iflink = vxcan_get_iflink, |
147 | .ndo_change_mtu = vxcan_change_mtu, |
148 | }; |
149 | |
150 | static const struct ethtool_ops vxcan_ethtool_ops = { |
151 | .get_ts_info = ethtool_op_get_ts_info, |
152 | }; |
153 | |
154 | static void vxcan_setup(struct net_device *dev) |
155 | { |
156 | struct can_ml_priv *can_ml; |
157 | |
158 | dev->type = ARPHRD_CAN; |
159 | dev->mtu = CANFD_MTU; |
160 | dev->hard_header_len = 0; |
161 | dev->addr_len = 0; |
162 | dev->tx_queue_len = 0; |
163 | dev->flags = IFF_NOARP; |
164 | dev->netdev_ops = &vxcan_netdev_ops; |
165 | dev->ethtool_ops = &vxcan_ethtool_ops; |
166 | dev->needs_free_netdev = true; |
167 | |
168 | can_ml = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN); |
169 | can_set_ml_priv(dev, ml_priv: can_ml); |
170 | } |
171 | |
172 | /* forward declaration for rtnl_create_link() */ |
173 | static struct rtnl_link_ops vxcan_link_ops; |
174 | |
175 | static int vxcan_newlink(struct net *net, struct net_device *dev, |
176 | struct nlattr *tb[], struct nlattr *data[], |
177 | struct netlink_ext_ack *extack) |
178 | { |
179 | struct vxcan_priv *priv; |
180 | struct net_device *peer; |
181 | struct net *peer_net; |
182 | |
183 | struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb; |
184 | char ifname[IFNAMSIZ]; |
185 | unsigned char name_assign_type; |
186 | struct ifinfomsg *ifmp = NULL; |
187 | int err; |
188 | |
189 | /* register peer device */ |
190 | if (data && data[VXCAN_INFO_PEER]) { |
191 | struct nlattr *nla_peer; |
192 | |
193 | nla_peer = data[VXCAN_INFO_PEER]; |
194 | ifmp = nla_data(nla: nla_peer); |
195 | err = rtnl_nla_parse_ifinfomsg(tb: peer_tb, nla_peer, exterr: extack); |
196 | if (err < 0) |
197 | return err; |
198 | |
199 | tbp = peer_tb; |
200 | } |
201 | |
202 | if (ifmp && tbp[IFLA_IFNAME]) { |
203 | nla_strscpy(dst: ifname, nla: tbp[IFLA_IFNAME], IFNAMSIZ); |
204 | name_assign_type = NET_NAME_USER; |
205 | } else { |
206 | snprintf(buf: ifname, IFNAMSIZ, DRV_NAME "%%d" ); |
207 | name_assign_type = NET_NAME_ENUM; |
208 | } |
209 | |
210 | peer_net = rtnl_link_get_net(src_net: net, tb: tbp); |
211 | if (IS_ERR(ptr: peer_net)) |
212 | return PTR_ERR(ptr: peer_net); |
213 | |
214 | peer = rtnl_create_link(net: peer_net, ifname, name_assign_type, |
215 | ops: &vxcan_link_ops, tb: tbp, extack); |
216 | if (IS_ERR(ptr: peer)) { |
217 | put_net(net: peer_net); |
218 | return PTR_ERR(ptr: peer); |
219 | } |
220 | |
221 | if (ifmp && dev->ifindex) |
222 | peer->ifindex = ifmp->ifi_index; |
223 | |
224 | err = register_netdevice(dev: peer); |
225 | put_net(net: peer_net); |
226 | peer_net = NULL; |
227 | if (err < 0) { |
228 | free_netdev(dev: peer); |
229 | return err; |
230 | } |
231 | |
232 | netif_carrier_off(dev: peer); |
233 | |
234 | err = rtnl_configure_link(dev: peer, ifm: ifmp, portid: 0, NULL); |
235 | if (err < 0) |
236 | goto unregister_network_device; |
237 | |
238 | /* register first device */ |
239 | if (tb[IFLA_IFNAME]) |
240 | nla_strscpy(dst: dev->name, nla: tb[IFLA_IFNAME], IFNAMSIZ); |
241 | else |
242 | snprintf(buf: dev->name, IFNAMSIZ, DRV_NAME "%%d" ); |
243 | |
244 | err = register_netdevice(dev); |
245 | if (err < 0) |
246 | goto unregister_network_device; |
247 | |
248 | netif_carrier_off(dev); |
249 | |
250 | /* cross link the device pair */ |
251 | priv = netdev_priv(dev); |
252 | rcu_assign_pointer(priv->peer, peer); |
253 | |
254 | priv = netdev_priv(dev: peer); |
255 | rcu_assign_pointer(priv->peer, dev); |
256 | |
257 | return 0; |
258 | |
259 | unregister_network_device: |
260 | unregister_netdevice(dev: peer); |
261 | return err; |
262 | } |
263 | |
264 | static void vxcan_dellink(struct net_device *dev, struct list_head *head) |
265 | { |
266 | struct vxcan_priv *priv; |
267 | struct net_device *peer; |
268 | |
269 | priv = netdev_priv(dev); |
270 | peer = rtnl_dereference(priv->peer); |
271 | |
272 | /* Note : dellink() is called from default_device_exit_batch(), |
273 | * before a rcu_synchronize() point. The devices are guaranteed |
274 | * not being freed before one RCU grace period. |
275 | */ |
276 | RCU_INIT_POINTER(priv->peer, NULL); |
277 | unregister_netdevice_queue(dev, head); |
278 | |
279 | if (peer) { |
280 | priv = netdev_priv(dev: peer); |
281 | RCU_INIT_POINTER(priv->peer, NULL); |
282 | unregister_netdevice_queue(dev: peer, head); |
283 | } |
284 | } |
285 | |
286 | static const struct nla_policy vxcan_policy[VXCAN_INFO_MAX + 1] = { |
287 | [VXCAN_INFO_PEER] = { .len = sizeof(struct ifinfomsg) }, |
288 | }; |
289 | |
290 | static struct net *vxcan_get_link_net(const struct net_device *dev) |
291 | { |
292 | struct vxcan_priv *priv = netdev_priv(dev); |
293 | struct net_device *peer = rtnl_dereference(priv->peer); |
294 | |
295 | return peer ? dev_net(dev: peer) : dev_net(dev); |
296 | } |
297 | |
298 | static struct rtnl_link_ops vxcan_link_ops = { |
299 | .kind = DRV_NAME, |
300 | .priv_size = ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN) + sizeof(struct can_ml_priv), |
301 | .setup = vxcan_setup, |
302 | .newlink = vxcan_newlink, |
303 | .dellink = vxcan_dellink, |
304 | .policy = vxcan_policy, |
305 | .maxtype = VXCAN_INFO_MAX, |
306 | .get_link_net = vxcan_get_link_net, |
307 | }; |
308 | |
309 | static __init int vxcan_init(void) |
310 | { |
311 | pr_info("vxcan: Virtual CAN Tunnel driver\n" ); |
312 | |
313 | return rtnl_link_register(ops: &vxcan_link_ops); |
314 | } |
315 | |
316 | static __exit void vxcan_exit(void) |
317 | { |
318 | rtnl_link_unregister(ops: &vxcan_link_ops); |
319 | } |
320 | |
321 | module_init(vxcan_init); |
322 | module_exit(vxcan_exit); |
323 | |