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