Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable use of a local PTP master clock on the daemon host #34

Closed
NotherGithubAccount opened this issue Feb 28, 2021 · 14 comments
Closed

Comments

@NotherGithubAccount
Copy link

I've encountered a problem trying to combine the AES67 daemon with PJSIP. To query devices and their capabilities, PJSIP will open them. However, when there is no PTP lock, opening the RAVENNA device has a timeout of over two minutes.

The delay appears to happen in audio_driver.c mr_alsa_audio_pcm_prepare() between

printk(KERN_DEBUG "mr_alsa_audio_pcm_prepare: rate=%d format=%d channels=%d period_size=%lu, nb periods=%u\n", runtime->rate, runtime->format, runtime->channels, runtime->period_size, runtime->periods);

and

printk(KERN_DEBUG "mr_alsa_audio_pcm_prepare for playback stream\n");

I'm guessing it's related to setting the sample rate.

I haven't found a way to run ptp4l on the same interface as the daemon, and since the system is designed to allow running PJSIP on other devices, too, I need to be able to query interfaces even when there's no PTP (c)lock.

Do you have an idea how to work around that dilemma?

Thanks!

@NotherGithubAccount
Copy link
Author

The problem appears to be in manager.c set_sample_rate(). It tries 4000 times to get a PTP lock with a 1ms sleep in between. though that should only be 4 seconds, I'm guessing it adds up with the various ALSA PCMs.

Is that really necessary, other than use of the device failing if there's no PTP lock?

@bondagit
Copy link
Owner

AES67 mandates the use of a PTP master clock. This clock provides the base reference for all the streams in the AES67 network. Without a master clock it's not possible to start sending or handling sync of received RTP streams.
The reason you cannot use ptp4l to sync the daemon running on the same device is that ptp4l disables the multicast loopback reception, so the driver will not receive the local ptp packets. It's possible to patch ptp4l to enable multicast loopback.

@NotherGithubAccount
Copy link
Author

Thanks. I understand a clock is needed. It's just (for my use case) a very inconvenient place to wait for PTP to maybe become active. I opened the ticket, because at first I didn't know what was causing that delay.

Patching ptp4l to allow a local clock to run with the daemon is an interesting idea. It'd be very useful to have the daemon with a clock in a single device.

@bondagit
Copy link
Owner

bondagit commented Mar 2, 2021

I see your point. This is also creating troubles to other sound systems like PulseAudio that queries all the available audio devices. Unfortunately the setting of the sample rate has to be completed prior to starting the tick timer interrupt because it impacts the frame size.

As discussed you can patch ptp4l to allow the driver to work as standard PTP slave. Anyway this is not the more convenient way to sync with the local clock. If the clock master is running on the same device the driver might read the PTP clock via other methods. At the moment this is not implemented.

@NotherGithubAccount
Copy link
Author

There appears to be more to it than enabling multicast loopback. I've changed ptp4l to set IP_MULTICAST_LOOP on the interface to 1 instead of 0. Unfortunately that didn't make a difference.

However, when I start the daemon, ptp4l seems to stop receiving packets from the multicast group also. There is no more indication of it receiving anything from the remote master and it selects itself as grand master. The daemon however does see and select the remote master.

When I test without another clock on the network and only patched ptp4l running locally, the daemon doesn't find any clock.

netstat -g shows the correct number of memberships to ptp-primary.mcast.net. (2 with ptp4l, 1 with the daemon, 3 with both.)

Any idea what I might be missing?

@NotherGithubAccount
Copy link
Author

Sorry, enabling multicast loop did work, I was accidentally running ptp4l in slave mode.

But the daemon still prevents ptp4l from seeing other clocks on the network, which is problematic when the rest of the network selects a different master.

@bondagit
Copy link
Owner

bondagit commented Mar 3, 2021

ok.
I think this problem depends on the fact that when the driver reads the PTP packets and these are actually used it drops them and they are not delivered to the user land preventing ptp4l from receiving them.
You may try to patch the driver to accept the PTP packets when they are used instead of dropping them.
Apply the following patch to the driver in the repo: https://github.com/bondagit/ravenna-alsa-lkm/tree/aes67-daemon

diff --git a/driver/EtherTubeNetfilter.c b/driver/EtherTubeNetfilter.c
index efad009..4a96187 100644
--- a/driver/EtherTubeNetfilter.c
+++ b/driver/EtherTubeNetfilter.c
@@ -287,8 +287,8 @@ int rx_packet(TEtherTubeNetfilter* self, void* packet, int packet_size, const ch
     switch (DispatchPacket(self->manager_ptr_, packet, packet_size))
     {
         case DR_RTP_PACKET_USED:
-        case DR_PTP_PACKET_USED:
             return 0; //NF_DROP;
+        case DR_PTP_PACKET_USED:
         case DR_PACKET_NOT_USED:
         case DR_RTP_MIDI_PACKET_USED:
         case DR_PACKET_ERROR:

It this works I may add this patch to the repo.

@NotherGithubAccount
Copy link
Author

That works, thanks!

Regarding ptp4l, I got myself a bit confused yesterday. There is no difference between setting IP_MULTICAST_LOOP on or off. The daemon doesn't see the clock when only announcing on Ethernet, but it works as expected when including loopback , i.e. ptp4l -i eth0 -i lo. So there's no need to patch ptp4l.

For reference, here are the changes I made to ptp4l:

diff -U 1 linuxptp-3.1/udp6.c linuxptp-3.1.edit/udp6.c
--- linuxptp-3.1/udp6.c	2020-09-25 18:15:43.000000000 +0200
+++ linuxptp-3.1.edit/udp6.c	2021-03-04 09:19:18.270857613 +0100
@@ -77,3 +77,3 @@
 {
-	int err, off = 0;
+	int err, on = 1;
 	struct ipv6_mreq req;
@@ -88,3 +88,3 @@
 	}
-	err = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off));
+	err = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
 	if (err) {
diff -U 1 linuxptp-3.1/udp.c linuxptp-3.1.edit/udp.c
--- linuxptp-3.1/udp.c	2020-09-25 18:15:43.000000000 +0200
+++ linuxptp-3.1.edit/udp.c	2021-03-04 09:19:06.830952055 +0100
@@ -66,3 +66,3 @@
 {
-	int err, off = 0;
+	int err, on = 1;
 	struct ip_mreqn req;
@@ -77,3 +77,3 @@
 	}
-	err = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &off, sizeof(off));
+	err = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &on, sizeof(on));
 	if (err) {

@bondagit
Copy link
Owner

bondagit commented Mar 4, 2021

Thanks for your tests. I tried myself and I have same result as you.
I thought I tested this in the past but it actually doesn't work.
The problem is related to the fact that although the driver (via NF_INET_PRE_ROUTING netfilter hook) does receive the UDP packets sent out locally these are captured without the MAC header and they are not processed correctly and get dropped.
It's possible to change the driver to support proper processing of the local traffic too but this would be useful for this use case only; that is to be able to receive the local PTP master clock traffic.
An alternative to support a local PTP master clock would be to read it directly with an ad hoc configuration.

@NotherGithubAccount
Copy link
Author

Thanks for confirming this. With your module patch and with software timestamping, it works fine running ptp4l on Ethernet and loopback at once. Since I'm running this on a Pi, I have to use software mode anyway, but I assume it's a showstopper for systems with hardware timestamping.

@bondagit
Copy link
Owner

bondagit commented Mar 6, 2021

I added a patch to the driver to allow locking on a local PTP master clock.
Can you please switch the driver to the branch aes67-daemon-local_traffic_support and give it a try ?
With this I am able to lock on the local PTP master and receive remote PTP traffic.
You have in any case to keep the patch to ptp4l to enable multicast loopback.
Thanks.

@NotherGithubAccount
Copy link
Author

Works with patched ptp4l running on eth0 only. The daemon sees both the local and remote clocks. Thank you!

@bondagit
Copy link
Owner

bondagit commented Mar 6, 2021

Great! Thanks for the quick feedback.
I will test this a bit longer and integrate it back into aes67-daemon branch when done.

@bondagit bondagit changed the title Long delay when attempting to open device before PTP lock enable use of a local PTP master clock on the daemon host Mar 11, 2021
@bondagit
Copy link
Owner

I merged the content aes67-daemon-local_traffic_support into aes67-daemon branch and changed the driver version to 1.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants