Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1420097 > unrolled thread

[very-RFC 0/8] TSN driver for the kernel

Started byHenrik Austad <henrik@austad.us>
First post2016-06-12 01:10 +0200
Last post2016-06-15 05:30 +0200
Articles 20 on this page of 47 — 9 participants

Back to article view | Back to linux.kernel


Contents

  [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-12 01:10 +0200
    [very-RFC 1/8] TSN: add documentation Henrik Austad <henrik@austad.us> - 2016-06-12 01:10 +0200
    [very-RFC 3/8] Adding TSN-driver to Intel I210 controller Henrik Austad <henrik@austad.us> - 2016-06-12 01:10 +0200
    [very-RFC 6/8] Add TSN event-tracing Henrik Austad <henrik@austad.us> - 2016-06-12 01:10 +0200
      Re: [very-RFC 6/8] Add TSN event-tracing Steven Rostedt <rostedt@goodmis.org> - 2016-06-12 19:00 +0200
        Re: [very-RFC 6/8] Add TSN event-tracing Henrik Austad <henrik@austad.us> - 2016-06-12 23:30 +0200
          Re: [very-RFC 6/8] Add TSN event-tracing Steven Rostedt <rostedt@goodmis.org> - 2016-06-13 04:30 +0200
            Re: [very-RFC 6/8] Add TSN event-tracing Henrik Austad <henrik@austad.us> - 2016-06-13 09:30 +0200
    [very-RFC 8/8] MAINTAINERS: add TSN/AVB-entries Henrik Austad <henrik@austad.us> - 2016-06-12 01:10 +0200
    Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-13 13:50 +0200
      Re: [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-13 15:10 +0200
        Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-13 21:40 +0200
          Re: [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-14 11:40 +0200
            Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-14 20:30 +0200
              Re: [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-14 22:40 +0200
                Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-15 09:10 +0200
                  Re: [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-15 10:00 +0200
                  Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-15 13:50 +0200
                Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-15 09:20 +0200
        Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-13 21:40 +0200
      Re: [very-RFC 0/8] TSN driver for the kernel Arnd Bergmann <arnd@linaro.org> - 2016-06-13 15:20 +0200
      Re: [very-RFC 0/8] TSN driver for the kernel John Fastabend <john.fastabend@gmail.com> - 2016-06-13 18:00 +0200
        Re: [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-14 10:40 +0200
      Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-13 22:00 +0200
        Re: [very-RFC 0/8] TSN driver for the kernel One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> - 2016-06-14 13:20 +0200
          Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-14 19:10 +0200
          Re: [very-RFC 0/8] TSN driver for the kernel Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2016-06-15 05:30 +0200
            Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-15 10:10 +0200
              Re: [very-RFC 0/8] TSN driver for the kernel Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2016-06-18 07:30 +0200
                Re: [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-19 00:50 +0200
                  Re: [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-19 11:50 +0200
                    Re: [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-20 11:50 +0200
                  Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> - 2016-06-20 13:20 +0200
                    Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-20 14:00 +0200
                    Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-20 14:30 +0200
                      Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-20 15:00 +0200
                        Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-20 17:40 +0200
                          Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Takashi Iwai <tiwai@suse.de> - 2016-06-21 08:00 +0200
                            Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-21 08:40 +0200
                              Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Takashi Iwai <tiwai@suse.de> - 2016-06-21 08:50 +0200
                        Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> - 2016-06-21 19:20 +0200
                      Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> - 2016-06-21 19:50 +0200
                        Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-21 23:20 +0200
                          Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> - 2016-06-22 14:40 +0200
                        Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Henrik Austad <henrik@austad.us> - 2016-06-23 12:40 +0200
                          Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel Richard Cochran <richardcochran@gmail.com> - 2016-06-23 15:30 +0200
          Re: [very-RFC 0/8] TSN driver for the kernel Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2016-06-15 05:30 +0200

Page 1 of 3  [1] 2 3  Next page →


#1420097 — [very-RFC 0/8] TSN driver for the kernel

FromHenrik Austad <henrik@austad.us>
Date2016-06-12 01:10 +0200
Subject[very-RFC 0/8] TSN driver for the kernel
Message-ID<rJ0cp-QL-3@gated-at.bofh.it>
Hi all
(series based on v4.7-rc2, now with the correct netdev)

This is a *very* early RFC for a TSN-driver in the kernel. It has been
floating around in my repo for a while and I would appreciate some
feedback on the overall design to avoid doing some major blunders.

TSN: Time Sensitive Networking, formely known as AVB (Audio/Video
Bridging).

There are at least one AVB-driver (the AV-part of TSN) in the kernel
already, however this driver aims to solve a wider scope as TSN can do
much more than just audio. A very basic ALSA-driver is added to the end
that allows you to play music between 2 machines using aplay in one end
and arecord | aplay on the other (some fiddling required) We have plans
for doing the same for v4l2 eventually (but there are other fishes to
fry first). The same goes for a TSN_SOCK type approach as well.

TSN is all about providing infrastructure. Allthough there are a few
very interesting uses for TSN (reliable, deterministic network for audio
and video), once you have that reliable link, you can do a lot more.

Some notes on the design:

The driver is directed via ConfigFS as we need userspace to handle
stream-reservation (MSRP), discovery and enumeration (IEEE 1722.1) and
whatever other management is needed. Once we have all the required
attributes, we can create link using mkdir, and use write() to set the
attributes. Once ready, specify the 'shim' (basically a thin wrapper
between TSN and another subsystem) and we start pushing out frames.

The network part: it ties directly into the rx-handler for receive and
writes skb's using netdev_start_xmit(). This could probably be
improved. 2 new fields in netdev_ops have been introduced, and the Intel
igb-driver has been updated (as this is available as a PCI-e card). The
igb-driver works-ish


What remains
- tie to (g)PTP properly, currently using ktime_get() for presentation
  time
- get time from shim into TSN and vice versa
- let shim create/manage buffer

Henrik Austad (8):
  TSN: add documentation
  TSN: Add the standard formerly known as AVB to the kernel
  Adding TSN-driver to Intel I210 controller
  Add TSN header for the driver
  Add TSN machinery to drive the traffic from a shim over the network
  Add TSN event-tracing
  AVB ALSA - Add ALSA shim for TSN
  MAINTAINERS: add TSN/AVB-entries

 Documentation/TSN/tsn.txt                 | 147 +++++
 MAINTAINERS                               |  14 +
 drivers/media/Kconfig                     |  15 +
 drivers/media/Makefile                    |   3 +-
 drivers/media/avb/Makefile                |   5 +
 drivers/media/avb/avb_alsa.c              | 742 +++++++++++++++++++++++
 drivers/media/avb/tsn_iec61883.h          | 124 ++++
 drivers/net/ethernet/intel/Kconfig        |  18 +
 drivers/net/ethernet/intel/igb/Makefile   |   2 +-
 drivers/net/ethernet/intel/igb/igb.h      |  19 +
 drivers/net/ethernet/intel/igb/igb_main.c |  10 +-
 drivers/net/ethernet/intel/igb/igb_tsn.c  | 396 ++++++++++++
 include/linux/netdevice.h                 |  32 +
 include/linux/tsn.h                       | 806 ++++++++++++++++++++++++
 include/trace/events/tsn.h                | 349 +++++++++++
 net/Kconfig                               |   1 +
 net/Makefile                              |   1 +
 net/tsn/Kconfig                           |  32 +
 net/tsn/Makefile                          |   6 +
 net/tsn/tsn_configfs.c                    | 623 +++++++++++++++++++
 net/tsn/tsn_core.c                        | 975 ++++++++++++++++++++++++++++++
 net/tsn/tsn_header.c                      | 203 +++++++
 net/tsn/tsn_internal.h                    | 383 ++++++++++++
 net/tsn/tsn_net.c                         | 403 ++++++++++++
 24 files changed, 5306 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/TSN/tsn.txt
 create mode 100644 drivers/media/avb/Makefile
 create mode 100644 drivers/media/avb/avb_alsa.c
 create mode 100644 drivers/media/avb/tsn_iec61883.h
 create mode 100644 drivers/net/ethernet/intel/igb/igb_tsn.c
 create mode 100644 include/linux/tsn.h
 create mode 100644 include/trace/events/tsn.h
 create mode 100644 net/tsn/Kconfig
 create mode 100644 net/tsn/Makefile
 create mode 100644 net/tsn/tsn_configfs.c
 create mode 100644 net/tsn/tsn_core.c
 create mode 100644 net/tsn/tsn_header.c
 create mode 100644 net/tsn/tsn_internal.h
 create mode 100644 net/tsn/tsn_net.c

--
2.7.4

[toc] | [next] | [standalone]


#1420098 — [very-RFC 1/8] TSN: add documentation

FromHenrik Austad <henrik@austad.us>
Date2016-06-12 01:10 +0200
Subject[very-RFC 1/8] TSN: add documentation
Message-ID<rJ0cp-QL-13@gated-at.bofh.it>
In reply to#1420097
From: Henrik Austad <haustad@cisco.com>

Describe the overall design behind the TSN standard, the TSN-driver,
requirements to userspace and new functionality introduced.

Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Henrik Austad <haustad@cisco.com>
---
 Documentation/TSN/tsn.txt | 147 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 147 insertions(+)
 create mode 100644 Documentation/TSN/tsn.txt

Index: linux/Documentation/TSN/tsn.txt
===================================================================
--- /dev/null
+++ linux/Documentation/TSN/tsn.txt
@@ -0,0 +1,188 @@
+		Time Sensitive Networking (TSN)
+		-------------------------------
+
+[work in progress]
+
+1. Motivation
+=============
+
+TSN is a set of open standards, formerly known as 'AVB' (Audio/Video
+Bridging). It was renamed to TSN to better reflect that it can do much
+more than just media transport.
+
+TSN is a way to create reliable streams across a network without loss of
+frames due to congestion in the network. By using gPTP (a specialized
+IEEE-1588v2 PTP profile), the time can be synchronized with sub-us
+granularity across all the connected devices in the AVB domain.
+
+2. Intro to AVB/TSN
+===================
+
+The original standards were written with Audio/Video in mind, so the
+initial standards refer to this as 'AVB'. In later standards, this has
+changed to TSN, and AVB now refers to a service you can add on top of
+TSN. Hopefully it will not be too confusing.
+
+In this document, we refer to the infrastructure part as TSN and AVB to
+the ALSA/V4L2 shim which can be added on top of TSN to provide a
+media-service.
+
+TSN operates with 'streams', and one stream can contain pretty much
+whatever you like. Currently, only media has been defined properly
+though, which is why you only have media-subtypes for the
+avtp_subtype-field.
+
+For a media-setup, one stream can contain multiple channels, all going
+to the same destination. A destination can be a single Listener
+(singlecast) or a group of Listeners (multicast).
+
+2.1 Endpoints
+
+A TSN 'endpoint' is where a stream either originates or ends -what
+others would call sources (Talkers) and sinks (Listeners). Looking back
+at pre-TSN when this was called AVB, these names make a bit more sense.
+
+Common for both types, they need to be PTPv2 capable, i.e. you need to
+timestamp gPTP frames upon ingress/egress to improve the accuracy of
+PTP.
+
+2.1.1 Talkers
+
+Hardware requirements:
+- Multiple Tx-queues
+- Credit based shaper on at least one of the queues for pacing the
+  frames onto the network
+- VLAN capable
+
+2.1.2 Listener
+
+A Listener does not have the same requirements as a Talker as it cannot
+control the pace of the incoming frames anyway. It is beneficial if the
+NIC understands VLANs and has a few Rx-queues so that you can steer all
+TSN-frames to a dedicated queue.
+
+2.2 Bridges
+
+What TSN calls switches that are TSN-capable. They must be able to
+prioritize TSN-streams, have the credit-based shaper available for that
+class, support SRP, support gPTP and so on.
+
+2.3 Relevant standards
+
+* IEEE 802.1BA-2011 Audio Video Bridging (AVB) Systems
+
+* IEEE 802.1Q-2011 sec 34 and 35
+
+  What is referred to as:
+  IEEE 802.1Qav (Forwarding and Queueing for Time-sensitive Streams)
+  IEEE 802.1Qat (Stream Registration protocol)
+
+* IEEE 802.1AS gPTP
+
+  A PTPv2 profile (from IEEE 1588) tailored for this domain. Notable
+  changes include the requirement that all nodes in the network must be
+  gPTP capable (i.e. no traversing non-PTP entities), and it allows
+  traffic over a wider range of medium that what "pure" PTPv2 allows.
+
+* IEEE 1722 AVTP Layer 2 Transport Protocol for Time-Sensitive
+  Applications in Bridged Local Area Networks
+
+* IEEE 1722.1 Device Discovery, Connection Management and Control for 1722
+
+  What allows AVB (TSN) devices to handle discovery, enumeration and
+  control, basically let you connect 2 devices from a 3rd
+
+  In this (in the scope of the Linux kernel TSN driver) must be done
+  purely from userspace as we do not want the kernel to suddenly attach
+  to a remote system without the user's knowledge. This is further
+  reflected in how the attributes for the link is managed via ConfigFS.
+
+
+3. Overview and/or design of the TSN-driver
+===========================================
+
+The driver handles the shifting of data for TSN-streams. Anything else
+is left for userspace to handle. This includes stream reservation (using
+some sort of MSRP client), negotiating multicast addresses, finding the
+value of the different attributes and connect application(s) to the
+exposed devices (currently we only have an ALSA-device).
+
+       	       /--------------------\
+       	       |                    |
+	       |  Media application |
+	       |       	       	    |
+	       \--------------------/
+		     | 	      |
+       	  +----------+	      +----+
+	  | 			   |
+	  | 			   |
+     +------------+		   |
+     |   ALSA  	  |		   |
+     +------------+		   |
+	  |			   |
+	  |			   |
+     +------------+          +--------------+
+     | 	avb_alsa  | 	     | tsn_configfs |
+     | (tsn-shim) |	     +--------------+
+     +------------+ 		   |
+       	  |  	    		   |
+	  |    	  		   |
+	  +------+     	  	   |
+	   	 |		   |
+       	       	 |		   |
+            +------------+	   |
+ 	    |  tsn_core  |<--------+
+            +------------+
+       	       	 |
+		 |
+            +------------+
+       	    |  tsn_net   |
+            +------------+
+		 |
+		 |
+	    +------------+
+	    |  network	 |
+       	    | subsystem  |
+	    +------------+
+	       	 |
+		 |
+		...
+
+
+3.1 Terms and concepts
+
+TSN uses the concept of streams and shims.
+
+- A shim is a thin wrapper that binds TSN to another subsystem (or
+  directly to userspace). avb_alsa is an example of such a shim.
+
+- A stream is the only data TSN cares about. What the data inside the
+  stream represents, is left for the associated shim to handle. TSN will
+  verify the headers up to the protocol specific header and then pass it
+  along to the shim.
+
+Note: currently, only the data-unit part is implemented, the control
+part, in which 1722.1 (discovery and enumeration) is part, is not
+handled.
+
+3.2 Userspace requirements
+
+(msrp-client, "tsnctl"-tool
+
+4. Creating a new link from userspace
+=====================================
+
+[coming]
+
+
+5. Creating a new shim
+======================
+
+shim_ops
+[coming]
+
+
+6. Other resources:
+===================
+
+https://en.wikipedia.org/wiki/Audio_Video_Bridging

[toc] | [prev] | [next] | [standalone]


#1420099 — [very-RFC 3/8] Adding TSN-driver to Intel I210 controller

FromHenrik Austad <henrik@austad.us>
Date2016-06-12 01:10 +0200
Subject[very-RFC 3/8] Adding TSN-driver to Intel I210 controller
Message-ID<rJ0cq-QL-19@gated-at.bofh.it>
In reply to#1420097
This adds support for loading the igb.ko module with tsn
capabilities. This requires a 2-step approach. First enabling TSN in
.config, then load the module with use_tsn=1.

Once enabled and loaded, the controller will be placed in "Qav-mode"
which is when the credit-based shaper is available, 3 of the queues are
removed from regular traffic, max payload is set to 1522 octets (no
jumboframes allowed).

It dumps the registers of interest before and after, so this clutters
kern.log a bit. In time this will be reduced / tied to the debug-param
for the module.

Note: currently this driver is *not* stable, it is still a work in
progress.

Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: intel-wired-lan@lists.osuosl.org
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Henrik Austad <haustad@cisco.com>
---
 drivers/net/ethernet/intel/Kconfig        |  18 ++
 drivers/net/ethernet/intel/igb/Makefile   |   2 +-
 drivers/net/ethernet/intel/igb/igb.h      |  19 ++
 drivers/net/ethernet/intel/igb/igb_main.c |  10 +-
 drivers/net/ethernet/intel/igb/igb_tsn.c  | 396 ++++++++++++++++++++++++++++++
 5 files changed, 443 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/igb/igb_tsn.c

diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 714bd10..8e620a9 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -99,6 +99,24 @@ config IGB
 	  To compile this driver as a module, choose M here. The module
 	  will be called igb.
 
+config IGB_TSN
+       tristate "TSN Support for Intel(R) 82575/82576 i210 Network Controller"
+       depends on IGB && TSN
+	---help---
+	  This driver supports TSN (AVB) on Intel I210 network controllers.
+
+	  When enabled, it will allow the module to be loaded with
+	  "use_tsn" which will initialize the controller to A/V-mode
+	  instead of legacy-mode. This will take 3 of the tx-queues and
+	  place them in 802.1Q QoS mode and enable the credit-based
+	  shaper for 2 of the queues.
+
+	  If built with this option, but not loaded with use_tsn, the
+	  only difference is a slightly larger module, no extra
+	  code paths are called.
+
+	  If unsure, say No
+
 config IGB_HWMON
 	bool "Intel(R) PCI-Express Gigabit adapters HWMON support"
 	default y
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index 5bcb2de..1a9b776 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -33,4 +33,4 @@ obj-$(CONFIG_IGB) += igb.o
 
 igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
 	    e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
-	    e1000_i210.o igb_ptp.o igb_hwmon.o
+	    e1000_i210.o igb_ptp.o igb_hwmon.o igb_tsn.o
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index b9609af..708f705 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -356,6 +356,7 @@ struct hwmon_buff {
 #define IGB_RETA_SIZE	128
 
 /* board specific private data structure */
+
 struct igb_adapter {
 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 
@@ -472,6 +473,13 @@ struct igb_adapter {
 	int copper_tries;
 	struct e1000_info ei;
 	u16 eee_advert;
+
+#if IS_ENABLED(CONFIG_IGB_TSN)
+	/* Reserved BW for class A and B */
+	u16 sra_idleslope_res;
+	u16 srb_idleslope_res;
+	u8 tsn_ready:1;
+#endif	/* IGB_TSN */
 };
 
 #define IGB_FLAG_HAS_MSI		BIT(0)
@@ -552,6 +560,17 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, unsigned char *va,
 			 struct sk_buff *skb);
 int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
 int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
+/* This should be the only place where we add ifdeffery
+ * to include tsn-stuff or not. Everything else is located in igb_tsn.c
+ */
+#if IS_ENABLED(CONFIG_IGB_TSN)
+void igb_tsn_init(struct igb_adapter *adapter);
+int igb_tsn_capable(struct net_device *netdev);
+int igb_tsn_link_configure(struct net_device *netdev, enum sr_class sr_class,
+			   u16 framesize, u16 vid);
+#else
+static inline void igb_tsn_init(struct igb_adapter *adapter) { }
+#endif	/* CONFIG_IGB_TSN */
 void igb_set_flag_queue_pairs(struct igb_adapter *, const u32);
 #ifdef CONFIG_IGB_HWMON
 void igb_sysfs_exit(struct igb_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index ef3d642..4d8789f 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2142,6 +2142,10 @@ static const struct net_device_ops igb_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= igb_netpoll,
 #endif
+#if IS_ENABLED(CONFIG_IGB_TSN)
+	.ndo_tsn_capable	= igb_tsn_capable,
+	.ndo_tsn_link_configure = igb_tsn_link_configure,
+#endif	/* CONFIG_IGB_TSN */
 	.ndo_fix_features	= igb_fix_features,
 	.ndo_set_features	= igb_set_features,
 	.ndo_fdb_add		= igb_ndo_fdb_add,
@@ -2665,6 +2669,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* do hw tstamp init after resetting */
 	igb_ptp_init(adapter);
 
+	igb_tsn_init(adapter);
+
 	dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
 	/* print bus type/speed/width info, not applicable to i354 */
 	if (hw->mac.type != e1000_i354) {
@@ -5323,8 +5329,10 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
 	/* The minimum packet size with TCTL.PSP set is 17 so pad the skb
 	 * in order to meet this minimum size requirement.
 	 */
-	if (skb_put_padto(skb, 17))
+	if (skb_put_padto(skb, 17)) {
+		pr_err("%s: skb_put_padto FAILED. skb->len < 17\n", __func__);
 		return NETDEV_TX_OK;
+	}
 
 	return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
 }
diff --git a/drivers/net/ethernet/intel/igb/igb_tsn.c b/drivers/net/ethernet/intel/igb/igb_tsn.c
new file mode 100644
index 0000000..641f4f2
--- /dev/null
+++ b/drivers/net/ethernet/intel/igb/igb_tsn.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright(c) 2015-2016 Henrik Austad <haustad@cisco.com>
+ *                        Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+/* FIXME: This should probably be handled by some Makefile-magic */
+
+#if IS_ENABLED(CONFIG_IGB_TSN)
+#include "igb.h"
+#include <linux/module.h>
+
+/* NOTE: keep the defines not present in e1000_regs.h to avoid
+ * cluttering too many files. Once we are pretty stable, these will move
+ * into it's proper home. Until then, make merge a bit easier by
+ * avoiding it
+ */
+
+/* Qav regs */
+#define E1000_IRPBS	 0x02404 /* Rx Packet Buffer Size - RW */
+#define E1000_ITPBS	 0x03404 /* Tx buffer size assignment */
+#define E1000_TQAVCTRL   0x03570 /* Tx Qav Control */
+#define E1000_DTXMXPKTSZ 0x0355C /* DMA TX Maximum Packet Size */
+
+/* Qav defines. */
+#define E1000_TQAVCH_ZERO_CREDIT       0x80000000
+#define E1000_LINK_RATE		       0x7735
+
+/* queue mode, 0=strict, 1=SR mode */
+#define E1000_TQAVCC_QUEUEMODE         0x80000000
+/* Transmit mode, 0=legacy, 1=QAV */
+#define E1000_TQAVCTRL_TXMODE          0x00000001
+/* report DMA time of tx packets */
+#define E1000_TQAVCTRL_1588_STAT_EN    0x00000004
+/* data fetch arbitration */
+#define E1000_TQAVCTRL_DATA_FETCH_ARB  0x00000010
+/* data tx arbitration */
+#define E1000_TQAVCTRL_DATA_TRAN_ARB   0x00000100
+/* data launch time valid */
+#define E1000_TQAVCTRL_DATA_TRAN_TIM   0x00000200
+/* stall SP to guarantee SR */
+#define E1000_TQAVCTRL_SP_WAIT_SR      0x00000400
+
+/* ... and associated shift value */
+#define E1000_TQAVCTRL_FETCH_TM_SHIFT  (16)
+
+/* QAV Tx mode control registers where _n can be 0 or 1. */
+#define E1000_TQAVCC(_idx)			(0x03004 + 0x40 * (_idx))
+
+/* Tx Qav High Credit - See 7.2.7.6 for calculations
+ * intel 8.12.18
+ */
+#define E1000_TQAVHC(_idx)			(0x0300C + 0x40 * (_idx))
+
+/* Queues priority masks where _n and _p can be 0-3. */
+
+#define MAX_FRAME_SIZE 1522
+#define MIN_FRAME_SIZE   64
+
+static int use_tsn = -1;
+static int debug_tsn = -1;
+module_param(use_tsn, int, 0);
+module_param(debug_tsn, int, 0);
+MODULE_PARM_DESC(use_tsn, "use_tsn (0=off, 1=enabled)");
+MODULE_PARM_DESC(debug_tsn, "debug_tsn (0=off, 1=enabled)");
+
+/* For a full list of the registers dumped here, see sec 8.1.3 in the
+ * i210 controller datasheet.
+ */
+static inline void _tsn_dump_regs(struct igb_adapter *adapter)
+{
+	u32 val = 0;
+	struct device *dev;
+	struct e1000_hw *hw = &adapter->hw;
+
+	/* do not dump regs if we're not debugging driver */
+	if (debug_tsn != 1)
+		return;
+
+	dev = &adapter->pdev->dev;
+	dev_info(dev, "num_tx_queues=%d, num_rx_queues=%d\n",
+		 adapter->num_tx_queues, adapter->num_rx_queues);
+
+	/* 0x0008 - E1000_STATUS Device status register */
+	val = rd32(E1000_STATUS);
+	dev_info(&adapter->pdev->dev, "\n");
+	dev_info(dev, "Status: FullDuplex=%s, LinkUp=%s, speed=%0x01x\n",
+		 val & 0x1 ? "FD" : "HD",
+		 val & 0x2 ? "LU" : "LD",
+		 val & 0xc0 >> 6);
+
+	/* E1000_VET vlan ether type */
+	val = rd32(E1000_VET);
+	dev_info(dev, "VLAN ether type: VET.VET=0x%04x, VET.VET_EXT=0x%04x\n",
+		 val & 0xffff, (val >> 16) & 0xffff);
+
+	/* E1000_RXPBS (RXPBSIZE) Rx Packet Buffer Size */
+	val = rd32(E1000_RXPBS);
+	dev_info(dev, "Rx Packet buffer: RXPBSIZE=%dkB, Bmc2ospbsize=%dkB, cfg_ts_en=%s\n",
+		 val & 0x1f,
+		 (val >> 6) & 0x1f,
+		 (val & (1 << 31)) ? "cfg_ts_en" : "cfg_ts_dis");
+
+	/* Transmit stuff */
+	/* E1000_TXPBS (TXPBSIZE) Tx Packet Buffer Size - RW */
+	val = rd32(E1000_TXPBS);
+	dev_info(dev, "Tx Packet buffer: Txpb0size=%dkB, Txpb1size=%dkB, Txpb2size=%dkB, Txpb3size=%dkB, os2Bmcpbsize=%dkB\n",
+		 val & 0x3f, (val >> 6) & 0x3f, (val >> 12) & 0x3f,
+		 (val >> 18) & 0x3f, (val >> 24) & 0x3f);
+
+	/* E1000_TCTL (TCTL) Tx control - RW*/
+	val = rd32(E1000_TCTL);
+	dev_info(dev, "Tx control reg: TxEnable=%s, CT=0x%X\n",
+		 val & 2 ? "EN" : "DIS", (val >> 3) & 0x3F);
+
+	/* TQAVHC     : Transmit Qav High credits 0x300C + 0x40*n - RW */
+	val = rd32(E1000_TQAVHC(0));
+	dev_info(dev, "E1000_TQAVHC0: %0x08x\n", val);
+	val = rd32(E1000_TQAVHC(1));
+	dev_info(dev, "E1000_TQAVHC1: %0x08x\n", val);
+
+	/* TQAVCC[0-1]: Transmit Qav 0x3004 + 0x40*n  - RW */
+	val = rd32(E1000_TQAVCC(0));
+	dev_info(dev, "E1000_TQAVCC0: idleSlope=%02x, QueueMode=%s\n",
+		 val % 0xff,
+		 val > 31 ? "Stream reservation" : "Strict priority");
+	val = rd32(E1000_TQAVCC(1));
+	dev_info(dev, "E1000_TQAVCC1: idleSlope=%02x, QueueMode=%s\n",
+		 val % 0xff,
+		 val > 31 ? "Stream reservation" : "Strict priority");
+
+	/* TQAVCTRL   : Transmit Qav control - RW */
+	val = rd32(E1000_TQAVCTRL);
+	dev_info(dev, "E1000_TQAVCTRL: TransmitMode=%s,1588_STAT_EN=%s,DataFetchARB=%s,DataTranARB=%s,DataTranTIM=%s,SP_WAIT_SR=%s,FetchTimDelta=%dns (0x%04x)\n",
+		 (val & 0x0001) ? "Qav" : "Legacy",
+		 (val & 0x0004) ? "En" : "Dis",
+		 (val & 0x0010) ? "Most Empty" : "Round Robin",
+		 (val & 0x0100) ? "Credit Shaper" : "Strict priority",
+		 (val & 0x0200) ? "Valid" : "N/A",
+		 (val & 0x0400) ? "Wait" : "nowait",
+		 (val >> 16) * 32, (val >> 16));
+}
+
+/* Place the NIC in Qav-mode.
+ *
+ * This will result in a _single_ queue for normal BE traffic, the rest
+ * will be grabbed by the Qav-machinery and kept for strict priority
+ * transmission.
+ *
+ * I210 Datasheet Sec 7.2.7.7 gives a lot of information.
+ */
+void igb_tsn_init(struct igb_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 val;
+
+	if (use_tsn != 1) {
+		adapter->tsn_ready = 0;
+		dev_info(&adapter->pdev->dev, "%s got use_tsn > 0 (%d)\n",
+			 __func__, use_tsn);
+		return;
+	}
+
+	if (debug_tsn < 0 || debug_tsn > 1)
+		debug_tsn = 0;
+
+	if (!adapter->pdev) {
+		adapter->tsn_ready = 0;
+		return;
+	}
+
+	switch (adapter->pdev->device) {
+	case 0x1533:   /* E1000_DEV_ID_I210_COPPER */
+	case 0x1536:   /* E1000_DEV_ID_I210_FIBER */
+	case 0x1537:   /* E1000_DEV_ID_I210_SERDES: */
+	case 0x1538:   /* E1000_DEV_ID_I210_SGMII: */
+	case 0x157b:   /* E1000_DEV_ID_I210_COPPER_FLASHLESS: */
+	case 0x157c:   /* E1000_DEV_ID_I210_SERDES_FLASHLESS: */
+		break;
+	default:
+		/* not a known IGB-TSN capable device */
+		adapter->tsn_ready = 0;
+		return;
+	}
+	_tsn_dump_regs(adapter);
+
+	/* Set Tx packet buffer size assignment, see 7.2.7.7 in i210
+	 * PB0: 8kB
+	 * PB1: 8kB
+	 * PB2: 4kB
+	 * PB3: 4kB
+	 * os2bmcsize: 2kB
+	 * sumTx: 26kB
+	 *
+	 * Rxpbsize: 0x20 (32kB)
+	 * bmc2ossize: 0x02
+	 * sumRx: 34kB
+	 *
+	 * See 8.3.1 && 8.3.2
+	 */
+	val = (0x02 << 24 | 0x04 << 18 | 0x04 << 12 | 0x08 << 6 | 0x08);
+	wr32(E1000_ITPBS, val);
+	wr32(E1000_IRPBS, (0x02 << 6 | 0x20));
+
+	/* DMA Tx maximum packet size, the largest frame DMA should transport
+	 * do not allow frames larger than 1522 + preample. Reg expects
+	 * size in 64B increments. 802.1BA 6.3
+	 * Round up to 1536 to handle 64B increments
+	 *
+	 * Initial value: 0x98 (152 => 9728 bytes)
+	 */
+	wr32(E1000_DTXMXPKTSZ, 1536 >> 6);
+
+	/* Place card in Qav-mode, use tx-queue 0,1 for Qav
+	 * (Credit-based shaper), 2,3 for standard priority (and
+	 * best-effort) traffic.
+	 *
+	 * i210 8.12.19 and 8.12.21
+	 *
+	 * - Fetch: most empty and time based (not round-robin)
+	 * - Transmit: Credit based shaper for SR queues
+	 * - Data launch time valid (in Qav mode)
+	 * - Wait for SR queues to ensure that launch time is always valid.
+	 * - Set ~10us wait-time-delta, 32ns granularity
+	 *
+	 * Do *not* enable Tx for shaper (E1000_TQAVCTRL_DATA_TRAN_ARB)
+	 * yet as we do not have data to Tx
+	 */
+	val = E1000_TQAVCTRL_TXMODE           |
+		E1000_TQAVCTRL_DATA_FETCH_ARB |
+		E1000_TQAVCTRL_DATA_TRAN_TIM  |
+		E1000_TQAVCTRL_SP_WAIT_SR     |
+		320 << E1000_TQAVCTRL_FETCH_TM_SHIFT;
+
+	wr32(E1000_TQAVCTRL, val);
+
+	/* For now, only set CreditBased shaper for A and B, not set
+	 * idleSlope as we have not yet gotten any streams.
+	 * 8.12.19
+	 */
+	wr32(E1000_TQAVCC(0), E1000_TQAVCC_QUEUEMODE);
+	wr32(E1000_TQAVCC(1), E1000_TQAVCC_QUEUEMODE);
+
+	wr32(E1000_TQAVHC(0), E1000_TQAVCH_ZERO_CREDIT);
+	wr32(E1000_TQAVHC(1), E1000_TQAVCH_ZERO_CREDIT);
+
+	/* reset Tx Descriptor tail and head for the queues */
+	wr32(E1000_TDT(0), 0);
+	wr32(E1000_TDT(1), 0);
+	wr32(E1000_TDH(0), 0);
+	wr32(E1000_TDH(1), 0);
+
+	_tsn_dump_regs(adapter);
+	dev_info(&adapter->pdev->dev, "\n");
+
+	adapter->sra_idleslope_res = 0;
+	adapter->srb_idleslope_res = 0;
+	adapter->tsn_ready = 1;
+
+	dev_info(&adapter->pdev->dev, "%s: setup done\n", __func__);
+}
+
+int igb_tsn_capable(struct net_device *netdev)
+{
+	struct igb_adapter *adapter;
+
+	if (!netdev)
+		return -EINVAL;
+	adapter = netdev_priv(netdev);
+	if (use_tsn == 1)
+		return adapter->tsn_ready == 1;
+	return 0;
+}
+
+/* igb_tsn_link_configure - configure NIC to handle a new stream
+ *
+ * @netdev: pointer to NIC device
+ * @class: the class for the stream used to find the correct queue.
+ * @framesize: size of each frame, *including* headers (not preamble)
+ * @vid: VLAN ID
+ *
+ * NOTE: the sr_class only instructs the driver which queue to use, not
+ * what priority the network expects for a given class. This is
+ * something userspace must find out and then let the tsn-driver set in
+ * the frame before xmit.
+ *
+ * FIXME: remove bw-req from a stream that goes away.
+ */
+int igb_tsn_link_configure(struct net_device *netdev, enum sr_class class,
+			   u16 framesize, u16 vid)
+{
+	/* FIXME: push into adapter-storage */
+	static int class_a_size;
+	static int class_b_size;
+	int err;
+	u32 idle_slope_a = 0;
+	u32 idle_slope_b = 0;
+	u32 new_is = 0;
+	u32 hicred_a = 0;
+	u32 hicred_b = 0;
+	u32 tqavctrl;
+
+	struct igb_adapter *adapter;
+	struct e1000_hw *hw;
+
+	if (!netdev)
+		return -EINVAL;
+	adapter  = netdev_priv(netdev);
+	hw = &adapter->hw;
+
+	if (!igb_tsn_capable(netdev)) {
+		pr_err("%s:  NIC not capable\n", __func__);
+		return -EINVAL;
+	}
+
+	if (framesize > MAX_FRAME_SIZE || framesize < MIN_FRAME_SIZE) {
+		pr_err("%s: framesize (%u) must be [%d,%d]\n", __func__,
+		       framesize, MIN_FRAME_SIZE, MAX_FRAME_SIZE);
+		return -EINVAL;
+	}
+
+	/* TODO: is this the correct place/way? Is it required? */
+	rtnl_lock();
+	pr_info("%s: adding VLAN %u to HW filter on device %s\n",
+		__func__, vid, netdev->name);
+	err = vlan_vid_add(netdev, htons(ETH_P_8021Q), vid);
+	if (err != 0)
+		pr_err("%s: error adding vlan %u, res=%d\n",
+		       __func__, vid, err);
+	rtnl_unlock();
+
+	/* Grab current values of idle_slope */
+	idle_slope_a = rd32(E1000_TQAVHC(0)) & ~E1000_TQAVCH_ZERO_CREDIT;
+	idle_slope_b = rd32(E1000_TQAVHC(1)) & ~E1000_TQAVCH_ZERO_CREDIT;
+
+	/* Calculate new idle slope and add to appropriate idle_slope
+	 * idle_slope = BW * linkrate * 2 (0r 0.2 for 100Mbit)
+	 * BW: % of total bandwidth
+	 */
+	new_is = framesize * E1000_LINK_RATE * 16 / 1000000;
+
+	switch (class) {
+	case SR_CLASS_A:
+		new_is *= 2; /* A is 8kHz, B is 4kHz */
+		idle_slope_a += new_is;
+		class_a_size  = framesize;
+		break;
+	case SR_CLASS_B:
+		idle_slope_b += new_is;
+		class_b_size  = framesize;
+		break;
+	default:
+		pr_err("%s: unhandled SR-class (%d)\n", __func__, class);
+		return -EINVAL;
+	}
+
+	/* HiCred: cred obtained while waiting for current frame &&
+	 * higher-class frames to finish xmit.
+	 *
+	 * Covered in detail in 7.2.7.6 in i210 datasheet
+	 * For class A: only worst-case framesize that just started;
+	 *		i.e. 1522 * idleSlope / linkrate;
+	 * For class B: (worst-case framesize + burstSize(A))*idleSlope
+	 *
+	 * See 802.1Q Annex L, eq L.10 for hicred_a and L.41 for
+	 * hicred_b
+	 */
+	if (class == SR_CLASS_A) {
+		hicred_a = E1000_TQAVCH_ZERO_CREDIT + idle_slope_a * MAX_FRAME_SIZE / E1000_LINK_RATE;
+		wr32(E1000_TQAVCC(0), E1000_TQAVCC_QUEUEMODE | idle_slope_a);
+		wr32(E1000_TQAVHC(0), hicred_a);
+	} else {
+		hicred_b = E1000_TQAVCH_ZERO_CREDIT | idle_slope_b * (MAX_FRAME_SIZE + class_a_size) / (E1000_LINK_RATE - idle_slope_a);
+		wr32(E1000_TQAVCC(1), E1000_TQAVCC_QUEUEMODE | idle_slope_b);
+		wr32(E1000_TQAVHC(1), hicred_b);
+	}
+
+	/* Enable Tx for shaper now that we have data */
+	tqavctrl = rd32(E1000_TQAVCTRL);
+	if (!(tqavctrl & E1000_TQAVCTRL_DATA_TRAN_ARB)) {
+		tqavctrl |= E1000_TQAVCTRL_DATA_TRAN_ARB;
+		wr32(E1000_TQAVCTRL, tqavctrl);
+	}
+	_tsn_dump_regs(netdev_priv(netdev));
+	return 0;
+}
+
+#endif	/* #if IS_ENABLED(CONFIG_IGB_TSN) */
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1420100 — [very-RFC 6/8] Add TSN event-tracing

FromHenrik Austad <henrik@austad.us>
Date2016-06-12 01:10 +0200
Subject[very-RFC 6/8] Add TSN event-tracing
Message-ID<rJ0cq-QL-21@gated-at.bofh.it>
In reply to#1420097
From: Henrik Austad <haustad@cisco.com>

This needs refactoring and should be updated to use TRACE_CLASS, but for
now it provides a fair debug-window into TSN.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Steven Rostedt <rostedt@goodmis.org> (maintainer:TRACING)
Cc: Ingo Molnar <mingo@redhat.com> (maintainer:TRACING)
Signed-off-by: Henrik Austad <haustad@cisco.com>
---
 include/trace/events/tsn.h | 349 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 349 insertions(+)
 create mode 100644 include/trace/events/tsn.h

diff --git a/include/trace/events/tsn.h b/include/trace/events/tsn.h
new file mode 100644
index 0000000..ac1f31b
--- /dev/null
+++ b/include/trace/events/tsn.h
@@ -0,0 +1,349 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM tsn
+
+#if !defined(_TRACE_TSN_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_TSN_H
+
+#include <linux/tsn.h>
+#include <linux/tracepoint.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+/* #include <linux/skbuff.h> */
+
+/* FIXME: update to TRACE_CLASS to reduce overhead */
+TRACE_EVENT(tsn_buffer_write,
+
+	TP_PROTO(struct tsn_link *link,
+		size_t bytes),
+
+	TP_ARGS(link, bytes),
+
+	TP_STRUCT__entry(
+		__field(u64, stream_id)
+		__field(size_t, size)
+		__field(size_t, bsize)
+		__field(size_t, size_left)
+		__field(void *, buffer)
+		__field(void *, head)
+		__field(void *, tail)
+		__field(void *, end)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->size = bytes;
+		__entry->bsize = link->used_buffer_size;
+		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
+		__entry->buffer = link->buffer;
+		__entry->head = link->head;
+		__entry->tail = link->tail;
+		__entry->end = link->end;
+		),
+
+	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
+		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
+		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
+
+	);
+
+TRACE_EVENT(tsn_buffer_write_net,
+
+	TP_PROTO(struct tsn_link *link,
+		size_t bytes),
+
+	TP_ARGS(link, bytes),
+
+	TP_STRUCT__entry(
+		__field(u64, stream_id)
+		__field(size_t, size)
+		__field(size_t, bsize)
+		__field(size_t, size_left)
+		__field(void *, buffer)
+		__field(void *, head)
+		__field(void *, tail)
+		__field(void *, end)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->size = bytes;
+		__entry->bsize = link->used_buffer_size;
+		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
+		__entry->buffer = link->buffer;
+		__entry->head = link->head;
+		__entry->tail = link->tail;
+		__entry->end = link->end;
+		),
+
+	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
+		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
+		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
+
+	);
+
+
+TRACE_EVENT(tsn_buffer_read,
+
+	TP_PROTO(struct tsn_link *link,
+		size_t bytes),
+
+	TP_ARGS(link, bytes),
+
+	TP_STRUCT__entry(
+		__field(u64, stream_id)
+		__field(size_t, size)
+		__field(size_t, bsize)
+		__field(size_t, size_left)
+		__field(void *, buffer)
+		__field(void *, head)
+		__field(void *, tail)
+		__field(void *, end)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->size = bytes;
+		__entry->bsize = link->used_buffer_size;
+		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
+		__entry->buffer = link->buffer;
+		__entry->head = link->head;
+		__entry->tail = link->tail;
+		__entry->end = link->end;
+		),
+
+	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
+		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
+		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
+
+	);
+
+TRACE_EVENT(tsn_refill,
+
+	TP_PROTO(struct tsn_link *link,
+		size_t reported_avail),
+
+	TP_ARGS(link, reported_avail),
+
+	TP_STRUCT__entry(
+		__field(u64, stream_id)
+		__field(size_t, bsize)
+		__field(size_t, size_left)
+		__field(size_t, reported_left)
+		__field(size_t, low_water)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->bsize = link->used_buffer_size;
+		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
+		__entry->reported_left = reported_avail;
+		__entry->low_water = link->low_water_mark;
+		),
+
+	TP_printk("stream_id=%llu, buffer=%zd, avail=%zd, reported=%zd, low=%zd",
+		__entry->stream_id, __entry->bsize, __entry->size_left, __entry->reported_left, __entry->low_water)
+	);
+
+TRACE_EVENT(tsn_send_batch,
+
+	TP_PROTO(struct tsn_link *link,
+		int num_send,
+		u64 ts_base_ns,
+		u64 ts_delta_ns),
+
+	TP_ARGS(link, num_send, ts_base_ns, ts_delta_ns),
+
+	TP_STRUCT__entry(
+		__field(u64, stream_id)
+		__field(int, seqnr)
+		__field(int, num_send)
+		__field(u64, ts_base_ns)
+		__field(u64, ts_delta_ns)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id   = link->stream_id;
+		__entry->seqnr	     = (int)link->last_seqnr;
+		__entry->ts_base_ns  = ts_base_ns;
+		__entry->ts_delta_ns = ts_delta_ns;
+		__entry->num_send    = num_send;
+		),
+
+	TP_printk("stream_id=%llu, seqnr=%d, num_send=%d, ts_base_ns=%llu, ts_delta_ns=%llu",
+		__entry->stream_id, __entry->seqnr, __entry->num_send, __entry->ts_base_ns, __entry->ts_delta_ns)
+	);
+
+
+TRACE_EVENT(tsn_rx_handler,
+
+	TP_PROTO(struct tsn_link *link,
+		const struct ethhdr *ethhdr,
+		u64 sid),
+
+	TP_ARGS(link, ethhdr, sid),
+
+	TP_STRUCT__entry(
+		__field(char *, name)
+		__field(u16, proto)
+		__field(u64, sid)
+		__field(u64, link_sid)
+		),
+	TP_fast_assign(
+		__entry->name  = link->nic->name;
+		__entry->proto = ethhdr->h_proto;
+		__entry->sid   = sid;
+		__entry->link_sid = link->stream_id;
+		),
+
+	TP_printk("name=%s, proto: 0x%04x, stream_id=%llu, link->sid=%llu",
+		__entry->name, ntohs(__entry->proto), __entry->sid, __entry->link_sid)
+	);
+
+TRACE_EVENT(tsn_du,
+
+	TP_PROTO(struct tsn_link *link,
+		size_t bytes),
+
+	TP_ARGS(link, bytes),
+
+	TP_STRUCT__entry(
+		__field(u64, link_sid)
+		__field(size_t, bytes)
+		),
+	TP_fast_assign(
+		__entry->link_sid = link->stream_id;
+		__entry->bytes = bytes;
+		),
+
+	TP_printk("stream_id=%llu,bytes=%zu",
+		__entry->link_sid, __entry->bytes)
+);
+
+TRACE_EVENT(tsn_set_buffer,
+
+	TP_PROTO(struct tsn_link *link, size_t bufsize),
+
+	TP_ARGS(link, bufsize),
+
+	TP_STRUCT__entry(
+		__field(u64,  stream_id)
+		__field(size_t, size)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->size = bufsize;
+		),
+
+	TP_printk("stream_id=%llu,buffer_size=%zu",
+		__entry->stream_id, __entry->size)
+
+	);
+
+TRACE_EVENT(tsn_free_buffer,
+
+	TP_PROTO(struct tsn_link *link),
+
+	TP_ARGS(link),
+
+	TP_STRUCT__entry(
+		__field(u64,  stream_id)
+		__field(size_t,	 bufsize)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->bufsize = link->buffer_size;
+		),
+
+	TP_printk("stream_id=%llu,size:%zd",
+		__entry->stream_id, __entry->bufsize)
+
+	);
+
+TRACE_EVENT(tsn_buffer_drain,
+
+	TP_PROTO(struct tsn_link *link, size_t used),
+
+	TP_ARGS(link, used),
+
+	TP_STRUCT__entry(
+		__field(u64, stream_id)
+		__field(size_t, used)
+	),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->used = used;
+	),
+
+	TP_printk("stream_id=%llu,used=%zu",
+		__entry->stream_id, __entry->used)
+
+);
+/* TODO: too long, need cleanup.
+ */
+TRACE_EVENT(tsn_pre_tx,
+
+	TP_PROTO(struct tsn_link *link, struct sk_buff *skb, size_t bytes),
+
+	TP_ARGS(link, skb, bytes),
+
+	TP_STRUCT__entry(
+		__field(u64, stream_id)
+		__field(u32, vlan_tag)
+		__field(size_t, bytes)
+		__field(size_t, data_len)
+		__field(unsigned int, headlen)
+		__field(u16, protocol)
+		__field(u16, prot_native)
+		__field(int, tx_idx)
+		__field(u16, mac_len)
+		__field(u16, hdr_len)
+		__field(u16, vlan_tci)
+		__field(u16, mac_header)
+		__field(unsigned int, tail)
+		__field(unsigned int, end)
+		__field(unsigned int, truesize)
+		),
+
+	TP_fast_assign(
+		__entry->stream_id = link->stream_id;
+		__entry->vlan_tag = (skb_vlan_tag_present(skb) ? skb_vlan_tag_get(skb) : 0);
+		__entry->bytes = bytes;
+		__entry->data_len = skb->data_len;
+		__entry->headlen = skb_headlen(skb);
+		__entry->protocol = ntohs(vlan_get_protocol(skb));
+		__entry->prot_native = ntohs(skb->protocol);
+		__entry->tx_idx = skb_get_queue_mapping(skb);
+
+		__entry->mac_len = skb->mac_len;
+		__entry->hdr_len = skb->hdr_len;
+		__entry->vlan_tci = skb->vlan_tci;
+		__entry->mac_header = skb->mac_header;
+		__entry->tail = (unsigned int)skb->tail;
+		__entry->end  = (unsigned int)skb->end;
+		__entry->truesize = skb->truesize;
+		),
+
+	TP_printk("stream_id=%llu,vlan_tag=0x%04x,data_size=%zd,data_len=%zd,headlen=%u,proto=0x%04x (0x%04x),tx_idx=%d,mac_len=%u,hdr_len=%u,vlan_tci=0x%02x,mac_header=0x%02x,tail=%u,end=%u,truesize=%u",
+		__entry->stream_id,
+		__entry->vlan_tag,
+		__entry->bytes,
+		__entry->data_len,
+		__entry->headlen,
+		__entry->protocol,
+		__entry->prot_native, __entry->tx_idx,
+		__entry->mac_len,
+		__entry->hdr_len,
+		__entry->vlan_tci,
+		__entry->mac_header,
+		__entry->tail,
+		__entry->end,
+		__entry->truesize)
+	);
+
+#endif	/* _TRACE_TSN_H || TRACE_HEADER_MULTI_READ */
+
+#include <trace/define_trace.h>
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1420298 — Re: [very-RFC 6/8] Add TSN event-tracing

FromSteven Rostedt <rostedt@goodmis.org>
Date2016-06-12 19:00 +0200
SubjectRe: [very-RFC 6/8] Add TSN event-tracing
Message-ID<rJgTT-2Fc-3@gated-at.bofh.it>
In reply to#1420100
On Sun, 12 Jun 2016 01:01:34 +0200
Henrik Austad <henrik@austad.us> wrote:

> From: Henrik Austad <haustad@cisco.com>
> 
> This needs refactoring and should be updated to use TRACE_CLASS, but for
> now it provides a fair debug-window into TSN.
> 
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Steven Rostedt <rostedt@goodmis.org> (maintainer:TRACING)
> Cc: Ingo Molnar <mingo@redhat.com> (maintainer:TRACING)
> Signed-off-by: Henrik Austad <haustad@cisco.com>
> ---
>  include/trace/events/tsn.h | 349 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 349 insertions(+)
>  create mode 100644 include/trace/events/tsn.h
> 
> diff --git a/include/trace/events/tsn.h b/include/trace/events/tsn.h
> new file mode 100644
> index 0000000..ac1f31b
> --- /dev/null
> +++ b/include/trace/events/tsn.h
> @@ -0,0 +1,349 @@
> +#undef TRACE_SYSTEM
> +#define TRACE_SYSTEM tsn
> +
> +#if !defined(_TRACE_TSN_H) || defined(TRACE_HEADER_MULTI_READ)
> +#define _TRACE_TSN_H
> +
> +#include <linux/tsn.h>
> +#include <linux/tracepoint.h>
> +
> +#include <linux/if_ether.h>
> +#include <linux/if_vlan.h>
> +/* #include <linux/skbuff.h> */
> +
> +/* FIXME: update to TRACE_CLASS to reduce overhead */

I'm curious to why I didn't do this now. A class would make less
duplication of typing too ;-)

> +TRACE_EVENT(tsn_buffer_write,
> +
> +	TP_PROTO(struct tsn_link *link,
> +		size_t bytes),
> +
> +	TP_ARGS(link, bytes),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, stream_id)
> +		__field(size_t, size)
> +		__field(size_t, bsize)
> +		__field(size_t, size_left)
> +		__field(void *, buffer)
> +		__field(void *, head)
> +		__field(void *, tail)
> +		__field(void *, end)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->size = bytes;
> +		__entry->bsize = link->used_buffer_size;
> +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;

Move this logic into the print statement, since you save head and tail.

> +		__entry->buffer = link->buffer;
> +		__entry->head = link->head;
> +		__entry->tail = link->tail;
> +		__entry->end = link->end;
> +		),
> +
> +	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
> +		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,

 __entry->stream_id, __entry->size, __entry->bsize,
 (__entry->head - __entry->tail) % __entry->bsize,

> +		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
> +
> +	);
> +
> +TRACE_EVENT(tsn_buffer_write_net,
> +
> +	TP_PROTO(struct tsn_link *link,
> +		size_t bytes),
> +
> +	TP_ARGS(link, bytes),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, stream_id)
> +		__field(size_t, size)
> +		__field(size_t, bsize)
> +		__field(size_t, size_left)
> +		__field(void *, buffer)
> +		__field(void *, head)
> +		__field(void *, tail)
> +		__field(void *, end)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->size = bytes;
> +		__entry->bsize = link->used_buffer_size;
> +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
> +		__entry->buffer = link->buffer;
> +		__entry->head = link->head;
> +		__entry->tail = link->tail;
> +		__entry->end = link->end;
> +		),
> +
> +	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
> +		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
> +		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
> +
> +	);
> +
> +
> +TRACE_EVENT(tsn_buffer_read,
> +
> +	TP_PROTO(struct tsn_link *link,
> +		size_t bytes),
> +
> +	TP_ARGS(link, bytes),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, stream_id)
> +		__field(size_t, size)
> +		__field(size_t, bsize)
> +		__field(size_t, size_left)
> +		__field(void *, buffer)
> +		__field(void *, head)
> +		__field(void *, tail)
> +		__field(void *, end)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->size = bytes;
> +		__entry->bsize = link->used_buffer_size;
> +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
> +		__entry->buffer = link->buffer;
> +		__entry->head = link->head;
> +		__entry->tail = link->tail;
> +		__entry->end = link->end;
> +		),
> +
> +	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
> +		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
> +		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
> +
> +	);
> +
> +TRACE_EVENT(tsn_refill,
> +
> +	TP_PROTO(struct tsn_link *link,
> +		size_t reported_avail),
> +
> +	TP_ARGS(link, reported_avail),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, stream_id)
> +		__field(size_t, bsize)
> +		__field(size_t, size_left)
> +		__field(size_t, reported_left)
> +		__field(size_t, low_water)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->bsize = link->used_buffer_size;
> +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;

As you don't save head and tail here, this logic needs to remain.

> +		__entry->reported_left = reported_avail;
> +		__entry->low_water = link->low_water_mark;
> +		),
> +
> +	TP_printk("stream_id=%llu, buffer=%zd, avail=%zd, reported=%zd, low=%zd",
> +		__entry->stream_id, __entry->bsize, __entry->size_left, __entry->reported_left, __entry->low_water)
> +	);
> +
> +TRACE_EVENT(tsn_send_batch,
> +
> +	TP_PROTO(struct tsn_link *link,
> +		int num_send,
> +		u64 ts_base_ns,
> +		u64 ts_delta_ns),
> +
> +	TP_ARGS(link, num_send, ts_base_ns, ts_delta_ns),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, stream_id)
> +		__field(int, seqnr)
> +		__field(int, num_send)
> +		__field(u64, ts_base_ns)
> +		__field(u64, ts_delta_ns)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id   = link->stream_id;
> +		__entry->seqnr	     = (int)link->last_seqnr;
> +		__entry->ts_base_ns  = ts_base_ns;
> +		__entry->ts_delta_ns = ts_delta_ns;
> +		__entry->num_send    = num_send;
> +		),
> +
> +	TP_printk("stream_id=%llu, seqnr=%d, num_send=%d, ts_base_ns=%llu, ts_delta_ns=%llu",
> +		__entry->stream_id, __entry->seqnr, __entry->num_send, __entry->ts_base_ns, __entry->ts_delta_ns)
> +	);
> +
> +
> +TRACE_EVENT(tsn_rx_handler,
> +
> +	TP_PROTO(struct tsn_link *link,
> +		const struct ethhdr *ethhdr,
> +		u64 sid),
> +
> +	TP_ARGS(link, ethhdr, sid),
> +
> +	TP_STRUCT__entry(
> +		__field(char *, name)
> +		__field(u16, proto)
> +		__field(u64, sid)
> +		__field(u64, link_sid)
> +		),
> +	TP_fast_assign(
> +		__entry->name  = link->nic->name;
> +		__entry->proto = ethhdr->h_proto;
> +		__entry->sid   = sid;
> +		__entry->link_sid = link->stream_id;
> +		),
> +
> +	TP_printk("name=%s, proto: 0x%04x, stream_id=%llu, link->sid=%llu",
> +		__entry->name, ntohs(__entry->proto), __entry->sid, __entry->link_sid)
> +	);
> +
> +TRACE_EVENT(tsn_du,
> +
> +	TP_PROTO(struct tsn_link *link,
> +		size_t bytes),
> +
> +	TP_ARGS(link, bytes),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, link_sid)
> +		__field(size_t, bytes)
> +		),
> +	TP_fast_assign(
> +		__entry->link_sid = link->stream_id;
> +		__entry->bytes = bytes;
> +		),
> +
> +	TP_printk("stream_id=%llu,bytes=%zu",
> +		__entry->link_sid, __entry->bytes)
> +);
> +
> +TRACE_EVENT(tsn_set_buffer,
> +
> +	TP_PROTO(struct tsn_link *link, size_t bufsize),
> +
> +	TP_ARGS(link, bufsize),
> +
> +	TP_STRUCT__entry(
> +		__field(u64,  stream_id)
> +		__field(size_t, size)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->size = bufsize;
> +		),
> +
> +	TP_printk("stream_id=%llu,buffer_size=%zu",
> +		__entry->stream_id, __entry->size)
> +
> +	);
> +
> +TRACE_EVENT(tsn_free_buffer,
> +
> +	TP_PROTO(struct tsn_link *link),
> +
> +	TP_ARGS(link),
> +
> +	TP_STRUCT__entry(
> +		__field(u64,  stream_id)
> +		__field(size_t,	 bufsize)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->bufsize = link->buffer_size;
> +		),
> +
> +	TP_printk("stream_id=%llu,size:%zd",
> +		__entry->stream_id, __entry->bufsize)
> +
> +	);
> +
> +TRACE_EVENT(tsn_buffer_drain,
> +
> +	TP_PROTO(struct tsn_link *link, size_t used),
> +
> +	TP_ARGS(link, used),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, stream_id)
> +		__field(size_t, used)
> +	),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->used = used;
> +	),
> +
> +	TP_printk("stream_id=%llu,used=%zu",
> +		__entry->stream_id, __entry->used)
> +
> +);
> +/* TODO: too long, need cleanup.
> + */
> +TRACE_EVENT(tsn_pre_tx,
> +
> +	TP_PROTO(struct tsn_link *link, struct sk_buff *skb, size_t bytes),
> +
> +	TP_ARGS(link, skb, bytes),
> +
> +	TP_STRUCT__entry(
> +		__field(u64, stream_id)
> +		__field(u32, vlan_tag)
> +		__field(size_t, bytes)
> +		__field(size_t, data_len)
> +		__field(unsigned int, headlen)
> +		__field(u16, protocol)
> +		__field(u16, prot_native)
> +		__field(int, tx_idx)
> +		__field(u16, mac_len)
> +		__field(u16, hdr_len)
> +		__field(u16, vlan_tci)
> +		__field(u16, mac_header)
> +		__field(unsigned int, tail)
> +		__field(unsigned int, end)
> +		__field(unsigned int, truesize)
> +		),
> +
> +	TP_fast_assign(
> +		__entry->stream_id = link->stream_id;
> +		__entry->vlan_tag = (skb_vlan_tag_present(skb) ? skb_vlan_tag_get(skb) : 0);
> +		__entry->bytes = bytes;
> +		__entry->data_len = skb->data_len;
> +		__entry->headlen = skb_headlen(skb);
> +		__entry->protocol = ntohs(vlan_get_protocol(skb));

Maybe it would be better to do the ntohs() in the TP_printk() as well.

> +		__entry->prot_native = ntohs(skb->protocol);

here too.

> +		__entry->tx_idx = skb_get_queue_mapping(skb);
> +
> +		__entry->mac_len = skb->mac_len;
> +		__entry->hdr_len = skb->hdr_len;
> +		__entry->vlan_tci = skb->vlan_tci;
> +		__entry->mac_header = skb->mac_header;
> +		__entry->tail = (unsigned int)skb->tail;
> +		__entry->end  = (unsigned int)skb->end;
> +		__entry->truesize = skb->truesize;
> +		),
> +
> +	TP_printk("stream_id=%llu,vlan_tag=0x%04x,data_size=%zd,data_len=%zd,headlen=%u,proto=0x%04x (0x%04x),tx_idx=%d,mac_len=%u,hdr_len=%u,vlan_tci=0x%02x,mac_header=0x%02x,tail=%u,end=%u,truesize=%u",
> +		__entry->stream_id,
> +		__entry->vlan_tag,
> +		__entry->bytes,
> +		__entry->data_len,
> +		__entry->headlen,
> +		__entry->protocol,
> +		__entry->prot_native, __entry->tx_idx,
> +		__entry->mac_len,
> +		__entry->hdr_len,
> +		__entry->vlan_tci,
> +		__entry->mac_header,

Is this an ether mac header? If so we support %M. But as it's defined
as only u16, it doesn't seem like it can be.

-- Steve

> +		__entry->tail,
> +		__entry->end,
> +		__entry->truesize)
> +	);
> +
> +#endif	/* _TRACE_TSN_H || TRACE_HEADER_MULTI_READ */
> +
> +#include <trace/define_trace.h>

[toc] | [prev] | [next] | [standalone]


#1420332 — Re: [very-RFC 6/8] Add TSN event-tracing

FromHenrik Austad <henrik@austad.us>
Date2016-06-12 23:30 +0200
SubjectRe: [very-RFC 6/8] Add TSN event-tracing
Message-ID<rJl7b-5ms-9@gated-at.bofh.it>
In reply to#1420298

[Multipart message — attachments visible in raw view] — view raw

On Sun, Jun 12, 2016 at 12:58:03PM -0400, Steven Rostedt wrote:
> On Sun, 12 Jun 2016 01:01:34 +0200
> Henrik Austad <henrik@austad.us> wrote:
> 
> > From: Henrik Austad <haustad@cisco.com>
> > 
> > This needs refactoring and should be updated to use TRACE_CLASS, but for
> > now it provides a fair debug-window into TSN.
> > 
> > Cc: "David S. Miller" <davem@davemloft.net>
> > Cc: Steven Rostedt <rostedt@goodmis.org> (maintainer:TRACING)
> > Cc: Ingo Molnar <mingo@redhat.com> (maintainer:TRACING)
> > Signed-off-by: Henrik Austad <haustad@cisco.com>
> > ---
> >  include/trace/events/tsn.h | 349 +++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 349 insertions(+)
> >  create mode 100644 include/trace/events/tsn.h
> > 
> > diff --git a/include/trace/events/tsn.h b/include/trace/events/tsn.h
> > new file mode 100644
> > index 0000000..ac1f31b
> > --- /dev/null
> > +++ b/include/trace/events/tsn.h
> > @@ -0,0 +1,349 @@
> > +#undef TRACE_SYSTEM
> > +#define TRACE_SYSTEM tsn
> > +
> > +#if !defined(_TRACE_TSN_H) || defined(TRACE_HEADER_MULTI_READ)
> > +#define _TRACE_TSN_H
> > +
> > +#include <linux/tsn.h>
> > +#include <linux/tracepoint.h>
> > +
> > +#include <linux/if_ether.h>
> > +#include <linux/if_vlan.h>
> > +/* #include <linux/skbuff.h> */
> > +
> > +/* FIXME: update to TRACE_CLASS to reduce overhead */
> 
> I'm curious to why I didn't do this now. A class would make less
> duplication of typing too ;-)

Yeah, I found this in a really great article written by some tracing-dude, 
I hear he talks really, really fast!

https://lwn.net/Articles/381064/

> > +TRACE_EVENT(tsn_buffer_write,
> > +
> > +	TP_PROTO(struct tsn_link *link,
> > +		size_t bytes),
> > +
> > +	TP_ARGS(link, bytes),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, stream_id)
> > +		__field(size_t, size)
> > +		__field(size_t, bsize)
> > +		__field(size_t, size_left)
> > +		__field(void *, buffer)
> > +		__field(void *, head)
> > +		__field(void *, tail)
> > +		__field(void *, end)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->size = bytes;
> > +		__entry->bsize = link->used_buffer_size;
> > +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
> 
> Move this logic into the print statement, since you save head and tail.

Ok, any particular reason?

> > +		__entry->buffer = link->buffer;
> > +		__entry->head = link->head;
> > +		__entry->tail = link->tail;
> > +		__entry->end = link->end;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
> > +		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
> 
>  __entry->stream_id, __entry->size, __entry->bsize,
>  (__entry->head - __entry->tail) % __entry->bsize,
> 

Ok, so is this about saving space by dropping one intermediate value, or is 
it some other point I'm missing here?

> > +		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
> > +
> > +	);
> > +
> > +TRACE_EVENT(tsn_buffer_write_net,
> > +
> > +	TP_PROTO(struct tsn_link *link,
> > +		size_t bytes),
> > +
> > +	TP_ARGS(link, bytes),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, stream_id)
> > +		__field(size_t, size)
> > +		__field(size_t, bsize)
> > +		__field(size_t, size_left)
> > +		__field(void *, buffer)
> > +		__field(void *, head)
> > +		__field(void *, tail)
> > +		__field(void *, end)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->size = bytes;
> > +		__entry->bsize = link->used_buffer_size;
> > +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
> > +		__entry->buffer = link->buffer;
> > +		__entry->head = link->head;
> > +		__entry->tail = link->tail;
> > +		__entry->end = link->end;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
> > +		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
> > +		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
> > +
> > +	);
> > +
> > +
> > +TRACE_EVENT(tsn_buffer_read,
> > +
> > +	TP_PROTO(struct tsn_link *link,
> > +		size_t bytes),
> > +
> > +	TP_ARGS(link, bytes),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, stream_id)
> > +		__field(size_t, size)
> > +		__field(size_t, bsize)
> > +		__field(size_t, size_left)
> > +		__field(void *, buffer)
> > +		__field(void *, head)
> > +		__field(void *, tail)
> > +		__field(void *, end)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->size = bytes;
> > +		__entry->bsize = link->used_buffer_size;
> > +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
> > +		__entry->buffer = link->buffer;
> > +		__entry->head = link->head;
> > +		__entry->tail = link->tail;
> > +		__entry->end = link->end;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
> > +		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,
> > +		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
> > +
> > +	);
> > +
> > +TRACE_EVENT(tsn_refill,
> > +
> > +	TP_PROTO(struct tsn_link *link,
> > +		size_t reported_avail),
> > +
> > +	TP_ARGS(link, reported_avail),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, stream_id)
> > +		__field(size_t, bsize)
> > +		__field(size_t, size_left)
> > +		__field(size_t, reported_left)
> > +		__field(size_t, low_water)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->bsize = link->used_buffer_size;
> > +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;
> 
> As you don't save head and tail here, this logic needs to remain.
> 
> > +		__entry->reported_left = reported_avail;
> > +		__entry->low_water = link->low_water_mark;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu, buffer=%zd, avail=%zd, reported=%zd, low=%zd",
> > +		__entry->stream_id, __entry->bsize, __entry->size_left, __entry->reported_left, __entry->low_water)
> > +	);
> > +
> > +TRACE_EVENT(tsn_send_batch,
> > +
> > +	TP_PROTO(struct tsn_link *link,
> > +		int num_send,
> > +		u64 ts_base_ns,
> > +		u64 ts_delta_ns),
> > +
> > +	TP_ARGS(link, num_send, ts_base_ns, ts_delta_ns),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, stream_id)
> > +		__field(int, seqnr)
> > +		__field(int, num_send)
> > +		__field(u64, ts_base_ns)
> > +		__field(u64, ts_delta_ns)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id   = link->stream_id;
> > +		__entry->seqnr	     = (int)link->last_seqnr;
> > +		__entry->ts_base_ns  = ts_base_ns;
> > +		__entry->ts_delta_ns = ts_delta_ns;
> > +		__entry->num_send    = num_send;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu, seqnr=%d, num_send=%d, ts_base_ns=%llu, ts_delta_ns=%llu",
> > +		__entry->stream_id, __entry->seqnr, __entry->num_send, __entry->ts_base_ns, __entry->ts_delta_ns)
> > +	);
> > +
> > +
> > +TRACE_EVENT(tsn_rx_handler,
> > +
> > +	TP_PROTO(struct tsn_link *link,
> > +		const struct ethhdr *ethhdr,
> > +		u64 sid),
> > +
> > +	TP_ARGS(link, ethhdr, sid),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(char *, name)
> > +		__field(u16, proto)
> > +		__field(u64, sid)
> > +		__field(u64, link_sid)
> > +		),
> > +	TP_fast_assign(
> > +		__entry->name  = link->nic->name;
> > +		__entry->proto = ethhdr->h_proto;
> > +		__entry->sid   = sid;
> > +		__entry->link_sid = link->stream_id;
> > +		),
> > +
> > +	TP_printk("name=%s, proto: 0x%04x, stream_id=%llu, link->sid=%llu",
> > +		__entry->name, ntohs(__entry->proto), __entry->sid, __entry->link_sid)
> > +	);
> > +
> > +TRACE_EVENT(tsn_du,
> > +
> > +	TP_PROTO(struct tsn_link *link,
> > +		size_t bytes),
> > +
> > +	TP_ARGS(link, bytes),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, link_sid)
> > +		__field(size_t, bytes)
> > +		),
> > +	TP_fast_assign(
> > +		__entry->link_sid = link->stream_id;
> > +		__entry->bytes = bytes;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu,bytes=%zu",
> > +		__entry->link_sid, __entry->bytes)
> > +);
> > +
> > +TRACE_EVENT(tsn_set_buffer,
> > +
> > +	TP_PROTO(struct tsn_link *link, size_t bufsize),
> > +
> > +	TP_ARGS(link, bufsize),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64,  stream_id)
> > +		__field(size_t, size)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->size = bufsize;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu,buffer_size=%zu",
> > +		__entry->stream_id, __entry->size)
> > +
> > +	);
> > +
> > +TRACE_EVENT(tsn_free_buffer,
> > +
> > +	TP_PROTO(struct tsn_link *link),
> > +
> > +	TP_ARGS(link),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64,  stream_id)
> > +		__field(size_t,	 bufsize)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->bufsize = link->buffer_size;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu,size:%zd",
> > +		__entry->stream_id, __entry->bufsize)
> > +
> > +	);
> > +
> > +TRACE_EVENT(tsn_buffer_drain,
> > +
> > +	TP_PROTO(struct tsn_link *link, size_t used),
> > +
> > +	TP_ARGS(link, used),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, stream_id)
> > +		__field(size_t, used)
> > +	),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->used = used;
> > +	),
> > +
> > +	TP_printk("stream_id=%llu,used=%zu",
> > +		__entry->stream_id, __entry->used)
> > +
> > +);
> > +/* TODO: too long, need cleanup.
> > + */
> > +TRACE_EVENT(tsn_pre_tx,
> > +
> > +	TP_PROTO(struct tsn_link *link, struct sk_buff *skb, size_t bytes),
> > +
> > +	TP_ARGS(link, skb, bytes),
> > +
> > +	TP_STRUCT__entry(
> > +		__field(u64, stream_id)
> > +		__field(u32, vlan_tag)
> > +		__field(size_t, bytes)
> > +		__field(size_t, data_len)
> > +		__field(unsigned int, headlen)
> > +		__field(u16, protocol)
> > +		__field(u16, prot_native)
> > +		__field(int, tx_idx)
> > +		__field(u16, mac_len)
> > +		__field(u16, hdr_len)
> > +		__field(u16, vlan_tci)
> > +		__field(u16, mac_header)
> > +		__field(unsigned int, tail)
> > +		__field(unsigned int, end)
> > +		__field(unsigned int, truesize)
> > +		),
> > +
> > +	TP_fast_assign(
> > +		__entry->stream_id = link->stream_id;
> > +		__entry->vlan_tag = (skb_vlan_tag_present(skb) ? skb_vlan_tag_get(skb) : 0);
> > +		__entry->bytes = bytes;
> > +		__entry->data_len = skb->data_len;
> > +		__entry->headlen = skb_headlen(skb);
> > +		__entry->protocol = ntohs(vlan_get_protocol(skb));
> 
> Maybe it would be better to do the ntohs() in the TP_printk() as well.
> 
> > +		__entry->prot_native = ntohs(skb->protocol);
> 
> here too.
> 
> > +		__entry->tx_idx = skb_get_queue_mapping(skb);
> > +
> > +		__entry->mac_len = skb->mac_len;
> > +		__entry->hdr_len = skb->hdr_len;
> > +		__entry->vlan_tci = skb->vlan_tci;
> > +		__entry->mac_header = skb->mac_header;
> > +		__entry->tail = (unsigned int)skb->tail;
> > +		__entry->end  = (unsigned int)skb->end;
> > +		__entry->truesize = skb->truesize;
> > +		),
> > +
> > +	TP_printk("stream_id=%llu,vlan_tag=0x%04x,data_size=%zd,data_len=%zd,headlen=%u,proto=0x%04x (0x%04x),tx_idx=%d,mac_len=%u,hdr_len=%u,vlan_tci=0x%02x,mac_header=0x%02x,tail=%u,end=%u,truesize=%u",
> > +		__entry->stream_id,
> > +		__entry->vlan_tag,
> > +		__entry->bytes,
> > +		__entry->data_len,
> > +		__entry->headlen,
> > +		__entry->protocol,
> > +		__entry->prot_native, __entry->tx_idx,
> > +		__entry->mac_len,
> > +		__entry->hdr_len,
> > +		__entry->vlan_tci,
> > +		__entry->mac_header,
> 
> Is this an ether mac header? If so we support %M. But as it's defined
> as only u16, it doesn't seem like it can be.

Actually, looking at the output, I'm not quite sure what it is that I 
wanted to grab with that, the skb->mac_header should give an offset into 
the header-area of skb, so it should be a constant offset from skb->head 
(that is an actual pointer).

I *think* I wanted to make sure I updated things correctly so that the 
offset didn't suddenly change, but the fact that I'm no longer sure 
indicates that I should just drop that one. That whole printout is too long 
anyway..

Thanks for pointing a finger at this!


I'm still a bit stymied as to why logic should be in TP_printk() and not 
TP_fast_assign(). Not that I really have any preferences either way, just 
curious.



-- 
Henrik Austad

[toc] | [prev] | [next] | [standalone]


#1420411 — Re: [very-RFC 6/8] Add TSN event-tracing

FromSteven Rostedt <rostedt@goodmis.org>
Date2016-06-13 04:30 +0200
SubjectRe: [very-RFC 6/8] Add TSN event-tracing
Message-ID<rJpNv-4T-1@gated-at.bofh.it>
In reply to#1420332
On Sun, 12 Jun 2016 23:25:10 +0200
Henrik Austad <henrik@austad.us> wrote:

> > > +#include <linux/if_ether.h>
> > > +#include <linux/if_vlan.h>
> > > +/* #include <linux/skbuff.h> */
> > > +
> > > +/* FIXME: update to TRACE_CLASS to reduce overhead */  
> > 
> > I'm curious to why I didn't do this now. A class would make less
> > duplication of typing too ;-)  
> 
> Yeah, I found this in a really great article written by some tracing-dude, 
> I hear he talks really, really fast!

I plead the 5th!

> 
> https://lwn.net/Articles/381064/
> 
> > > +TRACE_EVENT(tsn_buffer_write,
> > > +
> > > +	TP_PROTO(struct tsn_link *link,
> > > +		size_t bytes),
> > > +
> > > +	TP_ARGS(link, bytes),
> > > +
> > > +	TP_STRUCT__entry(
> > > +		__field(u64, stream_id)
> > > +		__field(size_t, size)
> > > +		__field(size_t, bsize)
> > > +		__field(size_t, size_left)
> > > +		__field(void *, buffer)
> > > +		__field(void *, head)
> > > +		__field(void *, tail)
> > > +		__field(void *, end)
> > > +		),
> > > +
> > > +	TP_fast_assign(
> > > +		__entry->stream_id = link->stream_id;
> > > +		__entry->size = bytes;
> > > +		__entry->bsize = link->used_buffer_size;
> > > +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;  
> > 
> > Move this logic into the print statement, since you save head and tail.  
> 
> Ok, any particular reason?

Because it removes calculations during the trace. The calculations done
in TP_printk() are done at the time of reading the trace, and
calculations done in TP_fast_assign() are done during the recording and
hence adding more overhead to the trace itself.


> 
> > > +		__entry->buffer = link->buffer;
> > > +		__entry->head = link->head;
> > > +		__entry->tail = link->tail;
> > > +		__entry->end = link->end;
> > > +		),
> > > +
> > > +	TP_printk("stream_id=%llu, copy=%zd, buffer: %zd, avail=%zd, [buffer=%p, head=%p, tail=%p, end=%p]",
> > > +		__entry->stream_id, __entry->size, __entry->bsize, __entry->size_left,  
> > 
> >  __entry->stream_id, __entry->size, __entry->bsize,
> >  (__entry->head - __entry->tail) % __entry->bsize,
> >   
> 
> Ok, so is this about saving space by dropping one intermediate value, or is 
> it some other point I'm missing here?

Nope, just moving the overhead from the recording of the trace to the
reading of the trace.

> 
> > > +		__entry->buffer,    __entry->head, __entry->tail,  __entry->end)
> > > +
> > > +	);
> > > +


> > > +
> > > +	TP_fast_assign(
> > > +		__entry->stream_id = link->stream_id;
> > > +		__entry->vlan_tag = (skb_vlan_tag_present(skb) ? skb_vlan_tag_get(skb) : 0);
> > > +		__entry->bytes = bytes;
> > > +		__entry->data_len = skb->data_len;
> > > +		__entry->headlen = skb_headlen(skb);
> > > +		__entry->protocol = ntohs(vlan_get_protocol(skb));  
> > 
> > Maybe it would be better to do the ntohs() in the TP_printk() as well.
> >   
> > > +		__entry->prot_native = ntohs(skb->protocol);  
> > 
> > here too.
> >   
> > > +		__entry->tx_idx = skb_get_queue_mapping(skb);
> > > +
> > > +		__entry->mac_len = skb->mac_len;
> > > +		__entry->hdr_len = skb->hdr_len;
> > > +		__entry->vlan_tci = skb->vlan_tci;
> > > +		__entry->mac_header = skb->mac_header;
> > > +		__entry->tail = (unsigned int)skb->tail;
> > > +		__entry->end  = (unsigned int)skb->end;
> > > +		__entry->truesize = skb->truesize;
> > > +		),
> > > +
> > > +	TP_printk("stream_id=%llu,vlan_tag=0x%04x,data_size=%zd,data_len=%zd,headlen=%u,proto=0x%04x (0x%04x),tx_idx=%d,mac_len=%u,hdr_len=%u,vlan_tci=0x%02x,mac_header=0x%02x,tail=%u,end=%u,truesize=%u",
> > > +		__entry->stream_id,
> > > +		__entry->vlan_tag,
> > > +		__entry->bytes,
> > > +		__entry->data_len,
> > > +		__entry->headlen,
> > > +		__entry->protocol,
> > > +		__entry->prot_native, __entry->tx_idx,
> > > +		__entry->mac_len,
> > > +		__entry->hdr_len,
> > > +		__entry->vlan_tci,
> > > +		__entry->mac_header,  
> > 
> > Is this an ether mac header? If so we support %M. But as it's defined
> > as only u16, it doesn't seem like it can be.  
> 
> Actually, looking at the output, I'm not quite sure what it is that I 
> wanted to grab with that, the skb->mac_header should give an offset into 
> the header-area of skb, so it should be a constant offset from skb->head 
> (that is an actual pointer).
> 
> I *think* I wanted to make sure I updated things correctly so that the 
> offset didn't suddenly change, but the fact that I'm no longer sure 
> indicates that I should just drop that one. That whole printout is too long 
> anyway..
> 
> Thanks for pointing a finger at this!
> 
> 
> I'm still a bit stymied as to why logic should be in TP_printk() and not 
> TP_fast_assign(). Not that I really have any preferences either way, just 
> curious.

As said above, it's simply just trying to make tracing have less of an
effect on what is being traced. The more you can do in the post
transactions the faster the trace becomes and less invasive the trace
is on the system performance.

-- Steve

[toc] | [prev] | [next] | [standalone]


#1420515 — Re: [very-RFC 6/8] Add TSN event-tracing

FromHenrik Austad <henrik@austad.us>
Date2016-06-13 09:30 +0200
SubjectRe: [very-RFC 6/8] Add TSN event-tracing
Message-ID<rJutQ-355-27@gated-at.bofh.it>
In reply to#1420411

[Multipart message — attachments visible in raw view] — view raw

On Sun, Jun 12, 2016 at 10:22:01PM -0400, Steven Rostedt wrote:
> On Sun, 12 Jun 2016 23:25:10 +0200
> Henrik Austad <henrik@austad.us> wrote:
> 
> > > > +#include <linux/if_ether.h>
> > > > +#include <linux/if_vlan.h>
> > > > +/* #include <linux/skbuff.h> */
> > > > +
> > > > +/* FIXME: update to TRACE_CLASS to reduce overhead */  
> > > 
> > > I'm curious to why I didn't do this now. A class would make less
> > > duplication of typing too ;-)  
> > 
> > Yeah, I found this in a really great article written by some tracing-dude, 
> > I hear he talks really, really fast!
> 
> I plead the 5th!
> 
> > 
> > https://lwn.net/Articles/381064/
> > 
> > > > +TRACE_EVENT(tsn_buffer_write,
> > > > +
> > > > +	TP_PROTO(struct tsn_link *link,
> > > > +		size_t bytes),
> > > > +
> > > > +	TP_ARGS(link, bytes),
> > > > +
> > > > +	TP_STRUCT__entry(
> > > > +		__field(u64, stream_id)
> > > > +		__field(size_t, size)
> > > > +		__field(size_t, bsize)
> > > > +		__field(size_t, size_left)
> > > > +		__field(void *, buffer)
> > > > +		__field(void *, head)
> > > > +		__field(void *, tail)
> > > > +		__field(void *, end)
> > > > +		),
> > > > +
> > > > +	TP_fast_assign(
> > > > +		__entry->stream_id = link->stream_id;
> > > > +		__entry->size = bytes;
> > > > +		__entry->bsize = link->used_buffer_size;
> > > > +		__entry->size_left = (link->head - link->tail) % link->used_buffer_size;  
> > > 
> > > Move this logic into the print statement, since you save head and tail.  
> > 
> > Ok, any particular reason?
> 
> Because it removes calculations during the trace. The calculations done
> in TP_printk() are done at the time of reading the trace, and
> calculations done in TP_fast_assign() are done during the recording and
> hence adding more overhead to the trace itself.

Aha! that makes sense, thanks!
(/me goes and updates the tracing-part)

-Henrik

[toc] | [prev] | [next] | [standalone]


#1420101 — [very-RFC 8/8] MAINTAINERS: add TSN/AVB-entries

FromHenrik Austad <henrik@austad.us>
Date2016-06-12 01:10 +0200
Subject[very-RFC 8/8] MAINTAINERS: add TSN/AVB-entries
Message-ID<rJ0cq-QL-23@gated-at.bofh.it>
In reply to#1420097
From: Henrik Austad <haustad@cisco.com>

Not sure how relevant this is other than making a point about
maintaining it.

Signed-off-by: Henrik Austad <haustad@cisco.com>
---
 MAINTAINERS | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ed42cb6..ef5d926 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11634,6 +11634,20 @@ T:	git git://linuxtv.org/anttip/media_tree.git
 S:	Maintained
 F:	drivers/media/tuners/tua9001*
 
+TSN CORE DRIVER
+M:	Henrik Austad <haustad@cisco.com>
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	drivers/net/tsn/
+F:	include/linux/tsn.h
+F:	include/trace/events/tsn.h
+
+TSN_AVB_DRIVER
+M:	Henrik Austad <haustad@cisco.com>
+L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:	Supported
+F:	drivers/media/avb/
+
 TULIP NETWORK DRIVERS
 L:	netdev@vger.kernel.org
 L:	linux-parisc@vger.kernel.org
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1420742

FromRichard Cochran <richardcochran@gmail.com>
Date2016-06-13 13:50 +0200
Message-ID<rJyxr-5JN-5@gated-at.bofh.it>
In reply to#1420097
Henrik,

On Sun, Jun 12, 2016 at 01:01:28AM +0200, Henrik Austad wrote:
> There are at least one AVB-driver (the AV-part of TSN) in the kernel
> already,

Which driver is that?

> however this driver aims to solve a wider scope as TSN can do
> much more than just audio. A very basic ALSA-driver is added to the end
> that allows you to play music between 2 machines using aplay in one end
> and arecord | aplay on the other (some fiddling required) We have plans
> for doing the same for v4l2 eventually (but there are other fishes to
> fry first). The same goes for a TSN_SOCK type approach as well.

Please, no new socket type for this.
 
> What remains
> - tie to (g)PTP properly, currently using ktime_get() for presentation
>   time
> - get time from shim into TSN and vice versa

... and a whole lot more, see below.

> - let shim create/manage buffer

(BTW, shim is a terrible name for that.)

[sigh]

People have been asking me about TSN and Linux, and we've made some
thoughts about it.  The interest is there, and so I am glad to see
discussion on this topic.

Having said that, your series does not even begin to address the real
issues.  I did not review the patches too carefully (because the
important stuff is missing), but surely configfs is the wrong
interface for this.  In the end, we will be able to support TSN using
the existing networking and audio interfaces, adding appropriate
extensions.

Your patch features a buffer shared by networking and audio.  This
isn't strictly necessary for TSN, and it may be harmful.  The
Listeners are supposed to calculate the delay from frame reception to
the DA conversion.  They can easily include the time needed for a user
space program to parse the frames, copy (and combine/convert) the
data, and re-start the audio transfer.  A flexible TSN implementation
will leave all of the format and encoding task to the userland.  After
all, TSN will some include more that just AV data, as you know.

Lets take a look at the big picture.  One aspect of TSN is already
fully supported, namely the gPTP.  Using the linuxptp user stack and a
modern kernel, you have a complete 802.1AS-2011 solution.

Here is what is missing to support audio TSN:

* User Space

1. A proper userland stack for AVDECC, MAAP, FQTSS, and so on.  The
   OpenAVB project does not offer much beyond simple examples.

2. A user space audio application that puts it all together, making
   use of the services in #1, the linuxptp gPTP service, the ALSA
   services, and the network connections.  This program will have all
   the knowledge about packet formats, AV encodings, and the local HW
   capabilities.  This program cannot yet be written, as we still need
   some kernel work in the audio and networking subsystems.

* Kernel Space

1. Providing frames with a future transmit time.  For normal sockets,
   this can be in the CMESG data.  For mmap'ed buffers, we will need a
   new format.  (I think Arnd is working on a new layout.)

2. Time based qdisc for transmitted frames.  For MACs that support
   this (like the i210), we only have to place the frame into the
   correct queue.  For normal HW, we want to be able to reserve a time
   window in which non-TSN frames are blocked.  This is some work, but
   in the end it should be a generic solution that not only works
   "perfectly" with TSN HW but also provides best effort service using
   any NIC.

3. ALSA support for tunable AD/DA clocks.  The rate of the Listener's
   DA clock must match that of the Talker and the other Listeners.
   Either you adjust it in HW using a VCO or similar, or you do
   adaptive sample rate conversion in the application. (And that is
   another reason for *not* having a shared kernel buffer.)  For the
   Talker, either you adjust the AD clock to match the PTP time, or
   you measure the frequency offset.

4. ALSA support for time triggered playback.  The patch series
   completely ignore the critical issue of media clock recovery.  The
   Listener must buffer the stream in order to play it exactly at a
   specified time.  It cannot simply send the stream ASAP to the audio
   HW, because some other Listener might need longer.  AFAICT, there
   is nothing in ALSA that allows you to say, sample X should be
   played at time Y.

These are some ideas about implementing TSN.  Maybe some of it is
wrong (especially about ALSA), but we definitely need a proper design
to get the kernel parts right.  There is plenty of work to do, but we
really don't need some hacky, in-kernel buffer with hard coded audio
formats.

Thanks,
Richard

[toc] | [prev] | [next] | [standalone]


#1420808

FromHenrik Austad <henrik@austad.us>
Date2016-06-13 15:10 +0200
Message-ID<rJzMR-6In-1@gated-at.bofh.it>
In reply to#1420742

[Multipart message — attachments visible in raw view] — view raw

On Mon, Jun 13, 2016 at 01:47:13PM +0200, Richard Cochran wrote:
> Henrik,

Hi Richard,

> On Sun, Jun 12, 2016 at 01:01:28AM +0200, Henrik Austad wrote:
> > There are at least one AVB-driver (the AV-part of TSN) in the kernel
> > already,
> 
> Which driver is that?

drivers/net/ethernet/renesas/

> > however this driver aims to solve a wider scope as TSN can do
> > much more than just audio. A very basic ALSA-driver is added to the end
> > that allows you to play music between 2 machines using aplay in one end
> > and arecord | aplay on the other (some fiddling required) We have plans
> > for doing the same for v4l2 eventually (but there are other fishes to
> > fry first). The same goes for a TSN_SOCK type approach as well.
> 
> Please, no new socket type for this.

The idea was to create a tsn-driver and then allow userspace to use it 
either for media or for whatever else they'd like - and then a socket made 
sense. Or so I thought :)

What is the rationale for no new sockets? To avoid cluttering? or do 
sockets have a drawback I'm not aware of?

> > What remains
> > - tie to (g)PTP properly, currently using ktime_get() for presentation
> >   time
> > - get time from shim into TSN and vice versa
> 
> ... and a whole lot more, see below.
> 
> > - let shim create/manage buffer
> 
> (BTW, shim is a terrible name for that.)

So something thin that is placed between to subystems should rather be 
called.. flimsy? The point of the name was to indicate that it glued 2 
pieces together. If you have a better suggestion, I'm all ears.

> [sigh]
> 
> People have been asking me about TSN and Linux, and we've made some
> thoughts about it.  The interest is there, and so I am glad to see
> discussion on this topic.

I'm not aware of any such discussions, could you point me to where TSN has 
been discussed, it would be nice to see other peoples thought on the matter 
(which was one of the ideas behind this series in the first place)

> Having said that, your series does not even begin to address the real
> issues. 

Well, in all honesty, I did say so :) It is marked as "very-RFC", and not 
for being included in the kernel as-is. I also made a short list of the 
most crucial bits missing.

I know there are real issues, but solving these won't matter if you don't 
have anything useful to do with it. I decided to start by adding a thin 
ALSA-driver and then continue to work with the kernel infrastructure. 
Having something that works-ish makes it a lot easier to test and get 
others interested in, especially when you are not deeply involved in a 
subsystem.

At one point you get to where you need input from other more intimate with 
then inner workings of the different subsystems to see how things should be 
created without making too much of a mess. So where we are :)

My primary motivation was to
a) gather feedback (which you have provided, and for which I am very 
   grateful)
b) get the discussion going on how/if TSN should be added to the kernel

> I did not review the patches too carefully (because the
> important stuff is missing), but surely configfs is the wrong
> interface for this. 

Why is configfs wrong?

Unless you want to implement discovery and enumeration and srp-negotiation 
in the kernel, you need userspace to handle this. Once userspace has done 
all that (found priority-codes, streamIDs, vlanIDs and all the required 
bits), then userspace can create a new link. For that I find ConfigFS to be 
quite useful and up to the task.

In my opinion, it also makes for a much tidier and saner interface than 
some obscure dark-magic ioctl()

> In the end, we will be able to support TSN using
> the existing networking and audio interfaces, adding appropriate
> extensions.

I surely hope so, but as I'm not deep into the networking part of the 
kernel finding those appropriate extensions is hard - which is why we 
started writing a standalone module-

> Your patch features a buffer shared by networking and audio.  This
> isn't strictly necessary for TSN, and it may be harmful. 

At one stage, data has to flow in/out of the network, and whoever's using 
TSN probably need to store data somewhere as well, so you need some form of 
buffering at one place in the path the data flows through.

That being said, one of the bits on my plate is to remove the 
"TSN-hosted-buffer" and let TSN read/write data via the shim_ops. What the 
best set of functions where are, remain to be seen, but it should provide a 
way to move data from either a single frame or a "few frames" to the shime 
(err.. <descriptive word for a thin layer slapped between 2 largers 
subsystems in the kernel> ;)

> The
> Listeners are supposed to calculate the delay from frame reception to
> the DA conversion.  They can easily include the time needed for a user
> space program to parse the frames, copy (and combine/convert) the
> data, and re-start the audio transfer.  A flexible TSN implementation
> will leave all of the format and encoding task to the userland.  After
> all, TSN will some include more that just AV data, as you know.

Yes, or a ALSA-driver capable of same task. But yes, you need a way to 
propagate the presentation-time (and maybe a timestamp for when a frame was 
received) to the final destination of the samples. As far as I've been able 
to tell, this is not possible in the kernel at the moment.

> Lets take a look at the big picture.  One aspect of TSN is already
> fully supported, namely the gPTP.  Using the linuxptp user stack and a
> modern kernel, you have a complete 802.1AS-2011 solution.

Yes, I thought so, which is also why I have put that to the side and why 
I'm using ktime_get() for timestamps at the moment. There's also the issue 
of hooking the time into ALSA/V4L2

> Here is what is missing to support audio TSN:
> 
> * User Space
> 
> 1. A proper userland stack for AVDECC, MAAP, FQTSS, and so on.  The
>    OpenAVB project does not offer much beyond simple examples.

yes, I've noticed. I've refered to an imaginary 'tsnctl' in the code, which 
is supposed to be a "userspace catch-all for TSN-housekeeping". You 
probably need a tsnd or similar as well to send keepalive frames etc.

> 2. A user space audio application that puts it all together, making
>    use of the services in #1, the linuxptp gPTP service, the ALSA
>    services, and the network connections.  This program will have all
>    the knowledge about packet formats, AV encodings, and the local HW
>    capabilities.  This program cannot yet be written, as we still need
>    some kernel work in the audio and networking subsystems.

Why? the whole point should be to make it as easy for userspace as 
possible. If you need to tailor each individual media-appliation to use 
AVB, it is not going to be very useful outside pro-Audio. Sure, there will 
be challenges, but one key element here should be to *not* require 
upgrading every single media application.

Then, back to the suggestion of adding a TSN_SOCKET (which you didn't like, 
but can we agree on a term "raw interface to TSN", and mode of transport 
can be defined later? ), was to let those applications that are TSN-aware 
to do what they need to do, whether it is controlling robots or media 
streams.


> * Kernel Space
> 
> 1. Providing frames with a future transmit time.  For normal sockets,
>    this can be in the CMESG data.  For mmap'ed buffers, we will need a
>    new format.  (I think Arnd is working on a new layout.)

Ah, I was unaware of this, both CMESG and mmap buffers.

What is the accuracy of deferred transmit? If you have a class A stream, 
you push out a new frame every 125 us, you may end up with 
accuracy-constraints lower than that if you want to be able to state "send 
frame X at time Y".

> 2. Time based qdisc for transmitted frames.  For MACs that support
>    this (like the i210), we only have to place the frame into the
>    correct queue.  For normal HW, we want to be able to reserve a time
>    window in which non-TSN frames are blocked.  This is some work, but
>    in the end it should be a generic solution that not only works
>    "perfectly" with TSN HW but also provides best effort service using
>    any NIC.

Yes, that would be very nice, and something like that is the ultimate goal 
of the netdev_ops I added, even though it is a far way away from that now.

> 3. ALSA support for tunable AD/DA clocks.  The rate of the Listener's
>    DA clock must match that of the Talker and the other Listeners.
>    Either you adjust it in HW using a VCO or similar, or you do
>    adaptive sample rate conversion in the application. (And that is
>    another reason for *not* having a shared kernel buffer.)  For the
>    Talker, either you adjust the AD clock to match the PTP time, or
>    you measure the frequency offset.

Yes, this is something missing that must be adressed. And yes, I know 
sharing a buffer the way the alsa-shim is currently doing is bad.

> 4. ALSA support for time triggered playback.  The patch series
>    completely ignore the critical issue of media clock recovery.  The
>    Listener must buffer the stream in order to play it exactly at a
>    specified time.  It cannot simply send the stream ASAP to the audio
>    HW, because some other Listener might need longer.  AFAICT, there
>    is nothing in ALSA that allows you to say, sample X should be
>    played at time Y.
> 
> These are some ideas about implementing TSN.  Maybe some of it is
> wrong (especially about ALSA), but we definitely need a proper design
> to get the kernel parts right.  There is plenty of work to do, but we
> really don't need some hacky, in-kernel buffer with hard coded audio
> formats.

Well, the hard-coded audio format you refer to is placed with the avb_alsa 
shim, avtp_du is part of the actual TSN-header so that is not audio-only. 
And yes, it must be separated.

Apart from requiring media-applications to know about AVB, I don't think 
we really disagree on anything. As I said, the main motivation for 
submitting this now was to kick off a discussion, get some critical 
response (your email was awesome - thanks!) and start steering the 
development in the right direction.

Regards,

-- 
Henrik Austad

[toc] | [prev] | [next] | [standalone]


#1421245

FromRichard Cochran <richardcochran@gmail.com>
Date2016-06-13 21:40 +0200
Message-ID<rJFSi-2fB-7@gated-at.bofh.it>
In reply to#1420808
On Mon, Jun 13, 2016 at 03:00:59PM +0200, Henrik Austad wrote:
> On Mon, Jun 13, 2016 at 01:47:13PM +0200, Richard Cochran wrote:
> > Which driver is that?
> 
> drivers/net/ethernet/renesas/

That driver is merely a PTP capable MAC driver, nothing more.
Although AVB is in the device name, the driver doesn't implement
anything beyond the PTP bits.
 
> What is the rationale for no new sockets? To avoid cluttering? or do 
> sockets have a drawback I'm not aware of?

The current raw sockets will work just fine.  Again, there should be a
application that sits in between with the network socket and the audio
interface.
 
> Why is configfs wrong?

Because the application will use the already existing network and
audio interfaces to configure the system.

> > Lets take a look at the big picture.  One aspect of TSN is already
> > fully supported, namely the gPTP.  Using the linuxptp user stack and a
> > modern kernel, you have a complete 802.1AS-2011 solution.
> 
> Yes, I thought so, which is also why I have put that to the side and why 
> I'm using ktime_get() for timestamps at the moment. There's also the issue 
> of hooking the time into ALSA/V4L2

So lets get that issue solved before anything else.  It is absolutely
essential for TSN.  Without the synchronization, you are only playing
audio over the network.  We already have software for that.
 
> > 2. A user space audio application that puts it all together, making
> >    use of the services in #1, the linuxptp gPTP service, the ALSA
> >    services, and the network connections.  This program will have all
> >    the knowledge about packet formats, AV encodings, and the local HW
> >    capabilities.  This program cannot yet be written, as we still need
> >    some kernel work in the audio and networking subsystems.
> 
> Why?

Because user space is right place to place the knowledge of the myriad
formats and options.

> the whole point should be to make it as easy for userspace as 
> possible. If you need to tailor each individual media-appliation to use 
> AVB, it is not going to be very useful outside pro-Audio. Sure, there will 
> be challenges, but one key element here should be to *not* require 
> upgrading every single media application.
> 
> Then, back to the suggestion of adding a TSN_SOCKET (which you didn't like, 
> but can we agree on a term "raw interface to TSN", and mode of transport 
> can be defined later? ), was to let those applications that are TSN-aware 
> to do what they need to do, whether it is controlling robots or media 
> streams.

First you say you don't want ot upgrade media applications, but then
you invent a new socket type.  That is a contradiction in terms.

Audio apps already use networking, and they already use the audio
subsystem.  We need to help them get their job done by providing the
missing kernel interfaces.  They don't need extra magic buffering the
kernel.  They already can buffer audio data by themselves.

> > * Kernel Space
> > 
> > 1. Providing frames with a future transmit time.  For normal sockets,
> >    this can be in the CMESG data.  For mmap'ed buffers, we will need a
> >    new format.  (I think Arnd is working on a new layout.)
> 
> Ah, I was unaware of this, both CMESG and mmap buffers.
> 
> What is the accuracy of deferred transmit? If you have a class A stream, 
> you push out a new frame every 125 us, you may end up with 
> accuracy-constraints lower than that if you want to be able to state "send 
> frame X at time Y".

I have no idea what you are asking here.
 
Sorry,
Richard

[toc] | [prev] | [next] | [standalone]


#1421712

FromHenrik Austad <henrik@austad.us>
Date2016-06-14 11:40 +0200
Message-ID<rJSZb-2YW-3@gated-at.bofh.it>
In reply to#1421245

[Multipart message — attachments visible in raw view] — view raw

On Mon, Jun 13, 2016 at 09:32:10PM +0200, Richard Cochran wrote:
> On Mon, Jun 13, 2016 at 03:00:59PM +0200, Henrik Austad wrote:
> > On Mon, Jun 13, 2016 at 01:47:13PM +0200, Richard Cochran wrote:
> > > Which driver is that?
> > 
> > drivers/net/ethernet/renesas/
> 
> That driver is merely a PTP capable MAC driver, nothing more.
> Although AVB is in the device name, the driver doesn't implement
> anything beyond the PTP bits.

Yes, I think they do the rest from userspace, not sure though :)

> > What is the rationale for no new sockets? To avoid cluttering? or do 
> > sockets have a drawback I'm not aware of?
> 
> The current raw sockets will work just fine.  Again, there should be a
> application that sits in between with the network socket and the audio
> interface.

So loop data from kernel -> userspace -> kernelspace and finally back to 
userspace and the media application? I agree that you need a way to pipe 
the incoming data directly from the network to userspace for those TSN 
users that can handle it. But again, for media-applications that don't know 
(or care) about AVB, it should be fed to ALSA/v4l2 directly and not jump 
between kernel and userspace an extra round.

I get the point of not including every single audio/video encoder in the 
kernel, but raw audio should be piped directly to alsa. V4L2 has a way of 
piping encoded video through the system and to the media application (in 
order to support cameras that to encoding). The same approach should be 
doable for AVB, no? (someone from alsa/v4l2 should probably comment on 
this)

> > Why is configfs wrong?
> 
> Because the application will use the already existing network and
> audio interfaces to configure the system.

Configuring this via the audio-interface is going to be a challenge since 
you need to configure the stream through the network before you can create 
the audio interface. If not, you will have to either drop data or block the 
caller until the link has been fully configured.

This is actually the reason why configfs is used in the series now, as it 
allows userspace to figure out all the different attributes and configure 
the link before letting ALSA start pushing data.

> > > Lets take a look at the big picture.  One aspect of TSN is already
> > > fully supported, namely the gPTP.  Using the linuxptp user stack and a
> > > modern kernel, you have a complete 802.1AS-2011 solution.
> > 
> > Yes, I thought so, which is also why I have put that to the side and why 
> > I'm using ktime_get() for timestamps at the moment. There's also the issue 
> > of hooking the time into ALSA/V4L2
> 
> So lets get that issue solved before anything else.  It is absolutely
> essential for TSN.  Without the synchronization, you are only playing
> audio over the network.  We already have software for that.

Yes, I agree, presentation-time and local time needs to be handled 
properly. The same for adjusting sample-rate etc. This is a lot of work, so 
I hope you can understand why I started out with a simple approach to spark 
a discussion before moving on to the larger bits.

> > > 2. A user space audio application that puts it all together, making
> > >    use of the services in #1, the linuxptp gPTP service, the ALSA
> > >    services, and the network connections.  This program will have all
> > >    the knowledge about packet formats, AV encodings, and the local HW
> > >    capabilities.  This program cannot yet be written, as we still need
> > >    some kernel work in the audio and networking subsystems.
> > 
> > Why?
> 
> Because user space is right place to place the knowledge of the myriad
> formats and options.

Se response above, better to let anything but uncompressed raw data trickle 
through.

> > the whole point should be to make it as easy for userspace as 
> > possible. If you need to tailor each individual media-appliation to use 
> > AVB, it is not going to be very useful outside pro-Audio. Sure, there will 
> > be challenges, but one key element here should be to *not* require 
> > upgrading every single media application.
> > 
> > Then, back to the suggestion of adding a TSN_SOCKET (which you didn't like, 
> > but can we agree on a term "raw interface to TSN", and mode of transport 
> > can be defined later? ), was to let those applications that are TSN-aware 
> > to do what they need to do, whether it is controlling robots or media 
> > streams.
> 
> First you say you don't want ot upgrade media applications, but then
> you invent a new socket type.  That is a contradiction in terms.

Hehe, no, bad phrasing on my part. I want *both* (hence the shim-interface) 
:)

> Audio apps already use networking, and they already use the audio
> subsystem.  We need to help them get their job done by providing the
> missing kernel interfaces.  They don't need extra magic buffering the
> kernel.  They already can buffer audio data by themselves.

Yes, I know some audio apps "use networking", I can stream netradio, I can 
use jack to connect devices using RTP and probably a whole lot of other 
applications do similar things. However, AVB is more about using the 
network as a virtual sound-card. For the media application, it should not 
have to care if the device it is using is a soudncard inside the box or a 
set of AVB-capable speakers somewhere on the network.

> > > * Kernel Space
> > > 
> > > 1. Providing frames with a future transmit time.  For normal sockets,
> > >    this can be in the CMESG data.  For mmap'ed buffers, we will need a
> > >    new format.  (I think Arnd is working on a new layout.)
> > 
> > Ah, I was unaware of this, both CMESG and mmap buffers.
> > 
> > What is the accuracy of deferred transmit? If you have a class A stream, 
> > you push out a new frame every 125 us, you may end up with 
> > accuracy-constraints lower than that if you want to be able to state "send 
> > frame X at time Y".
> 
> I have no idea what you are asking here.

I assumed that when you had a mmap'd buffer you'd have to specify a point 
in time at which the frame should be sent. And since a class A has a 125us 
interval of sending frames, you have to be able to send frames with enough 
accuray to that. That's a pretty strict deadline coming from userspace. But 
as they say, never assume.

I have a lot to dig into, and I've gotten a lot of very useful pointers. I 
should be busy for a while

-- 
Henrik Austad

[toc] | [prev] | [next] | [standalone]


#1422190

FromRichard Cochran <richardcochran@gmail.com>
Date2016-06-14 20:30 +0200
Message-ID<rK1g6-8wa-31@gated-at.bofh.it>
In reply to#1421712
On Tue, Jun 14, 2016 at 11:30:00AM +0200, Henrik Austad wrote:
> So loop data from kernel -> userspace -> kernelspace and finally back to 
> userspace and the media application?

Huh?  I wonder where you got that idea.  Let me show an example of
what I mean.

	void listener()
	{
		int in = socket();
		int out = open("/dev/dsp");
		char buf[];

		while (1) {
			recv(in, buf, packetsize);
			write(out, buf + offset, datasize);
		}
	}

See?

> Yes, I know some audio apps "use networking", I can stream netradio, I can 
> use jack to connect devices using RTP and probably a whole lot of other 
> applications do similar things. However, AVB is more about using the 
> network as a virtual sound-card.

That is news to me.  I don't recall ever having seen AVB described
like that before.

> For the media application, it should not 
> have to care if the device it is using is a soudncard inside the box or a 
> set of AVB-capable speakers somewhere on the network.

So you would like a remote listener to appear in the system as a local
PCM audio sink?  And a remote talker would be like a local media URL?
Sounds unworkable to me, but even if you were to implement it, the
logic would surely belong in alsa-lib and not in the kernel.  Behind
the enulated device, the library would run a loop like the example,
above.

In any case, your patches don't implement that sort of thing at all,
do they?

Thanks,
Richard

[toc] | [prev] | [next] | [standalone]


#1422313

FromHenrik Austad <henrik@austad.us>
Date2016-06-14 22:40 +0200
Message-ID<rK3hT-1kA-11@gated-at.bofh.it>
In reply to#1422190

[Multipart message — attachments visible in raw view] — view raw

On Tue, Jun 14, 2016 at 08:26:15PM +0200, Richard Cochran wrote:
> On Tue, Jun 14, 2016 at 11:30:00AM +0200, Henrik Austad wrote:
> > So loop data from kernel -> userspace -> kernelspace and finally back to 
> > userspace and the media application?
> 
> Huh?  I wonder where you got that idea.  Let me show an example of
> what I mean.
> 
> 	void listener()
> 	{
> 		int in = socket();
> 		int out = open("/dev/dsp");
> 		char buf[];
> 
> 		while (1) {
> 			recv(in, buf, packetsize);
> 			write(out, buf + offset, datasize);
> 		}
> 	}
> 
> See?

Where is your media-application in this? You only loop the audio from 
network to the dsp, is the media-application attached to the dsp-device?

Whereas I want to do 

aplay some_song.wav
or mplayer
or spotify
or ..


> > Yes, I know some audio apps "use networking", I can stream netradio, I can 
> > use jack to connect devices using RTP and probably a whole lot of other 
> > applications do similar things. However, AVB is more about using the 
> > network as a virtual sound-card.
> 
> That is news to me.  I don't recall ever having seen AVB described
> like that before.
> 
> > For the media application, it should not 
> > have to care if the device it is using is a soudncard inside the box or a 
> > set of AVB-capable speakers somewhere on the network.
> 
> So you would like a remote listener to appear in the system as a local
> PCM audio sink?  And a remote talker would be like a local media URL?
> Sounds unworkable to me, but even if you were to implement it, the
> logic would surely belong in alsa-lib and not in the kernel.  Behind
> the enulated device, the library would run a loop like the example,
> above.
> 
> In any case, your patches don't implement that sort of thing at all,
> do they?

Subject: [very-RFC 7/8] AVB ALSA - Add ALSA shim for TSN

Did you even bother to look?

-- 
Henrik Austad

[toc] | [prev] | [next] | [standalone]


#1422677

FromRichard Cochran <richardcochran@gmail.com>
Date2016-06-15 09:10 +0200
Message-ID<rKd7A-7Q2-7@gated-at.bofh.it>
In reply to#1422313
On Tue, Jun 14, 2016 at 10:38:10PM +0200, Henrik Austad wrote:
> Whereas I want to do 
> 
> aplay some_song.wav

Can you please explain how your patches accomplish this?

Thanks,
Richard

[toc] | [prev] | [next] | [standalone]


#1422758

FromHenrik Austad <henrik@austad.us>
Date2016-06-15 10:00 +0200
Message-ID<rKdTY-88q-15@gated-at.bofh.it>
In reply to#1422677

[Multipart message — attachments visible in raw view] — view raw

On Wed, Jun 15, 2016 at 09:04:41AM +0200, Richard Cochran wrote:
> On Tue, Jun 14, 2016 at 10:38:10PM +0200, Henrik Austad wrote:
> > Whereas I want to do 
> > 
> > aplay some_song.wav
> 
> Can you please explain how your patches accomplish this?

In short:

modprobe tsn
modprobe avb_alsa
mkdir /sys/kernel/config/eth0/link
cd /sys/kernel/config/eth0/link
<set approriate values vor the attributes>
echo alsa > enabled
aplay -Ddefault:CARD=avb some_song.wav

Likewise on the receiver side, except add 'Listener' to end_station 
attribute

arecord -c2 -r48000 -f S16_LE -Ddefault:CARD=avb > some_recording.wav

I've not had time to fully fix the hw-aprams for alsa, so some manual 
tweaking of arecord is required.


Again, this is a very early attempt to get something useful done with TSN, 
I know there are rough edges, I know buffer handling and timestamping is 
not finished


Note: if you don't have an intel-card, load tsn in debug-mode and it will 
let you use all NICs present.

modprobe tsn in_debug=1


-- 
Henrik Austad

[toc] | [prev] | [next] | [standalone]


#1422926

FromRichard Cochran <richardcochran@gmail.com>
Date2016-06-15 13:50 +0200
Message-ID<rKhux-21f-3@gated-at.bofh.it>
In reply to#1422677
On Wed, Jun 15, 2016 at 09:04:41AM +0200, Richard Cochran wrote:
> On Tue, Jun 14, 2016 at 10:38:10PM +0200, Henrik Austad wrote:
> > Whereas I want to do 
> > 
> > aplay some_song.wav
> 
> Can you please explain how your patches accomplish this?

Never mind.  Looking back, I found it in patch #7.

Thanks,
Richard

[toc] | [prev] | [next] | [standalone]


#1422682

FromRichard Cochran <richardcochran@gmail.com>
Date2016-06-15 09:20 +0200
Message-ID<rKdhg-7T3-7@gated-at.bofh.it>
In reply to#1422313
On Tue, Jun 14, 2016 at 10:38:10PM +0200, Henrik Austad wrote:
> Where is your media-application in this?

Um, that *is* a media application.  It plays music on the sound card.

> You only loop the audio from 
> network to the dsp, is the media-application attached to the dsp-device?

Sorry, I thought the old OSS API would be familiar and easy to
understand.  The /dev/dsp is the sound card.

Thanks,
Richard

[toc] | [prev] | [next] | [standalone]


#1421246

FromRichard Cochran <richardcochran@gmail.com>
Date2016-06-13 21:40 +0200
Message-ID<rJFSi-2fB-19@gated-at.bofh.it>
In reply to#1420808
On Mon, Jun 13, 2016 at 03:00:59PM +0200, Henrik Austad wrote:
> On Mon, Jun 13, 2016 at 01:47:13PM +0200, Richard Cochran wrote:
> > People have been asking me about TSN and Linux, and we've made some
> > thoughts about it.  The interest is there, and so I am glad to see
> > discussion on this topic.
> 
> I'm not aware of any such discussions, could you point me to where TSN has 
> been discussed, it would be nice to see other peoples thought on the matter 
> (which was one of the ideas behind this series in the first place)

To my knowledge, there hasn't been any previous TSN talk on lkml.

(You have just now started the discussion ;)

Sorry for not being clear.  

Richard

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | linux.kernel


csiph-web