* [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.