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, )) {
> + 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] [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(>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 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
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 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 richardcoch...@gmail.com

Acked-by: Jiri Benc jb...@redhat.com

-- 
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=154624111iu=/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 richardcoch...@gmail.com
 ---
  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=154624111iu=/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 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 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 jb...@redhat.com
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 jb...@redhat.com

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_slave(struct clock *c)
}
 }
 
-static int clock_utc_correct(struct clock *c, tmv_t ingress)
+static int clock_utc_correct(struct phys_clock *pc, tmv_t ingress)
 {
+   struct clock *c = pc-clock

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 jb...@redhat.com

-- 
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=154622311iu=/4140/ostg.clktrk
___
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 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 jb...@redhat.com
---
 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-nports + 1; i++) {
-   fwd = c-port[i];
-   if (fwd != p  forwarding(c, fwd)) {
-   /* delay calling msg_pre_send until

[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 jb...@redhat.com
---
 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 = 0)
pollfd[0].events |= POLLOUT;
 
cnt = poll(pollfd, N_FD, timeout);
@@ -572,7 +657,14 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
/* Send a new request if there are no pending messages

[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 jb...@redhat.com
---
 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);
+   portState = ((struct portDS *)data)-portState;
msg_put(msg);
+
+   switch (portState) {
+   case PS_MASTER

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


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


[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 jb...@redhat.com
---
 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);
+   portState = ((struct portDS *)data)-portState;
msg_put(msg);
+
+   switch (portState) {
+   case PS_MASTER

[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 jb...@redhat.com
---
 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 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 jb...@redhat.com
---
 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 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 jb...@redhat.com
---
 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) {
+   print_set_progname(progname);
+   print_set_verbose(verbose);
+   print_set_syslog(use_syslog);
+   print_set_level(print_level);
+
+   src = clock_add(node, src_name);
+   free(src_name);
+   node.master = src;
+   dst = clock_add(node, dst_name ? dst_name

[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 jb...@redhat.com
---
 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 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 jb...@redhat.com
---
 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 = 0)
pollfd[0].events |= POLLOUT;
 
cnt = poll(pollfd, N_FD, timeout);
@@ -572,7 +657,14 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
/* Send a new request if there are no pending messages

[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 jb...@redhat.com
---
 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 offset between the slave and master
 times updated according to the currentUtcOffset value obtained from ptp4l and
-the direction of the clock synchronization.
+the direction of the clock synchronization. Not compatible with the
+.B \-a
+option.
 .TP
 .BI \-n

[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 jb...@redhat.com
---
 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_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

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

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

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

diff --git a/phc2sys.c b/phc2sys.c
index 731c2bb1af35..d102ca8e8d93 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -22,6 +22,7 @@
 #include float.h
 #include inttypes.h
 #include limits.h
+#include net/if.h
 #include poll.h
 #include stdint.h
 #include stdio.h
@@ -105,9 +106,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)
 {
@@ -262,6 +265,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)
 {
@@ -460,7 +535,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);
@@ -469,13 +544,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;
@@ -483,18 +557,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, 0);
if (do_leap  0)
continue;
 
+   if (subscriptions) {
+   run_pmc_events(node);
+   if (node-state_changed) {
+   /* force getting offset, as it may have
+* changed after the port state change */
+   if (run_pmc_get_utc_offset(node, 1000) = 0

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

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

Signed-off-by: Jiri Benc jb...@redhat.com
---
 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


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 06/14] phc2sys: open devices in clock_add

2014-05-07 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 jb...@redhat.com
---
 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) {
+   print_set_progname(progname);
+   print_set_verbose(verbose);
+   print_set_syslog(use_syslog);
+   print_set_level(print_level);
+
+   src = clock_add(node, src_name);
+   free(src_name);
+   node.master = src;
+   dst = clock_add(node, dst_name ? dst_name

[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 jb...@redhat.com
---
 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:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 jb...@redhat.com
---
 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:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 jb...@redhat.com
---
 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 stdlib.h
 #include string.h
 #include sys/ioctl.h
+#include sys/queue.h
 #include sys/stat.h
 #include sys/types.h
 #include unistd.h
@@ -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)
+static int do_pps_loop(struct node *node, struct clock *clock, int fd)
 {
int64_t pps_offset

[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:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 jb...@redhat.com
---
 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 offset, uint64_t ts, int do_leap)
+{
+   if (!clock-leap  !do_leap)
+   return 0;
+
+   if (clock-clkid != CLOCK_REALTIME  src != CLOCK_REALTIME

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

2014-05-07 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 jb...@redhat.com
---
 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_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

[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 jb...@redhat.com
---
 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, char *argv[])
clockid_t src = CLOCK_INVALID;
clockid_t dst = CLOCK_REALTIME;
int c, domain_number = 0, pps_fd = -1;
-   int r, wait_sync = 0, forced_sync_offset = 0;
+   int r, wait_sync = 0;
int print_level = LOG_INFO

[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 jb...@redhat.com
---
 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:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 jb...@redhat.com
---
 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);
+   portState = ((struct portDS *)data)-portState;
msg_put(msg);
+
+   switch (portState) {
+   case PS_MASTER

[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 jb...@redhat.com
---
 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:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 14/14] phc2sys: man page update for -a and -r options

2014-05-07 Thread Jiri Benc
Signed-off-by: Jiri Benc jb...@redhat.com
---
 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 offset between the slave and master
 times updated according to the currentUtcOffset value obtained from ptp4l and
-the direction of the clock synchronization.
+the direction of the clock synchronization. Not compatible with the
+.B \-a
+option.
 .TP
 .BI \-n

[Linuxptp-devel] [PATCH v4 2/6] Subscription time limit

2014-05-06 Thread Jiri Benc
Add expiration time to subscriptions; they need to be renewed before they
expiry. This way, the subscription automatically times out when phc2sys is
killed.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |   38 ++
 tlv.c   |8 
 tlv.h   |1 +
 3 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/clock.c b/clock.c
index 45620784ecb2..e5d58bacc22c 100644
--- a/clock.c
+++ b/clock.c
@@ -66,6 +66,7 @@ struct clock_subscriber {
struct PortIdentity targetPortIdentity;
struct address addr;
UInteger16 sequenceId;
+   time_t expiration;
 };
 
 struct clock {
@@ -134,10 +135,11 @@ static void remove_subscriber(struct clock_subscriber *s)
 }
 
 static void clock_update_subscription(struct clock *c, struct ptp_message *req,
- uint8_t *bitmask)
+ uint8_t *bitmask, uint16_t duration)
 {
struct clock_subscriber *s;
int i, remove = 1;
+   struct timespec now;
 
for (i = 0; i  EVENT_BITMASK_CNT; i++) {
if (bitmask[i]) {
@@ -154,6 +156,8 @@ static void clock_update_subscription(struct clock *c, 
struct ptp_message *req,
if (!remove) {
s-addr = req-address;
memcpy(s-events, bitmask, EVENT_BITMASK_CNT);
+   clock_gettime(CLOCK_MONOTONIC, now);
+   s-expiration = now.tv_sec + duration;
} else {
remove_subscriber(s);
}
@@ -171,24 +175,33 @@ static void clock_update_subscription(struct clock *c, 
struct ptp_message *req,
s-targetPortIdentity = req-header.sourcePortIdentity;
s-addr = req-address;
memcpy(s-events, bitmask, EVENT_BITMASK_CNT);
+   clock_gettime(CLOCK_MONOTONIC, now);
+   s-expiration = now.tv_sec + duration;
s-sequenceId = 0;
LIST_INSERT_HEAD(c-subscribers, s, list);
 }
 
 static void clock_get_subscription(struct clock *c, struct ptp_message *req,
-  uint8_t *bitmask)
+  uint8_t *bitmask, uint16_t *duration)
 {
struct clock_subscriber *s;
+   struct timespec now;
 
LIST_FOREACH(s, c-subscribers, list) {
if (!memcmp(s-targetPortIdentity, 
req-header.sourcePortIdentity,
sizeof(struct PortIdentity))) {
memcpy(bitmask, s-events, EVENT_BITMASK_CNT);
+   clock_gettime(CLOCK_MONOTONIC, now);
+   if (s-expiration  now.tv_sec)
+   *duration = 0;
+   else
+   *duration = s-expiration - now.tv_sec;
return;
}
}
/* A client without entry means the client has no subscriptions. */
memset(bitmask, 0, EVENT_BITMASK_CNT);
+   *duration = 0;
 }
 
 static void clock_flush_subscriptions(struct clock *c)
@@ -200,6 +213,21 @@ static void clock_flush_subscriptions(struct clock *c)
}
 }
 
+static void clock_prune_subscriptions(struct clock *c)
+{
+   struct clock_subscriber *s, *tmp;
+   struct timespec now;
+
+   clock_gettime(CLOCK_MONOTONIC, now);
+   LIST_FOREACH_SAFE(s, c-subscribers, list, tmp) {
+   if (s-expiration = now.tv_sec) {
+   pr_info(subscriber %s timed out,
+   pid2str(s-targetPortIdentity));
+   remove_subscriber(s);
+   }
+   }
+}
+
 void clock_send_notification(struct clock *c, struct ptp_message *msg,
 int msglen, enum notification event)
 {
@@ -410,7 +438,7 @@ static int clock_management_get_response(struct clock *c, 
struct port *p,
break;
}
sen = (struct subscribe_events_np *)tlv-data;
-   clock_get_subscription(c, req, sen-bitmask);
+   clock_get_subscription(c, req, sen-bitmask, sen-duration);
respond = 1;
break;
}
@@ -450,7 +478,8 @@ static int clock_management_set(struct clock *c, struct 
port *p,
break;
case SUBSCRIBE_EVENTS_NP:
sen = (struct subscribe_events_np *)tlv-data;
-   clock_update_subscription(c, req, sen-bitmask);
+   clock_update_subscription(c, req, sen-bitmask,
+ sen-duration);
respond = 1;
break;
}
@@ -1103,6 +1132,7 @@ int clock_poll(struct clock *c)
if (sde)
handle_state_decision_event(c);
 
+   clock_prune_subscriptions(c);
return 0;
 }
 
diff --git a/tlv.c b/tlv.c
index 430410f75397..892e4bc2cea2 100644
--- a/tlv.c
+++ b/tlv.c
@@ -62,6 +62,7

[Linuxptp-devel] [PATCH v4 6/6] Custom management TLV PORT_PROPERTIES_NP

2014-05-06 Thread Jiri Benc
Will be used by phc2sys to find out interfaces corresponding to ports.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |9 +
 port.c  |   13 +
 tlv.c   |   14 ++
 tlv.h   |8 
 4 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/clock.c b/clock.c
index 32ba4907119c..4378dec3d17a 100644
--- a/clock.c
+++ b/clock.c
@@ -1025,6 +1025,15 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
}
 
switch (mgt-id) {
+   case PORT_PROPERTIES_NP:
+   if (p != c-port[c-nports]) {
+   /* Only the UDS port allowed. */
+   clock_management_send_error(p, msg, NOT_SUPPORTED);
+   return 0;
+   }
+   }
+
+   switch (mgt-id) {
case USER_DESCRIPTION:
case SAVE_IN_NON_VOLATILE_STORAGE:
case RESET_NON_VOLATILE_STORAGE:
diff --git a/port.c b/port.c
index eca4cd574220..63fabc103038 100644
--- a/port.c
+++ b/port.c
@@ -611,6 +611,7 @@ static int port_management_fill_response(struct port 
*target,
struct management_tlv_datum *mtd;
struct portDS *pds;
struct port_ds_np *pdsnp;
+   struct port_properties_np *ppn;
struct clock_description *desc;
struct mgmt_clock_description *cd;
uint8_t *buf;
@@ -760,6 +761,18 @@ static int port_management_fill_response(struct port 
*target,
datalen = sizeof(*pdsnp);
respond = 1;
break;
+   case PORT_PROPERTIES_NP:
+   ppn = (struct port_properties_np *)tlv-data;
+   ppn-portIdentity = target-portIdentity;
+   if (target-state == PS_GRAND_MASTER)
+   ppn-port_state = PS_MASTER;
+   else
+   ppn-port_state = target-state;
+   ppn-timestamping = target-timestamping;
+   ptp_text_set(ppn-interface, target-name);
+   datalen = sizeof(*ppn) + ppn-interface.length;
+   respond = 1;
+   break;
}
if (respond) {
if (datalen % 2) {
diff --git a/tlv.c b/tlv.c
index 892e4bc2cea2..4593c7758765 100644
--- a/tlv.c
+++ b/tlv.c
@@ -63,6 +63,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t 
data_len,
struct time_status_np *tsn;
struct grandmaster_settings_np *gsn;
struct subscribe_events_np *sen;
+   struct port_properties_np *ppn;
struct mgmt_clock_description *cd;
int extra_len = 0, len;
uint8_t *buf;
@@ -249,6 +250,14 @@ static int mgt_post_recv(struct management_tlv *m, 
uint16_t data_len,
sen = (struct subscribe_events_np *)m-data;
sen-duration = ntohs(sen-duration);
break;
+   case PORT_PROPERTIES_NP:
+   if (data_len  sizeof(struct port_properties_np))
+   goto bad_length;
+   ppn = (struct port_properties_np *)m-data;
+   ppn-portIdentity.portNumber = 
ntohs(ppn-portIdentity.portNumber);
+   extra_len = sizeof(struct port_properties_np);
+   extra_len += ppn-interface.length;
+   break;
case SAVE_IN_NON_VOLATILE_STORAGE:
case RESET_NON_VOLATILE_STORAGE:
case INITIALIZE:
@@ -281,6 +290,7 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
struct time_status_np *tsn;
struct grandmaster_settings_np *gsn;
struct subscribe_events_np *sen;
+   struct port_properties_np *ppn;
struct mgmt_clock_description *cd;
switch (m-id) {
case CLOCK_DESCRIPTION:
@@ -349,6 +359,10 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
sen = (struct subscribe_events_np *)m-data;
sen-duration = htons(sen-duration);
break;
+   case PORT_PROPERTIES_NP:
+   ppn = (struct port_properties_np *)m-data;
+   ppn-portIdentity.portNumber = 
htons(ppn-portIdentity.portNumber);
+   break;
}
 }
 
diff --git a/tlv.h b/tlv.h
index e5792ae728a7..a4bc2cebc68c 100644
--- a/tlv.h
+++ b/tlv.h
@@ -100,6 +100,7 @@ enum management_action {
 #define DELAY_MECHANISM0x6000
 #define LOG_MIN_PDELAY_REQ_INTERVAL0x6001
 #define PORT_DATA_SET_NP   0xC002
+#define PORT_PROPERTIES_NP 0xC004
 
 /* Management error ID values */
 #define RESPONSE_TOO_BIG   0x0001
@@ -205,6 +206,13 @@ struct subscribe_events_np {
uint8_t   bitmask[EVENT_BITMASK_CNT];
 } PACKED;
 
+struct port_properties_np {
+   struct PortIdentity portIdentity;
+   uint8_t port_state;
+   uint8_t timestamping;
+   struct PTPText interface;
+} PACKED;
+
 enum clock_type

[Linuxptp-devel] [PATCH v4 0/6] automatic phc2sys configuration, ptp4l part

2014-05-06 Thread Jiri Benc
v4: Changed from COMMAND to SET action for event subscribing.
Added space for even more events.
Renamed 'valid_time' to 'duration'.
Wrapped long lines.

v3: Split into two parts, this is the ptp4l part. The phc2sys part will
follow after this is accepted.
Reworked to use the new transport_sendto and common address interface.
Removed TLV PORT_ENUMERATION_NP, each port number is queried for its
existence instead.
Addressed all reviewers' comments to v2.

v2: rebased to the current HEAD

For the description of the set, see the v1 cover letter:
https://www.mail-archive.com/linuxptp-devel@lists.sourceforge.net/msg00236.html

Jiri Benc (6):
  Event subscribing
  Subscription time limit
  port: event notification
  clock: event notification
  Event notification: port state
  Custom management TLV PORT_PROPERTIES_NP

 clock.c|  236 +---
 clock.h|   19 +
 notification.h |   27 +++
 port.c |  117 +++-
 port.h |   23 ++
 tlv.c  |   26 ++
 tlv.h  |   17 
 7 files changed, 435 insertions(+), 30 deletions(-)
 create mode 100644 notification.h

-- 
1.7.6.5


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 v4 3/6] port: event notification

2014-05-06 Thread Jiri Benc
Split management message creation to more fine-grained functions to allow
notification messages to be created.

The new port_management_fill_response is called from
port_management_get_response (so the function behaves exactly the same
as before this patch) and from a new port_notify_event function. The
difference is port_management_get_response uses the request message to
construct the reply message, while port_notify_event constructs the
reply message based on the notification id.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 port.c |   94 ++-
 port.h |9 ++
 2 files changed, 83 insertions(+), 20 deletions(-)

diff --git a/port.c b/port.c
index d5650ac7172e..b3abc5d0 100644
--- a/port.c
+++ b/port.c
@@ -603,26 +603,19 @@ static void port_management_send_error(struct port *p, 
struct port *ingress,
 static const Octet profile_id_drr[] = {0x00, 0x1B, 0x19, 0x00, 0x01, 0x00};
 static const Octet profile_id_p2p[] = {0x00, 0x1B, 0x19, 0x00, 0x02, 0x00};
 
-static int port_management_get_response(struct port *target,
-   struct port *ingress, int id,
-   struct ptp_message *req)
+static int port_management_fill_response(struct port *target,
+struct ptp_message *rsp, int id)
 {
int datalen = 0, respond = 0;
struct management_tlv *tlv;
struct management_tlv_datum *mtd;
-   struct ptp_message *rsp;
struct portDS *pds;
struct port_ds_np *pdsnp;
-   struct PortIdentity pid = port_identity(target);
struct clock_description *desc;
struct mgmt_clock_description *cd;
uint8_t *buf;
uint16_t u16;
 
-   rsp = port_management_reply(pid, ingress, req);
-   if (!rsp) {
-   return 0;
-   }
tlv = (struct management_tlv *) rsp-management.suffix;
tlv-type = TLV_MANAGEMENT;
tlv-id = id;
@@ -776,10 +769,27 @@ static int port_management_get_response(struct port 
*target,
tlv-length = sizeof(tlv-id) + datalen;
rsp-header.messageLength += sizeof(*tlv) + datalen;
rsp-tlv_count = 1;
-   port_prepare_and_send(ingress, rsp, 0);
}
+   return respond;
+}
+
+static int port_management_get_response(struct port *target,
+   struct port *ingress, int id,
+   struct ptp_message *req)
+{
+   struct PortIdentity pid = port_identity(target);
+   struct ptp_message *rsp;
+   int respond;
+
+   rsp = port_management_reply(pid, ingress, req);
+   if (!rsp) {
+   return 0;
+   }
+   respond = port_management_fill_response(target, rsp, id);
+   if (respond)
+   port_prepare_and_send(ingress, rsp, 0);
msg_put(rsp);
-   return respond ? 1 : 0;
+   return respond;
 }
 
 static int port_management_set(struct port *target,
@@ -2271,9 +2281,11 @@ int port_management_error(struct PortIdentity pid, 
struct port *ingress,
return err;
 }
 
-struct ptp_message *port_management_reply(struct PortIdentity pid,
- struct port *ingress,
- struct ptp_message *req)
+static struct ptp_message *
+port_management_construct(struct PortIdentity pid, struct port *ingress,
+ UInteger16 sequenceId,
+ struct PortIdentity *targetPortIdentity,
+ UInteger8 boundaryHops, uint8_t action)
 {
struct ptp_message *msg;
int pdulen;
@@ -2290,16 +2302,16 @@ struct ptp_message *port_management_reply(struct 
PortIdentity pid,
msg-header.messageLength  = pdulen;
msg-header.domainNumber   = clock_domain_number(ingress-clock);
msg-header.sourcePortIdentity = pid;
-   msg-header.sequenceId = req-header.sequenceId;
+   msg-header.sequenceId = sequenceId;
msg-header.control= CTL_MANAGEMENT;
msg-header.logMessageInterval = 0x7f;
 
-   msg-management.targetPortIdentity = req-header.sourcePortIdentity;
-   msg-management.startingBoundaryHops =
-   req-management.startingBoundaryHops - 
req-management.boundaryHops;
-   msg-management.boundaryHops = msg-management.startingBoundaryHops;
+   if (targetPortIdentity)
+   msg-management.targetPortIdentity = *targetPortIdentity;
+   msg-management.startingBoundaryHops = boundaryHops;
+   msg-management.boundaryHops = boundaryHops;
 
-   switch (management_action(req)) {
+   switch (action) {
case GET: case SET:
msg-management.flags = RESPONSE;
break;
@@ -2310,6 +2322,48 @@ struct ptp_message *port_management_reply(struct 
PortIdentity pid,
return msg;
 }
 
+struct ptp_message

[Linuxptp-devel] [PATCH v4 5/6] Event notification: port state

2014-05-06 Thread Jiri Benc
Notify subscribers about port state changes.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 notification.h |2 +-
 port.c |6 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/notification.h b/notification.h
index 57e7a7856360..47c9b56c4f7e 100644
--- a/notification.h
+++ b/notification.h
@@ -21,7 +21,7 @@
 #define HAVE_NOTIFICATION_H
 
 enum notification {
-   NOTIFY_DUMMY,
+   NOTIFY_PORT_STATE,
 };
 
 #endif
diff --git a/port.c b/port.c
index 388f7571d680..eca4cd574220 100644
--- a/port.c
+++ b/port.c
@@ -2038,6 +2038,7 @@ int port_dispatch(struct port *p, enum fsm_event event, 
int mdiff)
if (next == PS_LISTENING  p-delayMechanism == DM_P2P) {
port_set_delay_tmo(p);
}
+   port_notify_event(p, NOTIFY_PORT_STATE);
return 1;
}
 
@@ -2053,6 +2054,7 @@ int port_dispatch(struct port *p, enum fsm_event event, 
int mdiff)
}
 
p-state = next;
+   port_notify_event(p, NOTIFY_PORT_STATE);
return 0;
 }
 
@@ -2351,7 +2353,9 @@ void port_notify_event(struct port *p, enum notification 
event)
int id;
 
switch (event) {
-   /* set id */
+   case NOTIFY_PORT_STATE:
+   id = PORT_DATA_SET;
+   break;
default:
return;
}
-- 
1.7.6.5


--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 v4 4/6] clock: event notification

2014-05-06 Thread Jiri Benc
Split management message creation to more fine-grained functions to allow
notification messages to be created.

The new clock_management_fill_response is called from
clock_management_get_response (so the function behaves exactly the same as
before this patch) and from a new clock_notify_event function. The
difference is clock_management_get_response uses the request message to
construct the reply message, while clock_notify_event constructs the reply
message based on the notification id.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |   63 +--
 clock.h |8 
 port.c  |8 +++-
 port.h  |   14 ++
 4 files changed, 82 insertions(+), 11 deletions(-)

diff --git a/clock.c b/clock.c
index e5d58bacc22c..32ba4907119c 100644
--- a/clock.c
+++ b/clock.c
@@ -314,23 +314,22 @@ static void clock_management_send_error(struct port *p,
pr_err(failed to send management error status);
 }
 
-static int clock_management_get_response(struct clock *c, struct port *p,
-int id, struct ptp_message *req)
+/* The 'p' and 'req' paremeters are needed for the GET actions that operate
+ * on per-client datasets. If such actions do not apply to the caller, it is
+ * allowed to pass both of them as NULL.
+ */
+static int clock_management_fill_response(struct clock *c, struct port *p,
+ struct ptp_message *req,
+ struct ptp_message *rsp, int id)
 {
int datalen = 0, respond = 0;
struct management_tlv *tlv;
struct management_tlv_datum *mtd;
-   struct ptp_message *rsp;
struct time_status_np *tsn;
struct grandmaster_settings_np *gsn;
struct subscribe_events_np *sen;
-   struct PortIdentity pid = port_identity(p);
struct PTPText *text;
 
-   rsp = port_management_reply(pid, p, req);
-   if (!rsp) {
-   return 0;
-   }
tlv = (struct management_tlv *) rsp-management.suffix;
tlv-type = TLV_MANAGEMENT;
tlv-id = id;
@@ -450,10 +449,26 @@ static int clock_management_get_response(struct clock *c, 
struct port *p,
tlv-length = sizeof(tlv-id) + datalen;
rsp-header.messageLength += sizeof(*tlv) + datalen;
rsp-tlv_count = 1;
-   port_prepare_and_send(p, rsp, 0);
}
+   return respond;
+}
+
+static int clock_management_get_response(struct clock *c, struct port *p,
+int id, struct ptp_message *req)
+{
+   struct PortIdentity pid = port_identity(p);
+   struct ptp_message *rsp;
+   int respond;
+
+   rsp = port_management_reply(pid, p, req);
+   if (!rsp) {
+   return 0;
+   }
+   respond = clock_management_fill_response(c, p, req, rsp, id);
+   if (respond)
+   port_prepare_and_send(p, rsp, 0);
msg_put(rsp);
-   return respond ? 1 : 0;
+   return respond;
 }
 
 static int clock_management_set(struct clock *c, struct port *p,
@@ -1064,6 +1079,34 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
return changed;
 }
 
+void clock_notify_event(struct clock *c, enum notification event)
+{
+   struct port *uds = c-port[c-nports];
+   struct PortIdentity pid = port_identity(uds);
+   struct ptp_message *msg;
+   UInteger16 msg_len;
+   int id;
+
+   switch (event) {
+   /* set id */
+   default:
+   return;
+   }
+   /* targetPortIdentity and sequenceId will be filled by
+* clock_send_notification */
+   msg = port_management_notify(pid, uds);
+   if (!msg)
+   return;
+   if (!clock_management_fill_response(c, NULL, NULL, msg, id))
+   goto err;
+   msg_len = msg-header.messageLength;
+   if (msg_pre_send(msg))
+   goto err;
+   clock_send_notification(c, msg, msg_len, event);
+err:
+   msg_put(msg);
+}
+
 struct parent_ds *clock_parent_ds(struct clock *c)
 {
return c-dad;
diff --git a/clock.h b/clock.h
index 8718f2db715b..92ec163d962f 100644
--- a/clock.h
+++ b/clock.h
@@ -145,6 +145,14 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
 int msglen, enum notification event);
 
 /**
+ * Construct and send notification to subscribers about an event that
+ * occured on the clock.
+ * @param c  The clock instance.
+ * @param event  The identification of the event.
+ */
+void clock_notify_event(struct clock *c, enum notification event);
+
+/**
  * Obtain a clock's parent data set.
  * @param c  The clock instance.
  * @return   A pointer to the parent data set of the clock.
diff --git a/port.c b/port.c
index b3abc5d0..388f7571d680 100644
--- a/port.c
+++ b/port.c
@@ -2337,6 +2337,12 @@ struct ptp_message

[Linuxptp-devel] [PATCH v4 1/6] Event subscribing

2014-05-06 Thread Jiri Benc
This puts groundwork for event subscription and notification. The individual
events are added by subsequent patches.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c|  134 
 clock.h|   11 +
 notification.h |   27 +++
 tlv.c  |4 ++
 tlv.h  |8 +++
 5 files changed, 184 insertions(+), 0 deletions(-)
 create mode 100644 notification.h

diff --git a/clock.c b/clock.c
index a85efdec2857..45620784ecb2 100644
--- a/clock.c
+++ b/clock.c
@@ -22,6 +22,7 @@
 #include string.h
 #include time.h
 
+#include address.h
 #include bmc.h
 #include clock.h
 #include clockadj.h
@@ -59,6 +60,14 @@ struct clock_stats {
unsigned int max_count;
 };
 
+struct clock_subscriber {
+   LIST_ENTRY(clock_subscriber) list;
+   uint8_t events[EVENT_BITMASK_CNT];
+   struct PortIdentity targetPortIdentity;
+   struct address addr;
+   UInteger16 sequenceId;
+};
+
 struct clock {
clockid_t clkid;
struct servo *servo;
@@ -99,6 +108,7 @@ struct clock {
int stats_interval;
struct clockcheck *sanity_check;
struct interface uds_interface;
+   LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
 };
 
 struct clock the_clock;
@@ -110,9 +120,114 @@ static int cid_eq(struct ClockIdentity *a, struct 
ClockIdentity *b)
return 0 == memcmp(a, b, sizeof(*a));
 }
 
+#ifndef LIST_FOREACH_SAFE
+#defineLIST_FOREACH_SAFE(var, head, field, tvar)   
\
+   for ((var) = LIST_FIRST((head));\
+   (var)  ((tvar) = LIST_NEXT((var), field), 1); \
+   (var) = (tvar))
+#endif
+
+static void remove_subscriber(struct clock_subscriber *s)
+{
+   LIST_REMOVE(s, list);
+   free(s);
+}
+
+static void clock_update_subscription(struct clock *c, struct ptp_message *req,
+ uint8_t *bitmask)
+{
+   struct clock_subscriber *s;
+   int i, remove = 1;
+
+   for (i = 0; i  EVENT_BITMASK_CNT; i++) {
+   if (bitmask[i]) {
+   remove = 0;
+   break;
+   }
+   }
+
+   LIST_FOREACH(s, c-subscribers, list) {
+   if (!memcmp(s-targetPortIdentity, 
req-header.sourcePortIdentity,
+   sizeof(struct PortIdentity))) {
+   /* Found, update the transport address and event
+* mask. */
+   if (!remove) {
+   s-addr = req-address;
+   memcpy(s-events, bitmask, EVENT_BITMASK_CNT);
+   } else {
+   remove_subscriber(s);
+   }
+   return;
+   }
+   }
+   if (remove)
+   return;
+   /* Not present yet, add the subscriber. */
+   s = malloc(sizeof(*s));
+   if (!s) {
+   pr_err(failed to allocate memory for a subscriber);
+   return;
+   }
+   s-targetPortIdentity = req-header.sourcePortIdentity;
+   s-addr = req-address;
+   memcpy(s-events, bitmask, EVENT_BITMASK_CNT);
+   s-sequenceId = 0;
+   LIST_INSERT_HEAD(c-subscribers, s, list);
+}
+
+static void clock_get_subscription(struct clock *c, struct ptp_message *req,
+  uint8_t *bitmask)
+{
+   struct clock_subscriber *s;
+
+   LIST_FOREACH(s, c-subscribers, list) {
+   if (!memcmp(s-targetPortIdentity, 
req-header.sourcePortIdentity,
+   sizeof(struct PortIdentity))) {
+   memcpy(bitmask, s-events, EVENT_BITMASK_CNT);
+   return;
+   }
+   }
+   /* A client without entry means the client has no subscriptions. */
+   memset(bitmask, 0, EVENT_BITMASK_CNT);
+}
+
+static void clock_flush_subscriptions(struct clock *c)
+{
+   struct clock_subscriber *s, *tmp;
+
+   LIST_FOREACH_SAFE(s, c-subscribers, list, tmp) {
+   remove_subscriber(s);
+   }
+}
+
+void clock_send_notification(struct clock *c, struct ptp_message *msg,
+int msglen, enum notification event)
+{
+   unsigned int event_pos = event / 8;
+   uint8_t mask = 1  (event % 8);
+   struct port *uds = c-port[c-nports];
+   struct clock_subscriber *s;
+
+   LIST_FOREACH(s, c-subscribers, list) {
+   if (!(s-events[event_pos]  mask))
+   continue;
+   /* send event */
+   msg-header.sequenceId = htons(s-sequenceId);
+   s-sequenceId++;
+   msg-management.targetPortIdentity.clockIdentity =
+   s-targetPortIdentity.clockIdentity;
+   msg-management.targetPortIdentity.portNumber =
+   htons(s-targetPortIdentity.portNumber

Re: [Linuxptp-devel] [PATCH v3 05/11] Event subscribing

2014-05-05 Thread Jiri Benc
On Sat, 3 May 2014 20:19:10 +0200, Richard Cochran wrote:
 On Fri, May 02, 2014 at 12:37:48PM +0200, Jiri Benc wrote:
  +static void clock_flush_subscriptions(struct clock *c)
  +{
  +   struct clock_subscriber *s, *tmp;
  +
  +   LIST_FOREACH_SAFE(s, c-subscribers, list, tmp) {
  +   remove_subscriber(s);
  +   }
 
 You are removing every item in the list, and so can just do this...
 
   while ((s = LIST_FIRST(c-subscribers)) != NULL) {
   LIST_REMOVE(s, list);
   /* or */
   remove_subscriber(s);
   }
 
 can't you?

As you said, we'll need LIST_FOREACH_SAFE anyway (and it's actually
already included in some sys/queue.h implementations). I think the way
I used makes clearer what's happening here. The additional variable will
likely be stored in a register by the compiler and this is not a
performance critical path anyway.

  +}
  +
  +void clock_send_notification(struct clock *c, struct ptp_message *msg,
  +int msglen, enum notification event)
  +{
  +   unsigned int event_pos = event / 8;
  +   uint8_t mask = 1  (event % 8);
  +   struct port *uds = c-port[c-nports];
  +   struct clock_subscriber *s;
  +
  +   LIST_FOREACH(s, c-subscribers, list) {
  +   if (!(s-events[event_pos]  mask))
  +   continue;
  +   /* send event */
  +   msg-header.sequenceId = htons(s-sequenceId);
  +   s-sequenceId++;
  +   msg-management.targetPortIdentity.clockIdentity = 
  s-targetPortIdentity.clockIdentity;
  +   msg-management.targetPortIdentity.portNumber = 
  htons(s-targetPortIdentity.portNumber);
 
 Lines too long.

I'll wrap them but the result will look uglier than this.

  @@ -842,6 +975,8 @@ int clock_manage(struct clock *c, struct port *p, 
  struct ptp_message *msg)
  return changed;
  break;
  case COMMAND:
  +   if (clock_management_cmd_response(c, p, mgt-id, msg))
  +   return changed;
 
 So does this really have to be a COMMAND action? It feels to me more
 like a SET action, configuring a per-client table of events.

The border between COMMAND and SET is fuzzy here. I don't have too
strong preference, except that I'd need to rewrite the set for the
4th time and retest it again :-/

 None of the existing COMMAND actions send any data (except for that
 useless initialization key) or configure anything. Instead, they are
 some sort of imperative like restart! or reset!

Except that the INITIALIZE command does have data. I thought about this
more like a send me notifications! command.

As a counter-argument, none of the existing SET actions act per-client,
they are used to set the (global) clock or port state.

In fact, neither of those fits. The closest thing in the standard is
unicast negotiation which uses a different TLV than management which is
not applicable here. I won't argue about this but I'm not thrilled
about rewriting and retesting this again for something that's just a
matter of taste.

  +#define EVENT_BITMASK_CNT 32
 
 Let's make this 64, for 512 event types.

Okay, whatever.

 Jiri

-- 
Jiri Benc

--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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


Re: [Linuxptp-devel] [PATCH v3 07/11] Subscription time limit

2014-05-05 Thread Jiri Benc
On Sat, 3 May 2014 20:32:01 +0200, Richard Cochran wrote:
 1. It is a good idea to let the client set the duration?

You wanted to get rid of the magic constant in ptp4l, this allowed me to
move it to phc2sys ;-)

Okay, seriously: I don't think this is a problem. It is limited to UDS
and the worst thing that can happen is attempting to send notifications
to a client when the client is long dead because it set too big value
and crashed.

As it is the client who knows when it will be able to renew the
subscription, it makes sense to be the client who sets the duration.

Obviously, the hyper correct way would be for the server to ack or deny
the request based on the duration value and internal policy, similarly
to e.g. bandwidth allocation in various protocols. I think it's
overkill for this case.

 2. Should we perhaps use a 32 bit field for this?
As is, it allows only 18 hours.

I even thought about limiting the maximum value to a hour or so. The
client is supposed to renew the subscription, otherwise the time limit
would be useless.

 Jiri

-- 
Jiri Benc

--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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


Re: [Linuxptp-devel] [PATCH v3 08/11] port: event notification

2014-05-05 Thread Jiri Benc
On Sat, 3 May 2014 20:49:16 +0200, Richard Cochran wrote:
 On Fri, May 02, 2014 at 12:37:51PM +0200, Jiri Benc wrote:
  Split management message creation to more fine-grained functions to allow
  notification messages to be created.
 
 I must admit I didn't understand what you did, at first reading. Can
 you lose a few words about how you split the code and why?
 
 Is it that the 'fill' method is shared by regular management replies
 and by the event notifiers?

Yes. And I wanted to avoid code duplication, thus I extracted the
generic part of port_management_get_response to a separate function.

The new port_management_fill_response is called from
port_management_get_response (so the function behaves exactly the same
as before this patch) and from a new port_notify_event function. The
difference is port_management_get_response uses the request message to
construct the reply message, while port_notify_event constructs the
reply message based on the notification id.

  +struct ptp_message *port_management_reply(struct PortIdentity pid,
  + struct port *ingress,
  + struct ptp_message *req)
  +{
  +   UInteger8 boundaryHops;
  +
  +   boundaryHops = req-management.startingBoundaryHops - 
  req-management.boundaryHops;
 
 Line too long.

Will split it.

 Jiri

-- 
Jiri Benc

--
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
#149; 3 signs your SCM is hindering your productivity
#149; Requirements for releasing software faster
#149; 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 v3 01/11] uds: don't output Connection refused

2014-05-02 Thread Jiri Benc
When phc2sys is started before ptp4l or it is interrupted before ptp4l has
a chance to reply to its query, the uds: sendto failed: Connection refused
message is output. This is not an interesting message.

Also, don't output the failed to send message error from pmc_send, as
all transports output errors in their send routine.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 pmc_common.c |   10 +++---
 uds.c|2 +-
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/pmc_common.c b/pmc_common.c
index a7201f92454d..2c75074c8fb7 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -143,18 +143,14 @@ static struct ptp_message *pmc_message(struct pmc *pmc, 
uint8_t action)
 
 static int pmc_send(struct pmc *pmc, struct ptp_message *msg, int pdulen)
 {
-   int cnt, err;
+   int err;
+
err = msg_pre_send(msg);
if (err) {
pr_err(msg_pre_send failed);
return -1;
}
-   cnt = transport_send(pmc-transport, pmc-fdarray, 0, msg);
-   if (cnt  0) {
-   pr_err(failed to send message);
-   return -1;
-   }
-   return 0;
+   return transport_send(pmc-transport, pmc-fdarray, 0, msg);
 }
 
 static int pmc_tlv_datalen(struct pmc *pmc, int id)
diff --git a/uds.c b/uds.c
index e88b333e4f00..e98e32c0351d 100644
--- a/uds.c
+++ b/uds.c
@@ -111,7 +111,7 @@ static int uds_send(struct transport *t, struct fdarray 
*fda, int event,
addr = uds-address;
 
cnt = sendto(fd, buf, buflen, 0, addr-sa, addr-len);
-   if (cnt = 0) {
+   if (cnt = 0  errno != ECONNREFUSED) {
pr_err(uds: sendto failed: %m);
}
return cnt;
-- 
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 v3 05/11] Event subscribing

2014-05-02 Thread Jiri Benc
This puts groundwork for event subscription and notification. The individual
events are added by subsequent patches.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c|  136 
 clock.h|   11 +
 notification.h |   27 +++
 tlv.c  |4 ++
 tlv.h  |8 +++
 5 files changed, 186 insertions(+), 0 deletions(-)
 create mode 100644 notification.h

diff --git a/clock.c b/clock.c
index a85efdec2857..600fc058a391 100644
--- a/clock.c
+++ b/clock.c
@@ -22,6 +22,7 @@
 #include string.h
 #include time.h
 
+#include address.h
 #include bmc.h
 #include clock.h
 #include clockadj.h
@@ -59,6 +60,14 @@ struct clock_stats {
unsigned int max_count;
 };
 
+struct clock_subscriber {
+   LIST_ENTRY(clock_subscriber) list;
+   uint8_t events[EVENT_BITMASK_CNT];
+   struct PortIdentity targetPortIdentity;
+   struct address addr;
+   UInteger16 sequenceId;
+};
+
 struct clock {
clockid_t clkid;
struct servo *servo;
@@ -99,6 +108,7 @@ struct clock {
int stats_interval;
struct clockcheck *sanity_check;
struct interface uds_interface;
+   LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
 };
 
 struct clock the_clock;
@@ -110,9 +120,96 @@ static int cid_eq(struct ClockIdentity *a, struct 
ClockIdentity *b)
return 0 == memcmp(a, b, sizeof(*a));
 }
 
+#ifndef LIST_FOREACH_SAFE
+#defineLIST_FOREACH_SAFE(var, head, field, tvar)   
\
+   for ((var) = LIST_FIRST((head));\
+   (var)  ((tvar) = LIST_NEXT((var), field), 1); \
+   (var) = (tvar))
+#endif
+
+static void remove_subscriber(struct clock_subscriber *s)
+{
+   LIST_REMOVE(s, list);
+   free(s);
+}
+
+static void clock_update_subscription(struct clock *c, struct ptp_message *req,
+ uint8_t *bitmask)
+{
+   struct clock_subscriber *s;
+   int i, remove = 1;
+
+   for (i = 0; i  EVENT_BITMASK_CNT; i++) {
+   if (bitmask[i]) {
+   remove = 0;
+   break;
+   }
+   }
+
+   LIST_FOREACH(s, c-subscribers, list) {
+   if (!memcmp(s-targetPortIdentity, 
req-header.sourcePortIdentity,
+   sizeof(struct PortIdentity))) {
+   /* Found, update the transport address and event
+* mask. */
+   if (!remove) {
+   s-addr = req-address;
+   memcpy(s-events, bitmask, EVENT_BITMASK_CNT);
+   } else {
+   remove_subscriber(s);
+   }
+   return;
+   }
+   }
+   if (remove)
+   return;
+   /* Not present yet, add the subscriber. */
+   s = malloc(sizeof(*s));
+   if (!s) {
+   pr_err(failed to allocate memory for a subscriber);
+   return;
+   }
+   s-targetPortIdentity = req-header.sourcePortIdentity;
+   s-addr = req-address;
+   memcpy(s-events, bitmask, EVENT_BITMASK_CNT);
+   s-sequenceId = 0;
+   LIST_INSERT_HEAD(c-subscribers, s, list);
+}
+
+static void clock_flush_subscriptions(struct clock *c)
+{
+   struct clock_subscriber *s, *tmp;
+
+   LIST_FOREACH_SAFE(s, c-subscribers, list, tmp) {
+   remove_subscriber(s);
+   }
+}
+
+void clock_send_notification(struct clock *c, struct ptp_message *msg,
+int msglen, enum notification event)
+{
+   unsigned int event_pos = event / 8;
+   uint8_t mask = 1  (event % 8);
+   struct port *uds = c-port[c-nports];
+   struct clock_subscriber *s;
+
+   LIST_FOREACH(s, c-subscribers, list) {
+   if (!(s-events[event_pos]  mask))
+   continue;
+   /* send event */
+   msg-header.sequenceId = htons(s-sequenceId);
+   s-sequenceId++;
+   msg-management.targetPortIdentity.clockIdentity = 
s-targetPortIdentity.clockIdentity;
+   msg-management.targetPortIdentity.portNumber = 
htons(s-targetPortIdentity.portNumber);
+   msg-address = s-addr;
+   port_forward_to(uds, msg);
+   }
+}
+
 void clock_destroy(struct clock *c)
 {
int i;
+
+   clock_flush_subscriptions(c);
for (i = 0; i  c-nports; i++) {
port_close(c-port[i]);
close(c-fault_fd[i]);
@@ -328,6 +425,40 @@ static int clock_management_set(struct clock *c, struct 
port *p,
return respond ? 1 : 0;
 }
 
+static int clock_management_cmd_response(struct clock *c, struct port *p,
+int id, struct ptp_message *req)
+{
+   int respond = 0;
+   struct ptp_message *rsp = NULL;
+   struct

[Linuxptp-devel] [PATCH v3 09/11] clock: event notification

2014-05-02 Thread Jiri Benc
Split management message creation to more fine-grained functions to allow
notification messages to be created.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |   58 --
 clock.h |8 
 port.c  |8 +++-
 port.h  |   14 ++
 4 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/clock.c b/clock.c
index 29d58b0c2461..e585074daea3 100644
--- a/clock.c
+++ b/clock.c
@@ -290,22 +290,16 @@ static void clock_management_send_error(struct port *p,
pr_err(failed to send management error status);
 }
 
-static int clock_management_get_response(struct clock *c, struct port *p,
-int id, struct ptp_message *req)
+static int clock_management_fill_response(struct clock *c,
+ struct ptp_message *rsp, int id)
 {
int datalen = 0, respond = 0;
struct management_tlv *tlv;
struct management_tlv_datum *mtd;
-   struct ptp_message *rsp;
struct time_status_np *tsn;
struct grandmaster_settings_np *gsn;
-   struct PortIdentity pid = port_identity(p);
struct PTPText *text;
 
-   rsp = port_management_reply(pid, p, req);
-   if (!rsp) {
-   return 0;
-   }
tlv = (struct management_tlv *) rsp-management.suffix;
tlv-type = TLV_MANAGEMENT;
tlv-id = id;
@@ -416,10 +410,26 @@ static int clock_management_get_response(struct clock *c, 
struct port *p,
tlv-length = sizeof(tlv-id) + datalen;
rsp-header.messageLength += sizeof(*tlv) + datalen;
rsp-tlv_count = 1;
-   port_prepare_and_send(p, rsp, 0);
}
+   return respond;
+}
+
+static int clock_management_get_response(struct clock *c, struct port *p,
+int id, struct ptp_message *req)
+{
+   struct PortIdentity pid = port_identity(p);
+   struct ptp_message *rsp;
+   int respond;
+
+   rsp = port_management_reply(pid, p, req);
+   if (!rsp) {
+   return 0;
+   }
+   respond = clock_management_fill_response(c, rsp, id);
+   if (respond)
+   port_prepare_and_send(p, rsp, 0);
msg_put(rsp);
-   return respond ? 1 : 0;
+   return respond;
 }
 
 static int clock_management_set(struct clock *c, struct port *p,
@@ -1062,6 +1072,34 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
return changed;
 }
 
+void clock_notify_event(struct clock *c, enum notification event)
+{
+   struct port *uds = c-port[c-nports];
+   struct PortIdentity pid = port_identity(uds);
+   struct ptp_message *msg;
+   UInteger16 msg_len;
+   int id;
+
+   switch (event) {
+   /* set id */
+   default:
+   return;
+   }
+   /* targetPortIdentity and sequenceId will be filled by
+* clock_send_notification */
+   msg = port_management_notify(pid, uds);
+   if (!msg)
+   return;
+   if (!clock_management_fill_response(c, msg, id))
+   goto err;
+   msg_len = msg-header.messageLength;
+   if (msg_pre_send(msg))
+   goto err;
+   clock_send_notification(c, msg, msg_len, event);
+err:
+   msg_put(msg);
+}
+
 struct parent_ds *clock_parent_ds(struct clock *c)
 {
return c-dad;
diff --git a/clock.h b/clock.h
index 8718f2db715b..92ec163d962f 100644
--- a/clock.h
+++ b/clock.h
@@ -145,6 +145,14 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
 int msglen, enum notification event);
 
 /**
+ * Construct and send notification to subscribers about an event that
+ * occured on the clock.
+ * @param c  The clock instance.
+ * @param event  The identification of the event.
+ */
+void clock_notify_event(struct clock *c, enum notification event);
+
+/**
  * Obtain a clock's parent data set.
  * @param c  The clock instance.
  * @return   A pointer to the parent data set of the clock.
diff --git a/port.c b/port.c
index d48d275ba1a3..29e98ceb66ce 100644
--- a/port.c
+++ b/port.c
@@ -2336,6 +2336,12 @@ struct ptp_message *port_management_reply(struct 
PortIdentity pid,
 management_action(req));
 }
 
+struct ptp_message *port_management_notify(struct PortIdentity pid,
+  struct port *port)
+{
+   return port_management_construct(pid, port, 0, NULL, 1, GET);
+}
+
 void port_notify_event(struct port *p, enum notification event)
 {
struct PortIdentity pid = port_identity(p);
@@ -2350,7 +2356,7 @@ void port_notify_event(struct port *p, enum notification 
event)
}
/* targetPortIdentity and sequenceId will be filled by
 * clock_send_notification */
-   msg = port_management_construct(pid, p, 0, NULL, 1, GET);
+   msg = port_management_notify

[Linuxptp-devel] [PATCH v3 03/11] Remove unneeded parameter in port_forward

2014-05-02 Thread Jiri Benc
This parameter was made obsolete by the common address refactoring.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |2 +-
 port.c  |2 +-
 port.h  |3 +--
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/clock.c b/clock.c
index c541951dcc68..a85efdec2857 100644
--- a/clock.c
+++ b/clock.c
@@ -785,7 +785,7 @@ static void clock_forward_mgmt_msg(struct clock *c, struct 
port *p, struct ptp_m
msg-management.boundaryHops--;
msg_pre_send(msg);
}
-   if (port_forward(fwd, msg, pdulen))
+   if (port_forward(fwd, msg))
pr_err(port %d: management forward 
failed, i + 1);
}
}
diff --git a/port.c b/port.c
index e84067395f53..164de9b6898d 100644
--- a/port.c
+++ b/port.c
@@ -2163,7 +2163,7 @@ enum fsm_event port_event(struct port *p, int fd_index)
return event;
 }
 
-int port_forward(struct port *p, struct ptp_message *msg, int msglen)
+int port_forward(struct port *p, struct ptp_message *msg)
 {
int cnt;
cnt = transport_send(p-trp, p-fda, 0, msg);
diff --git a/port.h b/port.h
index 804e4631d00c..86a6f173bf98 100644
--- a/port.h
+++ b/port.h
@@ -87,10 +87,9 @@ enum fsm_event port_event(struct port *port, int fd_index);
  * Forward a message on a given port.
  * @param portA pointer previously obtained via port_open().
  * @param msg The message to send. Must be in network byte order.
- * @param msglen  The length of the message in bytes.
  * @returnZero on success, non-zero otherwise.
  */
-int port_forward(struct port *p, struct ptp_message *msg, int msglen);
+int port_forward(struct port *p, struct ptp_message *msg);
 
 /**
  * Prepare message for transmission and send it to a given port. Note that
-- 
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 v3 10/11] Event notification: port state

2014-05-02 Thread Jiri Benc
Notify subscribers about port state changes.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 notification.h |2 +-
 port.c |6 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/notification.h b/notification.h
index 57e7a7856360..47c9b56c4f7e 100644
--- a/notification.h
+++ b/notification.h
@@ -21,7 +21,7 @@
 #define HAVE_NOTIFICATION_H
 
 enum notification {
-   NOTIFY_DUMMY,
+   NOTIFY_PORT_STATE,
 };
 
 #endif
diff --git a/port.c b/port.c
index 29e98ceb66ce..64c01be127e3 100644
--- a/port.c
+++ b/port.c
@@ -2038,6 +2038,7 @@ int port_dispatch(struct port *p, enum fsm_event event, 
int mdiff)
if (next == PS_LISTENING  p-delayMechanism == DM_P2P) {
port_set_delay_tmo(p);
}
+   port_notify_event(p, NOTIFY_PORT_STATE);
return 1;
}
 
@@ -2053,6 +2054,7 @@ int port_dispatch(struct port *p, enum fsm_event event, 
int mdiff)
}
 
p-state = next;
+   port_notify_event(p, NOTIFY_PORT_STATE);
return 0;
 }
 
@@ -2350,7 +2352,9 @@ void port_notify_event(struct port *p, enum notification 
event)
int id;
 
switch (event) {
-   /* set id */
+   case NOTIFY_PORT_STATE:
+   id = PORT_DATA_SET;
+   break;
default:
return;
}
-- 
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 v3 08/11] port: event notification

2014-05-02 Thread Jiri Benc
Split management message creation to more fine-grained functions to allow
notification messages to be created.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 port.c |   93 ++--
 port.h |9 ++
 2 files changed, 82 insertions(+), 20 deletions(-)

diff --git a/port.c b/port.c
index d5650ac7172e..d48d275ba1a3 100644
--- a/port.c
+++ b/port.c
@@ -603,26 +603,19 @@ static void port_management_send_error(struct port *p, 
struct port *ingress,
 static const Octet profile_id_drr[] = {0x00, 0x1B, 0x19, 0x00, 0x01, 0x00};
 static const Octet profile_id_p2p[] = {0x00, 0x1B, 0x19, 0x00, 0x02, 0x00};
 
-static int port_management_get_response(struct port *target,
-   struct port *ingress, int id,
-   struct ptp_message *req)
+static int port_management_fill_response(struct port *target,
+struct ptp_message *rsp, int id)
 {
int datalen = 0, respond = 0;
struct management_tlv *tlv;
struct management_tlv_datum *mtd;
-   struct ptp_message *rsp;
struct portDS *pds;
struct port_ds_np *pdsnp;
-   struct PortIdentity pid = port_identity(target);
struct clock_description *desc;
struct mgmt_clock_description *cd;
uint8_t *buf;
uint16_t u16;
 
-   rsp = port_management_reply(pid, ingress, req);
-   if (!rsp) {
-   return 0;
-   }
tlv = (struct management_tlv *) rsp-management.suffix;
tlv-type = TLV_MANAGEMENT;
tlv-id = id;
@@ -776,10 +769,27 @@ static int port_management_get_response(struct port 
*target,
tlv-length = sizeof(tlv-id) + datalen;
rsp-header.messageLength += sizeof(*tlv) + datalen;
rsp-tlv_count = 1;
-   port_prepare_and_send(ingress, rsp, 0);
}
+   return respond;
+}
+
+static int port_management_get_response(struct port *target,
+   struct port *ingress, int id,
+   struct ptp_message *req)
+{
+   struct PortIdentity pid = port_identity(target);
+   struct ptp_message *rsp;
+   int respond;
+
+   rsp = port_management_reply(pid, ingress, req);
+   if (!rsp) {
+   return 0;
+   }
+   respond = port_management_fill_response(target, rsp, id);
+   if (respond)
+   port_prepare_and_send(ingress, rsp, 0);
msg_put(rsp);
-   return respond ? 1 : 0;
+   return respond;
 }
 
 static int port_management_set(struct port *target,
@@ -2271,9 +2281,11 @@ int port_management_error(struct PortIdentity pid, 
struct port *ingress,
return err;
 }
 
-struct ptp_message *port_management_reply(struct PortIdentity pid,
- struct port *ingress,
- struct ptp_message *req)
+static struct ptp_message *
+port_management_construct(struct PortIdentity pid, struct port *ingress,
+ UInteger16 sequenceId,
+ struct PortIdentity *targetPortIdentity,
+ UInteger8 boundaryHops, uint8_t action)
 {
struct ptp_message *msg;
int pdulen;
@@ -2290,16 +2302,16 @@ struct ptp_message *port_management_reply(struct 
PortIdentity pid,
msg-header.messageLength  = pdulen;
msg-header.domainNumber   = clock_domain_number(ingress-clock);
msg-header.sourcePortIdentity = pid;
-   msg-header.sequenceId = req-header.sequenceId;
+   msg-header.sequenceId = sequenceId;
msg-header.control= CTL_MANAGEMENT;
msg-header.logMessageInterval = 0x7f;
 
-   msg-management.targetPortIdentity = req-header.sourcePortIdentity;
-   msg-management.startingBoundaryHops =
-   req-management.startingBoundaryHops - 
req-management.boundaryHops;
-   msg-management.boundaryHops = msg-management.startingBoundaryHops;
+   if (targetPortIdentity)
+   msg-management.targetPortIdentity = *targetPortIdentity;
+   msg-management.startingBoundaryHops = boundaryHops;
+   msg-management.boundaryHops = boundaryHops;
 
-   switch (management_action(req)) {
+   switch (action) {
case GET: case SET:
msg-management.flags = RESPONSE;
break;
@@ -2310,6 +2322,47 @@ struct ptp_message *port_management_reply(struct 
PortIdentity pid,
return msg;
 }
 
+struct ptp_message *port_management_reply(struct PortIdentity pid,
+ struct port *ingress,
+ struct ptp_message *req)
+{
+   UInteger8 boundaryHops;
+
+   boundaryHops = req-management.startingBoundaryHops - 
req-management.boundaryHops;
+   return port_management_construct(pid, ingress

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

2014-05-02 Thread Jiri Benc
v3: Split into two parts, this is the ptp4l part. The phc2sys part will
follow after this is accepted.
Reworked to use the new transport_sendto and common address interface.
Removed TLV PORT_ENUMERATION_NP, each port number is queried for its
existence instead.
Addressed all reviewers' comments to v2.

v2: rebased to the current HEAD

For the description of the set, see the v1 cover letter:
https://www.mail-archive.com/linuxptp-devel@lists.sourceforge.net/msg00236.html

Jiri Benc (11):
  uds: don't output Connection refused
  Respond with an error to management messages to non-existing ports
  Remove unneeded parameter in port_forward
  Implement port_forward_to
  Event subscribing
  Include TLV in replies to management commands
  Subscription time limit
  port: event notification
  clock: event notification
  Event notification: port state
  Custom management TLV PORT_PROPERTIES_NP

 clock.c|  246 ---
 clock.h|   19 +
 msg.c  |   17 
 msg.h  |   11 +++
 notification.h |   27 ++
 pmc_common.c   |   10 +--
 port.c |  131 --
 port.h |   37 -
 tlv.c  |   26 ++
 tlv.h  |   17 
 uds.c  |2 +-
 11 files changed, 494 insertions(+), 49 deletions(-)
 create mode 100644 notification.h

-- 
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 v3 11/11] Custom management TLV PORT_PROPERTIES_NP

2014-05-02 Thread Jiri Benc
Will be used by phc2sys to find out interfaces corresponding to ports.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |9 +
 port.c  |   13 +
 tlv.c   |   14 ++
 tlv.h   |8 
 4 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/clock.c b/clock.c
index e585074daea3..db96cb3f4b8e 100644
--- a/clock.c
+++ b/clock.c
@@ -1018,6 +1018,15 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
}
 
switch (mgt-id) {
+   case PORT_PROPERTIES_NP:
+   if (p != c-port[c-nports]) {
+   /* Only the UDS port allowed. */
+   clock_management_send_error(p, msg, NOT_SUPPORTED);
+   return 0;
+   }
+   }
+
+   switch (mgt-id) {
case USER_DESCRIPTION:
case SAVE_IN_NON_VOLATILE_STORAGE:
case RESET_NON_VOLATILE_STORAGE:
diff --git a/port.c b/port.c
index 64c01be127e3..b6abd0eb7fa3 100644
--- a/port.c
+++ b/port.c
@@ -611,6 +611,7 @@ static int port_management_fill_response(struct port 
*target,
struct management_tlv_datum *mtd;
struct portDS *pds;
struct port_ds_np *pdsnp;
+   struct port_properties_np *ppn;
struct clock_description *desc;
struct mgmt_clock_description *cd;
uint8_t *buf;
@@ -760,6 +761,18 @@ static int port_management_fill_response(struct port 
*target,
datalen = sizeof(*pdsnp);
respond = 1;
break;
+   case PORT_PROPERTIES_NP:
+   ppn = (struct port_properties_np *)tlv-data;
+   ppn-portIdentity = target-portIdentity;
+   if (target-state == PS_GRAND_MASTER)
+   ppn-port_state = PS_MASTER;
+   else
+   ppn-port_state = target-state;
+   ppn-timestamping = target-timestamping;
+   ptp_text_set(ppn-interface, target-name);
+   datalen = sizeof(*ppn) + ppn-interface.length;
+   respond = 1;
+   break;
}
if (respond) {
if (datalen % 2) {
diff --git a/tlv.c b/tlv.c
index 60df3575b5f0..d8c680f4640f 100644
--- a/tlv.c
+++ b/tlv.c
@@ -63,6 +63,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t 
data_len,
struct time_status_np *tsn;
struct grandmaster_settings_np *gsn;
struct subscribe_events_np *sen;
+   struct port_properties_np *ppn;
struct mgmt_clock_description *cd;
int extra_len = 0, len;
uint8_t *buf;
@@ -249,6 +250,14 @@ static int mgt_post_recv(struct management_tlv *m, 
uint16_t data_len,
sen = (struct subscribe_events_np *)m-data;
sen-valid_time = ntohs(sen-valid_time);
break;
+   case PORT_PROPERTIES_NP:
+   if (data_len  sizeof(struct port_properties_np))
+   goto bad_length;
+   ppn = (struct port_properties_np *)m-data;
+   ppn-portIdentity.portNumber = 
ntohs(ppn-portIdentity.portNumber);
+   extra_len = sizeof(struct port_properties_np);
+   extra_len += ppn-interface.length;
+   break;
case SAVE_IN_NON_VOLATILE_STORAGE:
case RESET_NON_VOLATILE_STORAGE:
case INITIALIZE:
@@ -281,6 +290,7 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
struct time_status_np *tsn;
struct grandmaster_settings_np *gsn;
struct subscribe_events_np *sen;
+   struct port_properties_np *ppn;
struct mgmt_clock_description *cd;
switch (m-id) {
case CLOCK_DESCRIPTION:
@@ -349,6 +359,10 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
sen = (struct subscribe_events_np *)m-data;
sen-valid_time = htons(sen-valid_time);
break;
+   case PORT_PROPERTIES_NP:
+   ppn = (struct port_properties_np *)m-data;
+   ppn-portIdentity.portNumber = 
htons(ppn-portIdentity.portNumber);
+   break;
}
 }
 
diff --git a/tlv.h b/tlv.h
index c383c822684b..8d52a4224781 100644
--- a/tlv.h
+++ b/tlv.h
@@ -100,6 +100,7 @@ enum management_action {
 #define DELAY_MECHANISM0x6000
 #define LOG_MIN_PDELAY_REQ_INTERVAL0x6001
 #define PORT_DATA_SET_NP   0xC002
+#define PORT_PROPERTIES_NP 0xC004
 
 /* Management error ID values */
 #define RESPONSE_TOO_BIG   0x0001
@@ -205,6 +206,13 @@ struct subscribe_events_np {
uint8_t   bitmask[EVENT_BITMASK_CNT];
 } PACKED;
 
+struct port_properties_np {
+   struct PortIdentity portIdentity;
+   uint8_t port_state;
+   uint8_t timestamping;
+   struct PTPText interface;
+} PACKED;
+
 enum clock_type

Re: [Linuxptp-devel] [PATCH 4/5] Common type holding an address

2014-04-22 Thread Jiri Benc
On Thu, 17 Apr 2014 07:19:05 +0200, Richard Cochran wrote:
 I don't see why you need to call into the transport twice.
 
 Can't you pass addr=NULL in order to get the default address?

Makes sense.

 Jiri

-- 
Jiri Benc

--
Start Your Social Network Today - Download eXo Platform
Build your Enterprise Intranet with eXo Platform Software
Java Based Open Source Intranet - Social, Extensible, Cloud Ready
Get Started Now And Turn Your Intranet Into A Collaboration Platform
http://p.sf.net/sfu/ExoPlatform
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 2/2] Implement transport_sendto

2014-04-22 Thread Jiri Benc
Also, document transport_send, transport_peer and transport_sendto usage.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 transport.c |8 
 transport.h |   33 +
 2 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/transport.c b/transport.c
index b2d4dd14ee65..fc187406b5bd 100644
--- a/transport.c
+++ b/transport.c
@@ -58,6 +58,14 @@ int transport_peer(struct transport *t, struct fdarray *fda, 
int event,
return t-send(t, fda, event, 1, msg, len, NULL, msg-hwts);
 }
 
+int transport_sendto(struct transport *t, struct fdarray *fda, int event,
+struct ptp_message *msg)
+{
+   int len = ntohs(msg-header.messageLength);
+
+   return t-send(t, fda, event, 0, msg, len, msg-address, msg-hwts);
+}
+
 int transport_physical_addr(struct transport *t, uint8_t *addr)
 {
if (t-physical_addr) {
diff --git a/transport.h b/transport.h
index 5153c46d7887..8e0d4214af5a 100644
--- a/transport.h
+++ b/transport.h
@@ -57,13 +57,46 @@ int transport_open(struct transport *t, const char *name,
 
 int transport_recv(struct transport *t, int fd, struct ptp_message *msg);
 
+/**
+ * Sends the PTP message using the given transport. The message is sent to
+ * the default (usually multicast) address, any address field in the
+ * ptp_message itself is ignored.
+ * @param tThe transport.
+ * @param fda  The array of descriptors filled in by transport_open.
+ * @param event1 for event message, 0 for general message.
+ * @param msg  The message to send.
+ * @return Number of bytes send, or negative value in case of an error.
+ */
 int transport_send(struct transport *t, struct fdarray *fda, int event,
   struct ptp_message *msg);
 
+/**
+ * Sends the PTP message using the given transport. The message is sent to
+ * the address used for p2p delay measurements (usually a multicast
+ * address), any address field in the ptp_message itself is ignored.
+ * @param tThe transport.
+ * @param fda  The array of descriptors filled in by transport_open.
+ * @param event1 for event message, 0 for general message.
+ * @param msg  The message to send.
+ * @return Number of bytes send, or negative value in case of an error.
+ */
 int transport_peer(struct transport *t, struct fdarray *fda, int event,
   struct ptp_message *msg);
 
 /**
+ * Sends the PTP message using the given transport. The address has to be
+ * provided in the address field of the message.
+ * @param tThe transport.
+ * @param fda  The array of descriptors filled in by transport_open.
+ * @param event1 for event message, 0 for general message.
+ * @param msg  The message to send. The address of the destination has to
+ * be set in the address field.
+ * @return Number of bytes send, or negative value in case of an error.
+ */
+int transport_sendto(struct transport *t, struct fdarray *fda, int event,
+struct ptp_message *msg);
+
+/**
  * Returns the transport's type.
  */
 enum transport_type transport_type(struct transport *t);
-- 
1.7.6.5


--
Start Your Social Network Today - Download eXo Platform
Build your Enterprise Intranet with eXo Platform Software
Java Based Open Source Intranet - Social, Extensible, Cloud Ready
Get Started Now And Turn Your Intranet Into A Collaboration Platform
http://p.sf.net/sfu/ExoPlatform
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 0/2] Common address struct, sendto implementation

2014-04-22 Thread Jiri Benc
Changes in v2: removed default_addr, passing NULL address to transport send
methods instead.

Jiri Benc (2):
  Common type holding an address
  Implement transport_sendto

 address.h   |   38 +++
 msg.h   |6 
 raw.c   |   50 +++-
 sk.c|   34 ++--
 sk.h|   11 ---
 transport.c |   14 --
 transport.h |   33 
 transport_private.h |8 +++--
 udp.c   |   66 ---
 udp6.c  |   70 +-
 uds.c   |   27 ---
 util.c  |   18 +++--
 12 files changed, 258 insertions(+), 117 deletions(-)
 create mode 100644 address.h

-- 
1.7.6.5


--
Start Your Social Network Today - Download eXo Platform
Build your Enterprise Intranet with eXo Platform Software
Java Based Open Source Intranet - Social, Extensible, Cloud Ready
Get Started Now And Turn Your Intranet Into A Collaboration Platform
http://p.sf.net/sfu/ExoPlatform
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 0/5] Common address struct, sendto implementation

2014-04-11 Thread Jiri Benc
As sugested by Richard, introduce a common address struct and let the
transports use it. I chose struct sockaddr to hold the actual address
contents, as it allows to store also an UDP port.

No functional changes by this patchset, just code refactoring. Tested with
UDPv4 E2E and P2P, UDPv6 E2E and P2P, 802.3 E2E and with pmc. The last
patch implements transport_sendto, which will be needed by phc2sys
autoconfiguration.

Signed-off-by: Jiri Benc jb...@redhat.com

Jiri Benc (5):
  raw: replace hard coded constants by MAC_LEN
  raw: separate src and dst addresses
  Let transport_recv/send/peer use ptp_message
  Common type holding an address
  Implement transport_sendto

 address.h   |   38 
 ether.h |   13 
 msg.h   |   20 -
 pmc_common.c|6 +--
 pmc_common.h|1 +
 port.c  |8 ++---
 raw.c   |   62 ++-
 sk.c|   34 -
 sk.h|   11 ---
 transport.c |   29 ++
 transport.h |   54 +++---
 transport_private.h |   11 +--
 udp.c   |   70 ++-
 udp6.c  |   81 ++-
 uds.c   |   34 ++---
 util.c  |   18 ++-
 16 files changed, 326 insertions(+), 164 deletions(-)
 create mode 100644 address.h

-- 
1.7.6.5


--
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test  Deployment 
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 4/5] Common type holding an address

2014-04-11 Thread Jiri Benc
On Fri, 11 Apr 2014 14:08:16 +0200, Richard Cochran wrote:
  +struct address {
  +   socklen_t len;
  +   union {
  +   struct sockaddr_storage ss;
  +   struct sockaddr_in sin;
  +   struct sockaddr_in6 sin6;
  +   struct sockaddr_un sun;
  +   struct sockaddr sa;
 
 Can't we use struct sockaddr_storage here?

It's the first member of the union. I originally had only struct
sockaddr_storage here but it led to horrible typecasting in the code
(which is quite error prone when you accidentally put an extra  before
the variable). In the end, I added the union here, which led to a
shorter and cleaner code, and the compiler being able to do type
checking as a bonus.

 Jiri

-- 
Jiri Benc

--
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test  Deployment 
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 10/27] Custom management TLV PORT_ENUMERATION_NP

2014-04-07 Thread Jiri Benc
On Sat, 5 Apr 2014 13:02:14 +0200, Richard Cochran wrote:
  +struct port_enumeration_np {
  +   UInteger16 numberPorts;
  +   UInteger16 portNumber[0];
  +} PACKED;
  +
 
 I don't like this variable sized message. We should stick to fixed
 sized items. Why do we need this at all?

The idea was to find out easily which ports are available. I wanted to
omit querying each port number in turn to find out whether it exists or
not (i.e. it's a hole).

If you prefer that, or have even better idea, I'm happy to rewrite this.

 BTW, regarding your dynamic port work, have you seen 1588
 Interpretation 21?

I did not, thanks for the pointer. If I'm reading it correctly, it
basically matches what I've been expecting.

Thanks,

 Jiri

-- 
Jiri Benc

--
Put Bad Developers to Shame
Dominate Development with Jenkins Continuous Integration
Continuously Automate Build, Test  Deployment 
Start a new project now. Try Jenkins in the cloud.
http://p.sf.net/sfu/13600_Cloudbees_APR
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 03/27] Allow sending to a specified (unicast) address

2014-04-02 Thread Jiri Benc
On Wed, 2 Apr 2014 18:15:27 +0200, Richard Cochran wrote:
  +/*
  + * Send message to the given address. This is intended for management
  + * messages only, thus goes always to the general port.
 
 There are a couple of unicast options for PTP. We should try to make
 this new interface in a way that will be useful later on to support
 unicast, which includes events, IIRC.

Okay, I can add a couple more parameters to match the send callback.
Not sure it's worth it, though - adding them later, when they are
actually needed, would be very easy.

I have no strong preference either way.

 Jiri

-- 
Jiri Benc

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


Re: [Linuxptp-devel] [PATCH 00/27] automatic phc2sys configuration

2014-03-24 Thread Jiri Benc
On Sun, 23 Mar 2014 13:10:14 +0100, Richard Cochran wrote:
 I tried latest git head and also v1.4, but I get the following
 applying the patches. Can you please bring this up to date?

Sure. It was on top of HEAD when I submitted it; rebased to the current
HEAD, will post shortly.

 Applying: Event subscribing
 /home/richard/git/linuxptp/.git/rebase-apply/patch:272: new blank line at EOF.
 +
 warning: 1 line adds whitespace errors.

Fixed.

 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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 00/27] automatic phc2sys configuration

2014-03-24 Thread Jiri Benc
v2: rebased to the current HEAD

For the description of the set, see the v1 cover letter:
https://www.mail-archive.com/linuxptp-devel@lists.sourceforge.net/msg00236.html

Jiri Benc (27):
  Move check of TLV length for management COMMAND messages
  Move common code into port_prepare_and_send
  Allow sending to a specified (unicast) address
  uds: don't output Connection refused
  Event subscribing
  Include TLV in replies to management commands
  port: event notification
  clock: event notification
  Event notification: port state
  Custom management TLV PORT_ENUMERATION_NP
  Event notification: port addition/removal
  Custom management TLV PORT_PROPERTIES_NP
  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
  pmc_common: implement pmc_send_command_action
  phc2sys: event subscription
  phc2sys: autoconfiguration
  phc2sys: autoconfigure realtime clock on demand only
  phc2sys: check clockIdentity
  Subscription time limit
  phc2sys: man page update for -a and -r options

 clock.c |  261 -
 clock.h |   19 +
 msg.c   |   17 +
 msg.h   |   11 +
 notification.h  |   28 ++
 phc2sys.8   |  115 --
 phc2sys.c   | 1037 ++-
 pmc_common.c|   40 ++-
 pmc_common.h|4 +-
 port.c  |  260 --
 port.h  |   57 +++
 tlv.c   |   76 
 tlv.h   |   19 +
 transport.c |   17 +
 transport.h |   25 ++
 transport_private.h |5 +
 uds.c   |   28 ++-
 17 files changed, 1582 insertions(+), 437 deletions(-)
 create mode 100644 notification.h

-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 10/27] Custom management TLV PORT_ENUMERATION_NP

2014-03-24 Thread Jiri Benc
Used to enumerate all ports. With the future dynamic port adding/removal,
there may be holes in the port number sequence. For now, just fill it with
the sequence numbers.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |   16 
 tlv.c   |   29 +
 tlv.h   |6 ++
 3 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/clock.c b/clock.c
index 010262f522e3..2e7794cc07cd 100644
--- a/clock.c
+++ b/clock.c
@@ -381,6 +381,21 @@ static int clock_management_fill_response(struct clock *c,
datalen = sizeof(*gsn);
respond = 1;
break;
+   case PORT_ENUMERATION_NP:
+   {
+   struct port_enumeration_np *pen;
+   int i;
+
+   if (c-nports  720)
+   break;
+   pen = (struct port_enumeration_np *)tlv-data;
+   pen-numberPorts = c-nports;
+   for (i = 0; i  c-nports; i++)
+   pen-portNumber[i] = i + 1;
+   datalen = sizeof(*pen) + pen-numberPorts * 
sizeof(UInteger16);
+   respond = 1;
+   }
+   break;
}
if (respond) {
if (datalen % 2) {
@@ -1030,6 +1045,7 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
case TIME_STATUS_NP:
case GRANDMASTER_SETTINGS_NP:
case SUBSCRIBE_EVENTS_NP:
+   case PORT_ENUMERATION_NP:
clock_management_send_error(p, msg, NOT_SUPPORTED);
break;
default:
diff --git a/tlv.c b/tlv.c
index 352026ee5f7a..8d635c452905 100644
--- a/tlv.c
+++ b/tlv.c
@@ -252,6 +252,24 @@ static int mgt_post_recv(struct management_tlv *m, 
uint16_t data_len,
sen-bitmask = ntohl(sen-bitmask);
}
break;
+   case PORT_ENUMERATION_NP:
+   {
+   struct port_enumeration_np *pen;
+   size_t expected_len;
+   int i;
+
+   if (data_len  sizeof(struct port_enumeration_np))
+   goto bad_length;
+   pen = (struct port_enumeration_np *)m-data;
+   pen-numberPorts = ntohs(pen-numberPorts);
+   expected_len = sizeof(struct port_enumeration_np) +
+  pen-numberPorts * sizeof(UInteger16);
+   if (data_len != expected_len)
+   goto bad_length;
+   for (i = 0; i  pen-numberPorts; i++)
+   pen-portNumber[i] = ntohs(pen-portNumber[i]);
+   }
+   break;
case SAVE_IN_NON_VOLATILE_STORAGE:
case RESET_NON_VOLATILE_STORAGE:
case INITIALIZE:
@@ -355,6 +373,17 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
sen-bitmask = htonl(sen-bitmask);
}
break;
+   case PORT_ENUMERATION_NP:
+   {
+   struct port_enumeration_np *pen;
+   int i;
+
+   pen = (struct port_enumeration_np *)m-data;
+   for (i = 0; i  pen-numberPorts; i++)
+   pen-portNumber[i] = htons(pen-portNumber[i]);
+   pen-numberPorts = htons(pen-numberPorts);
+   }
+   break;
}
 }
 
diff --git a/tlv.h b/tlv.h
index 8eb840685a81..dffdabda7d09 100644
--- a/tlv.h
+++ b/tlv.h
@@ -80,6 +80,7 @@ enum management_action {
 #define TIME_STATUS_NP 0xC000
 #define GRANDMASTER_SETTINGS_NP0xC001
 #define SUBSCRIBE_EVENTS_NP0xC003
+#define PORT_ENUMERATION_NP0xC004
 
 /* Port management ID values */
 #define NULL_MANAGEMENT0x
@@ -201,6 +202,11 @@ struct subscribe_events_np {
UInteger32bitmask;
 } PACKED;
 
+struct port_enumeration_np {
+   UInteger16 numberPorts;
+   UInteger16 portNumber[0];
+} PACKED;
+
 enum clock_type {
CLOCK_TYPE_ORDINARY   = 0x8000,
CLOCK_TYPE_BOUNDARY   = 0x4000,
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 17/27] phc2sys: rearrange declarations

2014-03-24 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 jb...@redhat.com
---
 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_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

[Linuxptp-devel] [PATCH v2 06/27] Include TLV in replies to management commands

2014-03-24 Thread Jiri Benc
The standard requires management TLV in replies to commands:

An acknowledge management message is a response to a command
management message. The value of the managementId shall be identical
to that in the command message.
(Table 38)

Just copy the TLV from the request.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |3 +++
 msg.c   |   17 +
 msg.h   |   11 +++
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/clock.c b/clock.c
index f06ebcd77032..80804cad1996 100644
--- a/clock.c
+++ b/clock.c
@@ -18,6 +18,7 @@
  */
 #include errno.h
 #include poll.h
+#include stddef.h
 #include stdlib.h
 #include string.h
 #include time.h
@@ -453,6 +454,8 @@ static int clock_management_cmd_response(struct clock *c, 
struct port *p,
pr_err(failed to allocate response message);
return 1;
}
+   msg_copy_tlv(rsp, offsetof(struct ptp_message, 
management.suffix),
+req, 0);
if (port_prepare_and_send(p, rsp, 0))
pr_err(failed to send response message);
msg_put(rsp);
diff --git a/msg.c b/msg.c
index 7edbdd2619b5..7b958e30bef9 100644
--- a/msg.c
+++ b/msg.c
@@ -470,3 +470,20 @@ int msg_sots_missing(struct ptp_message *m)
}
return (!m-hwts.ts.tv_sec  !m-hwts.ts.tv_nsec) ? 1 : 0;
 }
+
+void msg_copy_tlv(struct ptp_message *dest, unsigned int dest_base,
+ struct ptp_message *src, unsigned int src_base)
+{
+   unsigned int len;
+
+   if (!src_base)
+   src_base = dest_base;
+
+   len = src-header.messageLength;
+   if (len = src_base)
+   return;
+   len -= src_base;
+   memcpy((void *)dest + dest_base, (void *)src + src_base, len);
+   dest-header.messageLength = dest_base + len;
+   dest-tlv_count = src-tlv_count;
+}
diff --git a/msg.h b/msg.h
index 7f471ca555aa..a7155139fb2b 100644
--- a/msg.h
+++ b/msg.h
@@ -321,6 +321,17 @@ void msg_put(struct ptp_message *m);
 int msg_sots_missing(struct ptp_message *m);
 
 /**
+ * Copy TLVs from one message into another.
+ * @param dest   Destination message.
+ * @param dest_base  Offset of the suffix in the destination message.
+ * @param srcSource message.
+ * @param src_base   Offset of the suffix in the source message; 0 to use
+ *   the value in dest_base.
+ */
+void msg_copy_tlv(struct ptp_message *dest, unsigned int dest_base,
+ struct ptp_message *src, unsigned int src_base);
+
+/**
  * Work around buggy 802.1AS switches.
  */
 extern int assume_two_step;
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 13/27] phc2sys: generalize run_pmc

2014-03-24 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 jb...@redhat.com
---
 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);
+   portState = ((struct portDS *)data)-portState;
msg_put(msg);
+
+   switch (portState) {
+   case PS_MASTER

[Linuxptp-devel] [PATCH v2 18/27] phc2sys: open devices in clock_add

2014-03-24 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 jb...@redhat.com
---
 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) {
+   print_set_progname(progname);
+   print_set_verbose(verbose);
+   print_set_syslog(use_syslog);
+   print_set_level(print_level);
+
+   src = clock_add(node, src_name);
+   free(src_name);
+   node.master = src;
+   dst = clock_add(node, dst_name ? dst_name

[Linuxptp-devel] [PATCH v2 07/27] port: event notification

2014-03-24 Thread Jiri Benc
Split management message creation to more fine-grained functions to allow
notification messages to be created.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 port.c |   93 ++--
 port.h |9 ++
 2 files changed, 82 insertions(+), 20 deletions(-)

diff --git a/port.c b/port.c
index d8974ed1156b..a78eab24f8aa 100644
--- a/port.c
+++ b/port.c
@@ -603,26 +603,19 @@ static void port_management_send_error(struct port *p, 
struct port *ingress,
 static const Octet profile_id_drr[] = {0x00, 0x1B, 0x19, 0x00, 0x01, 0x00};
 static const Octet profile_id_p2p[] = {0x00, 0x1B, 0x19, 0x00, 0x02, 0x00};
 
-static int port_management_get_response(struct port *target,
-   struct port *ingress, int id,
-   struct ptp_message *req)
+static int port_management_fill_response(struct port *target,
+struct ptp_message *rsp, int id)
 {
int datalen = 0, respond = 0;
struct management_tlv *tlv;
struct management_tlv_datum *mtd;
-   struct ptp_message *rsp;
struct portDS *pds;
struct port_ds_np *pdsnp;
-   struct PortIdentity pid = port_identity(target);
struct clock_description *desc;
struct mgmt_clock_description *cd;
uint8_t *buf;
uint16_t u16;
 
-   rsp = port_management_reply(pid, ingress, req);
-   if (!rsp) {
-   return 0;
-   }
tlv = (struct management_tlv *) rsp-management.suffix;
tlv-type = TLV_MANAGEMENT;
tlv-id = id;
@@ -776,10 +769,27 @@ static int port_management_get_response(struct port 
*target,
tlv-length = sizeof(tlv-id) + datalen;
rsp-header.messageLength += sizeof(*tlv) + datalen;
rsp-tlv_count = 1;
-   port_prepare_and_send(ingress, rsp, 0);
}
+   return respond;
+}
+
+static int port_management_get_response(struct port *target,
+   struct port *ingress, int id,
+   struct ptp_message *req)
+{
+   struct PortIdentity pid = port_identity(target);
+   struct ptp_message *rsp;
+   int respond;
+
+   rsp = port_management_reply(pid, ingress, req);
+   if (!rsp) {
+   return 0;
+   }
+   respond = port_management_fill_response(target, rsp, id);
+   if (respond)
+   port_prepare_and_send(ingress, rsp, 0);
msg_put(rsp);
-   return respond ? 1 : 0;
+   return respond;
 }
 
 static int port_management_set(struct port *target,
@@ -2280,9 +2290,11 @@ int port_management_error(struct PortIdentity pid, 
struct port *ingress,
return err;
 }
 
-struct ptp_message *port_management_reply(struct PortIdentity pid,
- struct port *ingress,
- struct ptp_message *req)
+static struct ptp_message *
+port_management_construct(struct PortIdentity pid, struct port *ingress,
+ UInteger16 sequenceId,
+ struct PortIdentity *targetPortIdentity,
+ UInteger8 boundaryHops, uint8_t action)
 {
struct ptp_message *msg;
int pdulen;
@@ -2299,16 +2311,16 @@ struct ptp_message *port_management_reply(struct 
PortIdentity pid,
msg-header.messageLength  = pdulen;
msg-header.domainNumber   = clock_domain_number(ingress-clock);
msg-header.sourcePortIdentity = pid;
-   msg-header.sequenceId = req-header.sequenceId;
+   msg-header.sequenceId = sequenceId;
msg-header.control= CTL_MANAGEMENT;
msg-header.logMessageInterval = 0x7f;
 
-   msg-management.targetPortIdentity = req-header.sourcePortIdentity;
-   msg-management.startingBoundaryHops =
-   req-management.startingBoundaryHops - 
req-management.boundaryHops;
-   msg-management.boundaryHops = msg-management.startingBoundaryHops;
+   if (targetPortIdentity)
+   msg-management.targetPortIdentity = *targetPortIdentity;
+   msg-management.startingBoundaryHops = boundaryHops;
+   msg-management.boundaryHops = boundaryHops;
 
-   switch (management_action(req)) {
+   switch (action) {
case GET: case SET:
msg-management.flags = RESPONSE;
break;
@@ -2319,6 +2331,47 @@ struct ptp_message *port_management_reply(struct 
PortIdentity pid,
return msg;
 }
 
+struct ptp_message *port_management_reply(struct PortIdentity pid,
+ struct port *ingress,
+ struct ptp_message *req)
+{
+   UInteger8 boundaryHops;
+
+   boundaryHops = req-management.startingBoundaryHops - 
req-management.boundaryHops;
+   return port_management_construct(pid, ingress

[Linuxptp-devel] [PATCH v2 11/27] Event notification: port addition/removal

2014-03-24 Thread Jiri Benc
Add an event number for port adding/removal. As currently the ports are
static, this event is not emitted for now.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c|4 +++-
 notification.h |1 +
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/clock.c b/clock.c
index 2e7794cc07cd..20fea847ef68 100644
--- a/clock.c
+++ b/clock.c
@@ -1067,7 +1067,9 @@ void clock_notify_event(struct clock *c, enum 
notification event)
int id;
 
switch (event) {
-   /* set id */
+   case NOTIFY_PORT_ENUM:
+   id = PORT_ENUMERATION_NP;
+   break;
default:
return;
}
diff --git a/notification.h b/notification.h
index 47c9b56c4f7e..9e202c7d5fe0 100644
--- a/notification.h
+++ b/notification.h
@@ -22,6 +22,7 @@
 
 enum notification {
NOTIFY_PORT_STATE,
+   NOTIFY_PORT_ENUM,
 };
 
 #endif
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 09/27] Event notification: port state

2014-03-24 Thread Jiri Benc
Notify subscribers about port state changes.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 notification.h |2 +-
 port.c |6 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/notification.h b/notification.h
index 57e7a7856360..47c9b56c4f7e 100644
--- a/notification.h
+++ b/notification.h
@@ -21,7 +21,7 @@
 #define HAVE_NOTIFICATION_H
 
 enum notification {
-   NOTIFY_DUMMY,
+   NOTIFY_PORT_STATE,
 };
 
 #endif
diff --git a/port.c b/port.c
index 8b1f1927590b..fa70571678b6 100644
--- a/port.c
+++ b/port.c
@@ -2038,6 +2038,7 @@ int port_dispatch(struct port *p, enum fsm_event event, 
int mdiff)
if (next == PS_LISTENING  p-delayMechanism == DM_P2P) {
port_set_delay_tmo(p);
}
+   port_notify_event(p, NOTIFY_PORT_STATE);
return 1;
}
 
@@ -2053,6 +2054,7 @@ int port_dispatch(struct port *p, enum fsm_event event, 
int mdiff)
}
 
p-state = next;
+   port_notify_event(p, NOTIFY_PORT_STATE);
return 0;
 }
 
@@ -2359,7 +2361,9 @@ void port_notify_event(struct port *p, enum notification 
event)
int id;
 
switch (event) {
-   /* set id */
+   case NOTIFY_PORT_STATE:
+   id = PORT_DATA_SET;
+   break;
default:
return;
}
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 12/27] Custom management TLV PORT_PROPERTIES_NP

2014-03-24 Thread Jiri Benc
Will be used by phc2sys to find out interfaces corresponding to ports.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |9 +
 port.c  |   16 
 tlv.c   |   20 
 tlv.h   |8 
 4 files changed, 53 insertions(+), 0 deletions(-)

diff --git a/clock.c b/clock.c
index 20fea847ef68..c893a58391ce 100644
--- a/clock.c
+++ b/clock.c
@@ -1012,6 +1012,15 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
}
 
switch (mgt-id) {
+   case PORT_PROPERTIES_NP:
+   if (p != c-port[c-nports]) {
+   /* Only the UDS port allowed. */
+   clock_management_send_error(p, msg, NOT_SUPPORTED);
+   return 0;
+   }
+   }
+
+   switch (mgt-id) {
case USER_DESCRIPTION:
case SAVE_IN_NON_VOLATILE_STORAGE:
case RESET_NON_VOLATILE_STORAGE:
diff --git a/port.c b/port.c
index fa70571678b6..261237654828 100644
--- a/port.c
+++ b/port.c
@@ -760,6 +760,22 @@ static int port_management_fill_response(struct port 
*target,
datalen = sizeof(*pdsnp);
respond = 1;
break;
+   case PORT_PROPERTIES_NP:
+   {
+   struct port_properties_np *ppn;
+
+   ppn = (struct port_properties_np *)tlv-data;
+   ppn-portIdentity = target-portIdentity;
+   if (target-state == PS_GRAND_MASTER)
+   ppn-portState = PS_MASTER;
+   else
+   ppn-portState = target-state;
+   ppn-timestamping = target-timestamping;
+   ptp_text_set(ppn-interface, target-name);
+   datalen = sizeof(*ppn) + ppn-interface.length;
+   respond = 1;
+   }
+   break;
}
if (respond) {
if (datalen % 2) {
diff --git a/tlv.c b/tlv.c
index 8d635c452905..35c9773498be 100644
--- a/tlv.c
+++ b/tlv.c
@@ -270,6 +270,18 @@ static int mgt_post_recv(struct management_tlv *m, 
uint16_t data_len,
pen-portNumber[i] = ntohs(pen-portNumber[i]);
}
break;
+   case PORT_PROPERTIES_NP:
+   {
+   struct port_properties_np *ppn;
+
+   if (data_len  sizeof(struct port_properties_np))
+   goto bad_length;
+   ppn = (struct port_properties_np *)m-data;
+   ppn-portIdentity.portNumber = 
ntohs(ppn-portIdentity.portNumber);
+   extra_len = sizeof(struct port_properties_np);
+   extra_len += ppn-interface.length;
+   }
+   break;
case SAVE_IN_NON_VOLATILE_STORAGE:
case RESET_NON_VOLATILE_STORAGE:
case INITIALIZE:
@@ -384,6 +396,14 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
pen-numberPorts = htons(pen-numberPorts);
}
break;
+   case PORT_PROPERTIES_NP:
+   {
+   struct port_properties_np *ppn;
+
+   ppn = (struct port_properties_np *)m-data;
+   ppn-portIdentity.portNumber = 
htons(ppn-portIdentity.portNumber);
+   }
+   break;
}
 }
 
diff --git a/tlv.h b/tlv.h
index dffdabda7d09..4d2f3f41562a 100644
--- a/tlv.h
+++ b/tlv.h
@@ -101,6 +101,7 @@ enum management_action {
 #define DELAY_MECHANISM0x6000
 #define LOG_MIN_PDELAY_REQ_INTERVAL0x6001
 #define PORT_DATA_SET_NP   0xC002
+#define PORT_PROPERTIES_NP 0xC005
 
 /* Management error ID values */
 #define RESPONSE_TOO_BIG   0x0001
@@ -207,6 +208,13 @@ struct port_enumeration_np {
UInteger16 portNumber[0];
 } PACKED;
 
+struct port_properties_np {
+   struct PortIdentity portIdentity;
+   Enumeration8 portState;
+   Enumeration8 timestamping;
+   struct PTPText interface;
+} PACKED;
+
 enum clock_type {
CLOCK_TYPE_ORDINARY   = 0x8000,
CLOCK_TYPE_BOUNDARY   = 0x4000,
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


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

2014-03-24 Thread Jiri Benc
Signed-off-by: Jiri Benc jb...@redhat.com
---
 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 offset between the slave and master
 times updated according to the currentUtcOffset value obtained from ptp4l and
-the direction of the clock synchronization.
+the direction of the clock synchronization. Not compatible with the
+.B \-a
+option.
 .TP
 .BI \-n

[Linuxptp-devel] [PATCH v2 25/27] phc2sys: check clockIdentity

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

Signed-off-by: Jiri Benc jb...@redhat.com
---
 phc2sys.c |   39 +--
 1 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index e184fc9cd637..108a03f83b8b 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;
@@ -767,7 +778,8 @@ static int run_pmc(struct node *node, int timeout, int 
ds_id,
if (!*msg)
continue;
 
-   if (!is_msg_mgt(*msg) ||
+   if (!check_clock_identity(node, *msg) ||
+   !is_msg_mgt(*msg) ||
recv_subscribed(node, *msg, ds_id) ||
get_mgt_id(*msg) != ds_id) {
msg_put(*msg);
@@ -885,6 +897,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);
@@ -903,7 +933,7 @@ static int auto_init_ports(struct node *node, int add_rt)
char iface[IFNAMSIZ];
 
while (1) {
-   res = run_pmc(node, 1000, PORT_ENUMERATION_NP, msg);
+   res = run_pmc_clock_identity(node, 1000);
if (res  0)
return -1;
if (res  0)
@@ -911,6 +941,11 @@ static int auto_init_ports(struct node *node, int add_rt)
/* res == 0, timeout */
pr_notice(Waiting for ptp4l...);
}
+   res = run_pmc(node, 1000, PORT_ENUMERATION_NP, msg);
+   if (res = 0) {
+   pr_err(failed to enumerate ports);
+   return -1;
+   }
pen = get_mgt_data(msg);
 
res = run_pmc_subscribe(node, 1000);
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 15/27] phc2sys: split clock and node

2014-03-24 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 jb...@redhat.com
---
 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 stdlib.h
 #include string.h
 #include sys/ioctl.h
+#include sys/queue.h
 #include sys/stat.h
 #include sys/types.h
 #include unistd.h
@@ -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)
+static int do_pps_loop(struct node *node, struct clock *clock, int fd)
 {
int64_t pps_offset

[Linuxptp-devel] [PATCH v2 23/27] phc2sys: autoconfiguration

2014-03-24 Thread Jiri Benc
Add automatic configuration option (-a).

Signed-off-by: Jiri Benc jb...@redhat.com
---
 phc2sys.c |  247 ++---
 1 files changed, 236 insertions(+), 11 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index 369fb7c177a5..bc5c4dc61073 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -22,6 +22,7 @@
 #include float.h
 #include inttypes.h
 #include limits.h
+#include net/if.h
 #include poll.h
 #include stdint.h
 #include stdio.h
@@ -108,6 +109,8 @@ struct node {
 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 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)
 {
@@ -262,6 +265,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)
 {
@@ -469,13 +544,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;
@@ -487,14 +561,30 @@ static int do_loop(struct node *node)
if (do_leap  0)
continue;
 
+   if (subscriptions) {
+   run_pmc_events(node);
+   if (node-state_changed) {
+   /* force getting offset, as it may have
+* changed after the port state change */
+   if (run_pmc_get_utc_offset(node, 1000) = 0) {
+   pr_err(failed to get UTC offset);
+   continue;
+   }
+   reconfigure(node);
+   }
+   }
+   if (!node-master)
+   continue;
+
LIST_FOREACH(clock, node-clocks, list) {
-   if (clock == node-master)
+   if (clock-state != PS_MASTER)
continue;
 
if (clock-clkid == CLOCK_REALTIME 
node-master-sysoff_supported) {
/* use sysoff

[Linuxptp-devel] [PATCH v2 19/27] phc2sys: track ports

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

Signed-off-by: Jiri Benc jb...@redhat.com
---
 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


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 03/27] Allow sending to a specified (unicast) address

2014-03-20 Thread Jiri Benc
This will be needed for notifications. Only implemented for UDS.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 port.c  |   14 ++
 port.h  |   22 ++
 transport.c |   17 +
 transport.h |   25 +
 transport_private.h |5 +
 uds.c   |   26 ++
 6 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/port.c b/port.c
index 568bd30c8815..d8974ed1156b 100644
--- a/port.c
+++ b/port.c
@@ -2182,6 +2182,20 @@ int port_prepare_and_send(struct port *p, struct 
ptp_message *msg, int event)
return cnt = 0 ? -1 : 0;
 }
 
+int port_recv_addr(struct port *p, uint8_t *addr)
+{
+   return transport_recv_addr(p-trp, addr);
+}
+
+int port_forward_to(struct port *p, struct ptp_message *msg, int msglen,
+   uint8_t *addr, int addrlen)
+{
+   int cnt;
+
+   cnt = transport_sendto(p-trp, p-fda, msg, msglen, addr, addrlen);
+   return cnt = 0 ? -1 : 0;
+}
+
 struct PortIdentity port_identity(struct port *p)
 {
return p-portIdentity;
diff --git a/port.h b/port.h
index 9d1ddc9e94a3..8d78370992ca 100644
--- a/port.h
+++ b/port.h
@@ -105,6 +105,28 @@ int port_forward(struct port *p, struct ptp_message *msg, 
int msglen);
 int port_prepare_and_send(struct port *p, struct ptp_message *msg, int event);
 
 /**
+ * Get the source address of the last received message.
+ * @param pA pointer previously obtained via port_open().
+ * @param addr Buffer large enough (at least TRANSPORT_RECV_ADDR_LEN
+ * bytes).
+ * @return The number of bytes written to the buffer (address
+ * length).
+ */
+int port_recv_addr(struct port *p, uint8_t *addr);
+
+/**
+ * Forward a message on a given port to the given address.
+ * @param p   A pointer previously obtained via port_open().
+ * @param msg The message to send. Must be in network byte order.
+ * @param msglen  The length of the message in bytes.
+ * @param addrThe address to send the message to.
+ * @param addrlen The length of the address in bytes.
+ * @returnZero on success, non-zero otherwise.
+ */
+int port_forward_to(struct port *p, struct ptp_message *msg, int msglen,
+   uint8_t *addr, int addrlen);
+
+/**
  * Obtain a port's identity.
  * @param pA pointer previously obtained via port_open().
  * @return The port identity of 'p'.
diff --git a/transport.c b/transport.c
index b5346e5e51f4..7b8df79b19a7 100644
--- a/transport.c
+++ b/transport.c
@@ -53,6 +53,15 @@ int transport_peer(struct transport *t, struct fdarray *fda, 
int event,
return t-send(t, fda, event, 1, buf, buflen, hwts);
 }
 
+int transport_sendto(struct transport *t, struct fdarray *fda,
+void *buf, int buflen, uint8_t *addr, int addrlen)
+{
+   if (t-sendto) {
+   return t-sendto(t, fda, buf, buflen, addr, addrlen);
+   }
+   return -1;
+}
+
 int transport_physical_addr(struct transport *t, uint8_t *addr)
 {
if (t-physical_addr) {
@@ -69,6 +78,14 @@ int transport_protocol_addr(struct transport *t, uint8_t 
*addr)
return 0;
 }
 
+int transport_recv_addr(struct transport *t, uint8_t *addr)
+{
+   if (t-recv_addr) {
+   return t-recv_addr(t, addr);
+   }
+   return 0;
+}
+
 enum transport_type transport_type(struct transport *t)
 {
return t-type;
diff --git a/transport.h b/transport.h
index aa2018b4ecdf..fb7243f1fb16 100644
--- a/transport.h
+++ b/transport.h
@@ -76,6 +76,20 @@ int transport_send(struct transport *t, struct fdarray *fda, 
int event,
 int transport_peer(struct transport *t, struct fdarray *fda, int event,
   void *buf, int buflen, struct hw_timestamp *hwts);
 
+/*
+ * Send message to the given address. This is intended for management
+ * messages only, thus goes always to the general port.
+ * @param tThe transport.
+ * @param fda  Array of file descriptors to use.
+ * @param buf  Buffer with the message.
+ * @param buflen   Length of the buffer.
+ * @param addr Destination address.
+ * @param addrlen  Length of the destination address.
+ * @return Number of bytes sent or -1 in case of error.
+ */
+int transport_sendto(struct transport *t, struct fdarray *fda,
+void *buf, int buflen, uint8_t *addr, int addrlen);
+
 /**
  * Returns the transport's type.
  */
@@ -101,6 +115,17 @@ int transport_physical_addr(struct transport *t, uint8_t 
*addr);
  */
 int transport_protocol_addr(struct transport *t, uint8_t *addr);
 
+#define TRANSPORT_RECV_ADDR_LEN 128
+
+/**
+ * Gets the source address of the last received message.
+ * @param tThe transport.
+ * @param addr The address will be written to this buffer.
+ * @return The number of bytes written to the buffer. Will be 0-110
+ * bytes.
+ */
+int

[Linuxptp-devel] [PATCH 01/27] Move check of TLV length for management COMMAND messages

2014-03-20 Thread Jiri Benc
Currently, it is assumed that the management TLV data of management COMMAND
messages is always empty. This is not true for the INITIALIZE command and
also for a custom command we'll be introducing.

Move the check to msg_post_recv and let it check only the TLVs defined by
the standard.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |4 
 tlv.c   |9 +
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/clock.c b/clock.c
index 3aa2407d0bcc..10fa4b6621c4 100644
--- a/clock.c
+++ b/clock.c
@@ -848,10 +848,6 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
return changed;
break;
case COMMAND:
-   if (mgt-length != 2) {
-   clock_management_send_error(p, msg, WRONG_LENGTH);
-   return changed;
-   }
break;
default:
return changed;
diff --git a/tlv.c b/tlv.c
index f32514ff12c8..b8cdd3959c9b 100644
--- a/tlv.c
+++ b/tlv.c
@@ -242,6 +242,15 @@ static int mgt_post_recv(struct management_tlv *m, 
uint16_t data_len,
pdsnp-neighborPropDelayThresh = 
ntohl(pdsnp-neighborPropDelayThresh);
pdsnp-asCapable = ntohl(pdsnp-asCapable);
break;
+   case SAVE_IN_NON_VOLATILE_STORAGE:
+   case RESET_NON_VOLATILE_STORAGE:
+   case INITIALIZE:
+   case FAULT_LOG_RESET:
+   case ENABLE_PORT:
+   case DISABLE_PORT:
+   if (data_len != 0)
+   goto bad_length;
+   break;
}
if (extra_len) {
if (extra_len % 2)
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 24/27] phc2sys: autoconfigure realtime clock on demand only

2014-03-20 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 jb...@redhat.com
---
 phc2sys.c |   33 +
 1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/phc2sys.c b/phc2sys.c
index b0d8adb6828d..f29d8e7eeaab 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);
@@ -884,7 +891,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 ptp_message *msg;
struct port_enumeration_np *pen;
@@ -942,9 +949,14 @@ static int auto_init_ports(struct node *node)
}
node-state_changed = 1;
 
-   if (!clock_add(node, CLOCK_REALTIME)) {
-   res = -1;
-   goto out;
+   if (add_rt) {
+   clock = clock_add(node, CLOCK_REALTIME);
+   if (!clock) {
+   res = -1;
+   goto out;
+   }
+   if (add_rt == 1)
+   clock-dest_only = 1;
}
 
/* get initial offset */
@@ -1042,6 +1054,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
@@ -1074,7 +1088,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;
@@ -1094,11 +1108,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;
@@ -1228,7 +1245,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


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 21/27] pmc_common: implement pmc_send_command_action

2014-03-20 Thread Jiri Benc
Signed-off-by: Jiri Benc jb...@redhat.com
---
 pmc_common.c |   16 ++--
 pmc_common.h |2 +-
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/pmc_common.c b/pmc_common.c
index 061529e25b83..763b06e8e4c5 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -260,12 +260,14 @@ int pmc_send_get_action(struct pmc *pmc, int id)
return 0;
 }
 
-int pmc_send_set_action(struct pmc *pmc, int id, void *data, int datasize)
+static int pmc_send_data_action(struct pmc *pmc, int action, int id,
+   void *data, int datasize)
 {
int pdulen;
struct ptp_message *msg;
struct management_tlv *mgt;
-   msg = pmc_message(pmc, SET);
+
+   msg = pmc_message(pmc, action);
if (!msg) {
return -1;
}
@@ -283,6 +285,16 @@ int pmc_send_set_action(struct pmc *pmc, int id, void 
*data, int datasize)
return 0;
 }
 
+int pmc_send_set_action(struct pmc *pmc, int id, void *data, int datasize)
+{
+   return pmc_send_data_action(pmc, GET, id, data, datasize);
+}
+
+int pmc_send_command_action(struct pmc *pmc, int id, void *data, int datasize)
+{
+   return pmc_send_data_action(pmc, COMMAND, id, data, datasize);
+}
+
 struct ptp_message *pmc_recv(struct pmc *pmc)
 {
struct ptp_message *msg;
diff --git a/pmc_common.h b/pmc_common.h
index d55dfba56e7c..c56c50ada06a 100644
--- a/pmc_common.h
+++ b/pmc_common.h
@@ -34,8 +34,8 @@ void pmc_destroy(struct pmc *pmc);
 int pmc_get_transport_fd(struct pmc *pmc);
 
 int pmc_send_get_action(struct pmc *pmc, int id);
-
 int pmc_send_set_action(struct pmc *pmc, int id, void *data, int datasize);
+int pmc_send_command_action(struct pmc *pmc, int id, void *data, int datasize);
 
 struct ptp_message *pmc_recv(struct pmc *pmc);
 
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 06/27] Include TLV in replies to management commands

2014-03-20 Thread Jiri Benc
The standard requires management TLV in replies to commands:

An acknowledge management message is a response to a command
management message. The value of the managementId shall be identical
to that in the command message.
(Table 38)

Just copy the TLV from the request.

Signed-off-by: Jiri Benc jb...@redhat.com
---
 clock.c |3 +++
 msg.c   |   17 +
 msg.h   |   11 +++
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/clock.c b/clock.c
index f06ebcd77032..80804cad1996 100644
--- a/clock.c
+++ b/clock.c
@@ -18,6 +18,7 @@
  */
 #include errno.h
 #include poll.h
+#include stddef.h
 #include stdlib.h
 #include string.h
 #include time.h
@@ -453,6 +454,8 @@ static int clock_management_cmd_response(struct clock *c, 
struct port *p,
pr_err(failed to allocate response message);
return 1;
}
+   msg_copy_tlv(rsp, offsetof(struct ptp_message, 
management.suffix),
+req, 0);
if (port_prepare_and_send(p, rsp, 0))
pr_err(failed to send response message);
msg_put(rsp);
diff --git a/msg.c b/msg.c
index 7edbdd2619b5..7b958e30bef9 100644
--- a/msg.c
+++ b/msg.c
@@ -470,3 +470,20 @@ int msg_sots_missing(struct ptp_message *m)
}
return (!m-hwts.ts.tv_sec  !m-hwts.ts.tv_nsec) ? 1 : 0;
 }
+
+void msg_copy_tlv(struct ptp_message *dest, unsigned int dest_base,
+ struct ptp_message *src, unsigned int src_base)
+{
+   unsigned int len;
+
+   if (!src_base)
+   src_base = dest_base;
+
+   len = src-header.messageLength;
+   if (len = src_base)
+   return;
+   len -= src_base;
+   memcpy((void *)dest + dest_base, (void *)src + src_base, len);
+   dest-header.messageLength = dest_base + len;
+   dest-tlv_count = src-tlv_count;
+}
diff --git a/msg.h b/msg.h
index 7f471ca555aa..a7155139fb2b 100644
--- a/msg.h
+++ b/msg.h
@@ -321,6 +321,17 @@ void msg_put(struct ptp_message *m);
 int msg_sots_missing(struct ptp_message *m);
 
 /**
+ * Copy TLVs from one message into another.
+ * @param dest   Destination message.
+ * @param dest_base  Offset of the suffix in the destination message.
+ * @param srcSource message.
+ * @param src_base   Offset of the suffix in the source message; 0 to use
+ *   the value in dest_base.
+ */
+void msg_copy_tlv(struct ptp_message *dest, unsigned int dest_base,
+ struct ptp_message *src, unsigned int src_base);
+
+/**
  * Work around buggy 802.1AS switches.
  */
 extern int assume_two_step;
-- 
1.7.6.5


--
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/13534_NeoTech
___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


  1   2   >