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