Skip to contentSkip to conversation

can: add Virtual CAN Tunnel driver (vxcan)

RFC PATCH In review Oliver Hartkopp 2 participants 5 messages Apr 24, 2017 – Apr 25, 2017 CAN network drivers

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 can: add Virtual CAN Tunnel driver (vxcan)

---
 drivers/net/can/Kconfig        |  18 +++
 drivers/net/can/Makefile       |   1 +
 drivers/net/can/vxcan.c        | 313 +++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/can/vxcan.h |  12 ++
 4 files changed, 344 insertions(+)
 create mode 100644 drivers/net/can/vxcan.c
 create mode 100644 include/uapi/linux/can/vxcan.h
drivers/net/can/Kconfig +18 -0
index 22570ea3a8d2..61c2fcf7f880 100644
@@ -9,6 +9,24 @@ config CAN_VCAN
 	  This driver can also be built as a module.  If so, the module
 	  will be called vcan.
 
+config CAN_VXCAN
+	tristate "Virtual CAN Tunnel (vxcan)"
+	---help---
+	  Similar to the virtual ethernet driver veth, vxcan implements a
+	  local CAN traffic tunnel between two virtual CAN network devices.
+	  When creating a vxcan, two vxcan devices are created as pair.
+	  When one end receives the packet it appears on its pair and vice
+	  versa. The vxcan can be used for cross namespace communication.
+
+	  In opposite to vcan loopback devices the vxcan only forwards CAN
+	  frames to its pair and does *not* provide a local echo of sent
+	  CAN frames. To disable a potential echo in af_can.c the vxcan driver
+	  announces IFF_ECHO in the interface flags. To have a clean start
+	  in each namespace the CAN GW hop counter is set to zero.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called vxcan.
+
 config CAN_SLCAN
 	tristate "Serial / USB serial CAN Adaptors (slcan)"
 	depends on TTY
drivers/net/can/Makefile +1 -0
index 0da4f2f5c7e3..18cc6543b711 100644
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_CAN_VCAN)		+= vcan.o
+obj-$(CONFIG_CAN_VXCAN)		+= vxcan.o
 obj-$(CONFIG_CAN_SLCAN)		+= slcan.o
 
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
drivers/net/can/vxcan.c new file +313 -0

313 lines not on this page · raw message

include/uapi/linux/can/vxcan.h new file +12 -0
new file mode 100644
index 000000000000..ffb0b7156f7e
@@ -0,0 +1,12 @@
+#ifndef _UAPI_CAN_VXCAN_H
+#define _UAPI_CAN_VXCAN_H
+
+enum {
+	VXCAN_INFO_UNSPEC,
+	VXCAN_INFO_PEER,
+
+	__VXCAN_INFO_MAX
+#define VXCAN_INFO_MAX	(__VXCAN_INFO_MAX - 1)
+};
+
+#endif
Signature · 1 line
2.11.0
#1 lore raw

RFC PATCH 1/1 ip: link add vxcan support

---
 include/linux/can/vxcan.h | 12 +++++++
 ip/Makefile               |  2 +-
 ip/iplink_vxcan.c         | 87 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/can/vxcan.h
 create mode 100644 ip/iplink_vxcan.c
include/linux/can/vxcan.h new file +12 -0
new file mode 100644
index 00000000..ffb0b715
@@ -0,0 +1,12 @@
+#ifndef _UAPI_CAN_VXCAN_H
+#define _UAPI_CAN_VXCAN_H
+
+enum {
+	VXCAN_INFO_UNSPEC,
+	VXCAN_INFO_PEER,
+
+	__VXCAN_INFO_MAX
+#define VXCAN_INFO_MAX	(__VXCAN_INFO_MAX - 1)
+};
+
+#endif
ip/Makefile +1 -1
index 035d42c7..d5c6473a 100644
@@ -2,7 +2,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
     ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o iplink_dummy.o \
-    iplink_ifb.o iplink_nlmon.o iplink_team.o iplink_vcan.o \
+    iplink_ifb.o iplink_nlmon.o iplink_team.o iplink_vcan.o iplink_vxcan.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o iplink_xdp.o \
     iplink_macvlan.o ipl2tp.o link_vti.o link_vti6.o \
     iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
ip/iplink_vxcan.c new file +87 -0

87 lines not on this page · raw message

Signature · 1 line
2.11.0
#2 lore raw
In reply to Oliver Hartkopp
Quoted 33 lines · Oliver Hartkopp
drivers/net/can/vxcan.c new file +28 -0
@@ -0,0 +1,313 @@
[...]
+static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vxcan_priv *priv = netdev_priv(dev);
+	struct net_device *peer;
+	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
+	struct net_device_stats *stats = &dev->stats;
+
+	if (can_dropped_invalid_skb(dev, skb))
+		return NETDEV_TX_OK;
+
+	rcu_read_lock();
+	peer = rcu_dereference(priv->peer);
+	if (unlikely(!peer)) {
+		kfree_skb(skb);
+		dev->stats.tx_dropped++;
+		goto out_unlock;
+	}
+
+	skb = can_create_echo_skb(skb);
+	if (!skb)
+		return NETDEV_TX_OK;
+
+	stats->tx_packets++;
+	stats->tx_bytes += cfd->len;
+
+	/* reset CAN GW hop counter */
+	skb->csum_start = 0;
+

drivers/net/can/vxcan.c line 77

Quoted 10 lines
drivers/net/can/vxcan.c new file +10 -0
+	stats = &peer->stats;
+
+	stats->rx_packets++;
+	stats->rx_bytes += cfd->len;
+
+	skb->pkt_type  = PACKET_BROADCAST;
+	skb->dev       = peer;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	netif_rx_ni(skb);
     ^^^^^^^^^^

Wouldn't this result in the known out-of-order problem on SMP systems?

Best regards,
Alexander

#3 lore raw

Hi Alexander,

Quoted 6 lines · Alexander Stein

Review

Quoted 2 lines · Oliver Hartkopp
(quoted diff) +2 -0
+
+	netif_rx_ni(skb);
     ^^^^^^^^^^

Wouldn't this result in the known out-of-order problem on SMP systems?

I don't think so.
We're not dealing with irqs here that could reach different CPUs. This is all in softirq/userspace context.
It's the same thing we have with the virtual CAN vcan.

When there's something to fix, then we could fix up both vcan and vxcan. But I don't think so.

Regards,
Oliver

#4 lore raw

Hi Oliver,

Quoted 7 lines · Oliver Hartkopp
Quoted 6 lines · Alexander Stein

Review

Quoted 3 lines · Oliver Hartkopp
(quoted diff) +2 -0
+
+	netif_rx_ni(skb);
     ^^^^^^^^^^
Quoted 6 lines
Quoted 1 line

Wouldn't this result in the known out-of-order problem on SMP systems?

I don't think so.
We're not dealing with irqs here that could reach different CPUs. This is all in softirq/userspace context.
It's the same thing we have with the virtual CAN vcan.

That would be great. I don't know the complete code path but is it possible that this xmit function is executed on different CPUs at the same time? e.g. multiple sockets/threads writing a CAN frame.

Best regards,
Alexander