Hi,
As I thought that libpmc could be nice for several application that need to
communicate with the ptp4l.
I decided to make a short test.
First I patch the makefile to create the libpmc.so
diff --git a/makefile b/makefile
index a23945a..f5e12da 100644
--- a/makefile
+++ b/makefile
@@ -23,6 +23,7 @@ VER = -DVER=$(version)
CFLAGS = -Wall $(VER) $(incdefs) $(DEBUG) $(EXTRA_CFLAGS)
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
PRG = ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster
+LIBS = libpmc.so
FILTERS = filter.o mave.o mmedian.o
SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o
TRANSP = raw.o transport.o udp.o udp6.o uds.o
@@ -46,7 +47,7 @@ sbindir = $(prefix)/sbin
mandir = $(prefix)/man
man8dir = $(mandir)/man8
-all: $(PRG)
+all: $(PRG) $(LIBS)
ptp4l: $(OBJ)
@@ -56,6 +57,18 @@ nsm: config.o $(FILTERS) hash.o interface.o msg.o nsm.o
phc.o print.o \
pmc: config.o hash.o interface.o msg.o phc.o pmc.o pmc_common.o print.o sk.o \
tlv.o $(TRANSP) util.o version.o
+.libs:
+ @mkdir -p $@
+# Generic rule to compile for shared libraries
+.libs/%.o: %.c | .libs
+ $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -DPIC -c $< -o $@
+
+LIBPMC_OBJS:=$(foreach n,config.o hash.o interface.o msg.o phc.o \
+ pmc_common.o print.o sk.o tlv.o $(TRANSP) util.o version.o,.libs/$n)
+
+libpmc.so: $(LIBPMC_OBJS)
+ $(CC) -shared $^ $(LDLIBS) -o $@
+
phc2sys: clockadj.o clockcheck.o config.o hash.o interface.o msg.o \
phc.o phc2sys.o pmc_common.o print.o $(SERVOS) sk.o stats.o \
sysoff.o tlv.o $(TRANSP) util.o version.o
@@ -83,7 +96,7 @@ install: $(PRG)
done
clean:
- rm -f $(OBJECTS) $(DEPEND) $(PRG)
+ rm -f $(OBJECTS) $(DEPEND) $(PRG) $(LIBS) $(LIBPMC_OBJS)
distclean: clean
rm -f .version
diff --git a/.gitignore b/.gitignore
index 3dbcbfa..091fbf2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@
/phc_ctl
/snmp4lptp
/timemaster
+/libpmc.so
+/.libs/
Than I create a simple application
#include <poll.h>
#include <unistd.h>
extern "C"
{
#include "linuxptp/ds.h"
#include "linuxptp/fsm.h"
#include "linuxptp/notification.h"
#include "linuxptp/pmc_common.h"
#include "linuxptp/print.h"
#include "linuxptp/tlv.h"
#include "linuxptp/uds.h"
#include "linuxptp/util.h"
#include "linuxptp/version.h"
}
class My_Pmc
{
private:
bool init_done;
struct config *cfg;
struct pmc *pmc;
bool parse(struct ptp_message *msg);
bool get(int id);
public:
My_Pmc(const char *cfg_file, const char *uds_address, uint8_t
boundary_hops);
~My_Pmc();
bool get_port_data_set();
bool get_time_status_np();
// from TLV_PORT_DATA_SET - PORT_DATA_SET
int64_t peerMeanPathDelay;
std::string portState;
// from TLV_TIME_STATUS_NP - TIME_STATUS_NP
int64_t master_offset;
std::string gmIdentity;
};
bool My_Pmc::parse(struct ptp_message *msg)
{
if (msg_type(msg) != MANAGEMENT)
return false;
int action = management_action(msg);
if (action < GET || action > ACKNOWLEDGE)
return false;
if (msg_tlv_count(msg) != 1)
return false;
struct TLV *tlv = (struct TLV *)msg->management.suffix;
if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS && tlv->type != TLV_MANAGEMENT)
return false;
struct management_tlv *mgt;
mgt = (struct management_tlv *)msg->management.suffix;
if (mgt->length == 2 && mgt->id != TLV_NULL_MANAGEMENT)
return false;
struct time_status_np *tsn;
struct portDS *p;
switch (mgt->id) {
case TLV_PORT_DATA_SET:
p = (struct portDS *)mgt->data;
if (p->portState > PS_SLAVE)
portState = "NONE";
else
portState = ps_str[p->portState];
peerMeanPathDelay = p->peerMeanPathDelay >> 16;
break;
case TLV_TIME_STATUS_NP:
tsn = (struct time_status_np *)mgt->data;
master_offset = tsn->master_offset;
gmIdentity = cid2str(&tsn->gmIdentity);
break;
}
return true;
}
My_Pmc::My_Pmc(const char *cfg_file, const char *uds_address, uint8_t
boundary_hops):
init_done(false)
{
cfg = config_create();
if (cfg == nullptr)
return;
if (config_read(cfg_file, cfg))
return;
if (config_set_string(cfg, "uds_address", uds_address))
return;
if (config_set_int(cfg, "network_transport", TRANS_UDS))
return;
char uds_local[MAX_IFNAME_SIZE + 1];
snprintf(uds_local, sizeof(uds_local), "/var/run/pmc.%d", getpid());
pmc = pmc_create(cfg, TRANS_UDS, uds_local, boundary_hops,
config_get_int(cfg, nullptr, "domainNumber"),
config_get_int(cfg, nullptr, "transportSpecific") << 4, 0);
if (pmc != nullptr)
init_done = true;
}
bool My_Pmc::get(int id)
{
if (!init_done)
return false;
if (pmc_send_get_action(pmc, id))
return false;
struct pollfd pd;
pd.fd = pmc_get_transport_fd(pmc);
pd.events = POLLIN | POLLPRI;
int cnt = poll(&pd, 1, 200); // 200 milliseconds should be sufficient
if (cnt == 1) {
if (pd.revents & (POLLIN|POLLPRI)) {
struct ptp_message *msg = pmc_recv(pmc);
if (msg != nullptr) {
bool ret = parse(msg);
msg_put(msg);
return ret;
}
}
}
return false;
}
bool My_Pmc::get_port_data_set()
{
return get(TLV_PORT_DATA_SET); // PORT_DATA_SET
}
bool My_Pmc::get_time_status_np()
{
return get(TLV_TIME_STATUS_NP); // TIME_STATUS_NP
}
My_Pmc::~My_Pmc()
{
pmc_destroy(pmc);
msg_cleanup();
config_destroy(cfg);
}
#ifndef PIC
int main()
{
My_Pmc p("/etc/linuxptp/ptp4l.enp7s0.conf", "/var/run/ptp4l.enp7s0", 0);
if (!p.get_port_data_set())
printf("get_port_data_set fail\n");
if (!p.get_time_status_np())
printf("get_time_status_np fail\n");
printf("peerMeanPathDelay %ld portState %s master_offset %ld gmIdentity
%s\n",
p.peerMeanPathDelay,
p.portState.c_str(),
p.master_offset,
p.gmIdentity.c_str());
}
#endif
build
g++ -std=gnu++11 -Wall -Wextra -Winline -g -I../.. -c -o my_pmc.o my_pmc.cpp
g++ my_pmc.o -L../../linuxptp -lpmc -o my_pmc
And run and get the proper answer
LD_LIBRARY_PATH=. ./my_pmc
peerMeanPathDelay 124 portState SLAVE master_offset -1 gmIdentity
xxxxxx.fffe.xxxxxx
What do you think?
With best regards,
Erez Geva
AURELLY TECHNOLOGIES GmbH
External service provider at Siemens AG
Digital Industries
Process Automation
Software House Nbg
DI PA CI R&D 3
Nuremberg, Germany
_______________________________________________
Linuxptp-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel