0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0042
0043 #include <linux/ethtool.h>
0044 #include <linux/module.h>
0045 #include <linux/init.h>
0046 #include <linux/netdevice.h>
0047 #include <linux/if_arp.h>
0048 #include <linux/if_ether.h>
0049 #include <linux/can.h>
0050 #include <linux/can/can-ml.h>
0051 #include <linux/can/dev.h>
0052 #include <linux/can/skb.h>
0053 #include <linux/slab.h>
0054 #include <net/rtnetlink.h>
0055
0056 #define DRV_NAME "vcan"
0057
0058 MODULE_DESCRIPTION("virtual CAN interface");
0059 MODULE_LICENSE("Dual BSD/GPL");
0060 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
0061 MODULE_ALIAS_RTNL_LINK(DRV_NAME);
0062
0063
0064
0065
0066
0067
0068 static bool echo;
0069 module_param(echo, bool, 0444);
0070 MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");
0071
0072 static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
0073 {
0074 struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
0075 struct net_device_stats *stats = &dev->stats;
0076
0077 stats->rx_packets++;
0078 stats->rx_bytes += cfd->len;
0079
0080 skb->pkt_type = PACKET_BROADCAST;
0081 skb->dev = dev;
0082 skb->ip_summed = CHECKSUM_UNNECESSARY;
0083
0084 netif_rx(skb);
0085 }
0086
0087 static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
0088 {
0089 struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
0090 struct net_device_stats *stats = &dev->stats;
0091 int loop, len;
0092
0093 if (can_dropped_invalid_skb(dev, skb))
0094 return NETDEV_TX_OK;
0095
0096 len = cfd->can_id & CAN_RTR_FLAG ? 0 : cfd->len;
0097 stats->tx_packets++;
0098 stats->tx_bytes += len;
0099
0100
0101 loop = skb->pkt_type == PACKET_LOOPBACK;
0102
0103 skb_tx_timestamp(skb);
0104
0105 if (!echo) {
0106
0107 if (loop) {
0108
0109
0110
0111 stats->rx_packets++;
0112 stats->rx_bytes += len;
0113 }
0114 consume_skb(skb);
0115 return NETDEV_TX_OK;
0116 }
0117
0118
0119
0120 if (loop) {
0121 skb = can_create_echo_skb(skb);
0122 if (!skb)
0123 return NETDEV_TX_OK;
0124
0125
0126 vcan_rx(skb, dev);
0127 } else {
0128
0129 consume_skb(skb);
0130 }
0131 return NETDEV_TX_OK;
0132 }
0133
0134 static int vcan_change_mtu(struct net_device *dev, int new_mtu)
0135 {
0136
0137 if (dev->flags & IFF_UP)
0138 return -EBUSY;
0139
0140 if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU)
0141 return -EINVAL;
0142
0143 dev->mtu = new_mtu;
0144 return 0;
0145 }
0146
0147 static const struct net_device_ops vcan_netdev_ops = {
0148 .ndo_start_xmit = vcan_tx,
0149 .ndo_change_mtu = vcan_change_mtu,
0150 };
0151
0152 static const struct ethtool_ops vcan_ethtool_ops = {
0153 .get_ts_info = ethtool_op_get_ts_info,
0154 };
0155
0156 static void vcan_setup(struct net_device *dev)
0157 {
0158 dev->type = ARPHRD_CAN;
0159 dev->mtu = CANFD_MTU;
0160 dev->hard_header_len = 0;
0161 dev->addr_len = 0;
0162 dev->tx_queue_len = 0;
0163 dev->flags = IFF_NOARP;
0164 can_set_ml_priv(dev, netdev_priv(dev));
0165
0166
0167 if (echo)
0168 dev->flags |= IFF_ECHO;
0169
0170 dev->netdev_ops = &vcan_netdev_ops;
0171 dev->ethtool_ops = &vcan_ethtool_ops;
0172 dev->needs_free_netdev = true;
0173 }
0174
0175 static struct rtnl_link_ops vcan_link_ops __read_mostly = {
0176 .kind = DRV_NAME,
0177 .priv_size = sizeof(struct can_ml_priv),
0178 .setup = vcan_setup,
0179 };
0180
0181 static __init int vcan_init_module(void)
0182 {
0183 pr_info("Virtual CAN interface driver\n");
0184
0185 if (echo)
0186 pr_info("enabled echo on driver level.\n");
0187
0188 return rtnl_link_register(&vcan_link_ops);
0189 }
0190
0191 static __exit void vcan_cleanup_module(void)
0192 {
0193 rtnl_link_unregister(&vcan_link_ops);
0194 }
0195
0196 module_init(vcan_init_module);
0197 module_exit(vcan_cleanup_module);