Re: [Linuxptp-devel] Adding libpmc

2020-04-16 Thread Jiri Benc
On Thu, 16 Apr 2020 17:06:46 +, Geva, Erez wrote:
> While the Kernel is under GPL 2.
> The headers and system call are under exception, so user can use the
> Kernel with non GPL code. But any changes or addition to the kernel
> itself should be GPL 2.

This is very different. The Linux kernel is supposed to run any kind of
programs under various licenses. Linux PTP is not a generic mechanism
intended to run other software.

[Slightly off topic: Moreover, the kernel has a strict boundary (uAPI)
between its internals and the user space programs. It's so strictly
defined that it does not require LGPL but instead is covered by a GPL
exception. That is different to libraries. In fact, the kernel uAPI is
more close to stuff like RPC or REST API than to libraries.]

> The exception means that any code that is part of the LinuxPTP must
> be coverd by GPL.
> 
> But user may embedded a library in their non GPL application and
> communicate with the ptp4l.
> 
> Do you have another suggestion?

Why can't those applications that use parts of linuxptp code be licensed
under GPL? That seems like a win for everybody.

 Jiri



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] Adding libpmc

2020-04-16 Thread Jiri Benc
Hi Erez,

On Thu, 16 Apr 2020 14:18:25 +, Geva, Erez wrote:
> I see that linux PTP is under GPL 2.
> 
> I would like to ask your permission to allow using a libpmc library
> and headers needed by it under LGPL 2.

Could I ask you to provide more context, please?

I contributed to the Linux PTP project with the understanding it is
licensed under GPL; agreeing to provide my contribution under a
different license is something that I don't take lightly. You may
understand that it's difficult to do such important decision based
solely on a request without explanation about what project this needs,
under what license, who's going to develop it, etc. Please elaborate on
your plans.

> As you are the copywrite holders, we need your explicit consent.

I very much appreciate that you are aware of the legal implications and
that you're reaching to us.

Thanks,

 Jiri



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 5/6] Add PHC methods for querying and configuring the pin functionality.

2020-03-09 Thread Jiri Benc
On Mon, 9 Mar 2020 07:16:23 -0700, Richard Cochran wrote:
> But maybe that wouldn't be worst thing in the world.  There is a trade
> off between maintaining parallel copies of ptp_clock_caps and the
> convenience of compiling the stack just once with the "future" kernel
> definitions.
> 
> Thoughts?

The decision is ultimately yours but I'd prefer the copy of the struct
in missing.h.

Thanks,

 Jiri



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 5/6] Add PHC methods for querying and configuring the pin functionality.

2020-03-09 Thread Jiri Benc
On Fri,  6 Mar 2020 11:23:00 -0800, Richard Cochran wrote:
> +int phc_number_pins(clockid_t clkid)
> +{
> + struct ptp_clock_caps caps;
> +
> + if (phc_get_caps(clkid, &caps)) {
> + return 0;
> + }
> +#ifdef HAVE_PIN_SETFUNC
> + return caps.n_pins;
> +#else
> + return 0;
> +#endif
> +}
> +
> +int phc_pin_setfunc(clockid_t clkid, struct ptp_pin_desc *desc)
> +{
> + int err = -EOPNOTSUPP;
> +#ifdef HAVE_PIN_SETFUNC
> + err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_SETFUNC2, desc);
> + if (err) {
> + fprintf(stderr, PTP_PIN_SETFUNC_FAILED "\n");
> + }
> +#endif
> + return err;

If I'm reading the patches correctly, this would require a rebuild if
the kernel is updated in order for linuxptp to use the new kernel
functions.

It would be better to detect this at run time instead, allowing
linuxptp to use the best interface dynamically without recompiling. It
seems to be doable, the old kernels return -ENOTTY for unknown commands.

Thanks,

 Jiri



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ptp4l port 1: bad message

2019-10-10 Thread Jiri Benc
On Thu, 10 Oct 2019 14:23:44 + (UTC), RAVEENDRA M via Linuxptp-devel wrote:
>  Any fix will be provided soon for the "bad message" errors and
> protection from buggy HW?

I'm afraid this is something you'll have to sort out with the hardware
vendor. If they sold you the box as IEEE 1588-2008 compliant, ask them
to fix the box to be really compliant (because it isn't) or to return
the money.

If the box is not advertised as IEEE 1588-2008 compliant, you may still
try to complain; but it may very well be that it's just implementing
its own proprietary protocol which is not PTP compatible. You can't
expect it to be supported by a PTP daemon in such case.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] pmc: Support querying TLV_PORT_PROPERTIES_NP

2019-09-17 Thread Jiri Benc
On Mon, 16 Sep 2019 14:44:57 +, Petr Machata wrote:
> So you want to change the current TLV? I guess that's reasonable, since
> it is essentially an internal API.

Whatever, just have a way to extend this in the future, while allowing
the tools compiled today to still work after the extension.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] pmc: Support querying TLV_PORT_PROPERTIES_NP

2019-09-16 Thread Jiri Benc
On Mon, 16 Sep 2019 14:04:00 +, Petr Machata wrote:
> I was actually thinking about /var/run/netns being mounted elsewhere or
> some such, which would prevent "ip netns id" from working. The symbolic
> names seem to be accessible from other namespaces just fine --"ip netns
> exec foo ip netns exec bar bash" works-- but renaming /var/run breaks
> it.

/var/run/netns is a convention introduced by iproute2 and respected by
many, but sadly not all, other net management systems. There is no
concept of netns names in the kernel.

And it is a completely different thing than netnsids. The netns mounts
allow you to get a file descriptor referencing the target net name
space unambiguously. Such fd can be used for many operations, most
importantly to switch yourself into that net name space (see setns(2)).
You can obtain the fd by other means, too, for example by
opening /proc//ns/net.

netnsid is a different integer. It is valid only in the net name space
it was created in and references a target net name space. It can be
used only in netlink operations. It is completely managed by the kernel
and does not require the netns to be mounted nor /proc to be mounted.

> I don't have other ideas than this. I also think that having an easy to
> use way to access the interface outweighs the risks.

I think proper documentation might help. Add a warning that this
doesn't work across net name spaces and ensure that the API is flexible
enough to allow a new field to be added in the future without breaking
backwards compatibility if we ever need to start communicating also a
netns identifier.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] pmc: Support querying TLV_PORT_PROPERTIES_NP

2019-09-16 Thread Jiri Benc
On Mon, 16 Sep 2019 09:56:29 +, Petr Machata wrote:
> Inside the namespace you can do "ip netns id" to get the namespace that
> you are in.

Beware that this netnsid is only valid in the net name space that the
'ip' command ran in. It is not a global identifier and it is not valid
in another net name space.

In other words, ptp4l can't return a netnsid valid in the pmc net
name space (without doing gross and unreliable hacks).

> > Hmm. It's plausible the pmc instance wouldn't even know about the
> > device, but ptp4l itself doesn't know whether to hide that info or
> > not. Other way around could be that ptp4l is inside a namespace while
> > pmc is not, but again it's not obvious.  

Every process is in exactly one net name space. There are no processes
that are not in a net name space.

There is a root net name space that is a bit special in some situations
but it basically boils down to that it cannot be deleted. From a point
of view of a process, there's nothing different about it. A net name
space is a net name space.

> ptp4l already has a public API to obtain the device name: the VLA
> itself. There just isn't an easy way to invoke that interface. So we
> don't have to concern ourselves with whether to hide the interface name
> itself, that ship has sailed.

If the API is so hard that it's not in use in practice, it makes a
difference.

> About the namespace--as an unprivileged process you can't just ask about
> netns ids of random processes. So whether to allow ptp4l to give up this
> information is a good question, because that might go against the
> intentions of the admin of the machine.

It also does not work, see above :-)

> Maybe just documenting the issue is all that can be done.

Could be.

> I'm not sure I agree the process inside the namespace should be
> disallowed from knowing it is. I'm not really well versed in network
> namespaces, but looking at what "ip netns id" is doing under the hood it
> looks like the kernel has interfaces to just tell you (RTM_GETNSID).

Since every process is in a net name space (and exactly one net name
space), it already knows by definition that it is in a name space :-)

Whether referencing into other net name spaces makes sense or not,
depends on the use. I'd argue that a daemon (such as ptp4l) should not
mess with name spaces, as it needs the administrator to be able to run
it in whatever net name space they chooses. But it can certainly query
it if it is needed for proper interoperability.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] pmc: Support querying TLV_PORT_PROPERTIES_NP

2019-09-13 Thread Jiri Benc
On Fri, 13 Sep 2019 09:32:37 +, Petr Machata wrote:
> I would guess the same problem applies when phc2sys uses the interface.
> Why is it not an issue there?

It is an issue, too, of course, but it's mostly theoretical. It won't
happen in practice - usually, phc2sys will be started together with
ptp4l from the same environment.

pmc is different. It's not tied to the service start time, it's used by
administrators and by various scripts from varying environment. While
you can reasonably expect that ptp4l and phc2sys will be run in the
same name space, it's not necessarily the case for pmc.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] pmc: Support querying TLV_PORT_PROPERTIES_NP

2019-09-13 Thread Jiri Benc
On Thu, 12 Sep 2019 11:06:30 +, Petr Machata wrote:
> + text2str(&ppn->interface));

How does this work when net name spaces are in use? There's no guarantee
that pmc is run in the same net name space where ptp4l is running. The
returned interface name may correspond to a completely different
interface in the pmc net name space.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ptp4l wrongly takes padding bytes as TLV?

2019-02-05 Thread Jiri Benc
On Tue, 5 Feb 2019 15:44:47 +, Vincent Li X wrote:
> In our case, it's not wrong FCS or unwanted padding, but PHY replaced
> original FCS with frame padding of random value. 

I very much doubt that. I bet the FCS was just stripped. I have yet to
see a NIC that would replace FCS by a random value.

Much more likely, there was (wrong and uninitialized = security
problem) padding added by the sender, FCS was appended after it and
stripped on the receiver side. What you see is the padding.

> The thing is we should not try to decode any padding/bytes after PTP message
> body as TLV, because TLV is part of PTP message and total length is
> specified by the messageLength field. The description from 1588 is attached
> below:
> 
> 13.3.2.4 messageLength (UInteger16)
> The value of the messageLength shall be the total number of octets that form
> the PTP message. The
> counted octets start with the first octet of the header and include and
> terminate with the last octet of any
> suffix or, if there are no suffix members with the last octet of the message
> as defined in this clause.
> NOTE—The message length does not include any padding bits specified in Annex
> D.

The only thing this says is it's wrong to add padding at the end by the
sender (because that violates "the value of the messageLength shall be
the total number of octets that form the PTP message"). It says nothing
about what the receiver is supposed to do with a message in which
messageLength is not the total number of octets.

Specifically, it does not require the receiver to use messageLength;
note that with correct messages it does not matter as both approaches
(using messageLength vs. using real length) yield to the same result.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ptp4l wrongly takes padding bytes as TLV?

2019-01-31 Thread Jiri Benc
On Thu, 31 Jan 2019 16:28:30 +, Vincent Li X wrote:
> we might also need to check again m->header.messageLength is bigger than
> cnt.

This might not be a bad idea; if the packet length is inconsistent with
the PTP or 802.3 standard, a warning can be emitted and the packet
dropped and not processed further. This would make linuxptp more robust
against randomly malformed packets and would give some indication to
users that the other end or intermediate network equipment is broken.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ptp4l wrongly takes padding bytes as TLV?

2019-01-31 Thread Jiri Benc
On Thu, 31 Jan 2019 07:41:38 -0800, Richard Cochran wrote:
> FWIW, Wireshark shows "Bad FCS" for this frame.  Please fix it at the
> sender.

To be fair, this is just an artifact of Wireshark guessing wrong on the
packet structure. AFAIK there's no indication of the frames having FCS or
not in pcap. Wireshark has to guess and when it sees the packet being
6 bytes longer than the payload and 64 bytes in total, it's natural to
guess it's 2 bytes padding and 4 bytes FCS to satisfy the Ethernet
minimum length requirements.

While in fact, I expect that the FCS got stripped and the frame was
68 bytes. The real FCS was most likely correct.

Seeing the padding bytes not being zero, I cannot resist wondering what
part of its memory is the sender leaking. Could the leak be used to
gather some interesting data? ;-)

In any case, this behavior is wrong on several levels. And with the
likely security issue present, I don't think it's worth the time to
consider this hardware seriously.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ptp4l wrongly takes padding bytes as TLV?

2019-01-30 Thread Jiri Benc
On Wed, 30 Jan 2019 11:34:25 +0100, Miroslav Lichvar wrote:
> Are there other vendors than Qulsar that do this? If it's a common
> issue, it might need to be specified. IIRC there are few other cases
> where the spec had to be adjusted to follow what existing HW was doing.

The Qulsar hardware violates the PTP spec and as such, they cannot claim
PTP support. If they do, it's false advertisement and it's a reason to
demand fix from the vendor and if they can't deliver a fix, have the
device refunded.

I don't see reason why linuxptp should put hacks in place to workaround
broken hardware that knowingly violates the spec. I don't even see a
reason why the standard should be changed to accommodate such hardware
with no real technical reasons ("we were lazy to implement the spec
correctly and we just decided to violate the spec" is hardly a reason).

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 4/5] sk: Added functionality for reassociate namespace

2018-11-13 Thread Jiri Benc
On Tue, 13 Nov 2018 10:34:20 +, Anders Selhammer wrote:
> + snprintf(path, sizeof path, "/var/run/netns/%s", ns);

This path is just a convention used by iproute2. There's nothing that
forces a network name space to be mounted in /var/run/netns. It can be
mounted elsewhere or even nowhere at all.

 Jiri


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 1/8] rtnl: use ifinfomsg instead of rtgenmsg to request link info

2017-07-03 Thread Jiri Benc
On Mon, 3 Jul 2017 09:12:46 +0200, Richard Cochran wrote:
> We can even call uname(2) to check the kernel version when bonding is
> requested in the configuration.

Please don't do that. Always check for the feature being present, never
for a kernel version. It's common for various groups to backport newer
features to older kernels; kernel version alone does not indicate
anything.

Thanks,

 Jiri

--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] Force IPv6 to IPV6 only, no ipv4 to ipv6 mapping.

2015-08-10 Thread Jiri Benc
On Mon, 10 Aug 2015 12:14:56 -0700, Gary E. Miller wrote:
> By default, at least on Linux, opening a PF_INET6 socket also
> grabs the matching IPv4 port.  This patch stops that.

Looks good but I think it should have more detailed description.
Especially elaborate on the reasons why linuxptp needs to
unconditionally deviate from the system-wide setting.

I always hate when I'm debugging a problem, track it down to a
particular commit and it's completely unclear why the change was
introduced. Given the confusion this option creates, I think that more
detailed description is in place here. Think about somebody who expects
that the v6 socket listens also for v4 traffic as he's used from other
programs and tries to debug why linuxptp behaves differently (I know
that you stated that's only minor part of users and you're probably
right but that's going to change once IPv6 becomes more common and
people get used to this behavior).

> Only tested on Linux.  Unknown how this will work on *BSD or WinXX.

I wouldn't worry about it given the amount of Linux-only interfaces
linuxptp uses.

Thanks,

 Jiri

-- 
Jiri Benc

--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] unknown option ntpshm_segment at line 8 in eno1 section

2015-08-10 Thread Jiri Benc
On Mon, 10 Aug 2015 10:32:54 -0700, Gary E. Miller wrote:
> In keeping with the principla of least surprise, I would say go with the
> flow and implement IPV6_V6ONLY.

You could also argue that "least surprise" means to respect whatever the
administrator set in the bindv6only sysctl. It's there for a reason and
applications should respect the setting, unless they have a very good
exceptional reason to do otherwise.

 Jiri

-- 
Jiri Benc

--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] Add options to configure TTL/hop limit for UDP/UDP6 transports.

2015-08-10 Thread Jiri Benc
On Mon,  3 Aug 2015 15:49:43 +0200, Miroslav Lichvar wrote:
> --- a/default.cfg
> +++ b/default.cfg
> @@ -60,6 +60,8 @@ ntpshm_segment  0
>  transportSpecific0x0
>  ptp_dst_mac  01:1B:19:00:00:00
>  p2p_dst_mac  01:80:C2:00:00:0E
> +udp_ttl  1
> +udp6_hop_limit   1

I don't see much reasons for having different options for IPv4 and
IPv6. Just call it udp_ttl (or whatever) and use it for both IPv4 and
IPv6. The fact that IPv6 standard renamed the option sucks (and one can
argue it was not the best decision as it created more confusion than it
solved) but both TTL and hop limit are the exactly same thing in the
current networks and it doesn't make sense to distinguish them.

 Jiri

-- 
Jiri Benc

--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] unknown option ntpshm_segment at line 8 in eno1 section

2015-08-10 Thread Jiri Benc
On Tue, 4 Aug 2015 10:34:17 +0200, Miroslav Lichvar wrote:
> When I run "ptp4l -6 -S -i ens5 -m", ss reports only IPv6 sockets for
> ptp4l:
> 
> # ss -lup | grep ptp4l
> UNCONN 0  0 ::%ens5:ptp-event :::*
> users:(("ptp4l",pid=5862,fd=10))
> UNCONN 0  0 ::%ens5:ptp-general :::*  
>   users:(("ptp4l",pid=5862,fd=11))

Sadly, ss does not report whether a given socket has IPV6_V6ONLY set or
not. By default (unless /proc/sys/net/ipv6/bindv6only is set), the IPv6
socket listens for both IPv6 and IPv4 connections, returning the latter
as v4-mapped IPv6 address.

linuxptp does not seem to set IPV6_V6ONLY, thus creating an UDP6 socket
indeed prevents creating an UDP4 one on the same UDP port.

Whether or not ptp4l should set IPV6_V6ONLY unconditionally needs some
more thinking, but my first impression is it would need to use IPv4
multicast addresses (v4-mapped to IPv6) to send the packets to the v4
hosts and not the IPv6 multicast addresses. This doesn't seem worth the
complications and IPV6_V6ONLY looks like to be appropriate here. But
somebody should think it through first :-)

 Jiri

-- 
Jiri Benc

--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ntp SHMs

2015-02-25 Thread Jiri Benc
[Dropping Gary and Jacob from CC, this is not related to the original
topic anymore.]

On Wed, 25 Feb 2015 16:15:31 +0100, Miroslav Lichvar wrote:
> The man page says the clock is synchronized by another process.

It's not clear what that means, though. I think the behavior of ntpshm
is so special that it deserves a special chapter in the man page
describing how it works, how to use it and that specifying clock
sources (including the system clock and the -r parameter) has different
meaning with this servo. I mean, even I am very confused by this thing,
what about poor users ;-)

> > From the user point of view, the shm is just another time
> > source. In the code, it could be implemented as a fake clock (as you
> > need at least two clocks for phc2sys to do anything) driven by this
> > special servo.
> 
> I don't follow. What would the fake clock do?
> 
> > Requiring the user to add a random second clock for this
> > to work (be it a system clock or a different PHC) is very confusing.
> 
> It's not a random clock, it's the clock that is synchronized by the
> SHM consumer, i.e. the system clock with chronyd/ntpd. SHM samples
> contain timestamps from both clocks (PHC and system clock).

Hmm, I see. The fake clock would not help, then. I still don't like it
but I don't see a better way to do this, currently. We definitely need
a better documentation.

Thanks for the explanation,

 Jiri

-- 
Jiri Benc

--
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ntp SHMs

2015-02-25 Thread Jiri Benc
On Tue, 24 Feb 2015 21:33:49 +, Keller, Jacob E wrote:
> I do not believe Jiri is right. I ran a similar config and it appeared
> to work fine, without crazy clock jumping. Chronyd simply took the SHM
> reference and tuned the system clock over time, because the ntpshm
> servo presents itself to the ntp daemon.

You're right and I'm not. The ntpshm servo always sets the
SERVO_UNLOCKED state in the sample() callback, thus it never sets any
clock. I didn't know that and I dislike that very much. This is a gross
hack. Not mentioning it's not documented in the man page.

Miroslav, any chance to improve this to be better understandable to
users? From the user point of view, the shm is just another time
source. In the code, it could be implemented as a fake clock (as you
need at least two clocks for phc2sys to do anything) driven by this
special servo. Requiring the user to add a random second clock for this
to work (be it a system clock or a different PHC) is very confusing.

This still won't allow things like a two-PHC boundary clock with NTP
synchronization. For this, we'll need to be able to specify per-clock
servos. The ntpshm servo then will drive only the fake clock.

 Jiri

-- 
Jiri Benc

--
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] ntp SHMs

2015-02-25 Thread Jiri Benc
On Mon, 23 Feb 2015 18:48:51 -0800, Gary E. Miller wrote:
> ptp4l[364.654]: port 1: UNCALIBRATED to SLAVE on MASTER_CLOCK_SELECTED
> phc2sys[365.199]: port 002590.fffe.f355da-1 changed state
> phc2sys[365.199]: reconfiguring after port state change
> phc2sys[365.199]: selecting CLOCK_REALTIME for synchronization
> phc2sys[365.199]: selecting eth0 as the master clock
> phc2sys[365.199]: phc offset -70353239245525 s0 freq  +0 delay   1348
> 
> WTF was that???
> 
> ptp4l[365.571]: clockcheck: clock jumped forward or running faster than 
> expected!
> ptp4l[365.571]: master offset 70368744176888 s0 freq   -9485 path delay   
>   58263

You are apparently running several programs that try to drive the same
clock. This is going to fail, no matter what software you use. This is
most likely a misconfiguration on your side, perhaps you're running
multiple ptp4l instances over the same net interface.

On a similar note, earlier in the thread, you mentioned that you want
the realtime (system) clock to be set by other program than phc2sys. You
must not tell phc2sys to drive the system clock, then, otherwise those
two programs would fight each other. This means you must not pass "-r"
to phc2sys, that option tells phc2sys to drive the system clock (please
do read the phc2sys man page before asking more questions about this,
thanks).

Now, with a single interface and no system clock to sync (i.e. just
phc2sys -a), there's just one clock (the internal clock of the NIC).
phc2sys does synchronization of two or more clocks. If it has just one
clock, it has nothing to synchronize it with and as the consequence, it
does nothing.

As ntpshm is implemented as a servo, it does not come into the game at
all. phc2sys has nothing to synchronize, as synchronizing one clock is a
no-op, and thus does nothing. Using manual mode instead of the
automatic one won't change this.

What's needed is implementing ntpshm to be a clock, not a servo.

tl;dr: What you're trying to achieve does not work with linuxptp
currently.

 Jiri

-- 
Jiri Benc

--
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC 0/4] Time stamp asymmetry correction

2014-12-10 Thread Jiri Benc
On Wed, 10 Dec 2014 10:03:35 +0100, Delio Brignoli wrote:
> I just wanted to point out that, in the scenario above, correctly
> implemented drivers and user mode applications should also track link
> state changes (link speed mostly, but other factors could affect
> latency) and update corrections accordingly. Drivers should probably be
> given a chance to update the correction before user-mode is notified or
> you’d end up with driver defaults overriding user-mode settings.

You're right, that complicates things and means we'll need user space
to be involved in the decision anyway. And when the user space needs to
listen for link changes and act on them, there's no reason to put
complicated logic into the kernel. Seems that an interface to query
the driver for the current suggested correction is enough and the
actual addition/subtraction should be indeed done in ptp4l. It also
seems that ptp4l will need to listen for link change events.

 Jiri

-- 
Jiri Benc

--
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC 0/4] Time stamp asymmetry correction

2014-12-10 Thread Jiri Benc
On Mon, 8 Dec 2014 14:04:56 +0100, Delio Brignoli wrote:
> Yes, I was thinking it would allow to query if the driver supports this
> feature and get/set current offsets.

I agree. That way, with correctly implemented drivers the user will
get the right correction for free but will be still able to overrule
the values.

What I'm thinking of is having an ethtool operation to get/set
ingress/egress correction. This will be handled in the kernel (i.e. not
propagated to the drivers to prevent misuse). The driver provides
initial correction values (or zero if they're unknown) but user space
is free to alter them or reset them to the initial values. It is
obviously per-interface setting.

A nice bonus is this will work with all program using the time stamping
interface, not just linuxptp.

This is compatible with Richard's patchset, only the config options
would call the ethtool op instead of doing the correction in ptp4l.

 Jiri

-- 
Jiri Benc

--
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=164703151&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC V2 10/10] port: allow running a boundary clock with multiple clock devices.

2014-11-13 Thread Jiri Benc
On Wed,  5 Nov 2014 23:42:36 +0100, Richard Cochran wrote:
> If the user has configured the appropriate option, then simply warn about
> the clock device mismatch, open the port's clock device, and then go on.
> 
> Signed-off-by: Richard Cochran 
> ---
>  port.c |   25 ++---
>  1 file changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/port.c b/port.c
> index 2176962..95b6794 100644
> --- a/port.c
> +++ b/port.c
> @@ -29,6 +29,7 @@
>  #include "filter.h"
>  #include "missing.h"
>  #include "msg.h"
> +#include "phc.h"
>  #include "port.h"
>  #include "print.h"
>  #include "sk.h"
> @@ -65,6 +66,7 @@ struct port {
>   char *name;
>   struct clock *clock;
>   clockid_t clkid;
> + int max_adj;
>   struct transport *trp;
>   enum timestamp_type timestamping;
>   struct fdarray fda;
> @@ -1952,6 +1954,8 @@ void port_close(struct port *p)
>   filter_destroy(p->delay_filter);
>   if (p->fault_fd >= 0)
>   close(p->fault_fd);
> + if (p->max_adj)
> + phc_close(p->clkid);
>   free(p);
>  }
>  
> @@ -2463,10 +2467,25 @@ struct port *port_open(clockid_t clkid,
>   else if (!interface->ts_info.valid)
>   pr_warning("port %d: get_ts_info not supported", number);
>   else if (phc_index >= 0 && phc_index != interface->ts_info.phc_index) {
> + char phc[32];
> + snprintf(phc, 31, "/dev/ptp%d", interface->ts_info.phc_index);
>   pr_err("port %d: PHC device mismatch", number);
> - pr_err("port %d: /dev/ptp%d requested, but /dev/ptp%d attached",
> -number, phc_index, interface->ts_info.phc_index);
> - goto err_port;
> + pr_err("port %d: /dev/ptp%d requested, but %s attached",
> +number, phc_index, phc);
> + if (!interface->boundary_clock_jbod) {
> + goto err_port;
> + }
> + pr_warning("port %d: just a bunch of devices", number);

I think this warning is enough, the previous ones ("PHC device
mismatch" and "/dev/ptp%d requested, but %s attached") can be printed
only when boundary_clock_jbod is not set. After all, the user is
supposed to know what he's doing when enabling this.

> + p->clkid = phc_open(phc);
> + if (p->clkid == CLOCK_INVALID) {
> + pr_err("port %d: Failed to open %s: %m", number, phc);
> + goto err_port;
> + }
> +     p->max_adj = phc_max_adj(p->clkid);
> + if (!p->max_adj) {
> + pr_err("port %d: clock is not adjustable", number);
> + goto err_port;
> + }
>   }
>  
>   p->pod = interface->pod;

I think the servo state should be separate, too. The reference counted
structure would be a good place to hold that.

 Jiri

-- 
Jiri Benc

--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC V2 06/10] config: add a option to enable a poor man's boundary clock.

2014-11-13 Thread Jiri Benc
On Wed,  5 Nov 2014 23:42:32 +0100, Richard Cochran wrote:
> This patch adds a configuration option that allows running a boundary clock
> using "just a bunch of devices". Normally each port is probed to make sure
> they all share the same PTP hardware clock, but this option will allow a
> heterogeneous collection of devices, should the user really want it.
> 
> Signed-off-by: Richard Cochran 

Acked-by: Jiri Benc 

-- 
Jiri Benc

--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC V2 08/10] phc2sys: automatic mode: synchronize all non-slave ports.

2014-11-13 Thread Jiri Benc
On Wed,  5 Nov 2014 23:42:34 +0100, Richard Cochran wrote:
> When running a "jbod" Boundary Clock, as long as we have one slaved port,
> we always want the clocks on the other ports to be synchronized, regardless
> of their port state.
> 
> Signed-off-by: Richard Cochran 

Acked-by: Jiri Benc 

-- 
Jiri Benc

--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC V2 09/10] Push the node's clock ID into the port data structure.

2014-11-13 Thread Jiri Benc
On Wed,  5 Nov 2014 23:42:35 +0100, Richard Cochran wrote:
> This patch lets the ports (rather than the clock) remember the clock ID,
> passing it back to the clock code during synchronization. This does not
> represent a functional change, but rather paves the way for ports to
> override the clock ID when running a "jbod" BC.
> 
> Signed-off-by: Richard Cochran 
> ---
>  clock.c |   50 --
>  clock.h |2 ++
>  port.c  |8 ++--
>  port.h  |4 +++-
>  4 files changed, 35 insertions(+), 29 deletions(-)
> 
> diff --git a/clock.c b/clock.c
> index df82d2b..ca902ef 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -72,7 +72,6 @@ struct clock_subscriber {
>  };
>  
>  struct clock {
> - clockid_t clkid;
>   struct servo *servo;
>   struct defaultDS dds;
>   struct dataset default_dataset;
> @@ -268,9 +267,6 @@ void clock_destroy(struct clock *c)
>   }
>   port_close(c->uds_port);
>   free(c->pollfd);
> - if (c->clkid != CLOCK_REALTIME) {
> - phc_close(c->clkid);
> - }

I don't like that phc_close is not called anymore after this patch.
I understand that it's not easy to do but IMHO this points out that
this approach is not the best one.

What about creating a reference counted structure holding clkid and
reference it from struct port? This seems even better to me than my
original patch splitting struct clock.

 Jiri

-- 
Jiri Benc

--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH] phc2sys: fix overwriting of the clock state

2014-11-13 Thread Jiri Benc
The reconfigure function is missing a check whether state for the given
clock actually changed or not. This caused state for all unchanged ports to
be zeroed.

Reported-by: Richard Cochran 
Signed-off-by: Jiri Benc 
---
 phc2sys.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 22eb9c965ce9..67d8a588288f 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -305,11 +305,13 @@ static void reconfigure(struct node *node)
continue;
}
 
-   if (c->new_state == PS_MASTER)
-   clock_reinit(c);
+   if (c->new_state) {
+   if (c->new_state == PS_MASTER)
+   clock_reinit(c);
 
-   c->state = c->new_state;
-   c->new_state = 0;
+   c->state = c->new_state;
+   c->new_state = 0;
+   }
 
if (c->state == PS_SLAVE) {
src = c;
-- 
1.8.3.1


--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC V2 07/10] phc2sys: make automatic mode actually work.

2014-11-13 Thread Jiri Benc
On Wed,  5 Nov 2014 23:42:33 +0100, Richard Cochran wrote:
> The reconfigure function unnecessarily clears the 'new_state' variable.
> On the second and subsequent calls, this zero value incorrectly clobbers
> the state of any port whose state has *not* changed.
> 
> If, for example, a port in the MASTER state goes FAULTY, when it returns
> to MASTER state, phc2sys will not synchronize it, because the SLAVE port's
> state variable will have been cleared to zero, effectively erasing the
> local time source.
> 
> This patch fixes the issue by removing the assignment.
> 
> Signed-off-by: Richard Cochran 
> ---
>  phc2sys.c |1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index 22eb9c9..47ee3b8 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -309,7 +309,6 @@ static void reconfigure(struct node *node)
>   clock_reinit(c);
>  
>   c->state = c->new_state;
> - c->new_state = 0;
>  
>   if (c->state == PS_SLAVE) {
>   src = c;

With this, we're calling clock_reinit for the MASTER state even when it
did not change. The bug here is missing check for new_state == 0. I'll
send a patch.

Thanks,

 Jiri

-- 
Jiri Benc

--
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH RFC 0/3] Poor man's boundary clock

2014-11-05 Thread Jiri Benc
On Wed, 5 Nov 2014 19:58:32 +0100, Richard Cochran wrote:
> On Wed, Nov 05, 2014 at 05:56:28PM +0100, Jiri Benc wrote:
> > My plan for the next steps has been allowing ptp4l to work with
> > multiple independent PHCs that would form a PTP clock (and rely on
> > phc2sys to sync those PHCs).
> 
> Doesn't my patch #2 do this?

It's surely the intention. I just don't know how it works with things
like servo state shared across all of the ports.

> > This needs separation of struct clock into two
> > structures, as some fields are per-PTP clock and some are per-PHC.
> > I have a patch that does this but it needs to be rebased.
> 
> You mean, the phc2sys 'struct clock', I guess?

I really mean ptp4l.

> Please post the patch, so we see what you are talking about.

See below. It's very outdated, does not apply and is untested. I also
don't like the structure name (although wasn't able to come up with
anything better). It depends on a few more patches but those basically
do some code reorganization only and should not be crucial to
understanding of the intention.

I'm not sure whether this patch was enough to support the boundary
clock or more was needed but I remember I had the boundary clock stuff
done (though untested) and I cannot find anything on top of this, so
this was probably enough.

> > I think this is a prerequisite to having a boundary clock that uses
> > multiple PHCs, I cannot imagine how it could work without this
> > separation.
> 
> So, in the current form, what does the 'automatic' mode (I mean, -a
> without -r) provide? Nothing useful? We can't do a release with half
> baked stuff like that.

-a without -r can indeed be considered as not much useful with the
current code. I intended to send the rebased support for boundary
clock shortly afterwards but as the review was much slower than
I anticipated, I ran out of time allocated for this.

I wouldn't call that half baked but if you want to have the boundary
clock support before a new release, I can try to get some time to work
on this. If it's really needed--maybe your patchset works okay, I admit
I'm not 100% sure, I would have to spend some time looking into the
code, my original patchset is obsolete, the patches it depended on were
redesigned heavily.

Thanks,

 Jiri


commit abf3fde8ff5878b3aeab6ecafeae951ca0d6b876
Author: Jiri Benc 
Date:   Wed Dec 4 16:35:22 2013 +0100

Support for multiple physical clocks

Add support for multiple physical clocks. The "clock" term refers to the PTP
node (as defined in IEEE 1588), the "physical clock" term refers to the
piece of hardware that keeps time.

With this patch, ptp4l still represents a single clock (= single PTP node).
The ports it handles can have separate physical clocks attached, though.
Obviously, such physical clocks have to be synchronized. For now, it is the
responsiblity of the amdinistrator to set up phc2sys to synchronize the
physical clocks in the correct direction. The ultimate plan is to modify
phc2sys to do this automatically.

Signed-off-by: Jiri Benc 

diff --git a/clock.c b/clock.c
index 1bdf18445b13..e70d58f9eb84 100644
--- a/clock.c
+++ b/clock.c
@@ -57,9 +57,19 @@ struct clock_stats {
unsigned int max_count;
 };
 
-struct clock {
+struct phys_clock {
+   LIST_ENTRY(phys_clock) list;
+   struct clock *clock;
clockid_t clkid;
struct servo *servo;
+   enum servo_state servo_state;
+   struct clockcheck *sanity_check;
+   int nports;
+   int phc_index;
+};
+
+struct clock {
+   LIST_HEAD(phys_head, phys_clock) phys;
struct defaultDS dds;
struct dataset default_dataset;
struct currentDS cur;
@@ -79,10 +89,11 @@ struct clock {
int utc_timescale;
int leap_set;
int kernel_leap;
+   int sanity_freq_limit;
+   enum servo_type default_servo;
int utc_offset;  /* grand master role */
int time_flags;  /* grand master role */
int time_source; /* grand master role */
-   enum servo_state servo_state;
tmv_t master_offset;
tmv_t path_delay;
struct filter *delay_filter;
@@ -96,7 +107,6 @@ struct clock {
struct clock_description desc;
struct clock_stats stats;
int stats_interval;
-   struct clockcheck *sanity_check;
 };
 
 struct clock the_clock;
@@ -126,10 +136,6 @@ void clock_destroy(struct clock *c)
}
port_close(c->uds_port);
free(c->pollfd);
-   if (c->clkid != CLOCK_REALTIME) {
-   phc_close(c->clkid);
-   }
-   servo_destroy(c->servo);
filter_destroy(c->delay_filter);
stats_destroy(c->stats.offset);
stats_destroy(c->stats.freq);
@@ -488,8 +494,9 @@ static void clock_update_sla

Re: [Linuxptp-devel] [PATCH RFC 0/3] Poor man's boundary clock

2014-11-05 Thread Jiri Benc
On Wed, 5 Nov 2014 17:34:23 +0100, Richard Cochran wrote:
> I like the idea of "automatic" phc2sys, if it would only work right.

It's definitely not complete yet and I'm not surprised there are bugs
(although I did my best to support also future cases, it's hard to get
it right without the actual code to test it).

My plan for the next steps has been allowing ptp4l to work with multiple
independent PHCs that would form a PTP clock (and rely on phc2sys to
sync those PHCs). This needs separation of struct clock into two
structures, as some fields are per-PTP clock and some are per-PHC.
I have a patch that does this but it needs to be rebased.

I think this is a prerequisite to having a boundary clock that uses
multiple PHCs, I cannot imagine how it could work without this
separation.

What is not solved is the problem that Miroslav pointed out (and also
pointed out to me earlier): the sync messages cannot be sent until the
clock is really synced. This will need further communication between
ptp4l and phc2sys.

I still intend to work on this but have less time to work on linuxptp
than before.

 Jiri

-- 
Jiri Benc

--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 1/1] Restore the peer addresses in P2P mode.

2014-10-09 Thread Jiri Benc
On Thu,  9 Oct 2014 22:09:06 +0200, Richard Cochran wrote:
> Commit ea7a7882 removed the calls to transport_peer(), inadvertently
> substituting them with transport_send(), resulting in PDelay messages
> being sent with an incorrect destination address.
> 
> This patch fixes the issue by introducing peer_prepare_and_send(),
> analogous to the port_prepare_and_send() function.

I probably intended to pass the 'peer' argument to transport_send or
something similar. Sorry for introducing the bug.

Acked-by: Jiri Benc 

-- 
Jiri Benc

--
Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer
Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports
Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper
Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer
http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v5 6/6] Dynamic allocation of interface config entries

2014-08-14 Thread Jiri Benc
Remove the limit of MAX_PORTS ports also when parsing command line
arguments.

Signed-off-by: Jiri Benc 
---
 clock.c  | 11 +-
 clock.h  |  5 ++---
 config.c | 72 +---
 config.h | 11 ++
 ptp4l.c  | 41 +---
 5 files changed, 76 insertions(+), 64 deletions(-)

diff --git a/clock.c b/clock.c
index 76670e655725..726999e4b810 100644
--- a/clock.c
+++ b/clock.c
@@ -785,15 +785,16 @@ static void clock_remove_port(struct clock *c, struct 
port *p)
port_close(p);
 }
 
-struct clock *clock_create(int phc_index, struct interface *iface, int count,
+struct clock *clock_create(int phc_index, struct interfaces_head *ifaces,
   enum timestamp_type timestamping, struct default_ds 
*dds,
   enum servo_type servo)
 {
-   int i, fadj = 0, max_adj = 0.0, sw_ts = timestamping == TS_SOFTWARE ? 1 
: 0;
+   int fadj = 0, max_adj = 0.0, sw_ts = timestamping == TS_SOFTWARE ? 1 : 
0;
struct clock *c = &the_clock;
struct port *p;
char phc[32];
struct interface *udsif = &c->uds_interface;
+   struct interface *iface;
struct timespec ts;
 
clock_gettime(CLOCK_REALTIME, &ts);
@@ -909,9 +910,9 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
clock_fda_changed(c);
 
/* Create the ports. */
-   for (i = 0; i < count; i++) {
-   if (clock_add_port(c, phc_index, timestamping, &iface[i])) {
-   pr_err("failed to open port %s", iface[i].name);
+   STAILQ_FOREACH(iface, ifaces, list) {
+   if (clock_add_port(c, phc_index, timestamping, iface)) {
+   pr_err("failed to open port %s", iface->name);
return NULL;
}
}
diff --git a/clock.h b/clock.h
index 0702aca91715..a2b46be8cc1c 100644
--- a/clock.h
+++ b/clock.h
@@ -63,14 +63,13 @@ UInteger8 clock_class(struct clock *c);
  *
  * @param phc_indexPTP hardware clock device to use.
  * Pass -1 to select CLOCK_REALTIME.
- * @param interfaceAn array of network interfaces.
- * @param countThe number of elements in @a interfaces.
+ * @param ifaces   A queue of network interfaces.
  * @param timestamping The timestamping mode for this clock.
  * @param dds  A pointer to a default data set for the clock.
  * @param servoThe servo that this clock will use.
  * @return A pointer to the single global clock instance.
  */
-struct clock *clock_create(int phc_index, struct interface *iface, int count,
+struct clock *clock_create(int phc_index, struct interfaces_head *ifaces,
   enum timestamp_type timestamping, struct default_ds 
*dds,
   enum servo_type servo);
 
diff --git a/config.c b/config.c
index 0bc85c1ac084..4cee947d1b40 100644
--- a/config.c
+++ b/config.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "config.h"
 #include "ether.h"
@@ -162,40 +163,40 @@ static enum parser_result parse_pod_setting(const char 
*option,
 static enum parser_result parse_port_setting(const char *option,
const char *value,
struct config *cfg,
-   int p)
+   struct interface *iface)
 {
enum parser_result r;
int val;
 
-   r = parse_pod_setting(option, value, &cfg->iface[p].pod);
+   r = parse_pod_setting(option, value, &iface->pod);
if (r != NOT_PARSED)
return r;
 
if (!strcmp(option, "network_transport")) {
if (!strcasecmp("L2", value))
-   cfg->iface[p].transport = TRANS_IEEE_802_3;
+   iface->transport = TRANS_IEEE_802_3;
else if (!strcasecmp("UDPv4", value))
-   cfg->iface[p].transport = TRANS_UDP_IPV4;
+   iface->transport = TRANS_UDP_IPV4;
else if (!strcasecmp("UDPv6", value))
-   cfg->iface[p].transport = TRANS_UDP_IPV6;
+   iface->transport = TRANS_UDP_IPV6;
else
return BAD_VALUE;
 
} else if (!strcmp(option, "delay_mechanism")) {
if (!strcasecmp("Auto", value))
-   cfg->iface[p].dm = DM_AUTO;
+   iface->dm = DM_AUTO;
else if (!strcasecmp("E2E", value))
-   cfg->iface[p].dm = DM_E2E;
+   iface->dm = DM_E2E;
else if (!strcasecmp("P2P", value

[Linuxptp-devel] [PATCH v5 3/6] Dynamic port allocation

2014-08-14 Thread Jiri Benc
Remove the limit of MAX_PORTS ports (default 8) and keep the ports in
a linked list. This allows ptp4l to be used on large machines and in the
future, it will allow dynamic adding and removing of ports while ptp4l is
running.

For this to work, pollfd needs to be dynamically allocated. Changed pollfd
handling from clock_install_fda/clock_remove_fda to notification
(clock_fda_changed), where the clock will rebuild pollfd by querying all its
ports.

Signed-off-by: Jiri Benc 
---
 clock.c | 234 +++-
 clock.h |  15 +
 port.c  |  40 ---
 port.h  |  16 +
 4 files changed, 194 insertions(+), 111 deletions(-)

diff --git a/clock.c b/clock.c
index b487eef2e68d..3c6e5ce318c4 100644
--- a/clock.c
+++ b/clock.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "address.h"
 #include "bmc.h"
@@ -43,7 +44,9 @@
 #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer 
*/
 #define POW2_41 ((double)(1ULL << 41))
 
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+struct port {
+   LIST_ENTRY(port) list;
+};
 
 struct freq_estimator {
tmv_t origin1;
@@ -79,9 +82,9 @@ struct clock {
struct ClockIdentity ptl[PATH_TRACE_MAX];
struct foreign_clock *best;
struct ClockIdentity best_id;
-   struct port *port[MAX_PORTS];
+   LIST_HEAD(ports_head, port) ports;
struct port *uds_port;
-   struct pollfd pollfd[(MAX_PORTS + 1) * N_CLOCK_PFD];
+   struct pollfd *pollfd;
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -115,6 +118,8 @@ struct clock {
 struct clock the_clock;
 
 static void handle_state_decision_event(struct clock *c);
+static int clock_resize_pollfd(struct clock *c, int new_nports);
+static void clock_remove_port(struct clock *c, struct port *p);
 
 static int cid_eq(struct ClockIdentity *a, struct ClockIdentity *b)
 {
@@ -253,12 +258,14 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
 
 void clock_destroy(struct clock *c)
 {
-   int i;
+   struct port *p, *tmp;
 
clock_flush_subscriptions(c);
-   for (i = 0; i < c->nports; i++)
-   port_close(c->port[i]);
+   LIST_FOREACH_SAFE(p, &c->ports, list, tmp) {
+   clock_remove_port(c, p);
+   }
port_close(c->uds_port);
+   free(c->pollfd);
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
}
@@ -273,25 +280,25 @@ void clock_destroy(struct clock *c)
msg_cleanup();
 }
 
-static int clock_fault_timeout(struct clock *c, int index, int set)
+static int clock_fault_timeout(struct port *port, int set)
 {
struct fault_interval i;
 
if (!set) {
-   pr_debug("clearing fault on port %d", index + 1);
-   return port_set_fault_timer_lin(c->port[index], 0);
+   pr_debug("clearing fault on port %d", port_number(port));
+   return port_set_fault_timer_lin(port, 0);
}
 
-   fault_interval(c->port[index], last_fault_type(c->port[index]), &i);
+   fault_interval(port, last_fault_type(port), &i);
 
if (i.type == FTMO_LINEAR_SECONDS) {
pr_debug("waiting %d seconds to clear fault on port %d",
-i.val, index + 1);
-   return port_set_fault_timer_lin(c->port[index], i.val);
+i.val, port_number(port));
+   return port_set_fault_timer_lin(port, i.val);
} else if (i.type == FTMO_LOG2_SECONDS) {
pr_debug("waiting 2^{%d} seconds to clear fault on port %d",
-i.val, index + 1);
-   return port_set_fault_timer_log(c->port[index], 1, i.val);
+i.val, port_number(port));
+   return port_set_fault_timer_log(port, 1, i.val);
}
 
pr_err("Unsupported fault interval type %d", i.type);
@@ -743,12 +750,45 @@ UInteger8 clock_class(struct clock *c)
return c->dds.clockQuality.clockClass;
 }
 
+static int clock_add_port(struct clock *c, int phc_index,
+ enum timestamp_type timestamping, int number,
+ struct interface *iface)
+{
+   struct port *p;
+
+   if (clock_resize_pollfd(c, c->nports + 1))
+   return -1;
+   p = port_open(phc_index, timestamping, number, iface, c);
+   if (!p) {
+   /* No need to shrink pollfd */
+   return -1;
+   }
+   LIST_INSERT_HEAD(&c->ports, p, list);
+   c->nports++;
+   clock_fda_changed(c);
+   return 0;
+}
+
+static void clock_remove_port(struct clock *c, struct port *p)
+{
+   /* Do not call clock_resize_pollfd, it's pointless to shrink
+* t

[Linuxptp-devel] [PATCH v5 4/6] Lazy regeneration of pollfd

2014-08-14 Thread Jiri Benc
There's no need to regenerate pollfd multiple times during batches of port
operations (like creating of the clock). Just be lazy and regenerate it only
once it's needed.

Signed-off-by: Jiri Benc 
---
 clock.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/clock.c b/clock.c
index 3c6e5ce318c4..55a662f73128 100644
--- a/clock.c
+++ b/clock.c
@@ -85,6 +85,7 @@ struct clock {
LIST_HEAD(ports_head, port) ports;
struct port *uds_port;
struct pollfd *pollfd;
+   int pollfd_valid;
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -1002,16 +1003,24 @@ static void clock_fill_pollfd(struct pollfd *dest, 
struct port *p)
dest[i].events = POLLIN|POLLPRI;
 }
 
-void clock_fda_changed(struct clock *c)
+static void clock_check_pollfd(struct clock *c)
 {
struct port *p;
struct pollfd *dest = c->pollfd;
 
+   if (c->pollfd_valid)
+   return;
LIST_FOREACH(p, &c->ports, list) {
clock_fill_pollfd(dest, p);
dest += N_CLOCK_PFD;
}
clock_fill_pollfd(dest, c->uds_port);
+   c->pollfd_valid = 1;
+}
+
+void clock_fda_changed(struct clock *c)
+{
+   c->pollfd_valid = 0;
 }
 
 static int clock_do_forward_mgmt(struct clock *c,
@@ -1212,6 +1221,7 @@ int clock_poll(struct clock *c)
struct pollfd *cur;
struct port *p;
 
+   clock_check_pollfd(c);
cnt = poll(c->pollfd, (c->nports + 1) * N_CLOCK_PFD, -1);
if (cnt < 0) {
if (EINTR == errno) {
-- 
1.8.3.1


--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v5 1/6] Put fault_fd into struct port

2014-08-14 Thread Jiri Benc
The fault timer file descriptor is a per port item, put it inside struct
port where other per port file descriptors are kept.

Signed-off-by: Jiri Benc 
---
 clock.c | 18 +-
 port.c  | 49 -
 port.h  | 29 +
 3 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/clock.c b/clock.c
index 5b251c1498b3..6ed030531e62 100644
--- a/clock.c
+++ b/clock.c
@@ -82,7 +82,6 @@ struct clock {
struct ClockIdentity best_id;
struct port *port[CLK_N_PORTS];
struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD];
-   int fault_fd[CLK_N_PORTS];
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -257,10 +256,8 @@ void clock_destroy(struct clock *c)
int i;
 
clock_flush_subscriptions(c);
-   for (i = 0; i < c->nports; i++) {
+   for (i = 0; i < c->nports; i++)
port_close(c->port[i]);
-   close(c->fault_fd[i]);
-   }
port_close(c->port[i]); /*uds*/
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
@@ -282,7 +279,7 @@ static int clock_fault_timeout(struct clock *c, int index, 
int set)
 
if (!set) {
pr_debug("clearing fault on port %d", index + 1);
-   return set_tmo_lin(c->fault_fd[index], 0);
+   return port_set_fault_timer_lin(c->port[index], 0);
}
 
fault_interval(c->port[index], last_fault_type(c->port[index]), &i);
@@ -290,11 +287,11 @@ static int clock_fault_timeout(struct clock *c, int 
index, int set)
if (i.type == FTMO_LINEAR_SECONDS) {
pr_debug("waiting %d seconds to clear fault on port %d",
 i.val, index + 1);
-   return set_tmo_lin(c->fault_fd[index], i.val);
+   return port_set_fault_timer_lin(c->port[index], i.val);
} else if (i.type == FTMO_LOG2_SECONDS) {
pr_debug("waiting 2^{%d} seconds to clear fault on port %d",
 i.val, index + 1);
-   return set_tmo_log(c->fault_fd[index], 1, i.val);
+   return port_set_fault_timer_log(c->port[index], 1, i.val);
}
 
pr_err("Unsupported fault interval type %d", i.type);
@@ -863,12 +860,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
pr_err("failed to open port %s", iface[i].name);
return NULL;
}
-   c->fault_fd[i] = timerfd_create(CLOCK_MONOTONIC, 0);
-   if (c->fault_fd[i] < 0) {
-   pr_err("timerfd_create failed: %m");
-   return NULL;
-   }
-   c->pollfd[N_CLOCK_PFD * i + N_POLLFD].fd = c->fault_fd[i];
+   c->pollfd[N_CLOCK_PFD * i + N_POLLFD].fd = 
port_fault_fd(c->port[i]);
c->pollfd[N_CLOCK_PFD * i + N_POLLFD].events = POLLIN|POLLPRI;
}
 
diff --git a/port.c b/port.c
index 080bc8e70e38..bd1b1784dc39 100644
--- a/port.c
+++ b/port.c
@@ -65,6 +65,7 @@ struct port {
struct transport *trp;
enum timestamp_type timestamping;
struct fdarray fda;
+   int fault_fd;
struct foreign_clock *best;
enum syfu_state syfu;
struct ptp_message *last_syncfup;
@@ -193,6 +194,11 @@ int fault_interval(struct port *port, enum fault_type ft,
return 0;
 }
 
+int port_fault_fd(struct port *port)
+{
+   return port->fault_fd;
+}
+
 int set_tmo_log(int fd, unsigned int scale, int log_seconds)
 {
struct itimerspec tmo = {
@@ -253,6 +259,17 @@ int set_tmo_random(int fd, int min, int span, int 
log_seconds)
return timerfd_settime(fd, 0, &tmo, NULL);
 }
 
+int port_set_fault_timer_log(struct port *port,
+unsigned int scale, int log_seconds)
+{
+   return set_tmo_log(port->fault_fd, scale, log_seconds);
+}
+
+int port_set_fault_timer_lin(struct port *port, int seconds)
+{
+   return set_tmo_lin(port->fault_fd, seconds);
+}
+
 static void fc_clear(struct foreign_clock *fc)
 {
struct ptp_message *m;
@@ -1903,6 +1920,8 @@ void port_close(struct port *p)
}
transport_destroy(p->trp);
filter_destroy(p->delay_filter);
+   if (p->fault_fd >= 0)
+   close(p->fault_fd);
free(p);
 }
 
@@ -2408,18 +2427,15 @@ struct port *port_open(int phc_index,
pr_err("port %d: PHC device mismatch", number);
pr_err("port %d: /dev/ptp%d requested, but /dev/ptp%d attached",
   number, phc_index, interface->ts_info.phc_index);
-   free(p);
-   return NULL;
+   goto er

[Linuxptp-devel] [PATCH v5 0/6] Dynamic port allocation

2014-08-14 Thread Jiri Benc
Currently, there's a limit of MAX_PORTS ports (8 by default). This patchset
removes this limitation by using linked lists instead of fixed size arrays.

The core patches are 3/6 and 6/6, the rest are prerequisites: patch 1/6 is
moving per-port fields from struct clock to individual ports in order not to
have to maintain several linked lists, patch 2/6 moves the uds port from the
port array, as having it a part of linked list would make the various checks
for uds port unnecessary complicated, patch 5/6 replaces the port numbering
that is based on array of interface names by a per clock counter. The
remaining patch, 4/6, is a follow up optimization to 3/6.

Changes in v5: rebased. Addressed Richard's comments (comment in
clock_remove_port, calloc and cleanup of iface config).

Changes in v4: rebased on top of the current git.

Changes in v3: used the BSD implementation of LIST_FOREACH_SAFE, using the
system one where available.

Changes in v2: rebased on top of the current git, resolved warnings reported
by Richard.

Jiri Benc (6):
  Put fault_fd into struct port
  Make uds port a separate field in struct clock
  Dynamic port allocation
  Lazy regeneration of pollfd
  Remember last used port number
  Dynamic allocation of interface config entries

 clock.c  | 310 ++-
 clock.h  |  20 ++---
 config.c |  72 ---
 config.h |  11 ++-
 port.c   |  89 ++
 port.h   |  45 ++
 ptp4l.c  |  41 -
 7 files changed, 380 insertions(+), 208 deletions(-)

-- 
1.8.3.1


--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v5 2/6] Make uds port a separate field in struct clock

2014-08-14 Thread Jiri Benc
The uds port is handled specially in almost all cases, it doesn't behave
like the rest of ports in the port array. Make it a standalone member of
struct clock.

Signed-off-by: Jiri Benc 
---
 clock.c | 78 +
 1 file changed, 45 insertions(+), 33 deletions(-)

diff --git a/clock.c b/clock.c
index 6ed030531e62..b487eef2e68d 100644
--- a/clock.c
+++ b/clock.c
@@ -40,7 +40,6 @@
 #include "uds.h"
 #include "util.h"
 
-#define CLK_N_PORTS (MAX_PORTS + 1) /* plus one for the UDS interface */
 #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer 
*/
 #define POW2_41 ((double)(1ULL << 41))
 
@@ -80,8 +79,9 @@ struct clock {
struct ClockIdentity ptl[PATH_TRACE_MAX];
struct foreign_clock *best;
struct ClockIdentity best_id;
-   struct port *port[CLK_N_PORTS];
-   struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD];
+   struct port *port[MAX_PORTS];
+   struct port *uds_port;
+   struct pollfd pollfd[(MAX_PORTS + 1) * N_CLOCK_PFD];
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -233,7 +233,7 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
 {
unsigned int event_pos = event / 8;
uint8_t mask = 1 << (event % 8);
-   struct port *uds = c->port[c->nports];
+   struct port *uds = c->uds_port;
struct clock_subscriber *s;
 
LIST_FOREACH(s, &c->subscribers, list) {
@@ -258,7 +258,7 @@ void clock_destroy(struct clock *c)
clock_flush_subscriptions(c);
for (i = 0; i < c->nports; i++)
port_close(c->port[i]);
-   port_close(c->port[i]); /*uds*/
+   port_close(c->uds_port);
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
}
@@ -430,7 +430,7 @@ static int clock_management_fill_response(struct clock *c, 
struct port *p,
respond = 1;
break;
case TLV_SUBSCRIBE_EVENTS_NP:
-   if (p != c->port[c->nports]) {
+   if (p != c->uds_port) {
/* Only the UDS port allowed. */
break;
}
@@ -730,7 +730,7 @@ static int forwarding(struct clock *c, struct port *p)
default:
break;
}
-   if (p == c->port[c->nports] && ps != PS_FAULTY) { /*uds*/
+   if (p == c->uds_port && ps != PS_FAULTY) {
return 1;
}
return 0;
@@ -865,10 +865,10 @@ struct clock *clock_create(int phc_index, struct 
interface *iface, int count,
}
 
/*
-* One extra port is for the UDS interface.
+* Create the UDS interface.
 */
-   c->port[i] = port_open(phc_index, timestamping, 0, udsif, c);
-   if (!c->port[i]) {
+   c->uds_port = port_open(phc_index, timestamping, 0, udsif, c);
+   if (!c->uds_port) {
pr_err("failed to open the UDS port");
return NULL;
}
@@ -878,7 +878,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
for (i = 0; i < c->nports; i++)
port_dispatch(c->port[i], EV_INITIALIZE, 0);
 
-   port_dispatch(c->port[i], EV_INITIALIZE, 0); /*uds*/
+   port_dispatch(c->uds_port, EV_INITIALIZE, 0);
 
return c;
 }
@@ -938,10 +938,13 @@ struct ClockIdentity clock_identity(struct clock *c)
 void clock_install_fda(struct clock *c, struct port *p, struct fdarray fda)
 {
int i, j, k;
-   for (i = 0; i < c->nports + 1; i++) {
+
+   for (i = 0; i < c->nports; i++) {
if (p == c->port[i])
break;
}
+   if (p == c->uds_port)
+   i = c->nports;
for (j = 0; j < N_POLLFD; j++) {
k = N_CLOCK_PFD * i + j;
c->pollfd[k].fd = fda.fd[j];
@@ -949,26 +952,33 @@ void clock_install_fda(struct clock *c, struct port *p, 
struct fdarray fda)
}
 }
 
+static int clock_do_forward_mgmt(struct clock *c,
+struct port *in, struct port *out,
+struct ptp_message *msg, int *pre_sent)
+{
+   if (in == out || !forwarding(c, out))
+   return 0;
+   if (!*pre_sent) {
+   /* delay calling msg_pre_send until
+* actually forwarding */
+   msg_pre_send(msg);
+   *pre_sent = 1;
+   }
+   return port_forward(out, msg);
+}
+
 static void clock_forward_mgmt_msg(struct clock *c, struct port *p, struct 
ptp_message *msg)
 {
int i, pdulen = 0, msg_ready = 0;
-   struct port *fwd;
+
if (forwarding(c, p) && msg->management.boundaryHops) {
-   for (i = 0; i < c

[Linuxptp-devel] [PATCH v5 5/6] Remember last used port number

2014-08-14 Thread Jiri Benc
For the ports to be truly created and removed dynamically, the last used
port number has to be remembered by the clock and used for port creation.

Signed-off-by: Jiri Benc 
---
 clock.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/clock.c b/clock.c
index 55a662f73128..76670e655725 100644
--- a/clock.c
+++ b/clock.c
@@ -87,6 +87,7 @@ struct clock {
struct pollfd *pollfd;
int pollfd_valid;
int nports; /* does not include the UDS port */
+   int last_port_number;
int free_running;
int freq_est_interval;
int grand_master_capable; /* for 802.1AS only */
@@ -752,14 +753,15 @@ UInteger8 clock_class(struct clock *c)
 }
 
 static int clock_add_port(struct clock *c, int phc_index,
- enum timestamp_type timestamping, int number,
+ enum timestamp_type timestamping,
  struct interface *iface)
 {
struct port *p;
 
if (clock_resize_pollfd(c, c->nports + 1))
return -1;
-   p = port_open(phc_index, timestamping, number, iface, c);
+   p = port_open(phc_index, timestamping, ++c->last_port_number,
+ iface, c);
if (!p) {
/* No need to shrink pollfd */
return -1;
@@ -890,6 +892,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
 
LIST_INIT(&c->subscribers);
LIST_INIT(&c->ports);
+   c->last_port_number = 0;
 
/*
 * Create the UDS interface.
@@ -907,7 +910,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
 
/* Create the ports. */
for (i = 0; i < count; i++) {
-   if (clock_add_port(c, phc_index, timestamping, i + 1, 
&iface[i])) {
+   if (clock_add_port(c, phc_index, timestamping, &iface[i])) {
pr_err("failed to open port %s", iface[i].name);
return NULL;
}
-- 
1.8.3.1


--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v4 3/6] Dynamic port allocation

2014-08-14 Thread Jiri Benc
On Sat, 19 Jul 2014 09:33:38 +0200, Richard Cochran wrote:
> Sorry, just getting around to this. My general impression is that the
> series looks good. Two comments below, but neither are show stoppers.

Thanks. Sorry for the long delay, this time on my part because of summer
vacation and all things that piled up while I was off.

> > +struct port {
> > +   LIST_ENTRY(port) list;
> > +};
> 
> I almost objected to this, as a matter of principle, because it is
> more clean to have truly opaque objects. But on second thought, adding
> a wrapper around the port is extra busy work (malloc/free) without
> much benefit. So this is fine as is, but let's not get into the habit
> of "friend" classes, if you know what I mean.

Yes. I don't like it myself but I was not able to come up with anything
nicer. The most clean way would be to define

struct port_public {
LIST_ENTRY(port_public) list;
};

and modify struct public to look like:

struct port {
struct port_public public;
char *name;
struct clock *clock;
...
};

This is highly unpractical, though.

> > +static void clock_remove_port(struct clock *c, struct port *p)
> > +{
> > +   /* Do not bother with pollfd resizing, we don't mind if it's a bit
> > +* larger than needed and clock_destroy takes care of freeing it in
> > +* case we're shutting down. */
> 
> This comment is confusing. The only caller of clock_remove_port is
> clock_destroy anyhow.

Okay, fair enough.

> Should there be more callers one day, then to me
> it is more important to know that port_close sets all of the port's
> FDs to -1.

I'm not sure I follow. port_close destroys the port structure
completely. As part of the port removal, number of ports is decreased,
so pollfd contains always only fds for those ports that are present. No
-1's for removed ports.

 Jiri

-- 
Jiri Benc

--
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v4 3/6] Dynamic port allocation

2014-06-27 Thread Jiri Benc
Remove the limit of MAX_PORTS ports (default 8) and keep the ports in
a linked list. This allows ptp4l to be used on large machines and in the
future, it will allow dynamic adding and removing of ports while ptp4l is
running.

For this to work, pollfd needs to be dynamically allocated. Changed pollfd
handling from clock_install_fda/clock_remove_fda to notification
(clock_fda_changed), where the clock will rebuild pollfd by querying all its
ports.

Signed-off-by: Jiri Benc 
---
 clock.c |  232 ++-
 clock.h |   15 +---
 port.c  |   40 +--
 port.h  |   16 +
 4 files changed, 192 insertions(+), 111 deletions(-)

diff --git a/clock.c b/clock.c
index b561e63725e1..99b4b49d418c 100644
--- a/clock.c
+++ b/clock.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "address.h"
 #include "bmc.h"
@@ -43,7 +44,9 @@
 #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer 
*/
 #define POW2_41 ((double)(1ULL << 41))
 
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+struct port {
+   LIST_ENTRY(port) list;
+};
 
 struct freq_estimator {
tmv_t origin1;
@@ -79,9 +82,9 @@ struct clock {
struct ClockIdentity ptl[PATH_TRACE_MAX];
struct foreign_clock *best;
struct ClockIdentity best_id;
-   struct port *port[MAX_PORTS];
+   LIST_HEAD(ports_head, port) ports;
struct port *uds_port;
-   struct pollfd pollfd[(MAX_PORTS + 1) * N_CLOCK_PFD];
+   struct pollfd *pollfd;
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -115,6 +118,8 @@ struct clock {
 struct clock the_clock;
 
 static void handle_state_decision_event(struct clock *c);
+static int clock_resize_pollfd(struct clock *c, int new_nports);
+static void clock_remove_port(struct clock *c, struct port *p);
 
 static int cid_eq(struct ClockIdentity *a, struct ClockIdentity *b)
 {
@@ -253,12 +258,14 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
 
 void clock_destroy(struct clock *c)
 {
-   int i;
+   struct port *p, *tmp;
 
clock_flush_subscriptions(c);
-   for (i = 0; i < c->nports; i++)
-   port_close(c->port[i]);
+   LIST_FOREACH_SAFE(p, &c->ports, list, tmp) {
+   clock_remove_port(c, p);
+   }
port_close(c->uds_port);
+   free(c->pollfd);
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
}
@@ -273,25 +280,25 @@ void clock_destroy(struct clock *c)
msg_cleanup();
 }
 
-static int clock_fault_timeout(struct clock *c, int index, int set)
+static int clock_fault_timeout(struct port *port, int set)
 {
struct fault_interval i;
 
if (!set) {
-   pr_debug("clearing fault on port %d", index + 1);
-   return port_set_fault_timer_lin(c->port[index], 0);
+   pr_debug("clearing fault on port %d", port_number(port));
+   return port_set_fault_timer_lin(port, 0);
}
 
-   fault_interval(c->port[index], last_fault_type(c->port[index]), &i);
+   fault_interval(port, last_fault_type(port), &i);
 
if (i.type == FTMO_LINEAR_SECONDS) {
pr_debug("waiting %d seconds to clear fault on port %d",
-i.val, index + 1);
-   return port_set_fault_timer_lin(c->port[index], i.val);
+i.val, port_number(port));
+   return port_set_fault_timer_lin(port, i.val);
} else if (i.type == FTMO_LOG2_SECONDS) {
pr_debug("waiting 2^{%d} seconds to clear fault on port %d",
-i.val, index + 1);
-   return port_set_fault_timer_log(c->port[index], 1, i.val);
+i.val, port_number(port));
+   return port_set_fault_timer_log(port, 1, i.val);
}
 
pr_err("Unsupported fault interval type %d", i.type);
@@ -743,12 +750,43 @@ UInteger8 clock_class(struct clock *c)
return c->dds.clockQuality.clockClass;
 }
 
+static int clock_add_port(struct clock *c, int phc_index,
+ enum timestamp_type timestamping, int number,
+ struct interface *iface)
+{
+   struct port *p;
+
+   if (clock_resize_pollfd(c, c->nports + 1))
+   return -1;
+   p = port_open(phc_index, timestamping, number, iface, c);
+   if (!p) {
+   /* No need to shrink pollfd */
+   return -1;
+   }
+   LIST_INSERT_HEAD(&c->ports, p, list);
+   c->nports++;
+   clock_fda_changed(c);
+   return 0;
+}
+
+static void clock_remove_port(struct clock *c, struct port *p)
+{
+   /* Do not bother with pollfd resizing, we don't mind if it's a bit
+ 

[Linuxptp-devel] [PATCH v4 1/6] Put fault_fd into struct port

2014-06-27 Thread Jiri Benc
The fault timer file descriptor is a per port item, put it inside struct
port where other per port file descriptors are kept.

Signed-off-by: Jiri Benc 
---
 clock.c |   18 +-
 port.c  |   49 -
 port.h  |   29 +
 3 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/clock.c b/clock.c
index ddea72f059e1..a11971efa646 100644
--- a/clock.c
+++ b/clock.c
@@ -82,7 +82,6 @@ struct clock {
struct ClockIdentity best_id;
struct port *port[CLK_N_PORTS];
struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD];
-   int fault_fd[CLK_N_PORTS];
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -257,10 +256,8 @@ void clock_destroy(struct clock *c)
int i;
 
clock_flush_subscriptions(c);
-   for (i = 0; i < c->nports; i++) {
+   for (i = 0; i < c->nports; i++)
port_close(c->port[i]);
-   close(c->fault_fd[i]);
-   }
port_close(c->port[i]); /*uds*/
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
@@ -282,7 +279,7 @@ static int clock_fault_timeout(struct clock *c, int index, 
int set)
 
if (!set) {
pr_debug("clearing fault on port %d", index + 1);
-   return set_tmo_lin(c->fault_fd[index], 0);
+   return port_set_fault_timer_lin(c->port[index], 0);
}
 
fault_interval(c->port[index], last_fault_type(c->port[index]), &i);
@@ -290,11 +287,11 @@ static int clock_fault_timeout(struct clock *c, int 
index, int set)
if (i.type == FTMO_LINEAR_SECONDS) {
pr_debug("waiting %d seconds to clear fault on port %d",
 i.val, index + 1);
-   return set_tmo_lin(c->fault_fd[index], i.val);
+   return port_set_fault_timer_lin(c->port[index], i.val);
} else if (i.type == FTMO_LOG2_SECONDS) {
pr_debug("waiting 2^{%d} seconds to clear fault on port %d",
 i.val, index + 1);
-   return set_tmo_log(c->fault_fd[index], 1, i.val);
+   return port_set_fault_timer_log(c->port[index], 1, i.val);
}
 
pr_err("Unsupported fault interval type %d", i.type);
@@ -863,12 +860,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
pr_err("failed to open port %s", iface[i].name);
return NULL;
}
-   c->fault_fd[i] = timerfd_create(CLOCK_MONOTONIC, 0);
-   if (c->fault_fd[i] < 0) {
-   pr_err("timerfd_create failed: %m");
-   return NULL;
-   }
-   c->pollfd[N_CLOCK_PFD * i + N_POLLFD].fd = c->fault_fd[i];
+   c->pollfd[N_CLOCK_PFD * i + N_POLLFD].fd = 
port_fault_fd(c->port[i]);
c->pollfd[N_CLOCK_PFD * i + N_POLLFD].events = POLLIN|POLLPRI;
}
 
diff --git a/port.c b/port.c
index 63fabc103038..e2131c4d8693 100644
--- a/port.c
+++ b/port.c
@@ -65,6 +65,7 @@ struct port {
struct transport *trp;
enum timestamp_type timestamping;
struct fdarray fda;
+   int fault_fd;
struct foreign_clock *best;
enum syfu_state syfu;
struct ptp_message *last_syncfup;
@@ -193,6 +194,11 @@ int fault_interval(struct port *port, enum fault_type ft,
return 0;
 }
 
+int port_fault_fd(struct port *port)
+{
+   return port->fault_fd;
+}
+
 int set_tmo_log(int fd, unsigned int scale, int log_seconds)
 {
struct itimerspec tmo = {
@@ -253,6 +259,17 @@ int set_tmo_random(int fd, int min, int span, int 
log_seconds)
return timerfd_settime(fd, 0, &tmo, NULL);
 }
 
+int port_set_fault_timer_log(struct port *port,
+unsigned int scale, int log_seconds)
+{
+   return set_tmo_log(port->fault_fd, scale, log_seconds);
+}
+
+int port_set_fault_timer_lin(struct port *port, int seconds)
+{
+   return set_tmo_lin(port->fault_fd, seconds);
+}
+
 static void fc_clear(struct foreign_clock *fc)
 {
struct ptp_message *m;
@@ -1903,6 +1920,8 @@ void port_close(struct port *p)
}
transport_destroy(p->trp);
filter_destroy(p->delay_filter);
+   if (p->fault_fd >= 0)
+   close(p->fault_fd);
free(p);
 }
 
@@ -2408,18 +2427,15 @@ struct port *port_open(int phc_index,
pr_err("port %d: PHC device mismatch", number);
pr_err("port %d: /dev/ptp%d requested, but /dev/ptp%d attached",
   number, phc_index, interface->ts_info.phc_index);
-   free(p);
-   return NULL;
+   goto er

[Linuxptp-devel] [PATCH v4 0/6] Dynamic port allocation

2014-06-27 Thread Jiri Benc
This is a rebase of the dynamic port allocation patchset from the last year.

Currently, there's a limit of MAX_PORTS ports (8 by default). This patchset
removes this limitation by using linked lists instead of fixed size arrays.

The core patches are 3/6 and 6/6, the rest are prerequisites: patch 1/6 is
moving per-port fields from struct clock to individual ports in order not to
have to maintain several linked lists, patch 2/6 moves the uds port from the
port array, as having it a part of linked list would make the various checks
for uds port unnecessary complicated, patch 5/6 replaces the port numbering
that is based on array of interface names by a per clock counter. The
remaining patch, 4/6, is a follow up optimization to 3/6.

Changes in v4: rebased on top of the current git.

Changes in v3: used the BSD implementation of LIST_FOREACH_SAFE, using the
system one where available.

Changes in v2: rebased on top of the current git, resolved warnings reported
by Richard.

Jiri Benc (6):
  Put fault_fd into struct port
  Make uds port a separate field in struct clock
  Dynamic port allocation
  Lazy regeneration of pollfd
  Remember last used port number
  Dynamic allocation of interface config entries

 clock.c  |  308 ++
 clock.h  |   20 +---
 config.c |   66 +++---
 config.h |   10 +-
 port.c   |   89 +++
 port.h   |   45 +
 ptp4l.c  |   40 -
 7 files changed, 368 insertions(+), 210 deletions(-)

-- 
1.7.6.5


--
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v4 6/6] Dynamic allocation of interface config entries

2014-06-27 Thread Jiri Benc
Remove the limit of MAX_PORTS ports also when parsing command line
arguments.

Signed-off-by: Jiri Benc 
---
 clock.c  |   11 +
 clock.h  |5 +--
 config.c |   66 +++--
 config.h |   10 +---
 ptp4l.c  |   40 
 5 files changed, 66 insertions(+), 66 deletions(-)

diff --git a/clock.c b/clock.c
index 09ea385443ab..dde508f0a17f 100644
--- a/clock.c
+++ b/clock.c
@@ -783,15 +783,16 @@ static void clock_remove_port(struct clock *c, struct 
port *p)
port_close(p);
 }
 
-struct clock *clock_create(int phc_index, struct interface *iface, int count,
+struct clock *clock_create(int phc_index, struct interfaces_head *ifaces,
   enum timestamp_type timestamping, struct default_ds 
*dds,
   enum servo_type servo)
 {
-   int i, fadj = 0, max_adj = 0.0, sw_ts = timestamping == TS_SOFTWARE ? 1 
: 0;
+   int fadj = 0, max_adj = 0.0, sw_ts = timestamping == TS_SOFTWARE ? 1 : 
0;
struct clock *c = &the_clock;
struct port *p;
char phc[32];
struct interface *udsif = &c->uds_interface;
+   struct interface *iface;
struct timespec ts;
 
clock_gettime(CLOCK_REALTIME, &ts);
@@ -907,9 +908,9 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
clock_fda_changed(c);
 
/* Create the ports. */
-   for (i = 0; i < count; i++) {
-   if (clock_add_port(c, phc_index, timestamping, &iface[i])) {
-   pr_err("failed to open port %s", iface[i].name);
+   STAILQ_FOREACH(iface, ifaces, list) {
+   if (clock_add_port(c, phc_index, timestamping, iface)) {
+   pr_err("failed to open port %s", iface->name);
return NULL;
}
}
diff --git a/clock.h b/clock.h
index 0702aca91715..a2b46be8cc1c 100644
--- a/clock.h
+++ b/clock.h
@@ -63,14 +63,13 @@ UInteger8 clock_class(struct clock *c);
  *
  * @param phc_indexPTP hardware clock device to use.
  * Pass -1 to select CLOCK_REALTIME.
- * @param interfaceAn array of network interfaces.
- * @param countThe number of elements in @a interfaces.
+ * @param ifaces   A queue of network interfaces.
  * @param timestamping The timestamping mode for this clock.
  * @param dds  A pointer to a default data set for the clock.
  * @param servoThe servo that this clock will use.
  * @return A pointer to the single global clock instance.
  */
-struct clock *clock_create(int phc_index, struct interface *iface, int count,
+struct clock *clock_create(int phc_index, struct interfaces_head *ifaces,
   enum timestamp_type timestamping, struct default_ds 
*dds,
   enum servo_type servo);
 
diff --git a/config.c b/config.c
index 0bc85c1ac084..5fcd2150a88e 100644
--- a/config.c
+++ b/config.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "config.h"
 #include "ether.h"
@@ -162,40 +163,40 @@ static enum parser_result parse_pod_setting(const char 
*option,
 static enum parser_result parse_port_setting(const char *option,
const char *value,
struct config *cfg,
-   int p)
+   struct interface *iface)
 {
enum parser_result r;
int val;
 
-   r = parse_pod_setting(option, value, &cfg->iface[p].pod);
+   r = parse_pod_setting(option, value, &iface->pod);
if (r != NOT_PARSED)
return r;
 
if (!strcmp(option, "network_transport")) {
if (!strcasecmp("L2", value))
-   cfg->iface[p].transport = TRANS_IEEE_802_3;
+   iface->transport = TRANS_IEEE_802_3;
else if (!strcasecmp("UDPv4", value))
-   cfg->iface[p].transport = TRANS_UDP_IPV4;
+   iface->transport = TRANS_UDP_IPV4;
else if (!strcasecmp("UDPv6", value))
-   cfg->iface[p].transport = TRANS_UDP_IPV6;
+   iface->transport = TRANS_UDP_IPV6;
else
return BAD_VALUE;
 
} else if (!strcmp(option, "delay_mechanism")) {
if (!strcasecmp("Auto", value))
-   cfg->iface[p].dm = DM_AUTO;
+   iface->dm = DM_AUTO;
else if (!strcasecmp("E2E", value))
-   cfg->iface[p].dm = DM_E2E;
+   iface->dm = DM_E2E;
else if (!strcasecmp("P2P&quo

[Linuxptp-devel] [PATCH v4 4/6] Lazy regeneration of pollfd

2014-06-27 Thread Jiri Benc
There's no need to regenerate pollfd multiple times during batches of port
operations (like creating of the clock). Just be lazy and regenerate it only
once it's needed.

Signed-off-by: Jiri Benc 
---
 clock.c |   12 +++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/clock.c b/clock.c
index 99b4b49d418c..f70e87bb7239 100644
--- a/clock.c
+++ b/clock.c
@@ -85,6 +85,7 @@ struct clock {
LIST_HEAD(ports_head, port) ports;
struct port *uds_port;
struct pollfd *pollfd;
+   int pollfd_valid;
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -1000,16 +1001,24 @@ static void clock_fill_pollfd(struct pollfd *dest, 
struct port *p)
dest[i].events = POLLIN|POLLPRI;
 }
 
-void clock_fda_changed(struct clock *c)
+static void clock_check_pollfd(struct clock *c)
 {
struct port *p;
struct pollfd *dest = c->pollfd;
 
+   if (c->pollfd_valid)
+   return;
LIST_FOREACH(p, &c->ports, list) {
clock_fill_pollfd(dest, p);
dest += N_CLOCK_PFD;
}
clock_fill_pollfd(dest, c->uds_port);
+   c->pollfd_valid = 1;
+}
+
+void clock_fda_changed(struct clock *c)
+{
+   c->pollfd_valid = 0;
 }
 
 static int clock_do_forward_mgmt(struct clock *c,
@@ -1210,6 +1219,7 @@ int clock_poll(struct clock *c)
struct pollfd *cur;
struct port *p;
 
+   clock_check_pollfd(c);
cnt = poll(c->pollfd, (c->nports + 1) * N_CLOCK_PFD, -1);
if (cnt < 0) {
if (EINTR == errno) {
-- 
1.7.6.5


--
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v4 2/6] Make uds port a separate field in struct clock

2014-06-27 Thread Jiri Benc
The uds port is handled specially in almost all cases, it doesn't behave
like the rest of ports in the port array. Make it a standalone member of
struct clock.

Signed-off-by: Jiri Benc 
---
 clock.c |   78 --
 1 files changed, 45 insertions(+), 33 deletions(-)

diff --git a/clock.c b/clock.c
index a11971efa646..b561e63725e1 100644
--- a/clock.c
+++ b/clock.c
@@ -40,7 +40,6 @@
 #include "uds.h"
 #include "util.h"
 
-#define CLK_N_PORTS (MAX_PORTS + 1) /* plus one for the UDS interface */
 #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer 
*/
 #define POW2_41 ((double)(1ULL << 41))
 
@@ -80,8 +79,9 @@ struct clock {
struct ClockIdentity ptl[PATH_TRACE_MAX];
struct foreign_clock *best;
struct ClockIdentity best_id;
-   struct port *port[CLK_N_PORTS];
-   struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD];
+   struct port *port[MAX_PORTS];
+   struct port *uds_port;
+   struct pollfd pollfd[(MAX_PORTS + 1) * N_CLOCK_PFD];
int nports; /* does not include the UDS port */
int free_running;
int freq_est_interval;
@@ -233,7 +233,7 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
 {
unsigned int event_pos = event / 8;
uint8_t mask = 1 << (event % 8);
-   struct port *uds = c->port[c->nports];
+   struct port *uds = c->uds_port;
struct clock_subscriber *s;
 
LIST_FOREACH(s, &c->subscribers, list) {
@@ -258,7 +258,7 @@ void clock_destroy(struct clock *c)
clock_flush_subscriptions(c);
for (i = 0; i < c->nports; i++)
port_close(c->port[i]);
-   port_close(c->port[i]); /*uds*/
+   port_close(c->uds_port);
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
}
@@ -430,7 +430,7 @@ static int clock_management_fill_response(struct clock *c, 
struct port *p,
respond = 1;
break;
case SUBSCRIBE_EVENTS_NP:
-   if (p != c->port[c->nports]) {
+   if (p != c->uds_port) {
/* Only the UDS port allowed. */
break;
}
@@ -730,7 +730,7 @@ static int forwarding(struct clock *c, struct port *p)
default:
break;
}
-   if (p == c->port[c->nports] && ps != PS_FAULTY) { /*uds*/
+   if (p == c->uds_port && ps != PS_FAULTY) {
return 1;
}
return 0;
@@ -865,10 +865,10 @@ struct clock *clock_create(int phc_index, struct 
interface *iface, int count,
}
 
/*
-* One extra port is for the UDS interface.
+* Create the UDS interface.
 */
-   c->port[i] = port_open(phc_index, timestamping, 0, udsif, c);
-   if (!c->port[i]) {
+   c->uds_port = port_open(phc_index, timestamping, 0, udsif, c);
+   if (!c->uds_port) {
pr_err("failed to open the UDS port");
return NULL;
}
@@ -878,7 +878,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
for (i = 0; i < c->nports; i++)
port_dispatch(c->port[i], EV_INITIALIZE, 0);
 
-   port_dispatch(c->port[i], EV_INITIALIZE, 0); /*uds*/
+   port_dispatch(c->uds_port, EV_INITIALIZE, 0);
 
return c;
 }
@@ -938,10 +938,13 @@ struct ClockIdentity clock_identity(struct clock *c)
 void clock_install_fda(struct clock *c, struct port *p, struct fdarray fda)
 {
int i, j, k;
-   for (i = 0; i < c->nports + 1; i++) {
+
+   for (i = 0; i < c->nports; i++) {
if (p == c->port[i])
break;
}
+   if (p == c->uds_port)
+   i = c->nports;
for (j = 0; j < N_POLLFD; j++) {
k = N_CLOCK_PFD * i + j;
c->pollfd[k].fd = fda.fd[j];
@@ -949,26 +952,33 @@ void clock_install_fda(struct clock *c, struct port *p, 
struct fdarray fda)
}
 }
 
+static int clock_do_forward_mgmt(struct clock *c,
+struct port *in, struct port *out,
+struct ptp_message *msg, int *pre_sent)
+{
+   if (in == out || !forwarding(c, out))
+   return 0;
+   if (!*pre_sent) {
+   /* delay calling msg_pre_send until
+* actually forwarding */
+   msg_pre_send(msg);
+   *pre_sent = 1;
+   }
+   return port_forward(out, msg);
+}
+
 static void clock_forward_mgmt_msg(struct clock *c, struct port *p, struct 
ptp_message *msg)
 {
int i, pdulen = 0, msg_ready = 0;
-   struct port *fwd;
+
if (forwarding(c, p) && msg->management.boundaryHops) {
-   for (i = 0; i < c

[Linuxptp-devel] [PATCH v4 5/6] Remember last used port number

2014-06-27 Thread Jiri Benc
For the ports to be truly created and removed dynamically, the last used
port number has to be remembered by the clock and used for port creation.

Signed-off-by: Jiri Benc 
---
 clock.c |9 ++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/clock.c b/clock.c
index f70e87bb7239..09ea385443ab 100644
--- a/clock.c
+++ b/clock.c
@@ -87,6 +87,7 @@ struct clock {
struct pollfd *pollfd;
int pollfd_valid;
int nports; /* does not include the UDS port */
+   int last_port_number;
int free_running;
int freq_est_interval;
int grand_master_capable; /* for 802.1AS only */
@@ -752,14 +753,15 @@ UInteger8 clock_class(struct clock *c)
 }
 
 static int clock_add_port(struct clock *c, int phc_index,
- enum timestamp_type timestamping, int number,
+ enum timestamp_type timestamping,
  struct interface *iface)
 {
struct port *p;
 
if (clock_resize_pollfd(c, c->nports + 1))
return -1;
-   p = port_open(phc_index, timestamping, number, iface, c);
+   p = port_open(phc_index, timestamping, ++c->last_port_number,
+ iface, c);
if (!p) {
/* No need to shrink pollfd */
return -1;
@@ -888,6 +890,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
 
LIST_INIT(&c->subscribers);
LIST_INIT(&c->ports);
+   c->last_port_number = 0;
 
/*
 * Create the UDS interface.
@@ -905,7 +908,7 @@ struct clock *clock_create(int phc_index, struct interface 
*iface, int count,
 
/* Create the ports. */
for (i = 0; i < count; i++) {
-   if (clock_add_port(c, phc_index, timestamping, i + 1, 
&iface[i])) {
+   if (clock_add_port(c, phc_index, timestamping, &iface[i])) {
pr_err("failed to open port %s", iface[i].name);
return NULL;
}
-- 
1.7.6.5


--
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] phc2sys detecting ptp4l exit (was: Re: [PATCH v2 00/27] automatic phc2sys configuration)

2014-06-20 Thread Jiri Benc
On Fri, 20 Jun 2014 09:52:49 +0200, Miroslav Lichvar wrote:
> I think a combination of ptp4l sending notification on exit and
> phc2sys timing out when no reply is received in the pmc update
> interval (1 minute) would be good enough.

Except when ptp4l is killed/crashes and is restarted. That's something
that wouldn't be caught by this and would create quite a messy
situation, especially when it's restarted automatically by system
startup scripts (e.g. systemd).

> Switching to the SEQPACKET socket seems like a lot of work and it
> wouldn't detect unresponsive ptp4l, which might be a useful thing to
> have (the same applies to the process monitoring).

I don't think that unresponsive ptp4l is a likely state. How could this
happen, sans a horrible bug?

 Jiri

-- 
Jiri Benc

--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] phc2sys detecting ptp4l exit (was: Re: [PATCH v2 00/27] automatic phc2sys configuration)

2014-06-20 Thread Jiri Benc
On Thu, 19 Jun 2014 23:01:36 +0200, Stephan Gatzka wrote:
> > Better option would be asking ptp4l about its PID and monitoring it.
> > That would be reliable enough but still polling, although rather cheap
> > polling.
> 
> Is ptp4l writing a PID file? If so, you can use inotify for monitoring.

The problem is not detecting ptp4l start, that we can easily do using
management messages. The problem is ptp4l going away, and inotify
cannot help with that.

Moreover, pid file won't work with multiple domains, unless you ask
ptp4l about the pid file path, and then you can just ask about the pid
directly.

 Jiri

-- 
Jiri Benc

--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] phc2sys detecting ptp4l exit (was: Re: [PATCH v2 00/27] automatic phc2sys configuration)

2014-06-19 Thread Jiri Benc
On Thu, 3 Apr 2014 11:53:40 +0200, Miroslav Lichvar wrote:
> As a future improvement, I think it would be nice if ptp4l sent a
> notification when exiting so phc2sys could stop its synchronization
> and wait until ptp4l is running again.

I was thinking about how to implement this. In particular, I'd like
this to be more robust and detect also ptp4l being killed.

The most obvious option, detecting whether other side closed its part
of the unix socket, would require changing it from SOCK_DGRAM to
SOCK_SEQPACKET. Which means ptp4l would have to keep track of all
uds clients, deal with accept calls, etc., and most importantly, poll
these additional file descriptors. That would require quite substantial
changes throughout the whole code. But then, uds is treated specially
in most places, perhaps stopping pretending it's another transport
wouldn't be bad.

Other option is polling from phc2sys every phc_interval. That's ugly,
consuming unnecessary resources and unreliable anyway.

Better option would be asking ptp4l about its PID and monitoring it.
That would be reliable enough but still polling, although rather cheap
polling.

Thoughts? Different ideas?

Thanks,

 Jiri

-- 
Jiri Benc

--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 08/15] pmc_common: easy way to set port and broadcast target

2014-06-11 Thread Jiri Benc
Implement pmc_target_port to set a port number, leaving clock identity
unchanged, and pmc_target_all to set clock identity and port number to all
1's.

Signed-off-by: Jiri Benc 
---
 pmc_common.c |   12 +++-
 pmc_common.h |2 ++
 2 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/pmc_common.c b/pmc_common.c
index 2c75074c8fb7..41385da45209 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -78,7 +78,7 @@ struct pmc *pmc_create(enum transport_type transport_type, 
const char *iface_nam
goto failed;
}
pmc->port_identity.portNumber = 1;
-   memset(&pmc->target, 0xff, sizeof(pmc->target));
+   pmc_target_all(pmc);
 
pmc->boundary_hops = boundary_hops;
pmc->domain_number = domain_number;
@@ -325,3 +325,13 @@ int pmc_target(struct pmc *pmc, struct PortIdentity *pid)
pmc->target = *pid;
return 0;
 }
+
+void pmc_target_port(struct pmc *pmc, UInteger16 portNumber)
+{
+   pmc->target.portNumber = portNumber;
+}
+
+void pmc_target_all(struct pmc *pmc)
+{
+   memset(&pmc->target, 0xff, sizeof(pmc->target));
+}
diff --git a/pmc_common.h b/pmc_common.h
index 9fcb51da3fd4..9adb9d1dd98b 100644
--- a/pmc_common.h
+++ b/pmc_common.h
@@ -41,5 +41,7 @@ int pmc_send_set_action(struct pmc *pmc, int id, void *data, 
int datasize);
 struct ptp_message *pmc_recv(struct pmc *pmc);
 
 int pmc_target(struct pmc *pmc, struct PortIdentity *pid);
+void pmc_target_port(struct pmc *pmc, UInteger16 portNumber);
+void pmc_target_all(struct pmc *pmc);
 
 #endif
-- 
1.7.6.5


--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 15/15] phc2sys: reset sync offset if non PTP timescale

2014-06-11 Thread Jiri Benc
When grandmaster does not use PTP timescale but the previous one did, we
need to reset sync offset and leap flag.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 76810e7c169f..76f27e938270 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -867,6 +867,9 @@ static int run_pmc_get_utc_offset(struct node *node, int 
timeout)
node->leap = -1;
else
node->leap = 0;
+   } else {
+   node->sync_offset = 0;
+   node->leap = 0;
}
msg_put(msg);
return 1;
-- 
1.7.6.5


--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 10/15] phc2sys: propagate received errors

2014-06-11 Thread Jiri Benc
Recognize errors returned in MANAGEMENT_ERROR_STATUS TLV and return
a distinct value from run_pmc in case such error is received.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   34 +++---
 1 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 3af1e51df07c..678235e92a59 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -526,9 +526,11 @@ static int is_msg_mgt(struct ptp_message *msg)
if (msg->tlv_count != 1)
return 0;
tlv = (struct TLV *) msg->management.suffix;
-   if (tlv->type != TLV_MANAGEMENT)
-   return 0;
-   return 1;
+   if (tlv->type == TLV_MANAGEMENT)
+   return 1;
+   if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS)
+   return -1;
+   return 0;
 }
 
 static int get_mgt_id(struct ptp_message *msg)
@@ -543,6 +545,14 @@ static void *get_mgt_data(struct ptp_message *msg)
return mgt->data;
 }
 
+static int get_mgt_err_id(struct ptp_message *msg)
+{
+   struct management_error_status *mgt;
+
+   mgt = (struct management_error_status *)msg->management.suffix;
+   return mgt->id;
+}
+
 static int normalize_state(int state)
 {
if (state != PS_MASTER && state != PS_SLAVE &&
@@ -630,12 +640,18 @@ static int init_pmc(struct node *node, int domain_number)
return 0;
 }
 
+/* Return values:
+ * 1: success
+ * 0: timeout
+ * -1: error reported by the other side
+ * -2: local error, fatal
+ */
 static int run_pmc(struct node *node, int timeout, int ds_id,
   struct ptp_message **msg)
 {
 #define N_FD 1
struct pollfd pollfd[N_FD];
-   int cnt;
+   int cnt, res;
 
while (1) {
pollfd[0].fd = pmc_get_transport_fd(node->pmc);
@@ -646,7 +662,7 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
cnt = poll(pollfd, N_FD, timeout);
if (cnt < 0) {
pr_err("poll failed");
-   return -1;
+   return -2;
}
if (!cnt) {
/* Request the data set again in the next run. */
@@ -676,8 +692,12 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
if (!*msg)
continue;
 
-   if (!is_msg_mgt(*msg) ||
-   recv_subscribed(node, *msg, ds_id) ||
+   res = is_msg_mgt(*msg);
+   if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
+   node->pmc_ds_requested = 0;
+   return -1;
+   }
+   if (res <= 0 || recv_subscribed(node, *msg, ds_id) ||
get_mgt_id(*msg) != ds_id) {
msg_put(*msg);
*msg = NULL;
-- 
1.7.6.5


--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 14/15] phc2sys: man page update for -a and -r options

2014-06-11 Thread Jiri Benc
Signed-off-by: Jiri Benc 
---
 phc2sys.8 |  115 ++---
 1 files changed, 79 insertions(+), 36 deletions(-)

diff --git a/phc2sys.8 b/phc2sys.8
index fa3ae206f3df..37a39d0ba60f 100644
--- a/phc2sys.8
+++ b/phc2sys.8
@@ -1,12 +1,17 @@
 .TH PHC2SYS 8 "November 2012" "linuxptp"
 .SH NAME
-phc2sys \- synchronize two clocks
+phc2sys \- synchronize two or more clocks
 
 .SH SYNOPSIS
-.B phc2sys
+.B phc2sys \-a
 [
-.B \-wmqvx
+.B \-r
 ] [
+.B \-r
+] [ options ]
+.br
+.B phc2sys
+[
 .BI \-d " pps-device"
 ] [
 .BI \-s " device"
@@ -15,45 +20,53 @@ phc2sys \- synchronize two clocks
 ] [
 .BI \-O " offset"
 ] [
-.BI \-E " servo"
-] [
-.BI \-P " kp"
-] [
-.BI \-I " ki"
-] [
-.BI \-S " step"
-] [
-.BI \-F " step"
-] [
-.BI \-R " update-rate"
-] [
-.BI \-N " clock-readings"
-] [
-.BI \-L " freq-limit"
-] [
-.BI \-u " summary-updates"
-] [
-.BI \-n " domain-number"
-] [
-.BI \-l " print-level"
-]
+.BI \-w
+] [ options ]
 
 .SH DESCRIPTION
 .B phc2sys
-is a program which synchronizes two clocks in the system. Typically, it is used
-to synchronize the system clock to a PTP hardware clock (PHC), which itself is
-synchronized by the
+is a program which synchronizes two or more clocks in the system. Typically,
+it is used to synchronize the system clock to a PTP hardware clock (PHC),
+which itself is synchronized by the
 .BR ptp4l (8)
 program.
 
-Two synchronization modes are supported, one uses a pulse per second (PPS)
+With the
+.B \-a
+option, the clocks to synchronize are fetched from the running
+.B ptp4l
+daemon and the direction of synchronization automatically follows changes of
+the PTP port states.
+
+Manual configuration is also possible. When using manual configuration, two
+synchronization modes are supported, one uses a pulse per second (PPS)
 signal provided by the source clock and the other mode reads time from the
 source clock directly. Some clocks can be used in both modes, the mode which
-will synchronize the slave clock with better accuracy depends on hardware and
-driver implementation.
+will synchronize the slave clock with better accuracy depends on hardware
+and driver implementation.
 
 .SH OPTIONS
 .TP
+.BI \-a
+Read the clocks to synchronize from running
+.B ptp4l
+and follow changes in the port states, adjusting the synchronization
+direction automatically. The system clock (CLOCK_REALTIME) is not
+synchronized, unless the
+.B \-r
+option is also specified.
+.TP
+.BI \-r
+Only valid together with the
+.B \-a
+option. Instructs
+.B phc2sys
+to also synchronize the system clock (CLOCK_REALTIME). By default, the
+system clock is not considered as a possible time source. If you want the
+system clock to be eligible to become a time source, specify the
+.B \-r
+option twice.
+.TP
 .BI \-d " pps-device"
 Specify the PPS device of the master clock (e.g. /dev/pps0). With this option
 the PPS synchronization mode is used instead of the direct mode. As the PPS
@@ -68,7 +81,10 @@ option the PPS signal of the master clock is enabled 
automatically, otherwise
 it has to be enabled before
 .B phc2sys
 is started (e.g. by running \f(CWecho 1 > /sys/class/ptp/ptp0/pps_enable\fP).
-This option can be used only with the system clock as the slave clock.
+This option can be used only with the system clock as the slave clock. Not
+compatible with the
+.B \-a
+option.
 .TP
 .BI \-s " device"
 Specify the master clock by device (e.g. /dev/ptp0) or interface (e.g. eth0) or
@@ -76,7 +92,9 @@ by name (e.g. CLOCK_REALTIME for the system clock). When this 
option is used
 together with the
 .B \-d
 option, the master clock is used only to correct the offset by whole number of
-seconds, which cannot be fixed with PPS alone.
+seconds, which cannot be fixed with PPS alone. Not compatible with the
+.B \-a
+option.
 .TP
 .BI \-i " interface"
 Performs the exact same function as
@@ -89,7 +107,10 @@ should no longer be used.
 .TP
 .BI \-c " device"
 Specify the slave clock by device (e.g. /dev/ptp1) or interface (e.g. eth1) or
-by  name. The default is CLOCK_REALTIME (the system clock).
+by  name. The default is CLOCK_REALTIME (the system clock). Not compatible
+with the
+.B \-a
+option.
 .TP
 .BI \-E " servo"
 Specify which clock servo should be used. Valid values are pi for a PI
@@ -128,7 +149,10 @@ minimize the error caused by random delays in scheduling 
and bus utilization.
 The default is 5.
 .TP
 .BI \-O " offset"
-Specify the offset between the slave and master times in seconds.  See
+Specify the offset between the slave and master times in seconds. Not
+compatible with the
+.B \-a
+option.  See
 .SM
 .B TIME SCALE USAGE
 below.
@@ -154,7 +178,9 @@ Wait until ptp4l is in a synchronized state. If the
 .B \-O
 option is not used, also keep the offse

[Linuxptp-devel] [PATCH v3 04/15] phc2sys: store information about clocks being UTC or TAI

2014-06-11 Thread Jiri Benc
For now, only CLOCK_REALTIME can be UTC. This may stay this way forever but
now we have a clean separation between codepaths where CLOCK_REALTIME is
required and codepaths any UTC clock should take.

The main motiviation behind this change is removal of sync_offset_direction.
It has to be computed on the fly based on the source and destination when we
have multiple clocks supported and automatic following of ptp4l state
changes implemented.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   60 +---
 1 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 825d7328af15..5b1f243528ad 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -130,6 +130,7 @@ struct clock {
LIST_ENTRY(clock) list;
clockid_t clkid;
int sysoff_supported;
+   int is_utc;
struct servo *servo;
enum servo_state servo_state;
const char *source_label;
@@ -146,7 +147,7 @@ struct node {
int phc_readings;
double phc_interval;
int sync_offset;
-   int sync_offset_direction;
+   int forced_sync_offset;
int leap;
int leap_set;
int kernel_leap;
@@ -161,6 +162,15 @@ static int update_sync_offset(struct node *node);
 static int clock_handle_leap(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int do_leap);
 
+static int64_t get_sync_offset(struct node *node, struct clock *dst)
+{
+   int direction = node->forced_sync_offset;
+
+   if (!direction)
+   direction = dst->is_utc - node->master->is_utc;
+   return (int64_t)node->sync_offset * NS_PER_SEC * direction;
+}
+
 static void update_clock_stats(struct clock *clock, unsigned int max_count,
   int64_t offset, double freq, int64_t delay)
 {
@@ -206,9 +216,7 @@ static void update_clock(struct node *node, struct clock 
*clock,
if (clock_handle_leap(node, clock, offset, ts, do_leap))
return;
 
-   if (node->sync_offset_direction)
-   offset += node->sync_offset * NS_PER_SEC *
-   node->sync_offset_direction;
+   offset += get_sync_offset(node, clock);
 
if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts))
servo_reset(clock->servo);
@@ -290,7 +298,7 @@ static int do_pps_loop(struct node *node, struct clock 
*clock, int fd)
 
if (src == CLOCK_INVALID) {
/* The sync offset can't be applied with PPS alone. */
-   node->sync_offset_direction = 0;
+   node->sync_offset = 0;
} else {
enable_pps_output(node->master->clkid);
}
@@ -558,15 +566,14 @@ static int clock_handle_leap(struct node *node, struct 
clock *clock,
if (!node->leap && !do_leap)
return 0;
 
-   if (clock->clkid != CLOCK_REALTIME &&
-   node->master->clkid != CLOCK_REALTIME)
+   if (clock->is_utc == node->master->is_utc)
return 0;
 
/* If the system clock is the master clock, get a time stamp from
   it, as it is the clock which will include the leap second. */
-   if (node->master->clkid == CLOCK_REALTIME) {
+   if (node->master->is_utc) {
struct timespec tp;
-   if (clock_gettime(CLOCK_REALTIME, &tp)) {
+   if (clock_gettime(node->master->clkid, &tp)) {
pr_err("failed to read clock: %m");
return -1;
}
@@ -575,11 +582,8 @@ static int clock_handle_leap(struct node *node, struct 
clock *clock,
 
/* If the clock will be stepped, the time stamp has to be the
   target time. Ignore possible 1 second error in UTC offset. */
-   if (clock->clkid == CLOCK_REALTIME &&
-   clock->servo_state == SERVO_UNLOCKED) {
-   ts -= offset + node->sync_offset * NS_PER_SEC *
-   node->sync_offset_direction;
-   }
+   if (clock->is_utc && clock->servo_state == SERVO_UNLOCKED)
+   ts -= offset + get_sync_offset(node, clock);
 
/* Suspend clock updates in the last second before midnight. */
if (is_utc_ambiguous(ts)) {
@@ -610,10 +614,12 @@ static int clock_add(struct node *node, clockid_t clkid)
c->clkid = clkid;
c->servo_state = SERVO_UNLOCKED;
 
-   if (c->clkid == CLOCK_REALTIME)
+   if (c->clkid == CLOCK_REALTIME) {
c->source_label = "sys";
-   else
+   c->is_utc = 1;
+   } else {
c->source_label = "phc";
+   }
 
if (node->stats_max_count > 0) {
c->offset_stats = stats_create();
@@ -698,7 +704,7 @@ int main(in

[Linuxptp-devel] [PATCH v3 00/15] automatic phc2sys configuration, phc2sys part

2014-06-11 Thread Jiri Benc
Changes in v3:
- Fixed direction of sync offset.
- Fixed NULL ptr deref with manual configuration.
- Added a patch that resets sync offset when grandmaster time scale changes
  to a non PTP timescale, e.g. when ptp4l in software time stamping mode
  becomes grandmaster. This bug was the reason why I haven't noticed the
  swapped sync offset in the previous testing.
Changes in v2:
- added PMC_SUBSCRIBE_DURATION constant
- fixed wrong invocation of update_pmc

This is the phc2sys part of the autoconfig patchset. It uses the event
subscription mechanism implemented in ptp4l.

The patchset is prepared to handle the "emulated boundary clock" scenario,
i.e. ptp4l working over multiple PHC's. I have old patches to do that (the
dynamic port allocation patchset + patchset to support multiple PHC's) which
I'll rebase on top of this and post after the patchset is accepted.

Jiri Benc (15):
  phc2sys: generalize run_pmc
  phc2sys: split update_sync_offset
  phc2sys: split clock and node
  phc2sys: store information about clocks being UTC or TAI
  phc2sys: rearrange declarations
  phc2sys: open devices in clock_add
  phc2sys: track ports
  pmc_common: easy way to set port and broadcast target
  phc2sys: event subscription
  phc2sys: propagate received errors
  phc2sys: autoconfiguration
  phc2sys: autoconfigure realtime clock on demand only
  phc2sys: check clockIdentity
  phc2sys: man page update for -a and -r options
  phc2sys: reset sync offset if non PTP timescale

 phc2sys.8|  115 +--
 phc2sys.c| 1083 --
 pmc_common.c |   12 +-
 pmc_common.h |2 +
 4 files changed, 915 insertions(+), 297 deletions(-)

-- 
1.7.6.5


--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 13/15] phc2sys: check clockIdentity

2014-06-11 Thread Jiri Benc
Make sure that we handle only one PTP clock (node). This is for an extra
safety.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   44 ++--
 1 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 8890e5e1abad..76810e7c169f 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -107,6 +107,8 @@ struct node {
int pmc_ds_requested;
uint64_t pmc_last_update;
int state_changed;
+   int clock_identity_set;
+   struct ClockIdentity clock_identity;
LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
@@ -612,6 +614,15 @@ static int do_loop(struct node *node, int subscriptions)
return 0; /* unreachable */
 }
 
+static int check_clock_identity(struct node *node, struct ptp_message *msg)
+{
+   if (!node->clock_identity_set)
+   return 1;
+   return !memcmp(&node->clock_identity,
+  &msg->header.sourcePortIdentity.clockIdentity,
+  sizeof(struct ClockIdentity));
+}
+
 static int is_msg_mgt(struct ptp_message *msg)
 {
struct TLV *tlv;
@@ -789,6 +800,12 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
if (!*msg)
continue;
 
+   if (!check_clock_identity(node, *msg)) {
+   msg_put(*msg);
+   *msg = NULL;
+   continue;
+   }
+
res = is_msg_mgt(*msg);
if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
node->pmc_ds_requested = 0;
@@ -927,6 +944,24 @@ out:
return res;
 }
 
+static int run_pmc_clock_identity(struct node *node, int timeout)
+{
+   struct ptp_message *msg;
+   struct defaultDS *dds;
+   int res;
+
+   res = run_pmc(node, timeout, DEFAULT_DATA_SET, &msg);
+   if (res <= 0)
+   return res;
+
+   dds = (struct defaultDS *)get_mgt_data(msg);
+   memcpy(&node->clock_identity, &dds->clockIdentity,
+  sizeof(struct ClockIdentity));
+   node->clock_identity_set = 1;
+   msg_put(msg);
+   return 1;
+}
+
 static void close_pmc(struct node *node)
 {
pmc_destroy(node->pmc);
@@ -943,7 +978,7 @@ static int auto_init_ports(struct node *node, int add_rt)
char iface[IFNAMSIZ];
 
while (1) {
-   res = run_pmc_get_number_ports(node, 1000);
+   res = run_pmc_clock_identity(node, 1000);
if (res < 0)
return -1;
if (res > 0)
@@ -951,7 +986,12 @@ static int auto_init_ports(struct node *node, int add_rt)
/* res == 0, timeout */
pr_notice("Waiting for ptp4l...");
}
-   number_ports = res;
+
+   number_ports = run_pmc_get_number_ports(node, 1000);
+   if (number_ports <= 0) {
+   pr_err("failed to get number of ports");
+   return -1;
+   }
 
res = run_pmc_subscribe(node, 1000);
if (res <= 0) {
-- 
1.7.6.5


--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 06/15] phc2sys: open devices in clock_add

2014-06-11 Thread Jiri Benc
Do not call clock_open to open a clock device but let clock_add do that and
return the newly created struct. Also, store the device (interface) name in
struct clock.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   81 ++--
 1 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 3f086496ee76..cbbc583b01ac 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -67,6 +67,7 @@ struct clock {
int is_utc;
struct servo *servo;
enum servo_state servo_state;
+   char *device;
const char *source_label;
struct stats *offset_stats;
struct stats *freq_stats;
@@ -129,19 +130,27 @@ static clockid_t clock_open(char *device)
return clkid;
 }
 
-static int clock_add(struct node *node, clockid_t clkid)
+static struct clock *clock_add(struct node *node, char *device)
 {
struct clock *c;
+   clockid_t clkid = CLOCK_INVALID;
int max_ppb;
double ppb;
 
+   if (device) {
+   clkid = clock_open(device);
+   if (clkid == CLOCK_INVALID)
+   return NULL;
+   }
+
c = calloc(1, sizeof(*c));
if (!c) {
pr_err("failed to allocate memory for a clock");
-   return -1;
+   return NULL;
}
c->clkid = clkid;
c->servo_state = SERVO_UNLOCKED;
+   c->device = strdup(device);
 
if (c->clkid == CLOCK_REALTIME) {
c->source_label = "sys";
@@ -158,14 +167,14 @@ static int clock_add(struct node *node, clockid_t clkid)
!c->freq_stats ||
!c->delay_stats) {
pr_err("failed to create stats");
-   return -1;
+   return NULL;
}
}
if (node->sanity_freq_limit) {
c->sanity_check = clockcheck_create(node->sanity_freq_limit);
if (!c->sanity_check) {
pr_err("failed to create clock check");
-   return -1;
+   return NULL;
}
}
 
@@ -181,7 +190,7 @@ static int clock_add(struct node *node, clockid_t clkid)
max_ppb = phc_max_adj(c->clkid);
if (!max_ppb) {
pr_err("clock is not adjustable");
-   return -1;
+   return NULL;
}
}
 
@@ -194,7 +203,7 @@ static int clock_add(struct node *node, clockid_t clkid)
node->phc_readings));
 
LIST_INSERT_HEAD(&node->clocks, c, list);
-   return 0;
+   return c;
 }
 
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
@@ -699,8 +708,8 @@ static void usage(char *progname)
 int main(int argc, char *argv[])
 {
char *progname;
-   clockid_t src = CLOCK_INVALID;
-   clockid_t dst = CLOCK_REALTIME;
+   char *src_name = NULL, *dst_name = NULL;
+   struct clock *src, *dst;
int c, domain_number = 0, pps_fd = -1;
int r, wait_sync = 0;
int print_level = LOG_INFO, use_syslog = 1, verbose = 0;
@@ -723,7 +732,7 @@ int main(int argc, char *argv[])
  "c:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) {
switch (c) {
case 'c':
-   dst = clock_open(optarg);
+   dst_name = strdup(optarg);
break;
case 'd':
pps_fd = open(optarg, O_RDONLY);
@@ -737,7 +746,7 @@ int main(int argc, char *argv[])
fprintf(stderr,
"'-i' has been deprecated. please use '-s' 
instead.\n");
case 's':
-   src = clock_open(optarg);
+   src_name = strdup(optarg);
break;
case 'E':
if (!strcasecmp(optarg, "pi")) {
@@ -826,38 +835,46 @@ int main(int argc, char *argv[])
}
}
 
-   if (pps_fd < 0 && src == CLOCK_INVALID) {
+   if (pps_fd < 0 && !src_name) {
fprintf(stderr,
"valid source clock must be selected.\n");
goto bad_usage;
}
 
-   if (dst == CLOCK_INVALID) {
+   if (!wait_sync && !node.forced_sync_offset) {
fprintf(stderr,
-   "valid destination clock must be selected.\n");
+   "time offset must be specified using -w or -O\n");
goto bad_usage;
}
 
-   if (pps_fd >= 0 && dst != CLOCK_REALTIME) {

[Linuxptp-devel] [PATCH v3 12/15] phc2sys: autoconfigure realtime clock on demand only

2014-06-11 Thread Jiri Benc
By default, do not synchronize CLOCK_REALTIME. To do it, -r option is
needed. That will only consider CLOCK_REALTIME as the destination. To
consider it also as a possible time source, use -rr.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   31 ---
 1 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 51213a0ae976..8890e5e1abad 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -72,6 +72,7 @@ struct clock {
clockid_t clkid;
int sysoff_supported;
int is_utc;
+   int dest_only;
int state;
int new_state;
struct servo *servo;
@@ -328,10 +329,16 @@ static void reconfigure(struct node *node)
node->master = NULL;
return;
}
+   if ((!src_cnt && (!rt || rt->dest_only)) ||
+   (!dst_cnt && !rt)) {
+   pr_info("nothing to synchronize");
+   node->master = NULL;
+   return;
+   }
if (!src_cnt) {
src = rt;
rt->state = PS_SLAVE;
-   } else {
+   } else if (rt) {
if (rt->state != PS_MASTER) {
rt->state = PS_MASTER;
clock_reinit(rt);
@@ -926,7 +933,7 @@ static void close_pmc(struct node *node)
node->pmc = NULL;
 }
 
-static int auto_init_ports(struct node *node)
+static int auto_init_ports(struct node *node, int add_rt)
 {
struct port *port;
struct clock *clock;
@@ -981,8 +988,13 @@ static int auto_init_ports(struct node *node)
}
node->state_changed = 1;
 
-   if (!clock_add(node, "CLOCK_REALTIME"))
-   return -1;
+   if (add_rt) {
+   clock = clock_add(node, "CLOCK_REALTIME");
+   if (!clock)
+   return -1;
+   if (add_rt == 1)
+   clock->dest_only = 1;
+   }
 
/* get initial offset */
if (run_pmc_get_utc_offset(node, 1000) <= 0) {
@@ -1077,6 +1089,8 @@ static void usage(char *progname)
"\n"
" automatic configuration:\n"
" -a turn on autoconfiguration\n"
+   " -r synchronize system (realtime) clock\n"
+   "repeat -r to consider it also as a time 
source\n"
" manual configuration:\n"
" -c [dev|name]  slave clock (CLOCK_REALTIME)\n"
" -d [dev]   master PPS device\n"
@@ -1109,7 +1123,7 @@ int main(int argc, char *argv[])
char *progname;
char *src_name = NULL, *dst_name = NULL;
struct clock *src, *dst;
-   int autocfg = 0;
+   int autocfg = 0, rt = 0;
int c, domain_number = 0, pps_fd = -1;
int r, wait_sync = 0;
int print_level = LOG_INFO, use_syslog = 1, verbose = 0;
@@ -1129,11 +1143,14 @@ int main(int argc, char *argv[])
progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0];
while (EOF != (c = getopt(argc, argv,
- "ac:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) {
+ "arc:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) 
{
switch (c) {
case 'a':
autocfg = 1;
break;
+   case 'r':
+   rt++;
+   break;
case 'c':
dst_name = strdup(optarg);
break;
@@ -1263,7 +1280,7 @@ int main(int argc, char *argv[])
if (autocfg) {
if (init_pmc(&node, domain_number))
return -1;
-   if (auto_init_ports(&node) < 0)
+   if (auto_init_ports(&node, rt) < 0)
return -1;
return do_loop(&node, 1);
}
-- 
1.7.6.5


--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 07/15] phc2sys: track ports

2014-06-11 Thread Jiri Benc
Add tracking of which ports have been added and to which clock they belong.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   51 +++
 1 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index cbbc583b01ac..eed2171dc6d5 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -75,6 +75,12 @@ struct clock {
struct clockcheck *sanity_check;
 };
 
+struct port {
+   LIST_ENTRY(port) list;
+   unsigned int number;
+   struct clock *clock;
+};
+
 struct node {
unsigned int stats_max_count;
int sanity_freq_limit;
@@ -89,6 +95,7 @@ struct node {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
+   LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
 };
@@ -206,6 +213,50 @@ static struct clock *clock_add(struct node *node, char 
*device)
return c;
 }
 
+static struct port *port_get(struct node *node, unsigned int number)
+{
+   struct port *p;
+
+   LIST_FOREACH(p, &node->ports, list) {
+   if (p->number == number)
+   return p;
+   }
+   return NULL;
+}
+
+static struct port *port_add(struct node *node, unsigned int number,
+char *device)
+{
+   struct port *p;
+   struct clock *c = NULL, *tmp;
+
+   p = port_get(node, number);
+   if (p)
+   return p;
+   /* port is a new one, look whether we have the device already on
+* a different port */
+   LIST_FOREACH(tmp, &node->clocks, list) {
+   if (!strcmp(tmp->device, device)) {
+   c = tmp;
+   break;
+   }
+   }
+   if (!c) {
+   c = clock_add(node, device);
+   if (!c)
+   return NULL;
+   }
+   p = malloc(sizeof(*p));
+   if (!p) {
+   pr_err("failed to allocate memory for a port");
+   return NULL;
+   }
+   p->number = number;
+   p->clock = c;
+   LIST_INSERT_HEAD(&node->ports, p, list);
+   return p;
+}
+
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
int64_t *offset, uint64_t *ts, int64_t *delay)
 {
-- 
1.7.6.5


--
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 11/15] phc2sys: autoconfiguration

2014-06-11 Thread Jiri Benc
Add automatic configuration option (-a).

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  278 -
 1 files changed, 256 insertions(+), 22 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 678235e92a59..51213a0ae976 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -110,9 +111,11 @@ struct node {
struct clock *master;
 };
 
-static int update_sync_offset(struct node *node);
+static int update_pmc(struct node *node, int subscribe);
 static int clock_handle_leap(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int do_leap);
+static int run_pmc_get_utc_offset(struct node *node, int timeout);
+static void run_pmc_events(struct node *node);
 
 static clockid_t clock_open(char *device)
 {
@@ -267,6 +270,78 @@ static struct port *port_add(struct node *node, unsigned 
int number,
return p;
 }
 
+static void clock_reinit(struct clock *clock)
+{
+   servo_reset(clock->servo);
+   clock->servo_state = SERVO_UNLOCKED;
+
+   if (clock->offset_stats) {
+   stats_reset(clock->offset_stats);
+   stats_reset(clock->freq_stats);
+   stats_reset(clock->delay_stats);
+   }
+}
+
+static void reconfigure(struct node *node)
+{
+   struct clock *c, *rt, *src;
+   int src_cnt = 0, dst_cnt = 0;
+
+   pr_info("reconfiguring after port state change");
+   node->state_changed = 0;
+
+   src = rt = NULL;
+   LIST_FOREACH(c, &node->clocks, list) {
+   if (c->clkid == CLOCK_REALTIME) {
+   rt = c;
+   continue;
+   }
+
+   if (c->new_state == PS_MASTER)
+   clock_reinit(c);
+
+   c->state = c->new_state;
+   c->new_state = 0;
+
+   if (c->state == PS_SLAVE) {
+   src = c;
+   src_cnt++;
+   } else if (c->state == PS_UNCALIBRATED) {
+   src_cnt++;
+   } else if (c->state == PS_MASTER) {
+   pr_info("selecting %s for synchronization", c->device);
+   dst_cnt++;
+   }
+   }
+   if (src_cnt > 1) {
+   pr_info("multiple master clocks available, postponing sync...");
+   node->master = NULL;
+   return;
+   }
+   if (src_cnt > 0 && !src) {
+   pr_info("master clock not ready, waiting...");
+   node->master = NULL;
+   return;
+   }
+   if (!src_cnt && !dst_cnt) {
+   pr_info("no PHC ready, waiting...");
+   node->master = NULL;
+   return;
+   }
+   if (!src_cnt) {
+   src = rt;
+   rt->state = PS_SLAVE;
+   } else {
+   if (rt->state != PS_MASTER) {
+   rt->state = PS_MASTER;
+   clock_reinit(rt);
+   }
+   pr_info("selecting %s for synchronization", rt->device);
+   }
+   node->master = src;
+   pr_info("selecting %s as the master clock", src->device);
+}
+
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
int64_t *offset, uint64_t *ts, int64_t *delay)
 {
@@ -465,7 +540,7 @@ static int do_pps_loop(struct node *node, struct clock 
*clock, int fd)
pps_offset = pps_ts - phc_ts;
}
 
-   do_leap = update_sync_offset(node);
+   do_leap = update_pmc(node, 0);
if (do_leap < 0)
continue;
update_clock(node, clock, pps_offset, pps_ts, -1, do_leap);
@@ -474,13 +549,12 @@ static int do_pps_loop(struct node *node, struct clock 
*clock, int fd)
return 0;
 }
 
-static int do_loop(struct node *node)
+static int do_loop(struct node *node, int subscriptions)
 {
struct timespec interval;
struct clock *clock;
uint64_t ts;
int64_t offset, delay;
-   int src_fd = CLOCKID_TO_FD(node->master->clkid);
int do_leap;
 
interval.tv_sec = node->phc_interval;
@@ -488,18 +562,34 @@ static int do_loop(struct node *node)
 
while (1) {
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
-   do_leap = update_sync_offset(node);
+   do_leap = update_pmc(node, subscriptions);
if (do_leap < 0)
continue;
 
+   if (subscriptions) {
+   run_pmc_events(node);
+   if (node->state_changed) {
+

[Linuxptp-devel] [PATCH v3 01/15] phc2sys: generalize run_pmc

2014-06-11 Thread Jiri Benc
Make run_pmc usable for any kind of management message. Create wrappers for
waiting for ptp4l and for getting UTC offset.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  131 +++--
 1 files changed, 66 insertions(+), 65 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 5ecb602120c3..0581eb5bcb24 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -141,7 +141,6 @@ struct clock {
int leap_set;
int kernel_leap;
struct pmc *pmc;
-   int pmc_ds_idx;
int pmc_ds_requested;
uint64_t pmc_last_update;
struct clockcheck *sanity_check;
@@ -390,31 +389,14 @@ static int init_pmc(struct clock *clock, int 
domain_number)
return 0;
 }
 
-static int run_pmc(struct clock *clock, int timeout,
-  int wait_sync, int get_utc_offset)
+static int run_pmc(struct clock *clock, int timeout, int ds_id,
+  struct ptp_message **msg)
 {
-   struct ptp_message *msg;
-   struct timePropertiesDS *tds;
-   void *data;
 #define N_FD 1
struct pollfd pollfd[N_FD];
-   int cnt, ds_done;
-#define N_ID 2
-   int ds_ids[N_ID] = {
-   PORT_DATA_SET,
-   TIME_PROPERTIES_DATA_SET
-   };
-
-   while (clock->pmc_ds_idx < N_ID) {
-   /* Check if the data set is really needed. */
-   if ((ds_ids[clock->pmc_ds_idx] == PORT_DATA_SET &&
-!wait_sync) ||
-   (ds_ids[clock->pmc_ds_idx] == TIME_PROPERTIES_DATA_SET &&
-!get_utc_offset)) {
-   clock->pmc_ds_idx++;
-   continue;
-   }
+   int cnt;
 
+   while (1) {
pollfd[0].fd = pmc_get_transport_fd(clock->pmc);
pollfd[0].events = POLLIN|POLLPRI;
if (!clock->pmc_ds_requested)
@@ -434,62 +416,76 @@ static int run_pmc(struct clock *clock, int timeout,
/* Send a new request if there are no pending messages. */
if ((pollfd[0].revents & POLLOUT) &&
!(pollfd[0].revents & (POLLIN|POLLPRI))) {
-   pmc_send_get_action(clock->pmc,
-   ds_ids[clock->pmc_ds_idx]);
+   pmc_send_get_action(clock->pmc, ds_id);
clock->pmc_ds_requested = 1;
}
 
if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
continue;
 
-   msg = pmc_recv(clock->pmc);
+   *msg = pmc_recv(clock->pmc);
 
-   if (!msg)
+   if (!*msg)
continue;
 
-   if (!is_msg_mgt(msg) ||
-   get_mgt_id(msg) != ds_ids[clock->pmc_ds_idx]) {
-   msg_put(msg);
+   if (!is_msg_mgt(*msg) ||
+   get_mgt_id(*msg) != ds_id) {
+   msg_put(*msg);
+   *msg = NULL;
continue;
}
+   clock->pmc_ds_requested = 0;
+   return 1;
+   }
+}
 
-   data = get_mgt_data(msg);
-   ds_done = 0;
-
-   switch (get_mgt_id(msg)) {
-   case PORT_DATA_SET:
-   switch (((struct portDS *)data)->portState) {
-   case PS_MASTER:
-   case PS_SLAVE:
-   ds_done = 1;
-   break;
-   }
+static int run_pmc_wait_sync(struct clock *clock, int timeout)
+{
+   struct ptp_message *msg;
+   int res;
+   void *data;
+   Enumeration8 portState;
 
-   break;
-   case TIME_PROPERTIES_DATA_SET:
-   tds = (struct timePropertiesDS *)data;
-   if (tds->flags & PTP_TIMESCALE) {
-   clock->sync_offset = tds->currentUtcOffset;
-   if (tds->flags & LEAP_61)
-   clock->leap = 1;
-   else if (tds->flags & LEAP_59)
-   clock->leap = -1;
-   else
-   clock->leap = 0;
-   }
-   ds_done = 1;
-   break;
-   }
+   while (1) {
+   res = run_pmc(clock, timeout, PORT_DATA_SET, &msg);
+   if (res <= 0)
+   return res;
 
-   if (ds_done) {
-   /* Proceed with the next data set. */
-   clock->pmc_ds_idx++;
-   clock->pmc_ds_requested = 0;
-   }
+   data = get_mgt_data(msg);
+   port

[Linuxptp-devel] [PATCH v3 02/15] phc2sys: split update_sync_offset

2014-06-11 Thread Jiri Benc
Split the generic (global) part of update_sync_offset and the part that
affects individual clocks. This is in preparation for phc2sys handling
synchronization of more clocks.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   71 +++-
 1 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 0581eb5bcb24..19dce45964eb 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -60,7 +60,9 @@
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
 struct clock;
-static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t 
ts);
+static int update_sync_offset(struct clock *clock);
+static int clock_handle_leap(struct clock *clock, clockid_t src,
+int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -181,13 +183,14 @@ static void update_clock_stats(struct clock *clock,
stats_reset(clock->delay_stats);
 }
 
-static void update_clock(struct clock *clock,
-int64_t offset, uint64_t ts, int64_t delay)
+static void update_clock(struct clock *clock, clockid_t src,
+int64_t offset, uint64_t ts, int64_t delay,
+int do_leap)
 {
enum servo_state state;
double ppb;
 
-   if (update_sync_offset(clock, offset, ts))
+   if (clock_handle_leap(clock, src, offset, ts, do_leap))
return;
 
if (clock->sync_offset_direction)
@@ -268,6 +271,7 @@ static int do_pps_loop(struct clock *clock, int fd,
 {
int64_t pps_offset, phc_offset, phc_delay;
uint64_t pps_ts, phc_ts;
+   int do_leap;
 
clock->source_label = "pps";
 
@@ -304,7 +308,10 @@ static int do_pps_loop(struct clock *clock, int fd,
pps_offset = pps_ts - phc_ts;
}
 
-   update_clock(clock, pps_offset, pps_ts, -1);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, pps_offset, pps_ts, -1, do_leap);
}
close(fd);
return 0;
@@ -316,6 +323,7 @@ static int do_sysoff_loop(struct clock *clock, clockid_t 
src,
uint64_t ts;
int64_t offset, delay;
int err = 0, fd = CLOCKID_TO_FD(src);
+   int do_leap;
 
clock->source_label = "sys";
 
@@ -325,7 +333,10 @@ static int do_sysoff_loop(struct clock *clock, clockid_t 
src,
err = -1;
break;
}
-   update_clock(clock, offset, ts, delay);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, offset, ts, delay, do_leap);
}
return err;
 }
@@ -335,6 +346,7 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
 {
uint64_t ts;
int64_t offset, delay;
+   int do_leap;
 
clock->source_label = "phc";
 
@@ -344,7 +356,10 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
  &offset, &ts, &delay)) {
continue;
}
-   update_clock(clock, offset, ts, delay);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, offset, ts, delay, do_leap);
}
return 0;
 }
@@ -495,10 +510,19 @@ static void close_pmc(struct clock *clock)
clock->pmc = NULL;
 }
 
-static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t ts)
+/* Returns: -1 in case of error, 0 for normal sync, 1 to leap clock */
+static int update_sync_offset(struct clock *clock)
 {
+   struct timespec tp;
+   uint64_t ts;
int clock_leap;
 
+   if (clock_gettime(CLOCK_REALTIME, &tp)) {
+   pr_err("failed to read clock: %m");
+   return -1;
+   }
+   ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
+
if (clock->pmc &&
!(ts > clock->pmc_last_update &&
  ts - clock->pmc_last_update < PMC_UPDATE_INTERVAL)) {
@@ -511,9 +535,28 @@ static int update_sync_offset(struct clock *clock, int64_t 
offset, uint64_t ts)
if (!clock->leap && !clock->leap_set)
return 0;
 
+   clock_leap = leap_second_status(ts, clock->leap_set,
+   &clock->leap, &clock->sync_offset);
+   if (clock->leap_set != clock_leap) {
+   clock->leap_set = clock_leap;
+   return 1;
+   }
+   return 0;
+}
+
+/* Returns: non-zero to skip clock update */
+static int clock_handle_leap(struct clock *clock, clockid_t src,
+int64_t o

[Linuxptp-devel] [PATCH v3 03/15] phc2sys: split clock and node

2014-06-11 Thread Jiri Benc
Split members that apply to all synchronized clocks and members that apply
to an individual clock. Keep all clocks in a list, with a pointer to the
source clock. This will allow to support multiple clocks synchronization.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  397 +---
 1 files changed, 218 insertions(+), 179 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 19dce45964eb..825d7328af15 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -60,9 +61,6 @@
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
 struct clock;
-static int update_sync_offset(struct clock *clock);
-static int clock_handle_leap(struct clock *clock, clockid_t src,
-int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -129,14 +127,24 @@ static int read_phc(clockid_t clkid, clockid_t sysclk, 
int readings,
 }
 
 struct clock {
+   LIST_ENTRY(clock) list;
clockid_t clkid;
+   int sysoff_supported;
struct servo *servo;
enum servo_state servo_state;
const char *source_label;
struct stats *offset_stats;
struct stats *freq_stats;
struct stats *delay_stats;
+   struct clockcheck *sanity_check;
+};
+
+struct node {
unsigned int stats_max_count;
+   int sanity_freq_limit;
+   enum servo_type servo_type;
+   int phc_readings;
+   double phc_interval;
int sync_offset;
int sync_offset_direction;
int leap;
@@ -145,10 +153,15 @@ struct clock {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
-   struct clockcheck *sanity_check;
+   LIST_HEAD(clock_head, clock) clocks;
+   struct clock *master;
 };
 
-static void update_clock_stats(struct clock *clock,
+static int update_sync_offset(struct node *node);
+static int clock_handle_leap(struct node *node, struct clock *clock,
+int64_t offset, uint64_t ts, int do_leap);
+
+static void update_clock_stats(struct clock *clock, unsigned int max_count,
   int64_t offset, double freq, int64_t delay)
 {
struct stats_result offset_stats, freq_stats, delay_stats;
@@ -158,7 +171,7 @@ static void update_clock_stats(struct clock *clock,
if (delay >= 0)
stats_add_value(clock->delay_stats, delay);
 
-   if (stats_get_num_values(clock->offset_stats) < clock->stats_max_count)
+   if (stats_get_num_values(clock->offset_stats) < max_count)
return;
 
stats_get_result(clock->offset_stats, &offset_stats);
@@ -183,19 +196,19 @@ static void update_clock_stats(struct clock *clock,
stats_reset(clock->delay_stats);
 }
 
-static void update_clock(struct clock *clock, clockid_t src,
+static void update_clock(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int64_t delay,
 int do_leap)
 {
enum servo_state state;
double ppb;
 
-   if (clock_handle_leap(clock, src, offset, ts, do_leap))
+   if (clock_handle_leap(node, clock, offset, ts, do_leap))
return;
 
-   if (clock->sync_offset_direction)
-   offset += clock->sync_offset * NS_PER_SEC *
-   clock->sync_offset_direction;
+   if (node->sync_offset_direction)
+   offset += node->sync_offset * NS_PER_SEC *
+   node->sync_offset_direction;
 
if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts))
servo_reset(clock->servo);
@@ -221,15 +234,15 @@ static void update_clock(struct clock *clock, clockid_t 
src,
}
 
if (clock->offset_stats) {
-   update_clock_stats(clock, offset, ppb, delay);
+   update_clock_stats(clock, node->stats_max_count, offset, ppb, 
delay);
} else {
if (delay >= 0) {
pr_info("%s offset %9" PRId64 " s%d freq %+7.0f "
"delay %6" PRId64,
-   clock->source_label, offset, state, ppb, delay);
+   node->master->source_label, offset, state, ppb, 
delay);
} else {
pr_info("%s offset %9" PRId64 " s%d freq %+7.0f",
-   clock->source_label, offset, state, ppb);
+   node->master->source_label, offset, state, ppb);
}
}
 }
@@ -266,20 +279,20 @@ static int read_pps(int fd, int64_t *offset, uint64_t *ts)
return 1;
 }
 
-static int do_pps_loop(struct clock *clock, int fd,
-  clockid_t src, int n_readings)

[Linuxptp-devel] [PATCH v3 05/15] phc2sys: rearrange declarations

2014-06-11 Thread Jiri Benc
This just moves code around to have related functions together and forward
declaration at the beginning of the file. No code changes.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  208 ++---
 1 files changed, 103 insertions(+), 105 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 5b1f243528ad..3f086496ee76 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -60,7 +60,41 @@
 #define PHC_PPS_OFFSET_LIMIT 1000
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
-struct clock;
+struct clock {
+   LIST_ENTRY(clock) list;
+   clockid_t clkid;
+   int sysoff_supported;
+   int is_utc;
+   struct servo *servo;
+   enum servo_state servo_state;
+   const char *source_label;
+   struct stats *offset_stats;
+   struct stats *freq_stats;
+   struct stats *delay_stats;
+   struct clockcheck *sanity_check;
+};
+
+struct node {
+   unsigned int stats_max_count;
+   int sanity_freq_limit;
+   enum servo_type servo_type;
+   int phc_readings;
+   double phc_interval;
+   int sync_offset;
+   int forced_sync_offset;
+   int leap;
+   int leap_set;
+   int kernel_leap;
+   struct pmc *pmc;
+   int pmc_ds_requested;
+   uint64_t pmc_last_update;
+   LIST_HEAD(clock_head, clock) clocks;
+   struct clock *master;
+};
+
+static int update_sync_offset(struct node *node);
+static int clock_handle_leap(struct node *node, struct clock *clock,
+int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -95,6 +129,74 @@ static clockid_t clock_open(char *device)
return clkid;
 }
 
+static int clock_add(struct node *node, clockid_t clkid)
+{
+   struct clock *c;
+   int max_ppb;
+   double ppb;
+
+   c = calloc(1, sizeof(*c));
+   if (!c) {
+   pr_err("failed to allocate memory for a clock");
+   return -1;
+   }
+   c->clkid = clkid;
+   c->servo_state = SERVO_UNLOCKED;
+
+   if (c->clkid == CLOCK_REALTIME) {
+   c->source_label = "sys";
+   c->is_utc = 1;
+   } else {
+   c->source_label = "phc";
+   }
+
+   if (node->stats_max_count > 0) {
+   c->offset_stats = stats_create();
+   c->freq_stats = stats_create();
+   c->delay_stats = stats_create();
+   if (!c->offset_stats ||
+   !c->freq_stats ||
+   !c->delay_stats) {
+   pr_err("failed to create stats");
+   return -1;
+   }
+   }
+   if (node->sanity_freq_limit) {
+   c->sanity_check = clockcheck_create(node->sanity_freq_limit);
+   if (!c->sanity_check) {
+   pr_err("failed to create clock check");
+   return -1;
+   }
+   }
+
+   clockadj_init(c->clkid);
+   ppb = clockadj_get_freq(c->clkid);
+   /* The reading may silently fail and return 0, reset the frequency to
+  make sure ppb is the actual frequency of the clock. */
+   clockadj_set_freq(c->clkid, ppb);
+   if (c->clkid == CLOCK_REALTIME) {
+   sysclk_set_leap(0);
+   max_ppb = sysclk_max_freq();
+   } else {
+   max_ppb = phc_max_adj(c->clkid);
+   if (!max_ppb) {
+   pr_err("clock is not adjustable");
+   return -1;
+   }
+   }
+
+   c->servo = servo_create(node->servo_type, -ppb, max_ppb, 0);
+   servo_sync_interval(c->servo, node->phc_interval);
+
+   if (clkid != CLOCK_REALTIME)
+   c->sysoff_supported = (SYSOFF_SUPPORTED ==
+  sysoff_probe(CLOCKID_TO_FD(clkid),
+   node->phc_readings));
+
+   LIST_INSERT_HEAD(&node->clocks, c, list);
+   return 0;
+}
+
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
int64_t *offset, uint64_t *ts, int64_t *delay)
 {
@@ -126,42 +228,6 @@ static int read_phc(clockid_t clkid, clockid_t sysclk, int 
readings,
return 1;
 }
 
-struct clock {
-   LIST_ENTRY(clock) list;
-   clockid_t clkid;
-   int sysoff_supported;
-   int is_utc;
-   struct servo *servo;
-   enum servo_state servo_state;
-   const char *source_label;
-   struct stats *offset_stats;
-   struct stats *freq_stats;
-   struct stats *delay_stats;
-   struct clockcheck *sanity_check;
-};
-
-struct node {
-   unsigned int stats_max_count;
-   int sanity_freq_limit;
-   enum servo_type servo_type;
-   int phc_readings;
-   double phc_interval;
-   int sync_offs

[Linuxptp-devel] [PATCH v3 09/15] phc2sys: event subscription

2014-06-11 Thread Jiri Benc
Add support for subscribing to events (run_pmc_subscribe) and receiving and
handling of received events (run_pmc_events).

Add initial support for port status changes.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  116 +++-
 1 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index eed2171dc6d5..3af1e51df07c 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -41,6 +41,7 @@
 #include "ds.h"
 #include "fsm.h"
 #include "missing.h"
+#include "notification.h"
 #include "phc.h"
 #include "pi.h"
 #include "pmc_common.h"
@@ -59,12 +60,19 @@
 
 #define PHC_PPS_OFFSET_LIMIT 1000
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
+#define PMC_SUBSCRIBE_DURATION 180 /* 3 minutes */
+/* Note that PMC_SUBSCRIBE_DURATION has to be longer than
+ * PMC_UPDATE_INTERVAL otherwise subscription will time out before it is
+ * renewed.
+ */
 
 struct clock {
LIST_ENTRY(clock) list;
clockid_t clkid;
int sysoff_supported;
int is_utc;
+   int state;
+   int new_state;
struct servo *servo;
enum servo_state servo_state;
char *device;
@@ -78,6 +86,7 @@ struct clock {
 struct port {
LIST_ENTRY(port) list;
unsigned int number;
+   int state;
struct clock *clock;
 };
 
@@ -95,6 +104,7 @@ struct node {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
+   int state_changed;
LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
@@ -533,6 +543,81 @@ static void *get_mgt_data(struct ptp_message *msg)
return mgt->data;
 }
 
+static int normalize_state(int state)
+{
+   if (state != PS_MASTER && state != PS_SLAVE &&
+   state != PS_PRE_MASTER && state != PS_UNCALIBRATED) {
+   /* treat any other state as "not a master nor a slave" */
+   state = PS_DISABLED;
+   }
+   return state;
+}
+
+static int clock_compute_state(struct node *node, struct clock *clock)
+{
+   struct port *p;
+   int state = PS_DISABLED;
+
+   LIST_FOREACH(p, &node->ports, list) {
+   if (p->clock != clock)
+   continue;
+   /* PS_SLAVE takes the highest precedence, PS_UNCALIBRATED
+* after that, PS_MASTER is third, PS_PRE_MASTER fourth and
+* all of that overrides PS_DISABLED, which corresponds
+* nicely with the numerical values */
+   if (p->state > state)
+   state = p->state;
+   }
+   return state;
+}
+
+static int recv_subscribed(struct node *node, struct ptp_message *msg,
+  int excluded)
+{
+   int mgt_id, state;
+   struct portDS *pds;
+   struct port *port;
+   struct clock *clock;
+
+   mgt_id = get_mgt_id(msg);
+   if (mgt_id == excluded)
+   return 0;
+   switch (mgt_id) {
+   case PORT_DATA_SET:
+   pds = get_mgt_data(msg);
+   port = port_get(node, pds->portIdentity.portNumber);
+   if (!port) {
+   pr_info("received data for unknown port %s",
+   pid2str(&pds->portIdentity));
+   return 1;
+   }
+   state = normalize_state(pds->portState);
+   if (port->state != state) {
+   pr_info("port %s changed state",
+   pid2str(&pds->portIdentity));
+   port->state = state;
+   clock = port->clock;
+   state = clock_compute_state(node, clock);
+   if (clock->state != state) {
+   clock->new_state = state;
+   node->state_changed = 1;
+   }
+   }
+   return 1;
+   }
+   return 0;
+}
+
+static void send_subscription(struct node *node)
+{
+   struct subscribe_events_np sen;
+
+   memset(&sen, 0, sizeof(sen));
+   sen.duration = PMC_SUBSCRIBE_DURATION;
+   sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
+   pmc_send_set_action(node->pmc, SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
+}
+
 static int init_pmc(struct node *node, int domain_number)
 {
node->pmc = pmc_create(TRANS_UDS, "/var/run/phc2sys", 0,
@@ -555,7 +640,7 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
while (1) {
pollfd[0].fd = pmc_get_transport_fd(node->pmc);
pollfd[0].events = POLLIN|POLLPRI;
-   if (!node->pmc_ds_requested)
+   if (!node->pmc_ds_requested && ds_id >=

Re: [Linuxptp-devel] linuxptp in kernel 2.6.30+?

2014-06-03 Thread Jiri Benc
On Tue, 3 Jun 2014 10:24:16 +0200, Richard Cochran wrote:
> The reason I mentioned the RH and TI back ports was not to make
> anybody look bad. Rather, I am trying to suggest that making a working
> back port to 2.6.30 is not as easy as it sounds.

This is something I can very much agree with :-)

 Jiri

-- 
Jiri Benc

--
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their 
applications. Written by three acclaimed leaders in the field, 
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] linuxptp in kernel 2.6.30+?

2014-06-03 Thread Jiri Benc
On Tue, 3 Jun 2014 09:33:28 +0200, Richard Cochran wrote:
> On Mon, Jun 02, 2014 at 09:02:16PM +, Keller, Jacob E wrote:
> > Redhat did a semi-decent job in their RHEL 6.4, and 6.5 kernels. I've
> > tested ptp4l against them, and it mostly works.
> 
> Wasn't someone asking about the RH backport on the linuxptp lists a
> while back, with some unresolved problem?

I would be very interested in such problems. RHEL 6.4 support was buggy
(and it was not unexpected, we marked it as Tech Preview for a reason)
but RHEL 6.5 should work. We even found and fixed several upstream
problems while doing the backport. Feel free to send any problems in
6.5 you find my way. But this is off topic on this list...

 Jiri

-- 
Jiri Benc

--
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their 
applications. Written by three acclaimed leaders in the field, 
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 04/14] phc2sys: store information about clocks being UTC or TAI

2014-05-30 Thread Jiri Benc
On Fri, 23 May 2014 10:32:28 +0200, Miroslav Lichvar wrote:
> On Wed, May 14, 2014 at 03:39:40PM +0200, Jiri Benc wrote:
> > For now, only CLOCK_REALTIME can be UTC. This may stay this way forever but
> > now we have a clean separation between codepaths where CLOCK_REALTIME is
> > required and codepaths any UTC clock should take.
> > 
> > The main motiviation behind this change is removal of sync_offset_direction.
> > It has to be computed on the fly based on the source and destination when we
> > have multiple clocks supported and automatic following of ptp4l state
> > changes implemented.
> 
> I've noticed that the UTC-TAI offset is applied in the wrong
> direction, I'm seeing 70s offset to UTC with this patch.

Hmm, I see the error, 'offset' is slave - master, not master - slave.
The strange thing is I remember testing this in various combinations of
master/slave UTC/PTP time scale and offsets :-/

I'll fix this. Also, the second parameter to get_sync_offset is better
named 'dst'.

Thanks for the review,

 Jiri

-- 
Jiri Benc

--
Time is money. Stop wasting it! Get your web API in 5 minutes.
www.restlet.com/download
http://p.sf.net/sfu/restlet
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 11/14] phc2sys: autoconfiguration

2014-05-14 Thread Jiri Benc
Add automatic configuration option (-a).

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  265 +
 1 files changed, 250 insertions(+), 15 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index edb73be5080c..9a89667e1d47 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -110,9 +111,11 @@ struct node {
struct clock *master;
 };
 
-static int update_sync_offset(struct node *node);
+static int update_pmc(struct node *node, int subscribe);
 static int clock_handle_leap(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int do_leap);
+static int run_pmc_get_utc_offset(struct node *node, int timeout);
+static void run_pmc_events(struct node *node);
 
 static clockid_t clock_open(char *device)
 {
@@ -267,6 +270,78 @@ static struct port *port_add(struct node *node, unsigned 
int number,
return p;
 }
 
+static void clock_reinit(struct clock *clock)
+{
+   servo_reset(clock->servo);
+   clock->servo_state = SERVO_UNLOCKED;
+
+   if (clock->offset_stats) {
+   stats_reset(clock->offset_stats);
+   stats_reset(clock->freq_stats);
+   stats_reset(clock->delay_stats);
+   }
+}
+
+static void reconfigure(struct node *node)
+{
+   struct clock *c, *rt, *src;
+   int src_cnt = 0, dst_cnt = 0;
+
+   pr_info("reconfiguring after port state change");
+   node->state_changed = 0;
+
+   src = rt = NULL;
+   LIST_FOREACH(c, &node->clocks, list) {
+   if (c->clkid == CLOCK_REALTIME) {
+   rt = c;
+   continue;
+   }
+
+   if (c->new_state == PS_MASTER)
+   clock_reinit(c);
+
+   c->state = c->new_state;
+   c->new_state = 0;
+
+   if (c->state == PS_SLAVE) {
+   src = c;
+   src_cnt++;
+   } else if (c->state == PS_UNCALIBRATED) {
+   src_cnt++;
+   } else if (c->state == PS_MASTER) {
+   pr_info("selecting %s for synchronization", c->device);
+   dst_cnt++;
+   }
+   }
+   if (src_cnt > 1) {
+   pr_info("multiple master clocks available, postponing sync...");
+   node->master = NULL;
+   return;
+   }
+   if (src_cnt > 0 && !src) {
+   pr_info("master clock not ready, waiting...");
+   node->master = NULL;
+   return;
+   }
+   if (!src_cnt && !dst_cnt) {
+   pr_info("no PHC ready, waiting...");
+   node->master = NULL;
+   return;
+   }
+   if (!src_cnt) {
+   src = rt;
+   rt->state = PS_SLAVE;
+   } else {
+   if (rt->state != PS_MASTER) {
+   rt->state = PS_MASTER;
+   clock_reinit(rt);
+   }
+   pr_info("selecting %s for synchronization", rt->device);
+   }
+   node->master = src;
+   pr_info("selecting %s as the master clock", src->device);
+}
+
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
int64_t *offset, uint64_t *ts, int64_t *delay)
 {
@@ -465,7 +540,7 @@ static int do_pps_loop(struct node *node, struct clock 
*clock, int fd)
pps_offset = pps_ts - phc_ts;
}
 
-   do_leap = update_sync_offset(node);
+   do_leap = update_pmc(node, 0);
if (do_leap < 0)
continue;
update_clock(node, clock, pps_offset, pps_ts, -1, do_leap);
@@ -474,13 +549,12 @@ static int do_pps_loop(struct node *node, struct clock 
*clock, int fd)
return 0;
 }
 
-static int do_loop(struct node *node)
+static int do_loop(struct node *node, int subscriptions)
 {
struct timespec interval;
struct clock *clock;
uint64_t ts;
int64_t offset, delay;
-   int src_fd = CLOCKID_TO_FD(node->master->clkid);
int do_leap;
 
interval.tv_sec = node->phc_interval;
@@ -488,18 +562,34 @@ static int do_loop(struct node *node)
 
while (1) {
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
-   do_leap = update_sync_offset(node);
+   do_leap = update_pmc(node, subscriptions);
if (do_leap < 0)
continue;
 
+   if (subscriptions) {
+   run_pmc_events(node);
+   if (node->state_changed) {
+

[Linuxptp-devel] [PATCH v2 14/14] phc2sys: man page update for -a and -r options

2014-05-14 Thread Jiri Benc
Signed-off-by: Jiri Benc 
---
 phc2sys.8 |  115 ++---
 1 files changed, 79 insertions(+), 36 deletions(-)

diff --git a/phc2sys.8 b/phc2sys.8
index fa3ae206f3df..37a39d0ba60f 100644
--- a/phc2sys.8
+++ b/phc2sys.8
@@ -1,12 +1,17 @@
 .TH PHC2SYS 8 "November 2012" "linuxptp"
 .SH NAME
-phc2sys \- synchronize two clocks
+phc2sys \- synchronize two or more clocks
 
 .SH SYNOPSIS
-.B phc2sys
+.B phc2sys \-a
 [
-.B \-wmqvx
+.B \-r
 ] [
+.B \-r
+] [ options ]
+.br
+.B phc2sys
+[
 .BI \-d " pps-device"
 ] [
 .BI \-s " device"
@@ -15,45 +20,53 @@ phc2sys \- synchronize two clocks
 ] [
 .BI \-O " offset"
 ] [
-.BI \-E " servo"
-] [
-.BI \-P " kp"
-] [
-.BI \-I " ki"
-] [
-.BI \-S " step"
-] [
-.BI \-F " step"
-] [
-.BI \-R " update-rate"
-] [
-.BI \-N " clock-readings"
-] [
-.BI \-L " freq-limit"
-] [
-.BI \-u " summary-updates"
-] [
-.BI \-n " domain-number"
-] [
-.BI \-l " print-level"
-]
+.BI \-w
+] [ options ]
 
 .SH DESCRIPTION
 .B phc2sys
-is a program which synchronizes two clocks in the system. Typically, it is used
-to synchronize the system clock to a PTP hardware clock (PHC), which itself is
-synchronized by the
+is a program which synchronizes two or more clocks in the system. Typically,
+it is used to synchronize the system clock to a PTP hardware clock (PHC),
+which itself is synchronized by the
 .BR ptp4l (8)
 program.
 
-Two synchronization modes are supported, one uses a pulse per second (PPS)
+With the
+.B \-a
+option, the clocks to synchronize are fetched from the running
+.B ptp4l
+daemon and the direction of synchronization automatically follows changes of
+the PTP port states.
+
+Manual configuration is also possible. When using manual configuration, two
+synchronization modes are supported, one uses a pulse per second (PPS)
 signal provided by the source clock and the other mode reads time from the
 source clock directly. Some clocks can be used in both modes, the mode which
-will synchronize the slave clock with better accuracy depends on hardware and
-driver implementation.
+will synchronize the slave clock with better accuracy depends on hardware
+and driver implementation.
 
 .SH OPTIONS
 .TP
+.BI \-a
+Read the clocks to synchronize from running
+.B ptp4l
+and follow changes in the port states, adjusting the synchronization
+direction automatically. The system clock (CLOCK_REALTIME) is not
+synchronized, unless the
+.B \-r
+option is also specified.
+.TP
+.BI \-r
+Only valid together with the
+.B \-a
+option. Instructs
+.B phc2sys
+to also synchronize the system clock (CLOCK_REALTIME). By default, the
+system clock is not considered as a possible time source. If you want the
+system clock to be eligible to become a time source, specify the
+.B \-r
+option twice.
+.TP
 .BI \-d " pps-device"
 Specify the PPS device of the master clock (e.g. /dev/pps0). With this option
 the PPS synchronization mode is used instead of the direct mode. As the PPS
@@ -68,7 +81,10 @@ option the PPS signal of the master clock is enabled 
automatically, otherwise
 it has to be enabled before
 .B phc2sys
 is started (e.g. by running \f(CWecho 1 > /sys/class/ptp/ptp0/pps_enable\fP).
-This option can be used only with the system clock as the slave clock.
+This option can be used only with the system clock as the slave clock. Not
+compatible with the
+.B \-a
+option.
 .TP
 .BI \-s " device"
 Specify the master clock by device (e.g. /dev/ptp0) or interface (e.g. eth0) or
@@ -76,7 +92,9 @@ by name (e.g. CLOCK_REALTIME for the system clock). When this 
option is used
 together with the
 .B \-d
 option, the master clock is used only to correct the offset by whole number of
-seconds, which cannot be fixed with PPS alone.
+seconds, which cannot be fixed with PPS alone. Not compatible with the
+.B \-a
+option.
 .TP
 .BI \-i " interface"
 Performs the exact same function as
@@ -89,7 +107,10 @@ should no longer be used.
 .TP
 .BI \-c " device"
 Specify the slave clock by device (e.g. /dev/ptp1) or interface (e.g. eth1) or
-by  name. The default is CLOCK_REALTIME (the system clock).
+by  name. The default is CLOCK_REALTIME (the system clock). Not compatible
+with the
+.B \-a
+option.
 .TP
 .BI \-E " servo"
 Specify which clock servo should be used. Valid values are pi for a PI
@@ -128,7 +149,10 @@ minimize the error caused by random delays in scheduling 
and bus utilization.
 The default is 5.
 .TP
 .BI \-O " offset"
-Specify the offset between the slave and master times in seconds.  See
+Specify the offset between the slave and master times in seconds. Not
+compatible with the
+.B \-a
+option.  See
 .SM
 .B TIME SCALE USAGE
 below.
@@ -154,7 +178,9 @@ Wait until ptp4l is in a synchronized state. If the
 .B \-O
 option is not used, also keep the offse

[Linuxptp-devel] [PATCH v2 09/14] phc2sys: event subscription

2014-05-14 Thread Jiri Benc
Add support for subscribing to events (run_pmc_subscribe) and receiving and
handling of received events (run_pmc_events).

Add initial support for port status changes.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  116 +++-
 1 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index ece4560e0c67..5b90bb2a5106 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -41,6 +41,7 @@
 #include "ds.h"
 #include "fsm.h"
 #include "missing.h"
+#include "notification.h"
 #include "phc.h"
 #include "pi.h"
 #include "pmc_common.h"
@@ -59,12 +60,19 @@
 
 #define PHC_PPS_OFFSET_LIMIT 1000
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
+#define PMC_SUBSCRIBE_DURATION 180 /* 3 minutes */
+/* Note that PMC_SUBSCRIBE_DURATION has to be longer than
+ * PMC_UPDATE_INTERVAL otherwise subscription will time out before it is
+ * renewed.
+ */
 
 struct clock {
LIST_ENTRY(clock) list;
clockid_t clkid;
int sysoff_supported;
int is_utc;
+   int state;
+   int new_state;
struct servo *servo;
enum servo_state servo_state;
char *device;
@@ -78,6 +86,7 @@ struct clock {
 struct port {
LIST_ENTRY(port) list;
unsigned int number;
+   int state;
struct clock *clock;
 };
 
@@ -95,6 +104,7 @@ struct node {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
+   int state_changed;
LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
@@ -533,6 +543,81 @@ static void *get_mgt_data(struct ptp_message *msg)
return mgt->data;
 }
 
+static int normalize_state(int state)
+{
+   if (state != PS_MASTER && state != PS_SLAVE &&
+   state != PS_PRE_MASTER && state != PS_UNCALIBRATED) {
+   /* treat any other state as "not a master nor a slave" */
+   state = PS_DISABLED;
+   }
+   return state;
+}
+
+static int clock_compute_state(struct node *node, struct clock *clock)
+{
+   struct port *p;
+   int state = PS_DISABLED;
+
+   LIST_FOREACH(p, &node->ports, list) {
+   if (p->clock != clock)
+   continue;
+   /* PS_SLAVE takes the highest precedence, PS_UNCALIBRATED
+* after that, PS_MASTER is third, PS_PRE_MASTER fourth and
+* all of that overrides PS_DISABLED, which corresponds
+* nicely with the numerical values */
+   if (p->state > state)
+   state = p->state;
+   }
+   return state;
+}
+
+static int recv_subscribed(struct node *node, struct ptp_message *msg,
+  int excluded)
+{
+   int mgt_id, state;
+   struct portDS *pds;
+   struct port *port;
+   struct clock *clock;
+
+   mgt_id = get_mgt_id(msg);
+   if (mgt_id == excluded)
+   return 0;
+   switch (mgt_id) {
+   case PORT_DATA_SET:
+   pds = get_mgt_data(msg);
+   port = port_get(node, pds->portIdentity.portNumber);
+   if (!port) {
+   pr_info("received data for unknown port %s",
+   pid2str(&pds->portIdentity));
+   return 1;
+   }
+   state = normalize_state(pds->portState);
+   if (port->state != state) {
+   pr_info("port %s changed state",
+   pid2str(&pds->portIdentity));
+   port->state = state;
+   clock = port->clock;
+   state = clock_compute_state(node, clock);
+   if (clock->state != state) {
+   clock->new_state = state;
+   node->state_changed = 1;
+   }
+   }
+   return 1;
+   }
+   return 0;
+}
+
+static void send_subscription(struct node *node)
+{
+   struct subscribe_events_np sen;
+
+   memset(&sen, 0, sizeof(sen));
+   sen.duration = PMC_SUBSCRIBE_DURATION;
+   sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
+   pmc_send_set_action(node->pmc, SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
+}
+
 static int init_pmc(struct node *node, int domain_number)
 {
node->pmc = pmc_create(TRANS_UDS, "/var/run/phc2sys", 0,
@@ -555,7 +640,7 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
while (1) {
pollfd[0].fd = pmc_get_transport_fd(node->pmc);
pollfd[0].events = POLLIN|POLLPRI;
-   if (!node->pmc_ds_requested)
+   if (!node->pmc_ds_requested && ds_id >=

[Linuxptp-devel] [PATCH v2 07/14] phc2sys: track ports

2014-05-14 Thread Jiri Benc
Add tracking of which ports have been added and to which clock they belong.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   51 +++
 1 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 62e9b8c19e17..ece4560e0c67 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -75,6 +75,12 @@ struct clock {
struct clockcheck *sanity_check;
 };
 
+struct port {
+   LIST_ENTRY(port) list;
+   unsigned int number;
+   struct clock *clock;
+};
+
 struct node {
unsigned int stats_max_count;
int sanity_freq_limit;
@@ -89,6 +95,7 @@ struct node {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
+   LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
 };
@@ -206,6 +213,50 @@ static struct clock *clock_add(struct node *node, char 
*device)
return c;
 }
 
+static struct port *port_get(struct node *node, unsigned int number)
+{
+   struct port *p;
+
+   LIST_FOREACH(p, &node->ports, list) {
+   if (p->number == number)
+   return p;
+   }
+   return NULL;
+}
+
+static struct port *port_add(struct node *node, unsigned int number,
+char *device)
+{
+   struct port *p;
+   struct clock *c = NULL, *tmp;
+
+   p = port_get(node, number);
+   if (p)
+   return p;
+   /* port is a new one, look whether we have the device already on
+* a different port */
+   LIST_FOREACH(tmp, &node->clocks, list) {
+   if (!strcmp(tmp->device, device)) {
+   c = tmp;
+   break;
+   }
+   }
+   if (!c) {
+   c = clock_add(node, device);
+   if (!c)
+   return NULL;
+   }
+   p = malloc(sizeof(*p));
+   if (!p) {
+   pr_err("failed to allocate memory for a port");
+   return NULL;
+   }
+   p->number = number;
+   p->clock = c;
+   LIST_INSERT_HEAD(&node->ports, p, list);
+   return p;
+}
+
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
int64_t *offset, uint64_t *ts, int64_t *delay)
 {
-- 
1.7.6.5


--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 08/14] pmc_common: easy way to set port and broadcast target

2014-05-14 Thread Jiri Benc
Implement pmc_target_port to set a port number, leaving clock identity
unchanged, and pmc_target_all to set clock identity and port number to all
1's.

Signed-off-by: Jiri Benc 
---
 pmc_common.c |   12 +++-
 pmc_common.h |2 ++
 2 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/pmc_common.c b/pmc_common.c
index 2c75074c8fb7..41385da45209 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -78,7 +78,7 @@ struct pmc *pmc_create(enum transport_type transport_type, 
const char *iface_nam
goto failed;
}
pmc->port_identity.portNumber = 1;
-   memset(&pmc->target, 0xff, sizeof(pmc->target));
+   pmc_target_all(pmc);
 
pmc->boundary_hops = boundary_hops;
pmc->domain_number = domain_number;
@@ -325,3 +325,13 @@ int pmc_target(struct pmc *pmc, struct PortIdentity *pid)
pmc->target = *pid;
return 0;
 }
+
+void pmc_target_port(struct pmc *pmc, UInteger16 portNumber)
+{
+   pmc->target.portNumber = portNumber;
+}
+
+void pmc_target_all(struct pmc *pmc)
+{
+   memset(&pmc->target, 0xff, sizeof(pmc->target));
+}
diff --git a/pmc_common.h b/pmc_common.h
index 9fcb51da3fd4..9adb9d1dd98b 100644
--- a/pmc_common.h
+++ b/pmc_common.h
@@ -41,5 +41,7 @@ int pmc_send_set_action(struct pmc *pmc, int id, void *data, 
int datasize);
 struct ptp_message *pmc_recv(struct pmc *pmc);
 
 int pmc_target(struct pmc *pmc, struct PortIdentity *pid);
+void pmc_target_port(struct pmc *pmc, UInteger16 portNumber);
+void pmc_target_all(struct pmc *pmc);
 
 #endif
-- 
1.7.6.5


--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 05/14] phc2sys: rearrange declarations

2014-05-14 Thread Jiri Benc
This just moves code around to have related functions together and forward
declaration at the beginning of the file. No code changes.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  208 ++---
 1 files changed, 103 insertions(+), 105 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 6c86b4d9f028..34f5f94ccb91 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -60,7 +60,41 @@
 #define PHC_PPS_OFFSET_LIMIT 1000
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
-struct clock;
+struct clock {
+   LIST_ENTRY(clock) list;
+   clockid_t clkid;
+   int sysoff_supported;
+   int is_utc;
+   struct servo *servo;
+   enum servo_state servo_state;
+   const char *source_label;
+   struct stats *offset_stats;
+   struct stats *freq_stats;
+   struct stats *delay_stats;
+   struct clockcheck *sanity_check;
+};
+
+struct node {
+   unsigned int stats_max_count;
+   int sanity_freq_limit;
+   enum servo_type servo_type;
+   int phc_readings;
+   double phc_interval;
+   int sync_offset;
+   int forced_sync_offset;
+   int leap;
+   int leap_set;
+   int kernel_leap;
+   struct pmc *pmc;
+   int pmc_ds_requested;
+   uint64_t pmc_last_update;
+   LIST_HEAD(clock_head, clock) clocks;
+   struct clock *master;
+};
+
+static int update_sync_offset(struct node *node);
+static int clock_handle_leap(struct node *node, struct clock *clock,
+int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -95,6 +129,74 @@ static clockid_t clock_open(char *device)
return clkid;
 }
 
+static int clock_add(struct node *node, clockid_t clkid)
+{
+   struct clock *c;
+   int max_ppb;
+   double ppb;
+
+   c = calloc(1, sizeof(*c));
+   if (!c) {
+   pr_err("failed to allocate memory for a clock");
+   return -1;
+   }
+   c->clkid = clkid;
+   c->servo_state = SERVO_UNLOCKED;
+
+   if (c->clkid == CLOCK_REALTIME) {
+   c->source_label = "sys";
+   c->is_utc = 1;
+   } else {
+   c->source_label = "phc";
+   }
+
+   if (node->stats_max_count > 0) {
+   c->offset_stats = stats_create();
+   c->freq_stats = stats_create();
+   c->delay_stats = stats_create();
+   if (!c->offset_stats ||
+   !c->freq_stats ||
+   !c->delay_stats) {
+   pr_err("failed to create stats");
+   return -1;
+   }
+   }
+   if (node->sanity_freq_limit) {
+   c->sanity_check = clockcheck_create(node->sanity_freq_limit);
+   if (!c->sanity_check) {
+   pr_err("failed to create clock check");
+   return -1;
+   }
+   }
+
+   clockadj_init(c->clkid);
+   ppb = clockadj_get_freq(c->clkid);
+   /* The reading may silently fail and return 0, reset the frequency to
+  make sure ppb is the actual frequency of the clock. */
+   clockadj_set_freq(c->clkid, ppb);
+   if (c->clkid == CLOCK_REALTIME) {
+   sysclk_set_leap(0);
+   max_ppb = sysclk_max_freq();
+   } else {
+   max_ppb = phc_max_adj(c->clkid);
+   if (!max_ppb) {
+   pr_err("clock is not adjustable");
+   return -1;
+   }
+   }
+
+   c->servo = servo_create(node->servo_type, -ppb, max_ppb, 0);
+   servo_sync_interval(c->servo, node->phc_interval);
+
+   if (clkid != CLOCK_REALTIME)
+   c->sysoff_supported = (SYSOFF_SUPPORTED ==
+  sysoff_probe(CLOCKID_TO_FD(clkid),
+   node->phc_readings));
+
+   LIST_INSERT_HEAD(&node->clocks, c, list);
+   return 0;
+}
+
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
int64_t *offset, uint64_t *ts, int64_t *delay)
 {
@@ -126,42 +228,6 @@ static int read_phc(clockid_t clkid, clockid_t sysclk, int 
readings,
return 1;
 }
 
-struct clock {
-   LIST_ENTRY(clock) list;
-   clockid_t clkid;
-   int sysoff_supported;
-   int is_utc;
-   struct servo *servo;
-   enum servo_state servo_state;
-   const char *source_label;
-   struct stats *offset_stats;
-   struct stats *freq_stats;
-   struct stats *delay_stats;
-   struct clockcheck *sanity_check;
-};
-
-struct node {
-   unsigned int stats_max_count;
-   int sanity_freq_limit;
-   enum servo_type servo_type;
-   int phc_readings;
-   double phc_interval;
-   int sync_offs

[Linuxptp-devel] [PATCH v2 04/14] phc2sys: store information about clocks being UTC or TAI

2014-05-14 Thread Jiri Benc
For now, only CLOCK_REALTIME can be UTC. This may stay this way forever but
now we have a clean separation between codepaths where CLOCK_REALTIME is
required and codepaths any UTC clock should take.

The main motiviation behind this change is removal of sync_offset_direction.
It has to be computed on the fly based on the source and destination when we
have multiple clocks supported and automatic following of ptp4l state
changes implemented.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   60 +---
 1 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 825d7328af15..6c86b4d9f028 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -130,6 +130,7 @@ struct clock {
LIST_ENTRY(clock) list;
clockid_t clkid;
int sysoff_supported;
+   int is_utc;
struct servo *servo;
enum servo_state servo_state;
const char *source_label;
@@ -146,7 +147,7 @@ struct node {
int phc_readings;
double phc_interval;
int sync_offset;
-   int sync_offset_direction;
+   int forced_sync_offset;
int leap;
int leap_set;
int kernel_leap;
@@ -161,6 +162,15 @@ static int update_sync_offset(struct node *node);
 static int clock_handle_leap(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int do_leap);
 
+static int64_t get_sync_offset(struct node *node, struct clock *src)
+{
+   int direction = node->forced_sync_offset;
+
+   if (!direction)
+   direction = node->master->is_utc - src->is_utc;
+   return (int64_t)node->sync_offset * NS_PER_SEC * direction;
+}
+
 static void update_clock_stats(struct clock *clock, unsigned int max_count,
   int64_t offset, double freq, int64_t delay)
 {
@@ -206,9 +216,7 @@ static void update_clock(struct node *node, struct clock 
*clock,
if (clock_handle_leap(node, clock, offset, ts, do_leap))
return;
 
-   if (node->sync_offset_direction)
-   offset += node->sync_offset * NS_PER_SEC *
-   node->sync_offset_direction;
+   offset += get_sync_offset(node, clock);
 
if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts))
servo_reset(clock->servo);
@@ -290,7 +298,7 @@ static int do_pps_loop(struct node *node, struct clock 
*clock, int fd)
 
if (src == CLOCK_INVALID) {
/* The sync offset can't be applied with PPS alone. */
-   node->sync_offset_direction = 0;
+   node->sync_offset = 0;
} else {
enable_pps_output(node->master->clkid);
}
@@ -558,15 +566,14 @@ static int clock_handle_leap(struct node *node, struct 
clock *clock,
if (!node->leap && !do_leap)
return 0;
 
-   if (clock->clkid != CLOCK_REALTIME &&
-   node->master->clkid != CLOCK_REALTIME)
+   if (clock->is_utc == node->master->is_utc)
return 0;
 
/* If the system clock is the master clock, get a time stamp from
   it, as it is the clock which will include the leap second. */
-   if (node->master->clkid == CLOCK_REALTIME) {
+   if (node->master->is_utc) {
struct timespec tp;
-   if (clock_gettime(CLOCK_REALTIME, &tp)) {
+   if (clock_gettime(node->master->clkid, &tp)) {
pr_err("failed to read clock: %m");
return -1;
}
@@ -575,11 +582,8 @@ static int clock_handle_leap(struct node *node, struct 
clock *clock,
 
/* If the clock will be stepped, the time stamp has to be the
   target time. Ignore possible 1 second error in UTC offset. */
-   if (clock->clkid == CLOCK_REALTIME &&
-   clock->servo_state == SERVO_UNLOCKED) {
-   ts -= offset + node->sync_offset * NS_PER_SEC *
-   node->sync_offset_direction;
-   }
+   if (clock->is_utc && clock->servo_state == SERVO_UNLOCKED)
+   ts -= get_sync_offset(node, clock);
 
/* Suspend clock updates in the last second before midnight. */
if (is_utc_ambiguous(ts)) {
@@ -610,10 +614,12 @@ static int clock_add(struct node *node, clockid_t clkid)
c->clkid = clkid;
c->servo_state = SERVO_UNLOCKED;
 
-   if (c->clkid == CLOCK_REALTIME)
+   if (c->clkid == CLOCK_REALTIME) {
c->source_label = "sys";
-   else
+   c->is_utc = 1;
+   } else {
c->source_label = "phc";
+   }
 
if (node->stats_max_count > 0) {
c->offset_stats = stats_create();
@@ -698,7 +704,7 @@ int main(int argc, cha

[Linuxptp-devel] [PATCH v2 06/14] phc2sys: open devices in clock_add

2014-05-14 Thread Jiri Benc
Do not call clock_open to open a clock device but let clock_add do that and
return the newly created struct. Also, store the device (interface) name in
struct clock.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   81 ++--
 1 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 34f5f94ccb91..62e9b8c19e17 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -67,6 +67,7 @@ struct clock {
int is_utc;
struct servo *servo;
enum servo_state servo_state;
+   char *device;
const char *source_label;
struct stats *offset_stats;
struct stats *freq_stats;
@@ -129,19 +130,27 @@ static clockid_t clock_open(char *device)
return clkid;
 }
 
-static int clock_add(struct node *node, clockid_t clkid)
+static struct clock *clock_add(struct node *node, char *device)
 {
struct clock *c;
+   clockid_t clkid = CLOCK_INVALID;
int max_ppb;
double ppb;
 
+   if (device) {
+   clkid = clock_open(device);
+   if (clkid == CLOCK_INVALID)
+   return NULL;
+   }
+
c = calloc(1, sizeof(*c));
if (!c) {
pr_err("failed to allocate memory for a clock");
-   return -1;
+   return NULL;
}
c->clkid = clkid;
c->servo_state = SERVO_UNLOCKED;
+   c->device = strdup(device);
 
if (c->clkid == CLOCK_REALTIME) {
c->source_label = "sys";
@@ -158,14 +167,14 @@ static int clock_add(struct node *node, clockid_t clkid)
!c->freq_stats ||
!c->delay_stats) {
pr_err("failed to create stats");
-   return -1;
+   return NULL;
}
}
if (node->sanity_freq_limit) {
c->sanity_check = clockcheck_create(node->sanity_freq_limit);
if (!c->sanity_check) {
pr_err("failed to create clock check");
-   return -1;
+   return NULL;
}
}
 
@@ -181,7 +190,7 @@ static int clock_add(struct node *node, clockid_t clkid)
max_ppb = phc_max_adj(c->clkid);
if (!max_ppb) {
pr_err("clock is not adjustable");
-   return -1;
+   return NULL;
}
}
 
@@ -194,7 +203,7 @@ static int clock_add(struct node *node, clockid_t clkid)
node->phc_readings));
 
LIST_INSERT_HEAD(&node->clocks, c, list);
-   return 0;
+   return c;
 }
 
 static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
@@ -699,8 +708,8 @@ static void usage(char *progname)
 int main(int argc, char *argv[])
 {
char *progname;
-   clockid_t src = CLOCK_INVALID;
-   clockid_t dst = CLOCK_REALTIME;
+   char *src_name = NULL, *dst_name = NULL;
+   struct clock *src, *dst;
int c, domain_number = 0, pps_fd = -1;
int r, wait_sync = 0;
int print_level = LOG_INFO, use_syslog = 1, verbose = 0;
@@ -723,7 +732,7 @@ int main(int argc, char *argv[])
  "c:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) {
switch (c) {
case 'c':
-   dst = clock_open(optarg);
+   dst_name = strdup(optarg);
break;
case 'd':
pps_fd = open(optarg, O_RDONLY);
@@ -737,7 +746,7 @@ int main(int argc, char *argv[])
fprintf(stderr,
"'-i' has been deprecated. please use '-s' 
instead.\n");
case 's':
-   src = clock_open(optarg);
+   src_name = strdup(optarg);
break;
case 'E':
if (!strcasecmp(optarg, "pi")) {
@@ -826,38 +835,46 @@ int main(int argc, char *argv[])
}
}
 
-   if (pps_fd < 0 && src == CLOCK_INVALID) {
+   if (pps_fd < 0 && !src_name) {
fprintf(stderr,
"valid source clock must be selected.\n");
goto bad_usage;
}
 
-   if (dst == CLOCK_INVALID) {
+   if (!wait_sync && !node.forced_sync_offset) {
fprintf(stderr,
-   "valid destination clock must be selected.\n");
+   "time offset must be specified using -w or -O\n");
goto bad_usage;
}
 
-   if (pps_fd >= 0 && dst != CLOCK_REALTIME) {

[Linuxptp-devel] [PATCH v2 13/14] phc2sys: check clockIdentity

2014-05-14 Thread Jiri Benc
Make sure that we handle only one PTP clock (node). This is for an extra
safety.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   44 ++--
 1 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 52417268305c..f630ab05c9ed 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -107,6 +107,8 @@ struct node {
int pmc_ds_requested;
uint64_t pmc_last_update;
int state_changed;
+   int clock_identity_set;
+   struct ClockIdentity clock_identity;
LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
@@ -612,6 +614,15 @@ static int do_loop(struct node *node, int subscriptions)
return 0; /* unreachable */
 }
 
+static int check_clock_identity(struct node *node, struct ptp_message *msg)
+{
+   if (!node->clock_identity_set)
+   return 1;
+   return !memcmp(&node->clock_identity,
+  &msg->header.sourcePortIdentity.clockIdentity,
+  sizeof(struct ClockIdentity));
+}
+
 static int is_msg_mgt(struct ptp_message *msg)
 {
struct TLV *tlv;
@@ -789,6 +800,12 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
if (!*msg)
continue;
 
+   if (!check_clock_identity(node, *msg)) {
+   msg_put(*msg);
+   *msg = NULL;
+   continue;
+   }
+
res = is_msg_mgt(*msg);
if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
node->pmc_ds_requested = 0;
@@ -927,6 +944,24 @@ out:
return res;
 }
 
+static int run_pmc_clock_identity(struct node *node, int timeout)
+{
+   struct ptp_message *msg;
+   struct defaultDS *dds;
+   int res;
+
+   res = run_pmc(node, timeout, DEFAULT_DATA_SET, &msg);
+   if (res <= 0)
+   return res;
+
+   dds = (struct defaultDS *)get_mgt_data(msg);
+   memcpy(&node->clock_identity, &dds->clockIdentity,
+  sizeof(struct ClockIdentity));
+   node->clock_identity_set = 1;
+   msg_put(msg);
+   return 1;
+}
+
 static void close_pmc(struct node *node)
 {
pmc_destroy(node->pmc);
@@ -943,7 +978,7 @@ static int auto_init_ports(struct node *node, int add_rt)
char iface[IFNAMSIZ];
 
while (1) {
-   res = run_pmc_get_number_ports(node, 1000);
+   res = run_pmc_clock_identity(node, 1000);
if (res < 0)
return -1;
if (res > 0)
@@ -951,7 +986,12 @@ static int auto_init_ports(struct node *node, int add_rt)
/* res == 0, timeout */
pr_notice("Waiting for ptp4l...");
}
-   number_ports = res;
+
+   number_ports = run_pmc_get_number_ports(node, 1000);
+   if (number_ports <= 0) {
+   pr_err("failed to get number of ports");
+   return -1;
+   }
 
res = run_pmc_subscribe(node, 1000);
if (res <= 0) {
-- 
1.7.6.5


--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 12/14] phc2sys: autoconfigure realtime clock on demand only

2014-05-14 Thread Jiri Benc
By default, do not synchronize CLOCK_REALTIME. To do it, -r option is
needed. That will only consider CLOCK_REALTIME as the destination. To
consider it also as a possible time source, use -rr.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   31 ---
 1 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 9a89667e1d47..52417268305c 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -72,6 +72,7 @@ struct clock {
clockid_t clkid;
int sysoff_supported;
int is_utc;
+   int dest_only;
int state;
int new_state;
struct servo *servo;
@@ -328,10 +329,16 @@ static void reconfigure(struct node *node)
node->master = NULL;
return;
}
+   if ((!src_cnt && (!rt || rt->dest_only)) ||
+   (!dst_cnt && !rt)) {
+   pr_info("nothing to synchronize");
+   node->master = NULL;
+   return;
+   }
if (!src_cnt) {
src = rt;
rt->state = PS_SLAVE;
-   } else {
+   } else if (rt) {
if (rt->state != PS_MASTER) {
rt->state = PS_MASTER;
clock_reinit(rt);
@@ -926,7 +933,7 @@ static void close_pmc(struct node *node)
node->pmc = NULL;
 }
 
-static int auto_init_ports(struct node *node)
+static int auto_init_ports(struct node *node, int add_rt)
 {
struct port *port;
struct clock *clock;
@@ -981,8 +988,13 @@ static int auto_init_ports(struct node *node)
}
node->state_changed = 1;
 
-   if (!clock_add(node, "CLOCK_REALTIME"))
-   return -1;
+   if (add_rt) {
+   clock = clock_add(node, "CLOCK_REALTIME");
+   if (!clock)
+   return -1;
+   if (add_rt == 1)
+   clock->dest_only = 1;
+   }
 
/* get initial offset */
if (run_pmc_get_utc_offset(node, 1000) <= 0) {
@@ -1077,6 +1089,8 @@ static void usage(char *progname)
"\n"
" automatic configuration:\n"
" -a turn on autoconfiguration\n"
+   " -r synchronize system (realtime) clock\n"
+   "repeat -r to consider it also as a time 
source\n"
" manual configuration:\n"
" -c [dev|name]  slave clock (CLOCK_REALTIME)\n"
" -d [dev]   master PPS device\n"
@@ -1109,7 +1123,7 @@ int main(int argc, char *argv[])
char *progname;
char *src_name = NULL, *dst_name = NULL;
struct clock *src, *dst;
-   int autocfg = 0;
+   int autocfg = 0, rt = 0;
int c, domain_number = 0, pps_fd = -1;
int r, wait_sync = 0;
int print_level = LOG_INFO, use_syslog = 1, verbose = 0;
@@ -1129,11 +1143,14 @@ int main(int argc, char *argv[])
progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0];
while (EOF != (c = getopt(argc, argv,
- "ac:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) {
+ "arc:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) 
{
switch (c) {
case 'a':
autocfg = 1;
break;
+   case 'r':
+   rt++;
+   break;
case 'c':
dst_name = strdup(optarg);
break;
@@ -1263,7 +1280,7 @@ int main(int argc, char *argv[])
if (autocfg) {
if (init_pmc(&node, domain_number))
return -1;
-   if (auto_init_ports(&node) < 0)
+   if (auto_init_ports(&node, rt) < 0)
return -1;
return do_loop(&node, 1);
}
-- 
1.7.6.5


--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 03/14] phc2sys: split clock and node

2014-05-14 Thread Jiri Benc
Split members that apply to all synchronized clocks and members that apply
to an individual clock. Keep all clocks in a list, with a pointer to the
source clock. This will allow to support multiple clocks synchronization.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  397 +---
 1 files changed, 218 insertions(+), 179 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 19dce45964eb..825d7328af15 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -60,9 +61,6 @@
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
 struct clock;
-static int update_sync_offset(struct clock *clock);
-static int clock_handle_leap(struct clock *clock, clockid_t src,
-int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -129,14 +127,24 @@ static int read_phc(clockid_t clkid, clockid_t sysclk, 
int readings,
 }
 
 struct clock {
+   LIST_ENTRY(clock) list;
clockid_t clkid;
+   int sysoff_supported;
struct servo *servo;
enum servo_state servo_state;
const char *source_label;
struct stats *offset_stats;
struct stats *freq_stats;
struct stats *delay_stats;
+   struct clockcheck *sanity_check;
+};
+
+struct node {
unsigned int stats_max_count;
+   int sanity_freq_limit;
+   enum servo_type servo_type;
+   int phc_readings;
+   double phc_interval;
int sync_offset;
int sync_offset_direction;
int leap;
@@ -145,10 +153,15 @@ struct clock {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
-   struct clockcheck *sanity_check;
+   LIST_HEAD(clock_head, clock) clocks;
+   struct clock *master;
 };
 
-static void update_clock_stats(struct clock *clock,
+static int update_sync_offset(struct node *node);
+static int clock_handle_leap(struct node *node, struct clock *clock,
+int64_t offset, uint64_t ts, int do_leap);
+
+static void update_clock_stats(struct clock *clock, unsigned int max_count,
   int64_t offset, double freq, int64_t delay)
 {
struct stats_result offset_stats, freq_stats, delay_stats;
@@ -158,7 +171,7 @@ static void update_clock_stats(struct clock *clock,
if (delay >= 0)
stats_add_value(clock->delay_stats, delay);
 
-   if (stats_get_num_values(clock->offset_stats) < clock->stats_max_count)
+   if (stats_get_num_values(clock->offset_stats) < max_count)
return;
 
stats_get_result(clock->offset_stats, &offset_stats);
@@ -183,19 +196,19 @@ static void update_clock_stats(struct clock *clock,
stats_reset(clock->delay_stats);
 }
 
-static void update_clock(struct clock *clock, clockid_t src,
+static void update_clock(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int64_t delay,
 int do_leap)
 {
enum servo_state state;
double ppb;
 
-   if (clock_handle_leap(clock, src, offset, ts, do_leap))
+   if (clock_handle_leap(node, clock, offset, ts, do_leap))
return;
 
-   if (clock->sync_offset_direction)
-   offset += clock->sync_offset * NS_PER_SEC *
-   clock->sync_offset_direction;
+   if (node->sync_offset_direction)
+   offset += node->sync_offset * NS_PER_SEC *
+   node->sync_offset_direction;
 
if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts))
servo_reset(clock->servo);
@@ -221,15 +234,15 @@ static void update_clock(struct clock *clock, clockid_t 
src,
}
 
if (clock->offset_stats) {
-   update_clock_stats(clock, offset, ppb, delay);
+   update_clock_stats(clock, node->stats_max_count, offset, ppb, 
delay);
} else {
if (delay >= 0) {
pr_info("%s offset %9" PRId64 " s%d freq %+7.0f "
"delay %6" PRId64,
-   clock->source_label, offset, state, ppb, delay);
+   node->master->source_label, offset, state, ppb, 
delay);
} else {
pr_info("%s offset %9" PRId64 " s%d freq %+7.0f",
-   clock->source_label, offset, state, ppb);
+   node->master->source_label, offset, state, ppb);
}
}
 }
@@ -266,20 +279,20 @@ static int read_pps(int fd, int64_t *offset, uint64_t *ts)
return 1;
 }
 
-static int do_pps_loop(struct clock *clock, int fd,
-  clockid_t src, int n_readings)

[Linuxptp-devel] [PATCH v2 10/14] phc2sys: propagate received errors

2014-05-14 Thread Jiri Benc
Recognize errors returned in MANAGEMENT_ERROR_STATUS TLV and return
a distinct value from run_pmc in case such error is received.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   34 +++---
 1 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 5b90bb2a5106..edb73be5080c 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -526,9 +526,11 @@ static int is_msg_mgt(struct ptp_message *msg)
if (msg->tlv_count != 1)
return 0;
tlv = (struct TLV *) msg->management.suffix;
-   if (tlv->type != TLV_MANAGEMENT)
-   return 0;
-   return 1;
+   if (tlv->type == TLV_MANAGEMENT)
+   return 1;
+   if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS)
+   return -1;
+   return 0;
 }
 
 static int get_mgt_id(struct ptp_message *msg)
@@ -543,6 +545,14 @@ static void *get_mgt_data(struct ptp_message *msg)
return mgt->data;
 }
 
+static int get_mgt_err_id(struct ptp_message *msg)
+{
+   struct management_error_status *mgt;
+
+   mgt = (struct management_error_status *)msg->management.suffix;
+   return mgt->id;
+}
+
 static int normalize_state(int state)
 {
if (state != PS_MASTER && state != PS_SLAVE &&
@@ -630,12 +640,18 @@ static int init_pmc(struct node *node, int domain_number)
return 0;
 }
 
+/* Return values:
+ * 1: success
+ * 0: timeout
+ * -1: error reported by the other side
+ * -2: local error, fatal
+ */
 static int run_pmc(struct node *node, int timeout, int ds_id,
   struct ptp_message **msg)
 {
 #define N_FD 1
struct pollfd pollfd[N_FD];
-   int cnt;
+   int cnt, res;
 
while (1) {
pollfd[0].fd = pmc_get_transport_fd(node->pmc);
@@ -646,7 +662,7 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
cnt = poll(pollfd, N_FD, timeout);
if (cnt < 0) {
pr_err("poll failed");
-   return -1;
+   return -2;
}
if (!cnt) {
/* Request the data set again in the next run. */
@@ -676,8 +692,12 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
if (!*msg)
continue;
 
-   if (!is_msg_mgt(*msg) ||
-   recv_subscribed(node, *msg, ds_id) ||
+   res = is_msg_mgt(*msg);
+   if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
+   node->pmc_ds_requested = 0;
+   return -1;
+   }
+   if (res <= 0 || recv_subscribed(node, *msg, ds_id) ||
get_mgt_id(*msg) != ds_id) {
msg_put(*msg);
*msg = NULL;
-- 
1.7.6.5


--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 01/14] phc2sys: generalize run_pmc

2014-05-14 Thread Jiri Benc
Make run_pmc usable for any kind of management message. Create wrappers for
waiting for ptp4l and for getting UTC offset.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  131 +++--
 1 files changed, 66 insertions(+), 65 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 5ecb602120c3..0581eb5bcb24 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -141,7 +141,6 @@ struct clock {
int leap_set;
int kernel_leap;
struct pmc *pmc;
-   int pmc_ds_idx;
int pmc_ds_requested;
uint64_t pmc_last_update;
struct clockcheck *sanity_check;
@@ -390,31 +389,14 @@ static int init_pmc(struct clock *clock, int 
domain_number)
return 0;
 }
 
-static int run_pmc(struct clock *clock, int timeout,
-  int wait_sync, int get_utc_offset)
+static int run_pmc(struct clock *clock, int timeout, int ds_id,
+  struct ptp_message **msg)
 {
-   struct ptp_message *msg;
-   struct timePropertiesDS *tds;
-   void *data;
 #define N_FD 1
struct pollfd pollfd[N_FD];
-   int cnt, ds_done;
-#define N_ID 2
-   int ds_ids[N_ID] = {
-   PORT_DATA_SET,
-   TIME_PROPERTIES_DATA_SET
-   };
-
-   while (clock->pmc_ds_idx < N_ID) {
-   /* Check if the data set is really needed. */
-   if ((ds_ids[clock->pmc_ds_idx] == PORT_DATA_SET &&
-!wait_sync) ||
-   (ds_ids[clock->pmc_ds_idx] == TIME_PROPERTIES_DATA_SET &&
-!get_utc_offset)) {
-   clock->pmc_ds_idx++;
-   continue;
-   }
+   int cnt;
 
+   while (1) {
pollfd[0].fd = pmc_get_transport_fd(clock->pmc);
pollfd[0].events = POLLIN|POLLPRI;
if (!clock->pmc_ds_requested)
@@ -434,62 +416,76 @@ static int run_pmc(struct clock *clock, int timeout,
/* Send a new request if there are no pending messages. */
if ((pollfd[0].revents & POLLOUT) &&
!(pollfd[0].revents & (POLLIN|POLLPRI))) {
-   pmc_send_get_action(clock->pmc,
-   ds_ids[clock->pmc_ds_idx]);
+   pmc_send_get_action(clock->pmc, ds_id);
clock->pmc_ds_requested = 1;
}
 
if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
continue;
 
-   msg = pmc_recv(clock->pmc);
+   *msg = pmc_recv(clock->pmc);
 
-   if (!msg)
+   if (!*msg)
continue;
 
-   if (!is_msg_mgt(msg) ||
-   get_mgt_id(msg) != ds_ids[clock->pmc_ds_idx]) {
-   msg_put(msg);
+   if (!is_msg_mgt(*msg) ||
+   get_mgt_id(*msg) != ds_id) {
+   msg_put(*msg);
+   *msg = NULL;
continue;
}
+   clock->pmc_ds_requested = 0;
+   return 1;
+   }
+}
 
-   data = get_mgt_data(msg);
-   ds_done = 0;
-
-   switch (get_mgt_id(msg)) {
-   case PORT_DATA_SET:
-   switch (((struct portDS *)data)->portState) {
-   case PS_MASTER:
-   case PS_SLAVE:
-   ds_done = 1;
-   break;
-   }
+static int run_pmc_wait_sync(struct clock *clock, int timeout)
+{
+   struct ptp_message *msg;
+   int res;
+   void *data;
+   Enumeration8 portState;
 
-   break;
-   case TIME_PROPERTIES_DATA_SET:
-   tds = (struct timePropertiesDS *)data;
-   if (tds->flags & PTP_TIMESCALE) {
-   clock->sync_offset = tds->currentUtcOffset;
-   if (tds->flags & LEAP_61)
-   clock->leap = 1;
-   else if (tds->flags & LEAP_59)
-   clock->leap = -1;
-   else
-   clock->leap = 0;
-   }
-   ds_done = 1;
-   break;
-   }
+   while (1) {
+   res = run_pmc(clock, timeout, PORT_DATA_SET, &msg);
+   if (res <= 0)
+   return res;
 
-   if (ds_done) {
-   /* Proceed with the next data set. */
-   clock->pmc_ds_idx++;
-   clock->pmc_ds_requested = 0;
-   }
+   data = get_mgt_data(msg);
+   port

[Linuxptp-devel] [PATCH v2 00/14] automatic phc2sys configuration, phc2sys part

2014-05-14 Thread Jiri Benc
Changes in v2:
- added PMC_SUBSCRIBE_DURATION constant
- fixed wrong invocation of update_pmc

This is the phc2sys part of the autoconfig patchset. It uses the event
subscription mechanism implemented in ptp4l.

The patchset is prepared to handle the "emulated boundary clock" scenario,
i.e. ptp4l working over multiple PHC's. I have old patches to do that (the
dynamic port allocation patchset + patchset to support multiple PHC's) which
I'll rebase on top of this and post after the patchset is accepted.

Jiri Benc (14):
  phc2sys: generalize run_pmc
  phc2sys: split update_sync_offset
  phc2sys: split clock and node
  phc2sys: store information about clocks being UTC or TAI
  phc2sys: rearrange declarations
  phc2sys: open devices in clock_add
  phc2sys: track ports
  pmc_common: easy way to set port and broadcast target
  phc2sys: event subscription
  phc2sys: propagate received errors
  phc2sys: autoconfiguration
  phc2sys: autoconfigure realtime clock on demand only
  phc2sys: check clockIdentity
  phc2sys: man page update for -a and -r options

 phc2sys.8|  115 +--
 phc2sys.c| 1081 --
 pmc_common.c |   12 +-
 pmc_common.h |2 +
 4 files changed, 913 insertions(+), 297 deletions(-)

-- 
1.7.6.5


--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 02/14] phc2sys: split update_sync_offset

2014-05-14 Thread Jiri Benc
Split the generic (global) part of update_sync_offset and the part that
affects individual clocks. This is in preparation for phc2sys handling
synchronization of more clocks.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   71 +++-
 1 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 0581eb5bcb24..19dce45964eb 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -60,7 +60,9 @@
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
 struct clock;
-static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t 
ts);
+static int update_sync_offset(struct clock *clock);
+static int clock_handle_leap(struct clock *clock, clockid_t src,
+int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -181,13 +183,14 @@ static void update_clock_stats(struct clock *clock,
stats_reset(clock->delay_stats);
 }
 
-static void update_clock(struct clock *clock,
-int64_t offset, uint64_t ts, int64_t delay)
+static void update_clock(struct clock *clock, clockid_t src,
+int64_t offset, uint64_t ts, int64_t delay,
+int do_leap)
 {
enum servo_state state;
double ppb;
 
-   if (update_sync_offset(clock, offset, ts))
+   if (clock_handle_leap(clock, src, offset, ts, do_leap))
return;
 
if (clock->sync_offset_direction)
@@ -268,6 +271,7 @@ static int do_pps_loop(struct clock *clock, int fd,
 {
int64_t pps_offset, phc_offset, phc_delay;
uint64_t pps_ts, phc_ts;
+   int do_leap;
 
clock->source_label = "pps";
 
@@ -304,7 +308,10 @@ static int do_pps_loop(struct clock *clock, int fd,
pps_offset = pps_ts - phc_ts;
}
 
-   update_clock(clock, pps_offset, pps_ts, -1);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, pps_offset, pps_ts, -1, do_leap);
}
close(fd);
return 0;
@@ -316,6 +323,7 @@ static int do_sysoff_loop(struct clock *clock, clockid_t 
src,
uint64_t ts;
int64_t offset, delay;
int err = 0, fd = CLOCKID_TO_FD(src);
+   int do_leap;
 
clock->source_label = "sys";
 
@@ -325,7 +333,10 @@ static int do_sysoff_loop(struct clock *clock, clockid_t 
src,
err = -1;
break;
}
-   update_clock(clock, offset, ts, delay);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, offset, ts, delay, do_leap);
}
return err;
 }
@@ -335,6 +346,7 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
 {
uint64_t ts;
int64_t offset, delay;
+   int do_leap;
 
clock->source_label = "phc";
 
@@ -344,7 +356,10 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
  &offset, &ts, &delay)) {
continue;
}
-   update_clock(clock, offset, ts, delay);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, offset, ts, delay, do_leap);
}
return 0;
 }
@@ -495,10 +510,19 @@ static void close_pmc(struct clock *clock)
clock->pmc = NULL;
 }
 
-static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t ts)
+/* Returns: -1 in case of error, 0 for normal sync, 1 to leap clock */
+static int update_sync_offset(struct clock *clock)
 {
+   struct timespec tp;
+   uint64_t ts;
int clock_leap;
 
+   if (clock_gettime(CLOCK_REALTIME, &tp)) {
+   pr_err("failed to read clock: %m");
+   return -1;
+   }
+   ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
+
if (clock->pmc &&
!(ts > clock->pmc_last_update &&
  ts - clock->pmc_last_update < PMC_UPDATE_INTERVAL)) {
@@ -511,9 +535,28 @@ static int update_sync_offset(struct clock *clock, int64_t 
offset, uint64_t ts)
if (!clock->leap && !clock->leap_set)
return 0;
 
+   clock_leap = leap_second_status(ts, clock->leap_set,
+   &clock->leap, &clock->sync_offset);
+   if (clock->leap_set != clock_leap) {
+   clock->leap_set = clock_leap;
+   return 1;
+   }
+   return 0;
+}
+
+/* Returns: non-zero to skip clock update */
+static int clock_handle_leap(struct clock *clock, clockid_t src,
+int64_t o

Re: [Linuxptp-devel] [PATCH 09/14] phc2sys: event subscription

2014-05-14 Thread Jiri Benc
On Mon, 12 May 2014 17:35:18 +0200, Miroslav Lichvar wrote:
> One more comment, could you please define the 180 second constant as a
> macro near PMC_UPDATE_INTERVAL so it's more clear the two are related
> and changing one without other could break things.

Good idea.

Thanks,

 Jiri

-- 
Jiri Benc

--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 11/14] phc2sys: autoconfiguration

2014-05-14 Thread Jiri Benc
On Mon, 12 May 2014 17:25:51 +0200, Miroslav Lichvar wrote:
> On Wed, May 07, 2014 at 06:23:15PM +0200, Jiri Benc wrote:
> > +   do_leap = update_pmc(node, 0);
> 
> Shouldn't the second parameter be "subscriptions > 0"?

Yes. Seems it got incorrect during rework of the "Subscription time
limit" patch and apparently I haven't tested the new version long
enough (unlike the original version).

I'll fix it, thanks for catching this.

> Also, are you planning to implement some check that would abort/reinit
> phc2sys when ptp4l is killed (update_pmc fails to update the UTC
> offset or the resubscription fails)? I'm worried it's too easy to get
> into a state where phc2sys is not receiving updates and the user is
> wondering why it's not working as expected.

Yes. I have it on a todo list but as the problem exists with the
current code, too (albeit it's much less visible) I don't consider it
to be part of this set.

 Jiri

-- 
Jiri Benc

--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] Fix sk_interface_addr().

2014-05-12 Thread Jiri Benc
On Mon, 12 May 2014 18:35:16 +0200, Miroslav Lichvar wrote:
> This was broken in commit e804e6, ifa_addr is a pointer to sockaddr,
> it shouldn't be referenced for the memcpy call.

Oh, my fault, sorry for that and thanks for fixing it.

Acked-by: Jiri Benc 

-- 
Jiri Benc

--
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 14/14] phc2sys: man page update for -a and -r options

2014-05-07 Thread Jiri Benc
Signed-off-by: Jiri Benc 
---
 phc2sys.8 |  115 ++---
 1 files changed, 79 insertions(+), 36 deletions(-)

diff --git a/phc2sys.8 b/phc2sys.8
index fa3ae206f3df..37a39d0ba60f 100644
--- a/phc2sys.8
+++ b/phc2sys.8
@@ -1,12 +1,17 @@
 .TH PHC2SYS 8 "November 2012" "linuxptp"
 .SH NAME
-phc2sys \- synchronize two clocks
+phc2sys \- synchronize two or more clocks
 
 .SH SYNOPSIS
-.B phc2sys
+.B phc2sys \-a
 [
-.B \-wmqvx
+.B \-r
 ] [
+.B \-r
+] [ options ]
+.br
+.B phc2sys
+[
 .BI \-d " pps-device"
 ] [
 .BI \-s " device"
@@ -15,45 +20,53 @@ phc2sys \- synchronize two clocks
 ] [
 .BI \-O " offset"
 ] [
-.BI \-E " servo"
-] [
-.BI \-P " kp"
-] [
-.BI \-I " ki"
-] [
-.BI \-S " step"
-] [
-.BI \-F " step"
-] [
-.BI \-R " update-rate"
-] [
-.BI \-N " clock-readings"
-] [
-.BI \-L " freq-limit"
-] [
-.BI \-u " summary-updates"
-] [
-.BI \-n " domain-number"
-] [
-.BI \-l " print-level"
-]
+.BI \-w
+] [ options ]
 
 .SH DESCRIPTION
 .B phc2sys
-is a program which synchronizes two clocks in the system. Typically, it is used
-to synchronize the system clock to a PTP hardware clock (PHC), which itself is
-synchronized by the
+is a program which synchronizes two or more clocks in the system. Typically,
+it is used to synchronize the system clock to a PTP hardware clock (PHC),
+which itself is synchronized by the
 .BR ptp4l (8)
 program.
 
-Two synchronization modes are supported, one uses a pulse per second (PPS)
+With the
+.B \-a
+option, the clocks to synchronize are fetched from the running
+.B ptp4l
+daemon and the direction of synchronization automatically follows changes of
+the PTP port states.
+
+Manual configuration is also possible. When using manual configuration, two
+synchronization modes are supported, one uses a pulse per second (PPS)
 signal provided by the source clock and the other mode reads time from the
 source clock directly. Some clocks can be used in both modes, the mode which
-will synchronize the slave clock with better accuracy depends on hardware and
-driver implementation.
+will synchronize the slave clock with better accuracy depends on hardware
+and driver implementation.
 
 .SH OPTIONS
 .TP
+.BI \-a
+Read the clocks to synchronize from running
+.B ptp4l
+and follow changes in the port states, adjusting the synchronization
+direction automatically. The system clock (CLOCK_REALTIME) is not
+synchronized, unless the
+.B \-r
+option is also specified.
+.TP
+.BI \-r
+Only valid together with the
+.B \-a
+option. Instructs
+.B phc2sys
+to also synchronize the system clock (CLOCK_REALTIME). By default, the
+system clock is not considered as a possible time source. If you want the
+system clock to be eligible to become a time source, specify the
+.B \-r
+option twice.
+.TP
 .BI \-d " pps-device"
 Specify the PPS device of the master clock (e.g. /dev/pps0). With this option
 the PPS synchronization mode is used instead of the direct mode. As the PPS
@@ -68,7 +81,10 @@ option the PPS signal of the master clock is enabled 
automatically, otherwise
 it has to be enabled before
 .B phc2sys
 is started (e.g. by running \f(CWecho 1 > /sys/class/ptp/ptp0/pps_enable\fP).
-This option can be used only with the system clock as the slave clock.
+This option can be used only with the system clock as the slave clock. Not
+compatible with the
+.B \-a
+option.
 .TP
 .BI \-s " device"
 Specify the master clock by device (e.g. /dev/ptp0) or interface (e.g. eth0) or
@@ -76,7 +92,9 @@ by name (e.g. CLOCK_REALTIME for the system clock). When this 
option is used
 together with the
 .B \-d
 option, the master clock is used only to correct the offset by whole number of
-seconds, which cannot be fixed with PPS alone.
+seconds, which cannot be fixed with PPS alone. Not compatible with the
+.B \-a
+option.
 .TP
 .BI \-i " interface"
 Performs the exact same function as
@@ -89,7 +107,10 @@ should no longer be used.
 .TP
 .BI \-c " device"
 Specify the slave clock by device (e.g. /dev/ptp1) or interface (e.g. eth1) or
-by  name. The default is CLOCK_REALTIME (the system clock).
+by  name. The default is CLOCK_REALTIME (the system clock). Not compatible
+with the
+.B \-a
+option.
 .TP
 .BI \-E " servo"
 Specify which clock servo should be used. Valid values are pi for a PI
@@ -128,7 +149,10 @@ minimize the error caused by random delays in scheduling 
and bus utilization.
 The default is 5.
 .TP
 .BI \-O " offset"
-Specify the offset between the slave and master times in seconds.  See
+Specify the offset between the slave and master times in seconds. Not
+compatible with the
+.B \-a
+option.  See
 .SM
 .B TIME SCALE USAGE
 below.
@@ -154,7 +178,9 @@ Wait until ptp4l is in a synchronized state. If the
 .B \-O
 option is not used, also keep the offse

[Linuxptp-devel] [PATCH 04/14] phc2sys: store information about clocks being UTC or TAI

2014-05-07 Thread Jiri Benc
For now, only CLOCK_REALTIME can be UTC. This may stay this way forever but
now we have a clean separation between codepaths where CLOCK_REALTIME is
required and codepaths any UTC clock should take.

The main motiviation behind this change is removal of sync_offset_direction.
It has to be computed on the fly based on the source and destination when we
have multiple clocks supported and automatic following of ptp4l state
changes implemented.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   60 +---
 1 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 825d7328af15..6c86b4d9f028 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -130,6 +130,7 @@ struct clock {
LIST_ENTRY(clock) list;
clockid_t clkid;
int sysoff_supported;
+   int is_utc;
struct servo *servo;
enum servo_state servo_state;
const char *source_label;
@@ -146,7 +147,7 @@ struct node {
int phc_readings;
double phc_interval;
int sync_offset;
-   int sync_offset_direction;
+   int forced_sync_offset;
int leap;
int leap_set;
int kernel_leap;
@@ -161,6 +162,15 @@ static int update_sync_offset(struct node *node);
 static int clock_handle_leap(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int do_leap);
 
+static int64_t get_sync_offset(struct node *node, struct clock *src)
+{
+   int direction = node->forced_sync_offset;
+
+   if (!direction)
+   direction = node->master->is_utc - src->is_utc;
+   return (int64_t)node->sync_offset * NS_PER_SEC * direction;
+}
+
 static void update_clock_stats(struct clock *clock, unsigned int max_count,
   int64_t offset, double freq, int64_t delay)
 {
@@ -206,9 +216,7 @@ static void update_clock(struct node *node, struct clock 
*clock,
if (clock_handle_leap(node, clock, offset, ts, do_leap))
return;
 
-   if (node->sync_offset_direction)
-   offset += node->sync_offset * NS_PER_SEC *
-   node->sync_offset_direction;
+   offset += get_sync_offset(node, clock);
 
if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts))
servo_reset(clock->servo);
@@ -290,7 +298,7 @@ static int do_pps_loop(struct node *node, struct clock 
*clock, int fd)
 
if (src == CLOCK_INVALID) {
/* The sync offset can't be applied with PPS alone. */
-   node->sync_offset_direction = 0;
+   node->sync_offset = 0;
} else {
enable_pps_output(node->master->clkid);
}
@@ -558,15 +566,14 @@ static int clock_handle_leap(struct node *node, struct 
clock *clock,
if (!node->leap && !do_leap)
return 0;
 
-   if (clock->clkid != CLOCK_REALTIME &&
-   node->master->clkid != CLOCK_REALTIME)
+   if (clock->is_utc == node->master->is_utc)
return 0;
 
/* If the system clock is the master clock, get a time stamp from
   it, as it is the clock which will include the leap second. */
-   if (node->master->clkid == CLOCK_REALTIME) {
+   if (node->master->is_utc) {
struct timespec tp;
-   if (clock_gettime(CLOCK_REALTIME, &tp)) {
+   if (clock_gettime(node->master->clkid, &tp)) {
pr_err("failed to read clock: %m");
return -1;
}
@@ -575,11 +582,8 @@ static int clock_handle_leap(struct node *node, struct 
clock *clock,
 
/* If the clock will be stepped, the time stamp has to be the
   target time. Ignore possible 1 second error in UTC offset. */
-   if (clock->clkid == CLOCK_REALTIME &&
-   clock->servo_state == SERVO_UNLOCKED) {
-   ts -= offset + node->sync_offset * NS_PER_SEC *
-   node->sync_offset_direction;
-   }
+   if (clock->is_utc && clock->servo_state == SERVO_UNLOCKED)
+   ts -= get_sync_offset(node, clock);
 
/* Suspend clock updates in the last second before midnight. */
if (is_utc_ambiguous(ts)) {
@@ -610,10 +614,12 @@ static int clock_add(struct node *node, clockid_t clkid)
c->clkid = clkid;
c->servo_state = SERVO_UNLOCKED;
 
-   if (c->clkid == CLOCK_REALTIME)
+   if (c->clkid == CLOCK_REALTIME) {
c->source_label = "sys";
-   else
+   c->is_utc = 1;
+   } else {
c->source_label = "phc";
+   }
 
if (node->stats_max_count > 0) {
c->offset_stats = stats_create();
@@ -698,7 +704,7 @@ int main(int argc, cha

[Linuxptp-devel] [PATCH 12/14] phc2sys: autoconfigure realtime clock on demand only

2014-05-07 Thread Jiri Benc
By default, do not synchronize CLOCK_REALTIME. To do it, -r option is
needed. That will only consider CLOCK_REALTIME as the destination. To
consider it also as a possible time source, use -rr.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   31 ---
 1 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index d102ca8e8d93..29916a59f2a5 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -67,6 +67,7 @@ struct clock {
clockid_t clkid;
int sysoff_supported;
int is_utc;
+   int dest_only;
int state;
int new_state;
struct servo *servo;
@@ -323,10 +324,16 @@ static void reconfigure(struct node *node)
node->master = NULL;
return;
}
+   if ((!src_cnt && (!rt || rt->dest_only)) ||
+   (!dst_cnt && !rt)) {
+   pr_info("nothing to synchronize");
+   node->master = NULL;
+   return;
+   }
if (!src_cnt) {
src = rt;
rt->state = PS_SLAVE;
-   } else {
+   } else if (rt) {
if (rt->state != PS_MASTER) {
rt->state = PS_MASTER;
clock_reinit(rt);
@@ -921,7 +928,7 @@ static void close_pmc(struct node *node)
node->pmc = NULL;
 }
 
-static int auto_init_ports(struct node *node)
+static int auto_init_ports(struct node *node, int add_rt)
 {
struct port *port;
struct clock *clock;
@@ -976,8 +983,13 @@ static int auto_init_ports(struct node *node)
}
node->state_changed = 1;
 
-   if (!clock_add(node, "CLOCK_REALTIME"))
-   return -1;
+   if (add_rt) {
+   clock = clock_add(node, "CLOCK_REALTIME");
+   if (!clock)
+   return -1;
+   if (add_rt == 1)
+   clock->dest_only = 1;
+   }
 
/* get initial offset */
if (run_pmc_get_utc_offset(node, 1000) <= 0) {
@@ -1072,6 +1084,8 @@ static void usage(char *progname)
"\n"
" automatic configuration:\n"
" -a turn on autoconfiguration\n"
+   " -r synchronize system (realtime) clock\n"
+   "repeat -r to consider it also as a time 
source\n"
" manual configuration:\n"
" -c [dev|name]  slave clock (CLOCK_REALTIME)\n"
" -d [dev]   master PPS device\n"
@@ -1104,7 +1118,7 @@ int main(int argc, char *argv[])
char *progname;
char *src_name = NULL, *dst_name = NULL;
struct clock *src, *dst;
-   int autocfg = 0;
+   int autocfg = 0, rt = 0;
int c, domain_number = 0, pps_fd = -1;
int r, wait_sync = 0;
int print_level = LOG_INFO, use_syslog = 1, verbose = 0;
@@ -1124,11 +1138,14 @@ int main(int argc, char *argv[])
progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0];
while (EOF != (c = getopt(argc, argv,
- "ac:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) {
+ "arc:d:s:E:P:I:S:F:R:N:O:L:i:u:wn:xl:mqvh"))) 
{
switch (c) {
case 'a':
autocfg = 1;
break;
+   case 'r':
+   rt++;
+   break;
case 'c':
dst_name = strdup(optarg);
break;
@@ -1258,7 +1275,7 @@ int main(int argc, char *argv[])
if (autocfg) {
if (init_pmc(&node, domain_number))
return -1;
-   if (auto_init_ports(&node) < 0)
+   if (auto_init_ports(&node, rt) < 0)
return -1;
return do_loop(&node, 1);
}
-- 
1.7.6.5


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
• 3 signs your SCM is hindering your productivity
• Requirements for releasing software faster
• Expert tips and advice for migrating your SCM now
http://p.sf.net/sfu/perforce
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 13/14] phc2sys: check clockIdentity

2014-05-07 Thread Jiri Benc
Make sure that we handle only one PTP clock (node). This is for an extra
safety.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   44 ++--
 1 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 29916a59f2a5..d71422047df2 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -102,6 +102,8 @@ struct node {
int pmc_ds_requested;
uint64_t pmc_last_update;
int state_changed;
+   int clock_identity_set;
+   struct ClockIdentity clock_identity;
LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
@@ -607,6 +609,15 @@ static int do_loop(struct node *node, int subscriptions)
return 0; /* unreachable */
 }
 
+static int check_clock_identity(struct node *node, struct ptp_message *msg)
+{
+   if (!node->clock_identity_set)
+   return 1;
+   return !memcmp(&node->clock_identity,
+  &msg->header.sourcePortIdentity.clockIdentity,
+  sizeof(struct ClockIdentity));
+}
+
 static int is_msg_mgt(struct ptp_message *msg)
 {
struct TLV *tlv;
@@ -784,6 +795,12 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
if (!*msg)
continue;
 
+   if (!check_clock_identity(node, *msg)) {
+   msg_put(*msg);
+   *msg = NULL;
+   continue;
+   }
+
res = is_msg_mgt(*msg);
if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
node->pmc_ds_requested = 0;
@@ -922,6 +939,24 @@ out:
return res;
 }
 
+static int run_pmc_clock_identity(struct node *node, int timeout)
+{
+   struct ptp_message *msg;
+   struct defaultDS *dds;
+   int res;
+
+   res = run_pmc(node, timeout, DEFAULT_DATA_SET, &msg);
+   if (res <= 0)
+   return res;
+
+   dds = (struct defaultDS *)get_mgt_data(msg);
+   memcpy(&node->clock_identity, &dds->clockIdentity,
+  sizeof(struct ClockIdentity));
+   node->clock_identity_set = 1;
+   msg_put(msg);
+   return 1;
+}
+
 static void close_pmc(struct node *node)
 {
pmc_destroy(node->pmc);
@@ -938,7 +973,7 @@ static int auto_init_ports(struct node *node, int add_rt)
char iface[IFNAMSIZ];
 
while (1) {
-   res = run_pmc_get_number_ports(node, 1000);
+   res = run_pmc_clock_identity(node, 1000);
if (res < 0)
return -1;
if (res > 0)
@@ -946,7 +981,12 @@ static int auto_init_ports(struct node *node, int add_rt)
/* res == 0, timeout */
pr_notice("Waiting for ptp4l...");
}
-   number_ports = res;
+
+   number_ports = run_pmc_get_number_ports(node, 1000);
+   if (number_ports <= 0) {
+   pr_err("failed to get number of ports");
+   return -1;
+   }
 
res = run_pmc_subscribe(node, 1000);
if (res <= 0) {
-- 
1.7.6.5


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
• 3 signs your SCM is hindering your productivity
• Requirements for releasing software faster
• Expert tips and advice for migrating your SCM now
http://p.sf.net/sfu/perforce
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 01/14] phc2sys: generalize run_pmc

2014-05-07 Thread Jiri Benc
Make run_pmc usable for any kind of management message. Create wrappers for
waiting for ptp4l and for getting UTC offset.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  131 +++--
 1 files changed, 66 insertions(+), 65 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 5ecb602120c3..0581eb5bcb24 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -141,7 +141,6 @@ struct clock {
int leap_set;
int kernel_leap;
struct pmc *pmc;
-   int pmc_ds_idx;
int pmc_ds_requested;
uint64_t pmc_last_update;
struct clockcheck *sanity_check;
@@ -390,31 +389,14 @@ static int init_pmc(struct clock *clock, int 
domain_number)
return 0;
 }
 
-static int run_pmc(struct clock *clock, int timeout,
-  int wait_sync, int get_utc_offset)
+static int run_pmc(struct clock *clock, int timeout, int ds_id,
+  struct ptp_message **msg)
 {
-   struct ptp_message *msg;
-   struct timePropertiesDS *tds;
-   void *data;
 #define N_FD 1
struct pollfd pollfd[N_FD];
-   int cnt, ds_done;
-#define N_ID 2
-   int ds_ids[N_ID] = {
-   PORT_DATA_SET,
-   TIME_PROPERTIES_DATA_SET
-   };
-
-   while (clock->pmc_ds_idx < N_ID) {
-   /* Check if the data set is really needed. */
-   if ((ds_ids[clock->pmc_ds_idx] == PORT_DATA_SET &&
-!wait_sync) ||
-   (ds_ids[clock->pmc_ds_idx] == TIME_PROPERTIES_DATA_SET &&
-!get_utc_offset)) {
-   clock->pmc_ds_idx++;
-   continue;
-   }
+   int cnt;
 
+   while (1) {
pollfd[0].fd = pmc_get_transport_fd(clock->pmc);
pollfd[0].events = POLLIN|POLLPRI;
if (!clock->pmc_ds_requested)
@@ -434,62 +416,76 @@ static int run_pmc(struct clock *clock, int timeout,
/* Send a new request if there are no pending messages. */
if ((pollfd[0].revents & POLLOUT) &&
!(pollfd[0].revents & (POLLIN|POLLPRI))) {
-   pmc_send_get_action(clock->pmc,
-   ds_ids[clock->pmc_ds_idx]);
+   pmc_send_get_action(clock->pmc, ds_id);
clock->pmc_ds_requested = 1;
}
 
if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
continue;
 
-   msg = pmc_recv(clock->pmc);
+   *msg = pmc_recv(clock->pmc);
 
-   if (!msg)
+   if (!*msg)
continue;
 
-   if (!is_msg_mgt(msg) ||
-   get_mgt_id(msg) != ds_ids[clock->pmc_ds_idx]) {
-   msg_put(msg);
+   if (!is_msg_mgt(*msg) ||
+   get_mgt_id(*msg) != ds_id) {
+   msg_put(*msg);
+   *msg = NULL;
continue;
}
+   clock->pmc_ds_requested = 0;
+   return 1;
+   }
+}
 
-   data = get_mgt_data(msg);
-   ds_done = 0;
-
-   switch (get_mgt_id(msg)) {
-   case PORT_DATA_SET:
-   switch (((struct portDS *)data)->portState) {
-   case PS_MASTER:
-   case PS_SLAVE:
-   ds_done = 1;
-   break;
-   }
+static int run_pmc_wait_sync(struct clock *clock, int timeout)
+{
+   struct ptp_message *msg;
+   int res;
+   void *data;
+   Enumeration8 portState;
 
-   break;
-   case TIME_PROPERTIES_DATA_SET:
-   tds = (struct timePropertiesDS *)data;
-   if (tds->flags & PTP_TIMESCALE) {
-   clock->sync_offset = tds->currentUtcOffset;
-   if (tds->flags & LEAP_61)
-   clock->leap = 1;
-   else if (tds->flags & LEAP_59)
-   clock->leap = -1;
-   else
-   clock->leap = 0;
-   }
-   ds_done = 1;
-   break;
-   }
+   while (1) {
+   res = run_pmc(clock, timeout, PORT_DATA_SET, &msg);
+   if (res <= 0)
+   return res;
 
-   if (ds_done) {
-   /* Proceed with the next data set. */
-   clock->pmc_ds_idx++;
-   clock->pmc_ds_requested = 0;
-   }
+   data = get_mgt_data(msg);
+   port

[Linuxptp-devel] [PATCH 09/14] phc2sys: event subscription

2014-05-07 Thread Jiri Benc
Add support for subscribing to events (run_pmc_subscribe) and receiving and
handling of received events (run_pmc_events).

Add initial support for port status changes.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  111 +++-
 1 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index ece4560e0c67..f7af1b26451b 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -41,6 +41,7 @@
 #include "ds.h"
 #include "fsm.h"
 #include "missing.h"
+#include "notification.h"
 #include "phc.h"
 #include "pi.h"
 #include "pmc_common.h"
@@ -65,6 +66,8 @@ struct clock {
clockid_t clkid;
int sysoff_supported;
int is_utc;
+   int state;
+   int new_state;
struct servo *servo;
enum servo_state servo_state;
char *device;
@@ -78,6 +81,7 @@ struct clock {
 struct port {
LIST_ENTRY(port) list;
unsigned int number;
+   int state;
struct clock *clock;
 };
 
@@ -95,6 +99,7 @@ struct node {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
+   int state_changed;
LIST_HEAD(port_head, port) ports;
LIST_HEAD(clock_head, clock) clocks;
struct clock *master;
@@ -533,6 +538,81 @@ static void *get_mgt_data(struct ptp_message *msg)
return mgt->data;
 }
 
+static int normalize_state(int state)
+{
+   if (state != PS_MASTER && state != PS_SLAVE &&
+   state != PS_PRE_MASTER && state != PS_UNCALIBRATED) {
+   /* treat any other state as "not a master nor a slave" */
+   state = PS_DISABLED;
+   }
+   return state;
+}
+
+static int clock_compute_state(struct node *node, struct clock *clock)
+{
+   struct port *p;
+   int state = PS_DISABLED;
+
+   LIST_FOREACH(p, &node->ports, list) {
+   if (p->clock != clock)
+   continue;
+   /* PS_SLAVE takes the highest precedence, PS_UNCALIBRATED
+* after that, PS_MASTER is third, PS_PRE_MASTER fourth and
+* all of that overrides PS_DISABLED, which corresponds
+* nicely with the numerical values */
+   if (p->state > state)
+   state = p->state;
+   }
+   return state;
+}
+
+static int recv_subscribed(struct node *node, struct ptp_message *msg,
+  int excluded)
+{
+   int mgt_id, state;
+   struct portDS *pds;
+   struct port *port;
+   struct clock *clock;
+
+   mgt_id = get_mgt_id(msg);
+   if (mgt_id == excluded)
+   return 0;
+   switch (mgt_id) {
+   case PORT_DATA_SET:
+   pds = get_mgt_data(msg);
+   port = port_get(node, pds->portIdentity.portNumber);
+   if (!port) {
+   pr_info("received data for unknown port %s",
+   pid2str(&pds->portIdentity));
+   return 1;
+   }
+   state = normalize_state(pds->portState);
+   if (port->state != state) {
+   pr_info("port %s changed state",
+   pid2str(&pds->portIdentity));
+   port->state = state;
+   clock = port->clock;
+   state = clock_compute_state(node, clock);
+   if (clock->state != state) {
+   clock->new_state = state;
+   node->state_changed = 1;
+   }
+   }
+   return 1;
+   }
+   return 0;
+}
+
+static void send_subscription(struct node *node)
+{
+   struct subscribe_events_np sen;
+
+   memset(&sen, 0, sizeof(sen));
+   sen.duration = 180; /* 3 minutes */
+   sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
+   pmc_send_set_action(node->pmc, SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
+}
+
 static int init_pmc(struct node *node, int domain_number)
 {
node->pmc = pmc_create(TRANS_UDS, "/var/run/phc2sys", 0,
@@ -555,7 +635,7 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
while (1) {
pollfd[0].fd = pmc_get_transport_fd(node->pmc);
pollfd[0].events = POLLIN|POLLPRI;
-   if (!node->pmc_ds_requested)
+   if (!node->pmc_ds_requested && ds_id >= 0)
pollfd[0].events |= POLLOUT;
 
cnt = poll(pollfd, N_FD, timeout);
@@ -572,7 +652,14 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
/* Send a new request if there are no pending messages. */
if ((pollfd[0].rev

[Linuxptp-devel] [PATCH 10/14] phc2sys: propagate received errors

2014-05-07 Thread Jiri Benc
Recognize errors returned in MANAGEMENT_ERROR_STATUS TLV and return
a distinct value from run_pmc in case such error is received.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   34 +++---
 1 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index f7af1b26451b..731c2bb1af35 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -521,9 +521,11 @@ static int is_msg_mgt(struct ptp_message *msg)
if (msg->tlv_count != 1)
return 0;
tlv = (struct TLV *) msg->management.suffix;
-   if (tlv->type != TLV_MANAGEMENT)
-   return 0;
-   return 1;
+   if (tlv->type == TLV_MANAGEMENT)
+   return 1;
+   if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS)
+   return -1;
+   return 0;
 }
 
 static int get_mgt_id(struct ptp_message *msg)
@@ -538,6 +540,14 @@ static void *get_mgt_data(struct ptp_message *msg)
return mgt->data;
 }
 
+static int get_mgt_err_id(struct ptp_message *msg)
+{
+   struct management_error_status *mgt;
+
+   mgt = (struct management_error_status *)msg->management.suffix;
+   return mgt->id;
+}
+
 static int normalize_state(int state)
 {
if (state != PS_MASTER && state != PS_SLAVE &&
@@ -625,12 +635,18 @@ static int init_pmc(struct node *node, int domain_number)
return 0;
 }
 
+/* Return values:
+ * 1: success
+ * 0: timeout
+ * -1: error reported by the other side
+ * -2: local error, fatal
+ */
 static int run_pmc(struct node *node, int timeout, int ds_id,
   struct ptp_message **msg)
 {
 #define N_FD 1
struct pollfd pollfd[N_FD];
-   int cnt;
+   int cnt, res;
 
while (1) {
pollfd[0].fd = pmc_get_transport_fd(node->pmc);
@@ -641,7 +657,7 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
cnt = poll(pollfd, N_FD, timeout);
if (cnt < 0) {
pr_err("poll failed");
-   return -1;
+   return -2;
}
if (!cnt) {
/* Request the data set again in the next run. */
@@ -671,8 +687,12 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
if (!*msg)
continue;
 
-   if (!is_msg_mgt(*msg) ||
-   recv_subscribed(node, *msg, ds_id) ||
+   res = is_msg_mgt(*msg);
+   if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
+   node->pmc_ds_requested = 0;
+   return -1;
+   }
+   if (res <= 0 || recv_subscribed(node, *msg, ds_id) ||
get_mgt_id(*msg) != ds_id) {
msg_put(*msg);
*msg = NULL;
-- 
1.7.6.5


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
• 3 signs your SCM is hindering your productivity
• Requirements for releasing software faster
• Expert tips and advice for migrating your SCM now
http://p.sf.net/sfu/perforce
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 08/14] pmc_common: easy way to set port and broadcast target

2014-05-07 Thread Jiri Benc
Implement pmc_target_port to set a port number, leaving clock identity
unchanged, and pmc_target_all to set clock identity and port number to all
1's.

Signed-off-by: Jiri Benc 
---
 pmc_common.c |   12 +++-
 pmc_common.h |2 ++
 2 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/pmc_common.c b/pmc_common.c
index 2c75074c8fb7..41385da45209 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -78,7 +78,7 @@ struct pmc *pmc_create(enum transport_type transport_type, 
const char *iface_nam
goto failed;
}
pmc->port_identity.portNumber = 1;
-   memset(&pmc->target, 0xff, sizeof(pmc->target));
+   pmc_target_all(pmc);
 
pmc->boundary_hops = boundary_hops;
pmc->domain_number = domain_number;
@@ -325,3 +325,13 @@ int pmc_target(struct pmc *pmc, struct PortIdentity *pid)
pmc->target = *pid;
return 0;
 }
+
+void pmc_target_port(struct pmc *pmc, UInteger16 portNumber)
+{
+   pmc->target.portNumber = portNumber;
+}
+
+void pmc_target_all(struct pmc *pmc)
+{
+   memset(&pmc->target, 0xff, sizeof(pmc->target));
+}
diff --git a/pmc_common.h b/pmc_common.h
index 9fcb51da3fd4..9adb9d1dd98b 100644
--- a/pmc_common.h
+++ b/pmc_common.h
@@ -41,5 +41,7 @@ int pmc_send_set_action(struct pmc *pmc, int id, void *data, 
int datasize);
 struct ptp_message *pmc_recv(struct pmc *pmc);
 
 int pmc_target(struct pmc *pmc, struct PortIdentity *pid);
+void pmc_target_port(struct pmc *pmc, UInteger16 portNumber);
+void pmc_target_all(struct pmc *pmc);
 
 #endif
-- 
1.7.6.5


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
• 3 signs your SCM is hindering your productivity
• Requirements for releasing software faster
• Expert tips and advice for migrating your SCM now
http://p.sf.net/sfu/perforce
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 03/14] phc2sys: split clock and node

2014-05-07 Thread Jiri Benc
Split members that apply to all synchronized clocks and members that apply
to an individual clock. Keep all clocks in a list, with a pointer to the
source clock. This will allow to support multiple clocks synchronization.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |  397 +---
 1 files changed, 218 insertions(+), 179 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 19dce45964eb..825d7328af15 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -60,9 +61,6 @@
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
 struct clock;
-static int update_sync_offset(struct clock *clock);
-static int clock_handle_leap(struct clock *clock, clockid_t src,
-int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -129,14 +127,24 @@ static int read_phc(clockid_t clkid, clockid_t sysclk, 
int readings,
 }
 
 struct clock {
+   LIST_ENTRY(clock) list;
clockid_t clkid;
+   int sysoff_supported;
struct servo *servo;
enum servo_state servo_state;
const char *source_label;
struct stats *offset_stats;
struct stats *freq_stats;
struct stats *delay_stats;
+   struct clockcheck *sanity_check;
+};
+
+struct node {
unsigned int stats_max_count;
+   int sanity_freq_limit;
+   enum servo_type servo_type;
+   int phc_readings;
+   double phc_interval;
int sync_offset;
int sync_offset_direction;
int leap;
@@ -145,10 +153,15 @@ struct clock {
struct pmc *pmc;
int pmc_ds_requested;
uint64_t pmc_last_update;
-   struct clockcheck *sanity_check;
+   LIST_HEAD(clock_head, clock) clocks;
+   struct clock *master;
 };
 
-static void update_clock_stats(struct clock *clock,
+static int update_sync_offset(struct node *node);
+static int clock_handle_leap(struct node *node, struct clock *clock,
+int64_t offset, uint64_t ts, int do_leap);
+
+static void update_clock_stats(struct clock *clock, unsigned int max_count,
   int64_t offset, double freq, int64_t delay)
 {
struct stats_result offset_stats, freq_stats, delay_stats;
@@ -158,7 +171,7 @@ static void update_clock_stats(struct clock *clock,
if (delay >= 0)
stats_add_value(clock->delay_stats, delay);
 
-   if (stats_get_num_values(clock->offset_stats) < clock->stats_max_count)
+   if (stats_get_num_values(clock->offset_stats) < max_count)
return;
 
stats_get_result(clock->offset_stats, &offset_stats);
@@ -183,19 +196,19 @@ static void update_clock_stats(struct clock *clock,
stats_reset(clock->delay_stats);
 }
 
-static void update_clock(struct clock *clock, clockid_t src,
+static void update_clock(struct node *node, struct clock *clock,
 int64_t offset, uint64_t ts, int64_t delay,
 int do_leap)
 {
enum servo_state state;
double ppb;
 
-   if (clock_handle_leap(clock, src, offset, ts, do_leap))
+   if (clock_handle_leap(node, clock, offset, ts, do_leap))
return;
 
-   if (clock->sync_offset_direction)
-   offset += clock->sync_offset * NS_PER_SEC *
-   clock->sync_offset_direction;
+   if (node->sync_offset_direction)
+   offset += node->sync_offset * NS_PER_SEC *
+   node->sync_offset_direction;
 
if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts))
servo_reset(clock->servo);
@@ -221,15 +234,15 @@ static void update_clock(struct clock *clock, clockid_t 
src,
}
 
if (clock->offset_stats) {
-   update_clock_stats(clock, offset, ppb, delay);
+   update_clock_stats(clock, node->stats_max_count, offset, ppb, 
delay);
} else {
if (delay >= 0) {
pr_info("%s offset %9" PRId64 " s%d freq %+7.0f "
"delay %6" PRId64,
-   clock->source_label, offset, state, ppb, delay);
+   node->master->source_label, offset, state, ppb, 
delay);
} else {
pr_info("%s offset %9" PRId64 " s%d freq %+7.0f",
-   clock->source_label, offset, state, ppb);
+   node->master->source_label, offset, state, ppb);
}
}
 }
@@ -266,20 +279,20 @@ static int read_pps(int fd, int64_t *offset, uint64_t *ts)
return 1;
 }
 
-static int do_pps_loop(struct clock *clock, int fd,
-  clockid_t src, int n_readings)

[Linuxptp-devel] [PATCH 00/14] automatic phc2sys configuration, phc2sys part

2014-05-07 Thread Jiri Benc
This is the phc2sys part of the autoconfig patchset. It uses the event
subscription mechanism implemented in ptp4l.

The patchset is prepared to handle the "emulated boundary clock" scenario,
i.e. ptp4l working over multiple PHC's. I have old patches to do that (the
dynamic port allocation patchset + patchset to support multiple PHC's) which
I'll rebase on top of this and post after the patchset is accepted.

 Jiri

Jiri Benc (14):
  phc2sys: generalize run_pmc
  phc2sys: split update_sync_offset
  phc2sys: split clock and node
  phc2sys: store information about clocks being UTC or TAI
  phc2sys: rearrange declarations
  phc2sys: open devices in clock_add
  phc2sys: track ports
  pmc_common: easy way to set port and broadcast target
  phc2sys: event subscription
  phc2sys: propagate received errors
  phc2sys: autoconfiguration
  phc2sys: autoconfigure realtime clock on demand only
  phc2sys: check clockIdentity
  phc2sys: man page update for -a and -r options

 phc2sys.8|  115 +--
 phc2sys.c| 1076 --
 pmc_common.c |   12 +-
 pmc_common.h |2 +
 4 files changed, 908 insertions(+), 297 deletions(-)

-- 
1.7.6.5


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
• 3 signs your SCM is hindering your productivity
• Requirements for releasing software faster
• Expert tips and advice for migrating your SCM now
http://p.sf.net/sfu/perforce
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 02/14] phc2sys: split update_sync_offset

2014-05-07 Thread Jiri Benc
Split the generic (global) part of update_sync_offset and the part that
affects individual clocks. This is in preparation for phc2sys handling
synchronization of more clocks.

Signed-off-by: Jiri Benc 
---
 phc2sys.c |   71 +++-
 1 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 0581eb5bcb24..19dce45964eb 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -60,7 +60,9 @@
 #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
 
 struct clock;
-static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t 
ts);
+static int update_sync_offset(struct clock *clock);
+static int clock_handle_leap(struct clock *clock, clockid_t src,
+int64_t offset, uint64_t ts, int do_leap);
 
 static clockid_t clock_open(char *device)
 {
@@ -181,13 +183,14 @@ static void update_clock_stats(struct clock *clock,
stats_reset(clock->delay_stats);
 }
 
-static void update_clock(struct clock *clock,
-int64_t offset, uint64_t ts, int64_t delay)
+static void update_clock(struct clock *clock, clockid_t src,
+int64_t offset, uint64_t ts, int64_t delay,
+int do_leap)
 {
enum servo_state state;
double ppb;
 
-   if (update_sync_offset(clock, offset, ts))
+   if (clock_handle_leap(clock, src, offset, ts, do_leap))
return;
 
if (clock->sync_offset_direction)
@@ -268,6 +271,7 @@ static int do_pps_loop(struct clock *clock, int fd,
 {
int64_t pps_offset, phc_offset, phc_delay;
uint64_t pps_ts, phc_ts;
+   int do_leap;
 
clock->source_label = "pps";
 
@@ -304,7 +308,10 @@ static int do_pps_loop(struct clock *clock, int fd,
pps_offset = pps_ts - phc_ts;
}
 
-   update_clock(clock, pps_offset, pps_ts, -1);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, pps_offset, pps_ts, -1, do_leap);
}
close(fd);
return 0;
@@ -316,6 +323,7 @@ static int do_sysoff_loop(struct clock *clock, clockid_t 
src,
uint64_t ts;
int64_t offset, delay;
int err = 0, fd = CLOCKID_TO_FD(src);
+   int do_leap;
 
clock->source_label = "sys";
 
@@ -325,7 +333,10 @@ static int do_sysoff_loop(struct clock *clock, clockid_t 
src,
err = -1;
break;
}
-   update_clock(clock, offset, ts, delay);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, offset, ts, delay, do_leap);
}
return err;
 }
@@ -335,6 +346,7 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
 {
uint64_t ts;
int64_t offset, delay;
+   int do_leap;
 
clock->source_label = "phc";
 
@@ -344,7 +356,10 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
  &offset, &ts, &delay)) {
continue;
}
-   update_clock(clock, offset, ts, delay);
+   do_leap = update_sync_offset(clock);
+   if (do_leap <= 0)
+   continue;
+   update_clock(clock, src, offset, ts, delay, do_leap);
}
return 0;
 }
@@ -495,10 +510,19 @@ static void close_pmc(struct clock *clock)
clock->pmc = NULL;
 }
 
-static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t ts)
+/* Returns: -1 in case of error, 0 for normal sync, 1 to leap clock */
+static int update_sync_offset(struct clock *clock)
 {
+   struct timespec tp;
+   uint64_t ts;
int clock_leap;
 
+   if (clock_gettime(CLOCK_REALTIME, &tp)) {
+   pr_err("failed to read clock: %m");
+   return -1;
+   }
+   ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
+
if (clock->pmc &&
!(ts > clock->pmc_last_update &&
  ts - clock->pmc_last_update < PMC_UPDATE_INTERVAL)) {
@@ -511,9 +535,28 @@ static int update_sync_offset(struct clock *clock, int64_t 
offset, uint64_t ts)
if (!clock->leap && !clock->leap_set)
return 0;
 
+   clock_leap = leap_second_status(ts, clock->leap_set,
+   &clock->leap, &clock->sync_offset);
+   if (clock->leap_set != clock_leap) {
+   clock->leap_set = clock_leap;
+   return 1;
+   }
+   return 0;
+}
+
+/* Returns: non-zero to skip clock update */
+static int clock_handle_leap(struct clock *clock, clockid_t src,
+int64_t o

  1   2   3   >