Discussion:
[Linuxptp-devel] [PATCH 1/3] Set program name for print().
Miroslav Lichvar
2013-01-29 17:06:16 UTC
Permalink
The printing facility is used by different programs, allow to set the
program name which prefixes the messages written to stdout.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
pmc.c | 1 +
print.c | 9 ++++++++-
print.h | 1 +
ptp4l.c | 1 +
4 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/pmc.c b/pmc.c
index 3fe0be7..3d8ed68 100644
--- a/pmc.c
+++ b/pmc.c
@@ -553,6 +553,7 @@ int main(int argc, char *argv[])
pollfd[1].fd = fdarray.fd[FD_GENERAL];
pollfd[1].events = POLLIN|POLLPRI;

+ print_set_progname(progname);
print_set_syslog(1);
print_set_verbose(1);

diff --git a/print.c b/print.c
index 069cec6..7c21902 100644
--- a/print.c
+++ b/print.c
@@ -27,6 +27,12 @@
static int verbose = 0;
static int print_level = LOG_INFO;
static int use_syslog = 1;
+static const char *progname;
+
+void print_set_progname(const char *name)
+{
+ progname = name;
+}

void print_set_syslog(int value)
{
@@ -59,7 +65,8 @@ void print(int level, char const *format, ...)
va_end(ap);

if (verbose) {
- fprintf(stdout, "ptp4l[%ld.%03ld]: %s\n",
+ fprintf(stdout, "%s[%ld.%03ld]: %s\n",
+ progname ? progname : "",
ts.tv_sec, ts.tv_nsec / 1000000, buf);
fflush(stdout);
}
diff --git a/print.h b/print.h
index d85b26f..56b2104 100644
--- a/print.h
+++ b/print.h
@@ -27,6 +27,7 @@

void print(int level, char const *format, ...);

+void print_set_progname(const char *name);
void print_set_syslog(int value);
void print_set_level(int level);
void print_set_verbose(int value);
diff --git a/ptp4l.c b/ptp4l.c
index 4fc0c88..4f27fb3 100644
--- a/ptp4l.c
+++ b/ptp4l.c
@@ -245,6 +245,7 @@ int main(int argc, char *argv[])
ds->clockQuality.clockClass = 255;
}

+ print_set_progname(progname);
print_set_verbose(cfg_settings.verbose);
print_set_syslog(cfg_settings.use_syslog);
print_set_level(cfg_settings.print_level);
--
1.7.11.7
Miroslav Lichvar
2013-01-29 17:06:17 UTC
Permalink
Move some code which can be shared between PTP management clients to
a new file.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
makefile | 5 +-
pmc.c | 131 ++++++-----------------------------------
pmc_common.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
pmc_common.h | 40 +++++++++++++
4 files changed, 247 insertions(+), 115 deletions(-)
create mode 100644 pmc_common.c
create mode 100644 pmc_common.h

diff --git a/makefile b/makefile
index d144949..2fa6a09 100644
--- a/makefile
+++ b/makefile
@@ -33,7 +33,7 @@ OBJ = bmc.o clock.o config.o fsm.o ptp4l.o mave.o msg.o phc.o pi.o port.o \
print.o raw.o servo.o sk.o tlv.o tmtab.o transport.o udp.o udp6.o uds.o util.o \
version.o

-OBJECTS = $(OBJ) pmc.o phc2sys.o hwstamp_ctl.o sysoff.o
+OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
SRC = $(OBJECTS:.o=.c)
DEPEND = $(OBJECTS:.o=.d)
srcdir := $(dir $(lastword $(MAKEFILE_LIST)))
@@ -49,7 +49,8 @@ all: $(PRG)

ptp4l: $(OBJ)

-pmc: pmc.o msg.o print.o raw.o sk.o tlv.o transport.o udp.o udp6.o uds.o util.o version.o
+pmc: msg.o pmc.o pmc_common.o print.o raw.o sk.o tlv.o transport.o udp.o \
+ udp6.o uds.o util.o version.o

phc2sys: phc2sys.o pi.o servo.o sk.o sysoff.o print.o version.o

diff --git a/pmc.c b/pmc.c
index 3d8ed68..3f94985 100644
--- a/pmc.c
+++ b/pmc.c
@@ -27,10 +27,9 @@

#include "ds.h"
#include "fsm.h"
-#include "msg.h"
+#include "pmc_common.h"
#include "print.h"
#include "tlv.h"
-#include "transport.h"
#include "util.h"
#include "version.h"

@@ -40,14 +39,7 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define P41 ((double)(1ULL << 41))

-static UInteger16 sequence_id;
-static UInteger8 boundary_hops = 1;
-static UInteger8 domain_number;
-static UInteger8 transport_specific;
-static struct PortIdentity port_identity;
-
-static struct transport *transport;
-static struct fdarray fdarray;
+static struct pmc *pmc;

static void do_get_action(int action, int index);
static void not_supported(int action, int index);
@@ -112,52 +104,6 @@ struct management_id idtab[] = {
{ "LOG_MIN_PDELAY_REQ_INTERVAL", LOG_MIN_PDELAY_REQ_INTERVAL, not_supported },
};

-static struct ptp_message *pmc_message(uint8_t action)
-{
- struct ptp_message *msg;
- int pdulen;
-
- msg = msg_allocate();
- if (!msg)
- return NULL;
-
- pdulen = sizeof(struct management_msg);
- msg->hwts.type = TS_SOFTWARE;
-
- msg->header.tsmt = MANAGEMENT | transport_specific;
- msg->header.ver = PTP_VERSION;
- msg->header.messageLength = pdulen;
- msg->header.domainNumber = domain_number;
- msg->header.sourcePortIdentity = port_identity;
- msg->header.sequenceId = sequence_id++;
- msg->header.control = CTL_MANAGEMENT;
- msg->header.logMessageInterval = 0x7f;
-
- memset(&msg->management.targetPortIdentity, 0xff,
- sizeof(msg->management.targetPortIdentity));
- msg->management.startingBoundaryHops = boundary_hops;
- msg->management.boundaryHops = boundary_hops;
- msg->management.flags = action;
-
- return msg;
-}
-
-static int pmc_send(struct ptp_message *msg, int pdulen)
-{
- int cnt, err;
- err = msg_pre_send(msg);
- if (err) {
- fprintf(stderr, "msg_pre_send failed\n");
- return -1;
- }
- cnt = transport_send(transport, &fdarray, 0, msg, pdulen, &msg->hwts);
- if (cnt < 0) {
- fprintf(stderr, "failed to send message\n");
- return -1;
- }
- return 0;
-}
-
static char *action_string[] = {
"GET",
"SET",
@@ -330,30 +276,10 @@ out:
fflush(fp);
}

-static void get_action(int id)
-{
- int pdulen;
- struct ptp_message *msg;
- struct management_tlv *mgt;
- msg = pmc_message(GET);
- if (!msg) {
- return;
- }
- mgt = (struct management_tlv *) msg->management.suffix;
- mgt->type = TLV_MANAGEMENT;
- mgt->length = 2;
- mgt->id = id;
- pdulen = msg->header.messageLength + sizeof(*mgt);
- msg->header.messageLength = pdulen;
- msg->tlv_count = 1;
- pmc_send(msg, pdulen);
- msg_put(msg);
-}
-
static void do_get_action(int action, int index)
{
if (action == GET)
- get_action(idtab[index].code);
+ pmc_send_get_action(pmc, idtab[index].code);
else
fprintf(stderr, "%s only allows GET\n", idtab[index].name);
}
@@ -366,7 +292,7 @@ static void not_supported(int action, int index)
static void null_management(int action, int index)
{
if (action == GET)
- get_action(idtab[index].code);
+ pmc_send_get_action(pmc, idtab[index].code);
else
puts("non-get actions still todo");
}
@@ -479,6 +405,7 @@ int main(int argc, char *argv[])
int c, cnt, length, tmo = -1;
char line[1024];
enum transport_type transport_type = TRANS_UDP_IPV4;
+ UInteger8 boundary_hops = 1, domain_number = 0, transport_specific = 0;
struct ptp_message *msg;
#define N_FD 2
struct pollfd pollfd[N_FD];
@@ -531,32 +458,22 @@ int main(int argc, char *argv[])
if (!iface_name) {
iface_name = transport_type == TRANS_UDS ? "/tmp/pmc" : "eth0";
}
- if (transport_type != TRANS_UDS &&
- generate_clock_identity(&port_identity.clockIdentity, iface_name)) {
- fprintf(stderr, "failed to generate a clock identity\n");
- return -1;
- }
- port_identity.portNumber = 1;
- transport = transport_create(transport_type);
- if (!transport) {
- fprintf(stderr, "failed to create transport\n");
- return -1;
- }
- if (transport_open(transport, iface_name, &fdarray, TS_SOFTWARE)) {
- fprintf(stderr, "failed to open transport\n");
- transport_destroy(transport);
+
+ print_set_progname(progname);
+ print_set_syslog(1);
+ print_set_verbose(1);
+
+ pmc = pmc_create(transport_type, iface_name, boundary_hops, domain_number, transport_specific);
+ if (!pmc) {
+ fprintf(stderr, "failed to create pmc\n");
return -1;
}

pollfd[0].fd = STDIN_FILENO;
pollfd[0].events = POLLIN|POLLPRI;
- pollfd[1].fd = fdarray.fd[FD_GENERAL];
+ pollfd[1].fd = pmc_get_transport_fd(pmc);
pollfd[1].events = POLLIN|POLLPRI;

- print_set_progname(progname);
- print_set_syslog(1);
- print_set_verbose(1);
-
while (1) {
cnt = poll(pollfd, N_FD, tmo);
if (cnt < 0) {
@@ -593,26 +510,14 @@ int main(int argc, char *argv[])
}
}
if (pollfd[1].revents & (POLLIN|POLLPRI)) {
- msg = msg_allocate();
- if (!msg) {
- fprintf(stderr, "low memory\n");
- return -1;
- }
- msg->hwts.type = TS_SOFTWARE;
- cnt = transport_recv(transport, pollfd[1].fd, msg,
- sizeof(msg->data), &msg->hwts);
- if (cnt <= 0) {
- fprintf(stderr, "recv message failed\n");
- } else if (msg_post_recv(msg, cnt)) {
- fprintf(stderr, "bad message\n");
- } else {
+ msg = pmc_recv(pmc);
+ if (msg) {
pmc_show(msg, stdout);
+ msg_put(msg);
}
- msg_put(msg);
}
}

- transport_close(transport, &fdarray);
- transport_destroy(transport);
+ pmc_destroy(pmc);
return 0;
}
diff --git a/pmc_common.c b/pmc_common.c
new file mode 100644
index 0000000..797ec24
--- /dev/null
+++ b/pmc_common.c
@@ -0,0 +1,186 @@
+/**
+ * @file pmc_common.c
+ * @note Copyright (C) 2013 Richard Cochran <***@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#include "print.h"
+#include "tlv.h"
+#include "transport.h"
+#include "util.h"
+
+struct pmc {
+ UInteger16 sequence_id;
+ UInteger8 boundary_hops;
+ UInteger8 domain_number;
+ UInteger8 transport_specific;
+ struct PortIdentity port_identity;
+
+ struct transport *transport;
+ struct fdarray fdarray;
+};
+
+struct pmc *pmc_create(enum transport_type transport_type, char *iface_name,
+ UInteger8 boundary_hops, UInteger8 domain_number,
+ UInteger8 transport_specific)
+{
+ struct pmc *pmc;
+
+ pmc = calloc(1, sizeof *pmc);
+ if (!pmc)
+ return NULL;
+
+ if (transport_type != TRANS_UDS &&
+ generate_clock_identity(&pmc->port_identity.clockIdentity,
+ iface_name)) {
+ pr_err("failed to generate a clock identity");
+ goto failed;
+ }
+
+ pmc->port_identity.portNumber = 1;
+ pmc->boundary_hops = boundary_hops;
+ pmc->domain_number = domain_number;
+ pmc->transport_specific = transport_specific;
+
+ pmc->transport = transport_create(transport_type);
+ if (!pmc->transport) {
+ pr_err("failed to create transport");
+ goto failed;
+ }
+ if (transport_open(pmc->transport, iface_name,
+ &pmc->fdarray, TS_SOFTWARE)) {
+ pr_err("failed to open transport");
+ goto failed;
+ }
+
+ return pmc;
+
+failed:
+ if (pmc->transport)
+ transport_destroy(pmc->transport);
+ free(pmc);
+ return NULL;
+}
+
+void pmc_destroy(struct pmc *pmc)
+{
+ transport_close(pmc->transport, &pmc->fdarray);
+ transport_destroy(pmc->transport);
+ free(pmc);
+}
+
+static struct ptp_message *pmc_message(struct pmc *pmc, uint8_t action)
+{
+ struct ptp_message *msg;
+ int pdulen;
+
+ msg = msg_allocate();
+ if (!msg)
+ return NULL;
+
+ pdulen = sizeof(struct management_msg);
+ msg->hwts.type = TS_SOFTWARE;
+
+ msg->header.tsmt = MANAGEMENT | pmc->transport_specific;
+ msg->header.ver = PTP_VERSION;
+ msg->header.messageLength = pdulen;
+ msg->header.domainNumber = pmc->domain_number;
+ msg->header.sourcePortIdentity = pmc->port_identity;
+ msg->header.sequenceId = pmc->sequence_id++;
+ msg->header.control = CTL_MANAGEMENT;
+ msg->header.logMessageInterval = 0x7f;
+
+ memset(&msg->management.targetPortIdentity, 0xff,
+ sizeof(msg->management.targetPortIdentity));
+ msg->management.startingBoundaryHops = pmc->boundary_hops;
+ msg->management.boundaryHops = pmc->boundary_hops;
+ msg->management.flags = action;
+
+ return msg;
+}
+
+static int pmc_send(struct pmc *pmc, struct ptp_message *msg, int pdulen)
+{
+ int cnt, 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, pdulen, &msg->hwts);
+ if (cnt < 0) {
+ pr_err("failed to send message");
+ return -1;
+ }
+ return 0;
+}
+
+int pmc_get_transport_fd(struct pmc *pmc)
+{
+ return pmc->fdarray.fd[FD_GENERAL];
+}
+
+int pmc_send_get_action(struct pmc *pmc, int id)
+{
+ int pdulen;
+ struct ptp_message *msg;
+ struct management_tlv *mgt;
+ msg = pmc_message(pmc, GET);
+ if (!msg) {
+ return -1;
+ }
+ mgt = (struct management_tlv *) msg->management.suffix;
+ mgt->type = TLV_MANAGEMENT;
+ mgt->length = 2;
+ mgt->id = id;
+ pdulen = msg->header.messageLength + sizeof(*mgt);
+ msg->header.messageLength = pdulen;
+ msg->tlv_count = 1;
+ pmc_send(pmc, msg, pdulen);
+ msg_put(msg);
+
+ return 0;
+}
+
+struct ptp_message *pmc_recv(struct pmc *pmc)
+{
+ struct ptp_message *msg;
+ int cnt;
+
+ msg = msg_allocate();
+ if (!msg) {
+ pr_err("low memory");
+ return NULL;
+ }
+ msg->hwts.type = TS_SOFTWARE;
+ cnt = transport_recv(pmc->transport, pmc_get_transport_fd(pmc),
+ msg, sizeof(msg->data), &msg->hwts);
+ if (cnt <= 0) {
+ pr_err("recv message failed");
+ goto failed;
+ } else if (msg_post_recv(msg, cnt)) {
+ pr_err("bad message");
+ goto failed;
+ }
+
+ return msg;
+failed:
+ msg_put(msg);
+ return NULL;
+}
diff --git a/pmc_common.h b/pmc_common.h
new file mode 100644
index 0000000..cccef55
--- /dev/null
+++ b/pmc_common.h
@@ -0,0 +1,40 @@
+/**
+ * @file pmc_common.h
+ * @brief Code shared between PTP management clients.
+ * @note Copyright (C) 2013 Richard Cochran <***@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef HAVE_PMC_COMMON_H
+#define HAVE_PMC_COMMON_H
+
+#include "msg.h"
+
+struct pmc;
+
+struct pmc *pmc_create(enum transport_type transport_type, char *iface_name,
+ UInteger8 boundary_hops, UInteger8 domain_number,
+ UInteger8 transport_specific);
+
+void pmc_destroy(struct pmc *pmc);
+
+int pmc_get_transport_fd(struct pmc *pmc);
+
+void pmc_send_get_action(struct pmc *pmc, int id);
+
+struct ptp_message *pmc_recv(struct pmc *pmc);
+
+#endif
--
1.7.11.7
Richard Cochran
2013-01-30 15:35:00 UTC
Permalink
Post by Miroslav Lichvar
diff --git a/pmc_common.c b/pmc_common.c
new file mode 100644
index 0000000..797ec24
--- /dev/null
+++ b/pmc_common.c
@@ -0,0 +1,186 @@
+/**
...
Post by Miroslav Lichvar
diff --git a/pmc_common.h b/pmc_common.h
new file mode 100644
index 0000000..cccef55
--- /dev/null
+++ b/pmc_common.h
@@ -0,0 +1,40 @@
+/**
I think if you introduce new files, then your own copyright should go
at the top. The header file is surely your own original work.

What do you think?

Thanks,
Richard
Miroslav Lichvar
2013-01-30 16:03:57 UTC
Permalink
Post by Richard Cochran
Post by Miroslav Lichvar
diff --git a/pmc_common.c b/pmc_common.c
new file mode 100644
index 0000000..797ec24
--- /dev/null
+++ b/pmc_common.c
@@ -0,0 +1,186 @@
+/**
...
Post by Miroslav Lichvar
diff --git a/pmc_common.h b/pmc_common.h
new file mode 100644
index 0000000..cccef55
--- /dev/null
+++ b/pmc_common.h
@@ -0,0 +1,40 @@
+/**
I think if you introduce new files, then your own copyright should go
at the top. The header file is surely your own original work.
What do you think?
I'm not sure, in other projects I try to follow the "10 lines or more
of new code" rule and in this patch there is not much of new code.

If the header file had my copyright and the c file had both yours and
mine, what that be ok with you?

Thanks,
--
Miroslav Lichvar
Richard Cochran
2013-01-30 17:02:58 UTC
Permalink
Post by Miroslav Lichvar
If the header file had my copyright and the c file had both yours and
mine, what that be ok with you?
Okay, fine.

Thanks,
Richard
Miroslav Lichvar
2013-01-30 17:31:50 UTC
Permalink
Move some code which can be shared between PTP management clients to
a new file.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
makefile | 5 +-
pmc.c | 131 ++++++-----------------------------------
pmc_common.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
pmc_common.h | 40 +++++++++++++
4 files changed, 248 insertions(+), 115 deletions(-)
create mode 100644 pmc_common.c
create mode 100644 pmc_common.h

diff --git a/makefile b/makefile
index d144949..2fa6a09 100644
--- a/makefile
+++ b/makefile
@@ -33,7 +33,7 @@ OBJ = bmc.o clock.o config.o fsm.o ptp4l.o mave.o msg.o phc.o pi.o port.o \
print.o raw.o servo.o sk.o tlv.o tmtab.o transport.o udp.o udp6.o uds.o util.o \
version.o

-OBJECTS = $(OBJ) pmc.o phc2sys.o hwstamp_ctl.o sysoff.o
+OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
SRC = $(OBJECTS:.o=.c)
DEPEND = $(OBJECTS:.o=.d)
srcdir := $(dir $(lastword $(MAKEFILE_LIST)))
@@ -49,7 +49,8 @@ all: $(PRG)

ptp4l: $(OBJ)

-pmc: pmc.o msg.o print.o raw.o sk.o tlv.o transport.o udp.o udp6.o uds.o util.o version.o
+pmc: msg.o pmc.o pmc_common.o print.o raw.o sk.o tlv.o transport.o udp.o \
+ udp6.o uds.o util.o version.o

phc2sys: phc2sys.o pi.o servo.o sk.o sysoff.o print.o version.o

diff --git a/pmc.c b/pmc.c
index 3d8ed68..3f94985 100644
--- a/pmc.c
+++ b/pmc.c
@@ -27,10 +27,9 @@

#include "ds.h"
#include "fsm.h"
-#include "msg.h"
+#include "pmc_common.h"
#include "print.h"
#include "tlv.h"
-#include "transport.h"
#include "util.h"
#include "version.h"

@@ -40,14 +39,7 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define P41 ((double)(1ULL << 41))

-static UInteger16 sequence_id;
-static UInteger8 boundary_hops = 1;
-static UInteger8 domain_number;
-static UInteger8 transport_specific;
-static struct PortIdentity port_identity;
-
-static struct transport *transport;
-static struct fdarray fdarray;
+static struct pmc *pmc;

static void do_get_action(int action, int index);
static void not_supported(int action, int index);
@@ -112,52 +104,6 @@ struct management_id idtab[] = {
{ "LOG_MIN_PDELAY_REQ_INTERVAL", LOG_MIN_PDELAY_REQ_INTERVAL, not_supported },
};

-static struct ptp_message *pmc_message(uint8_t action)
-{
- struct ptp_message *msg;
- int pdulen;
-
- msg = msg_allocate();
- if (!msg)
- return NULL;
-
- pdulen = sizeof(struct management_msg);
- msg->hwts.type = TS_SOFTWARE;
-
- msg->header.tsmt = MANAGEMENT | transport_specific;
- msg->header.ver = PTP_VERSION;
- msg->header.messageLength = pdulen;
- msg->header.domainNumber = domain_number;
- msg->header.sourcePortIdentity = port_identity;
- msg->header.sequenceId = sequence_id++;
- msg->header.control = CTL_MANAGEMENT;
- msg->header.logMessageInterval = 0x7f;
-
- memset(&msg->management.targetPortIdentity, 0xff,
- sizeof(msg->management.targetPortIdentity));
- msg->management.startingBoundaryHops = boundary_hops;
- msg->management.boundaryHops = boundary_hops;
- msg->management.flags = action;
-
- return msg;
-}
-
-static int pmc_send(struct ptp_message *msg, int pdulen)
-{
- int cnt, err;
- err = msg_pre_send(msg);
- if (err) {
- fprintf(stderr, "msg_pre_send failed\n");
- return -1;
- }
- cnt = transport_send(transport, &fdarray, 0, msg, pdulen, &msg->hwts);
- if (cnt < 0) {
- fprintf(stderr, "failed to send message\n");
- return -1;
- }
- return 0;
-}
-
static char *action_string[] = {
"GET",
"SET",
@@ -330,30 +276,10 @@ out:
fflush(fp);
}

-static void get_action(int id)
-{
- int pdulen;
- struct ptp_message *msg;
- struct management_tlv *mgt;
- msg = pmc_message(GET);
- if (!msg) {
- return;
- }
- mgt = (struct management_tlv *) msg->management.suffix;
- mgt->type = TLV_MANAGEMENT;
- mgt->length = 2;
- mgt->id = id;
- pdulen = msg->header.messageLength + sizeof(*mgt);
- msg->header.messageLength = pdulen;
- msg->tlv_count = 1;
- pmc_send(msg, pdulen);
- msg_put(msg);
-}
-
static void do_get_action(int action, int index)
{
if (action == GET)
- get_action(idtab[index].code);
+ pmc_send_get_action(pmc, idtab[index].code);
else
fprintf(stderr, "%s only allows GET\n", idtab[index].name);
}
@@ -366,7 +292,7 @@ static void not_supported(int action, int index)
static void null_management(int action, int index)
{
if (action == GET)
- get_action(idtab[index].code);
+ pmc_send_get_action(pmc, idtab[index].code);
else
puts("non-get actions still todo");
}
@@ -479,6 +405,7 @@ int main(int argc, char *argv[])
int c, cnt, length, tmo = -1;
char line[1024];
enum transport_type transport_type = TRANS_UDP_IPV4;
+ UInteger8 boundary_hops = 1, domain_number = 0, transport_specific = 0;
struct ptp_message *msg;
#define N_FD 2
struct pollfd pollfd[N_FD];
@@ -531,32 +458,22 @@ int main(int argc, char *argv[])
if (!iface_name) {
iface_name = transport_type == TRANS_UDS ? "/tmp/pmc" : "eth0";
}
- if (transport_type != TRANS_UDS &&
- generate_clock_identity(&port_identity.clockIdentity, iface_name)) {
- fprintf(stderr, "failed to generate a clock identity\n");
- return -1;
- }
- port_identity.portNumber = 1;
- transport = transport_create(transport_type);
- if (!transport) {
- fprintf(stderr, "failed to create transport\n");
- return -1;
- }
- if (transport_open(transport, iface_name, &fdarray, TS_SOFTWARE)) {
- fprintf(stderr, "failed to open transport\n");
- transport_destroy(transport);
+
+ print_set_progname(progname);
+ print_set_syslog(1);
+ print_set_verbose(1);
+
+ pmc = pmc_create(transport_type, iface_name, boundary_hops, domain_number, transport_specific);
+ if (!pmc) {
+ fprintf(stderr, "failed to create pmc\n");
return -1;
}

pollfd[0].fd = STDIN_FILENO;
pollfd[0].events = POLLIN|POLLPRI;
- pollfd[1].fd = fdarray.fd[FD_GENERAL];
+ pollfd[1].fd = pmc_get_transport_fd(pmc);
pollfd[1].events = POLLIN|POLLPRI;

- print_set_progname(progname);
- print_set_syslog(1);
- print_set_verbose(1);
-
while (1) {
cnt = poll(pollfd, N_FD, tmo);
if (cnt < 0) {
@@ -593,26 +510,14 @@ int main(int argc, char *argv[])
}
}
if (pollfd[1].revents & (POLLIN|POLLPRI)) {
- msg = msg_allocate();
- if (!msg) {
- fprintf(stderr, "low memory\n");
- return -1;
- }
- msg->hwts.type = TS_SOFTWARE;
- cnt = transport_recv(transport, pollfd[1].fd, msg,
- sizeof(msg->data), &msg->hwts);
- if (cnt <= 0) {
- fprintf(stderr, "recv message failed\n");
- } else if (msg_post_recv(msg, cnt)) {
- fprintf(stderr, "bad message\n");
- } else {
+ msg = pmc_recv(pmc);
+ if (msg) {
pmc_show(msg, stdout);
+ msg_put(msg);
}
- msg_put(msg);
}
}

- transport_close(transport, &fdarray);
- transport_destroy(transport);
+ pmc_destroy(pmc);
return 0;
}
diff --git a/pmc_common.c b/pmc_common.c
new file mode 100644
index 0000000..71854c0
--- /dev/null
+++ b/pmc_common.c
@@ -0,0 +1,187 @@
+/**
+ * @file pmc_common.c
+ * @note Copyright (C) 2012 Richard Cochran <***@gmail.com>
+ * @note Copyright (C) 2013 Miroslav Lichvar <***@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#include "print.h"
+#include "tlv.h"
+#include "transport.h"
+#include "util.h"
+
+struct pmc {
+ UInteger16 sequence_id;
+ UInteger8 boundary_hops;
+ UInteger8 domain_number;
+ UInteger8 transport_specific;
+ struct PortIdentity port_identity;
+
+ struct transport *transport;
+ struct fdarray fdarray;
+};
+
+struct pmc *pmc_create(enum transport_type transport_type, char *iface_name,
+ UInteger8 boundary_hops, UInteger8 domain_number,
+ UInteger8 transport_specific)
+{
+ struct pmc *pmc;
+
+ pmc = calloc(1, sizeof *pmc);
+ if (!pmc)
+ return NULL;
+
+ if (transport_type != TRANS_UDS &&
+ generate_clock_identity(&pmc->port_identity.clockIdentity,
+ iface_name)) {
+ pr_err("failed to generate a clock identity");
+ goto failed;
+ }
+
+ pmc->port_identity.portNumber = 1;
+ pmc->boundary_hops = boundary_hops;
+ pmc->domain_number = domain_number;
+ pmc->transport_specific = transport_specific;
+
+ pmc->transport = transport_create(transport_type);
+ if (!pmc->transport) {
+ pr_err("failed to create transport");
+ goto failed;
+ }
+ if (transport_open(pmc->transport, iface_name,
+ &pmc->fdarray, TS_SOFTWARE)) {
+ pr_err("failed to open transport");
+ goto failed;
+ }
+
+ return pmc;
+
+failed:
+ if (pmc->transport)
+ transport_destroy(pmc->transport);
+ free(pmc);
+ return NULL;
+}
+
+void pmc_destroy(struct pmc *pmc)
+{
+ transport_close(pmc->transport, &pmc->fdarray);
+ transport_destroy(pmc->transport);
+ free(pmc);
+}
+
+static struct ptp_message *pmc_message(struct pmc *pmc, uint8_t action)
+{
+ struct ptp_message *msg;
+ int pdulen;
+
+ msg = msg_allocate();
+ if (!msg)
+ return NULL;
+
+ pdulen = sizeof(struct management_msg);
+ msg->hwts.type = TS_SOFTWARE;
+
+ msg->header.tsmt = MANAGEMENT | pmc->transport_specific;
+ msg->header.ver = PTP_VERSION;
+ msg->header.messageLength = pdulen;
+ msg->header.domainNumber = pmc->domain_number;
+ msg->header.sourcePortIdentity = pmc->port_identity;
+ msg->header.sequenceId = pmc->sequence_id++;
+ msg->header.control = CTL_MANAGEMENT;
+ msg->header.logMessageInterval = 0x7f;
+
+ memset(&msg->management.targetPortIdentity, 0xff,
+ sizeof(msg->management.targetPortIdentity));
+ msg->management.startingBoundaryHops = pmc->boundary_hops;
+ msg->management.boundaryHops = pmc->boundary_hops;
+ msg->management.flags = action;
+
+ return msg;
+}
+
+static int pmc_send(struct pmc *pmc, struct ptp_message *msg, int pdulen)
+{
+ int cnt, 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, pdulen, &msg->hwts);
+ if (cnt < 0) {
+ pr_err("failed to send message");
+ return -1;
+ }
+ return 0;
+}
+
+int pmc_get_transport_fd(struct pmc *pmc)
+{
+ return pmc->fdarray.fd[FD_GENERAL];
+}
+
+int pmc_send_get_action(struct pmc *pmc, int id)
+{
+ int pdulen;
+ struct ptp_message *msg;
+ struct management_tlv *mgt;
+ msg = pmc_message(pmc, GET);
+ if (!msg) {
+ return -1;
+ }
+ mgt = (struct management_tlv *) msg->management.suffix;
+ mgt->type = TLV_MANAGEMENT;
+ mgt->length = 2;
+ mgt->id = id;
+ pdulen = msg->header.messageLength + sizeof(*mgt);
+ msg->header.messageLength = pdulen;
+ msg->tlv_count = 1;
+ pmc_send(pmc, msg, pdulen);
+ msg_put(msg);
+
+ return 0;
+}
+
+struct ptp_message *pmc_recv(struct pmc *pmc)
+{
+ struct ptp_message *msg;
+ int cnt;
+
+ msg = msg_allocate();
+ if (!msg) {
+ pr_err("low memory");
+ return NULL;
+ }
+ msg->hwts.type = TS_SOFTWARE;
+ cnt = transport_recv(pmc->transport, pmc_get_transport_fd(pmc),
+ msg, sizeof(msg->data), &msg->hwts);
+ if (cnt <= 0) {
+ pr_err("recv message failed");
+ goto failed;
+ } else if (msg_post_recv(msg, cnt)) {
+ pr_err("bad message");
+ goto failed;
+ }
+
+ return msg;
+failed:
+ msg_put(msg);
+ return NULL;
+}
diff --git a/pmc_common.h b/pmc_common.h
new file mode 100644
index 0000000..cd4d2c0
--- /dev/null
+++ b/pmc_common.h
@@ -0,0 +1,40 @@
+/**
+ * @file pmc_common.h
+ * @brief Code shared between PTP management clients.
+ * @note Copyright (C) 2013 Miroslav Lichvar <***@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef HAVE_PMC_COMMON_H
+#define HAVE_PMC_COMMON_H
+
+#include "msg.h"
+
+struct pmc;
+
+struct pmc *pmc_create(enum transport_type transport_type, char *iface_name,
+ UInteger8 boundary_hops, UInteger8 domain_number,
+ UInteger8 transport_specific);
+
+void pmc_destroy(struct pmc *pmc);
+
+int pmc_get_transport_fd(struct pmc *pmc);
+
+void pmc_send_get_action(struct pmc *pmc, int id);
+
+struct ptp_message *pmc_recv(struct pmc *pmc);
+
+#endif
--
1.7.11.7
Miroslav Lichvar
2013-01-29 17:06:18 UTC
Permalink
Add a new option to wait for ptp4l to be in a synchronized state.
Periodically check PORT_DATA_SET and wait until there is a port in
SLAVE, MASTER or GRAND_MASTER state. Also, set the default
synchronization offset according to the currentUtcOffset value from
TIME_PROPERTIES_DATA_SET and the direction of the clock synchronization.

Signed-off-by: Miroslav Lichvar <***@redhat.com>
---
makefile | 3 +-
phc2sys.8 | 14 +++++-
phc2sys.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 165 insertions(+), 4 deletions(-)

diff --git a/makefile b/makefile
index 2fa6a09..9f2b587 100644
--- a/makefile
+++ b/makefile
@@ -52,7 +52,8 @@ ptp4l: $(OBJ)
pmc: msg.o pmc.o pmc_common.o print.o raw.o sk.o tlv.o transport.o udp.o \
udp6.o uds.o util.o version.o

-phc2sys: phc2sys.o pi.o servo.o sk.o sysoff.o print.o version.o
+phc2sys: msg.o phc2sys.o pmc_common.o print.o pi.o servo.o raw.o sk.o sysoff.o \
+ tlv.o transport.o udp.o udp6.o uds.o util.o version.o

hwstamp_ctl: hwstamp_ctl.o version.o

diff --git a/phc2sys.8 b/phc2sys.8
index a5051c8..e26641a 100644
--- a/phc2sys.8
+++ b/phc2sys.8
@@ -27,6 +27,8 @@ phc2sys \- synchronize two clocks
] [
.BI \-O " offset"
] [
+.B \-w
+] [
.B \-v
]

@@ -90,8 +92,16 @@ 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.
-The default is 0 seconds.
+Specify the offset between the slave and master times in seconds. With the
+.B \-w
+option the default value is set automatically according to the currentUtcOffset
+value obtained from ptp4l and the direction of the clock synchronization.
+Without
+.B \-w
+the default is 0.
+.TP
+.B \-w
+Wait until ptp4l is in a synchronized state.
.TP
.BI \-h
Display a help message.
diff --git a/phc2sys.c b/phc2sys.c
index 988a3f0..455ca02 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -19,6 +19,7 @@
*/
#include <errno.h>
#include <fcntl.h>
+#include <poll.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -33,11 +34,16 @@
#include <linux/pps.h>
#include <linux/ptp_clock.h>

+#include "ds.h"
+#include "fsm.h"
#include "missing.h"
#include "pi.h"
+#include "pmc_common.h"
+#include "print.h"
#include "servo.h"
#include "sk.h"
#include "sysoff.h"
+#include "tlv.h"
#include "version.h"

#define KP 0.7
@@ -285,6 +291,125 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
return 0;
}

+static int is_msg_mgt(struct ptp_message *msg)
+{
+ struct TLV *tlv;
+
+ if (msg_type(msg) != MANAGEMENT)
+ return 0;
+ if (management_action(msg) != RESPONSE)
+ return 0;
+ if (msg->tlv_count != 1)
+ return 0;
+ tlv = (struct TLV *) msg->management.suffix;
+ if (tlv->type != TLV_MANAGEMENT)
+ return 0;
+ return 1;
+}
+
+static int get_mgt_id(struct ptp_message *msg)
+{
+ return ((struct management_tlv *) msg->management.suffix)->id;
+}
+
+static void *get_mgt_data(struct ptp_message *msg)
+{
+ return ((struct management_tlv *) msg->management.suffix)->data;
+}
+
+static int run_pmc(int wait_sync, int *utc_offset)
+{
+ struct ptp_message *msg;
+ struct pmc *pmc;
+ void *data;
+#define N_FD 1
+ struct pollfd pollfd[N_FD];
+#define N_ID 2
+ int cnt, i = 0, ds_done, ds_requested = 0;
+ int ds_ids[N_ID] = {
+ PORT_DATA_SET,
+ TIME_PROPERTIES_DATA_SET
+ };
+
+ pmc = pmc_create(TRANS_UDS, "/tmp/phc2sys", 0, 0, 0);
+ if (!pmc) {
+ fprintf(stderr, "failed to create pmc\n");
+ return -1;
+ }
+
+ while (i < N_ID) {
+ pollfd[0].fd = pmc_get_transport_fd(pmc);
+ pollfd[0].events = POLLIN|POLLPRI;
+ if (!ds_requested)
+ pollfd[0].events |= POLLOUT;
+
+ cnt = poll(pollfd, N_FD, 1000);
+ if (cnt < 0) {
+ fprintf(stderr, "poll failed\n");
+ return -1;
+ }
+ if (!cnt) {
+ /* Request the data set again. */
+ ds_requested = 0;
+ fprintf(stderr, "Waiting for ptp4l...\n");
+ continue;
+ }
+
+ if (pollfd[0].revents & POLLOUT) {
+ pmc_send_get_action(pmc, ds_ids[i]);
+ ds_requested = 1;
+ }
+
+ if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
+ continue;
+
+ msg = pmc_recv(pmc);
+
+ if (!msg)
+ continue;
+
+ if (!is_msg_mgt(msg) || get_mgt_id(msg) != ds_ids[i]) {
+ msg_put(msg);
+ continue;
+ }
+
+ data = get_mgt_data(msg);
+ ds_done = 0;
+
+ switch (get_mgt_id(msg)) {
+ case PORT_DATA_SET:
+ if (!wait_sync)
+ ds_done = 1;
+
+ switch (((struct portDS *)data)->portState) {
+ case PS_MASTER:
+ case PS_GRAND_MASTER:
+ case PS_SLAVE:
+ ds_done = 1;
+ break;
+ }
+
+ break;
+ case TIME_PROPERTIES_DATA_SET:
+ *utc_offset = ((struct timePropertiesDS *)data)->
+ currentUtcOffset;
+ ds_done = 1;
+ break;
+ }
+
+ if (ds_done) {
+ /* Proceed with the next data set. */
+ i++;
+ ds_requested = 0;
+ }
+ msg_put(msg);
+ }
+
+ pmc_destroy(pmc);
+
+ return 0;
+}
+
static void usage(char *progname)
{
fprintf(stderr,
@@ -299,6 +424,7 @@ static void usage(char *progname)
" -R [rate] slave clock update rate in HZ (1)\n"
" -N [num] number of master clock readings per update (5)\n"
" -O [offset] slave-master time offset (0)\n"
+ " -w wait for ptp4l\n"
" -h prints this message and exits\n"
" -v prints the software version and exits\n"
"\n",
@@ -310,6 +436,7 @@ int main(int argc, char *argv[])
char *device = NULL, *progname, *ethdev = NULL;
clockid_t src = CLOCK_INVALID;
int c, phc_readings = 5, phc_rate = 1, sync_offset = 0;
+ int wait_sync = 0, forced_sync_offset = 0;
double ppb;
struct clock dst_clock = {
.clkid = CLOCK_REALTIME,
@@ -322,7 +449,7 @@ int main(int argc, char *argv[])
/* Process the command line arguments. */
progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0];
- while (EOF != (c = getopt(argc, argv, "c:d:hs:P:I:R:N:O:i:v"))) {
+ while (EOF != (c = getopt(argc, argv, "c:d:hs:P:I:R:N:O:i:wv"))) {
switch (c) {
case 'c':
dst_clock.clkid = clock_open(optarg);
@@ -347,10 +474,14 @@ int main(int argc, char *argv[])
break;
case 'O':
sync_offset = atoi(optarg);
+ forced_sync_offset = 1;
break;
case 'i':
ethdev = optarg;
break;
+ case 'w':
+ wait_sync = 1;
+ break;
case 'v':
version_show(stdout);
return 0;
@@ -384,6 +515,25 @@ int main(int argc, char *argv[])
return -1;
}

+ print_set_progname(progname);
+ print_set_verbose(1);
+ print_set_syslog(0);
+
+ if (wait_sync) {
+ int ptp_utc_offset;
+
+ run_pmc(wait_sync, &ptp_utc_offset);
+
+ if (!forced_sync_offset) {
+ if (src != CLOCK_REALTIME &&
+ dst_clock.clkid == CLOCK_REALTIME)
+ sync_offset = -ptp_utc_offset;
+ else if (src == CLOCK_REALTIME &&
+ dst_clock.clkid != CLOCK_REALTIME)
+ sync_offset = ptp_utc_offset;
+ }
+ }
+
ppb = clock_ppb_read(dst_clock.clkid);
/* The reading may silently fail and return 0, reset the frequency to
make sure ppb is the actual frequency of the clock. */
--
1.7.11.7
Richard Cochran
2013-02-03 17:52:04 UTC
Permalink
This patchset adds a PTP management client to phc2sys to allow waiting
on ptp4l before setting the system clock and also to set automatically
the synchronization offset. It moves some code which can be shared
with pmc to pmc_common.c. I'm not very sure with the file name and if
it wouldn't be better to have it in pmc.c and pmc.c rename to pmc_?.c.
I think its okay the way you have it, and I will apply this series.
BTW, the port state enum includes a PS_GRAND_MASTER state, which I
couldn't find in the 1588 spec. Isn't that an incompatibility with
other PTP management clients?
Yes, it is. Thanks for spotting this. I'll will fix it.

Richard

Loading...