All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan)
@ 2017-04-24 20:12 Oliver Hartkopp
  2017-04-24 20:12 ` [PATCH RFC] ip: link add vxcan support Oliver Hartkopp
  2017-04-25  5:35 ` [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan) Alexander Stein
  0 siblings, 2 replies; 5+ messages in thread
From: Oliver Hartkopp @ 2017-04-24 20:12 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 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

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 22570ea3a8d2..61c2fcf7f880 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -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
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 0da4f2f5c7e3..18cc6543b711 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -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
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
new file mode 100644
index 000000000000..1e55159f6fb0
--- /dev/null
+++ b/drivers/net/can/vxcan.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2017 Oliver Hartkopp <socketcan@hartkopp.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/skb.h>
+#include <linux/can/vxcan.h>
+#include <linux/slab.h>
+#include <net/rtnetlink.h>
+
+#define DRV_NAME "vxcan"
+
+MODULE_DESCRIPTION("Virtual CAN Tunnel");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>");
+MODULE_ALIAS_RTNL_LINK(DRV_NAME);
+
+struct vxcan_priv {
+	struct net_device __rcu	*peer;
+};
+
+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;
+
+	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);
+
+out_unlock:
+	rcu_read_unlock();
+	return NETDEV_TX_OK;
+}
+
+
+static int vxcan_open(struct net_device *dev)
+{
+	struct vxcan_priv *priv = netdev_priv(dev);
+	struct net_device *peer = rtnl_dereference(priv->peer);
+
+	if (!peer)
+		return -ENOTCONN;
+
+	if (peer->flags & IFF_UP) {
+		netif_carrier_on(dev);
+		netif_carrier_on(peer);
+	}
+	return 0;
+}
+
+static int vxcan_close(struct net_device *dev)
+{
+	struct vxcan_priv *priv = netdev_priv(dev);
+	struct net_device *peer = rtnl_dereference(priv->peer);
+
+	netif_carrier_off(dev);
+	if (peer)
+		netif_carrier_off(peer);
+
+	return 0;
+}
+
+static int vxcan_get_iflink(const struct net_device *dev)
+{
+	struct vxcan_priv *priv = netdev_priv(dev);
+	struct net_device *peer;
+	int iflink;
+
+	rcu_read_lock();
+	peer = rcu_dereference(priv->peer);
+	iflink = peer ? peer->ifindex : 0;
+	rcu_read_unlock();
+
+	return iflink;
+}
+
+static int vxcan_change_mtu(struct net_device *dev, int new_mtu)
+{
+	/* Do not allow changing the MTU while running */
+	if (dev->flags & IFF_UP)
+		return -EBUSY;
+
+	if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU)
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+static const struct net_device_ops vxcan_netdev_ops = {
+	.ndo_open	= vxcan_open,
+	.ndo_stop	= vxcan_close,
+	.ndo_start_xmit	= vxcan_xmit,
+	.ndo_get_iflink	= vxcan_get_iflink,
+	.ndo_change_mtu = vxcan_change_mtu,
+};
+
+static void vxcan_setup(struct net_device *dev)
+{
+	dev->type		= ARPHRD_CAN;
+	dev->mtu		= CAN_MTU;
+	dev->hard_header_len	= 0;
+	dev->addr_len		= 0;
+	dev->tx_queue_len	= 0;
+	dev->flags		= (IFF_NOARP|IFF_ECHO);
+	dev->netdev_ops		= &vxcan_netdev_ops;
+	dev->destructor		= free_netdev;
+}
+
+/* forward declaration for rtnl_create_link() */
+static struct rtnl_link_ops vxcan_link_ops;
+
+static int vxcan_newlink(struct net *net, struct net_device *dev,
+			 struct nlattr *tb[], struct nlattr *data[])
+{
+	struct vxcan_priv *priv;
+	struct net_device *peer;
+	struct net *peer_net;
+
+	struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
+	char ifname[IFNAMSIZ];
+	unsigned char name_assign_type;
+	struct ifinfomsg *ifmp = NULL;
+	int err;
+
+	/* register peer device */
+	if (data && data[VXCAN_INFO_PEER]) {
+		struct nlattr *nla_peer;
+
+		nla_peer = data[VXCAN_INFO_PEER];
+		ifmp = nla_data(nla_peer);
+		err = rtnl_nla_parse_ifla(peer_tb,
+					  nla_data(nla_peer) +
+					  sizeof(struct ifinfomsg),
+					  nla_len(nla_peer) -
+					  sizeof(struct ifinfomsg),
+					  NULL);
+		if (err < 0)
+			return err;
+
+		tbp = peer_tb;
+	} else {
+		tbp = tb;
+	}
+
+	if (tbp[IFLA_IFNAME]) {
+		nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
+		name_assign_type = NET_NAME_USER;
+	} else {
+		snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
+		name_assign_type = NET_NAME_ENUM;
+	}
+
+	peer_net = rtnl_link_get_net(net, tbp);
+	if (IS_ERR(peer_net))
+		return PTR_ERR(peer_net);
+
+	peer = rtnl_create_link(peer_net, ifname, name_assign_type,
+				&vxcan_link_ops, tbp);
+	if (IS_ERR(peer)) {
+		put_net(peer_net);
+		return PTR_ERR(peer);
+	}
+
+	if (ifmp && dev->ifindex)
+		peer->ifindex = ifmp->ifi_index;
+
+	err = register_netdevice(peer);
+	put_net(peer_net);
+	peer_net = NULL;
+	if (err < 0) {
+		free_netdev(peer);
+		return err;
+	}
+
+	netif_carrier_off(peer);
+
+	err = rtnl_configure_link(peer, ifmp);
+	if (err < 0) {
+		unregister_netdevice(peer);
+		return err;
+	}
+
+	/* register first device */
+	if (tb[IFLA_IFNAME])
+		nla_strlcpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);
+	else
+		snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d");
+
+	err = register_netdevice(dev);
+	if (err < 0) {
+		unregister_netdevice(peer);
+		return err;
+	}
+
+	netif_carrier_off(dev);
+
+	/* cross link the device pair */
+	priv = netdev_priv(dev);
+	rcu_assign_pointer(priv->peer, peer);
+
+	priv = netdev_priv(peer);
+	rcu_assign_pointer(priv->peer, dev);
+
+	return 0;
+}
+
+static void vxcan_dellink(struct net_device *dev, struct list_head *head)
+{
+	struct vxcan_priv *priv;
+	struct net_device *peer;
+
+	priv = netdev_priv(dev);
+	peer = rtnl_dereference(priv->peer);
+
+	/* Note : dellink() is called from default_device_exit_batch(),
+	 * before a rcu_synchronize() point. The devices are guaranteed
+	 * not being freed before one RCU grace period.
+	 */
+	RCU_INIT_POINTER(priv->peer, NULL);
+	unregister_netdevice_queue(dev, head);
+
+	if (peer) {
+		priv = netdev_priv(peer);
+		RCU_INIT_POINTER(priv->peer, NULL);
+		unregister_netdevice_queue(peer, head);
+	}
+}
+
+static const struct nla_policy vxcan_policy[VXCAN_INFO_MAX + 1] = {
+	[VXCAN_INFO_PEER] = { .len = sizeof(struct ifinfomsg) },
+};
+
+static struct net *vxcan_get_link_net(const struct net_device *dev)
+{
+	struct vxcan_priv *priv = netdev_priv(dev);
+	struct net_device *peer = rtnl_dereference(priv->peer);
+
+	return peer ? dev_net(peer) : dev_net(dev);
+}
+
+static struct rtnl_link_ops vxcan_link_ops = {
+	.kind		= DRV_NAME,
+	.priv_size	= sizeof(struct vxcan_priv),
+	.setup		= vxcan_setup,
+	.newlink	= vxcan_newlink,
+	.dellink	= vxcan_dellink,
+	.policy		= vxcan_policy,
+	.maxtype	= VXCAN_INFO_MAX,
+	.get_link_net	= vxcan_get_link_net,
+};
+
+static __init int vxcan_init(void)
+{
+	return rtnl_link_register(&vxcan_link_ops);
+}
+
+static __exit void vxcan_exit(void)
+{
+	rtnl_link_unregister(&vxcan_link_ops);
+}
+
+module_init(vxcan_init);
+module_exit(vxcan_exit);
diff --git a/include/uapi/linux/can/vxcan.h b/include/uapi/linux/can/vxcan.h
new file mode 100644
index 000000000000..ffb0b7156f7e
--- /dev/null
+++ b/include/uapi/linux/can/vxcan.h
@@ -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
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH RFC] ip: link add vxcan support
  2017-04-24 20:12 [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan) Oliver Hartkopp
@ 2017-04-24 20:12 ` Oliver Hartkopp
  2017-04-25  5:35 ` [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan) Alexander Stein
  1 sibling, 0 replies; 5+ messages in thread
From: Oliver Hartkopp @ 2017-04-24 20:12 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 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

diff --git a/include/linux/can/vxcan.h b/include/linux/can/vxcan.h
new file mode 100644
index 00000000..ffb0b715
--- /dev/null
+++ b/include/linux/can/vxcan.h
@@ -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
diff --git a/ip/Makefile b/ip/Makefile
index 035d42c7..d5c6473a 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -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 \
diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c
new file mode 100644
index 00000000..0074ae38
--- /dev/null
+++ b/ip/iplink_vxcan.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <net/if.h>
+#include <linux/can/vxcan.h>
+
+#include "utils.h"
+#include "ip_common.h"
+
+static void print_usage(FILE *f)
+{
+	printf("Usage: ip link <options> type vxcan [peer <options>]\n"
+	       "To get <options> type 'ip link add help'\n");
+}
+
+static void usage(void)
+{
+	print_usage(stderr);
+}
+
+static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
+			  struct nlmsghdr *hdr)
+{
+	char *dev = NULL;
+	char *name = NULL;
+	char *link = NULL;
+	char *type = NULL;
+	int index = 0;
+	int err, len;
+	struct rtattr *data;
+	int group;
+	struct ifinfomsg *ifm, *peer_ifm;
+	unsigned int ifi_flags, ifi_change;
+
+	if (strcmp(argv[0], "peer") != 0) {
+		usage();
+		return -1;
+	}
+
+	ifm = NLMSG_DATA(hdr);
+	ifi_flags = ifm->ifi_flags;
+	ifi_change = ifm->ifi_change;
+	ifm->ifi_flags = 0;
+	ifm->ifi_change = 0;
+
+	data = NLMSG_TAIL(hdr);
+	addattr_l(hdr, 1024, VXCAN_INFO_PEER, NULL, 0);
+
+	hdr->nlmsg_len += sizeof(struct ifinfomsg);
+
+	err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr,
+			   &name, &type, &link, &dev, &group, &index);
+	if (err < 0)
+		return err;
+
+	if (name) {
+		len = strlen(name) + 1;
+		if (len > IFNAMSIZ)
+			invarg("\"name\" too long\n", *argv);
+		addattr_l(hdr, 1024, IFLA_IFNAME, name, len);
+	}
+
+	peer_ifm = RTA_DATA(data);
+	peer_ifm->ifi_index = index;
+	peer_ifm->ifi_flags = ifm->ifi_flags;
+	peer_ifm->ifi_change = ifm->ifi_change;
+	ifm->ifi_flags = ifi_flags;
+	ifm->ifi_change = ifi_change;
+
+	if (group != -1)
+		addattr32(hdr, 1024, IFLA_GROUP, group);
+
+	data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data;
+	return argc - 1 - err;
+}
+
+static void vxcan_print_help(struct link_util *lu, int argc, char **argv,
+	FILE *f)
+{
+	print_usage(f);
+}
+
+struct link_util vxcan_link_util = {
+	.id = "vxcan",
+	.parse_opt = vxcan_parse_opt,
+	.print_help = vxcan_print_help,
+};
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan)
  2017-04-24 20:12 [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan) Oliver Hartkopp
  2017-04-24 20:12 ` [PATCH RFC] ip: link add vxcan support Oliver Hartkopp
@ 2017-04-25  5:35 ` Alexander Stein
  2017-04-25  6:28   ` Oliver Hartkopp
  1 sibling, 1 reply; 5+ messages in thread
From: Alexander Stein @ 2017-04-25  5:35 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can

On Monday 24 April 2017 22:12:37, Oliver Hartkopp wrote:
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
> --- /dev/null
> +++ b/drivers/net/can/vxcan.c
> @@ -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;
> +
> +	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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan)
  2017-04-25  5:35 ` [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan) Alexander Stein
@ 2017-04-25  6:28   ` Oliver Hartkopp
  2017-04-25  8:14     ` Alexander Stein
  0 siblings, 1 reply; 5+ messages in thread
From: Oliver Hartkopp @ 2017-04-25  6:28 UTC (permalink / raw)
  To: Alexander Stein; +Cc: linux-can

Hi Alexander,

On 04/25/2017 07:35 AM, Alexander Stein wrote:
> On Monday 24 April 2017 22:12:37, Oliver Hartkopp wrote:

>> +
>> +	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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan)
  2017-04-25  6:28   ` Oliver Hartkopp
@ 2017-04-25  8:14     ` Alexander Stein
  0 siblings, 0 replies; 5+ messages in thread
From: Alexander Stein @ 2017-04-25  8:14 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can

Hi Oliver,

On Tuesday 25 April 2017 08:28:11, Oliver Hartkopp wrote:
> On 04/25/2017 07:35 AM, Alexander Stein wrote:
> > On Monday 24 April 2017 22:12:37, Oliver Hartkopp wrote:
> >> +
> >> +	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.

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


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-04-25  8:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-24 20:12 [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan) Oliver Hartkopp
2017-04-24 20:12 ` [PATCH RFC] ip: link add vxcan support Oliver Hartkopp
2017-04-25  5:35 ` [PATCH RFC] can: add Virtual CAN Tunnel driver (vxcan) Alexander Stein
2017-04-25  6:28   ` Oliver Hartkopp
2017-04-25  8:14     ` Alexander Stein

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.