diff --git a/port.c b/port.c index 978fca3..d4449ee 100644 --- a/port.c +++ b/port.c @@ -40,7 +40,7 @@ struct port { char *name; struct clock *clock; - struct transport *transport; + struct transport *trp; enum timestamp_type timestamping; struct fdarray fda; struct foreign_clock *best; @@ -351,7 +351,7 @@ static int port_delay_request(struct port *p) if (msg_pre_send(msg)) goto out; - cnt = p->transport->send(&p->fda, 1, msg, pdulen, &msg->hwts); + cnt = transport_send(p->trp, &p->fda, 1, msg, pdulen, &msg->hwts); if (cnt <= 0) { pr_err("port %hu: send delay request failed", portnum(p)); goto out; @@ -420,7 +420,7 @@ static int port_tx_announce(struct port *p) err = -1; goto out; } - cnt = p->transport->send(&p->fda, 0, msg, pdulen, &msg->hwts); + cnt = transport_send(p->trp, &p->fda, 0, msg, pdulen, &msg->hwts); if (cnt <= 0) { pr_err("port %hu: send announce failed", portnum(p)); err = -1; @@ -464,7 +464,7 @@ static int port_tx_sync(struct port *p) err = -1; goto out; } - cnt = p->transport->send(&p->fda, 1, msg, pdulen, &msg->hwts); + cnt = transport_send(p->trp, &p->fda, 1, msg, pdulen, &msg->hwts); if (cnt <= 0) { pr_err("port %hu: send sync failed", portnum(p)); err = -1; @@ -497,7 +497,7 @@ static int port_tx_sync(struct port *p) err = -1; goto out; } - cnt = p->transport->send(&p->fda, 0, fup, pdulen, &fup->hwts); + cnt = transport_send(p->trp, &p->fda, 0, fup, pdulen, &fup->hwts); if (cnt <= 0) { pr_err("port %hu: send follow up failed", portnum(p)); err = -1; @@ -531,7 +531,7 @@ static int port_initialize(struct port *p) goto no_timers; } } - if (p->transport->open(p->name, &p->fda, p->timestamping)) + if (transport_open(p->trp, p->name, &p->fda, p->timestamping)) goto no_tropen; for (i = 0; i < N_TIMER_FDS; i++) { @@ -546,7 +546,7 @@ static int port_initialize(struct port *p) return 0; no_tmo: - p->transport->close(&p->fda); + transport_close(p->trp, &p->fda); no_tropen: no_timers: for (i = 0; i < N_TIMER_FDS; i++) { @@ -646,7 +646,7 @@ static int process_delay_req(struct port *p, struct ptp_message *m) err = -1; goto out; } - cnt = p->transport->send(&p->fda, 0, msg, pdulen, NULL); + cnt = transport_send(p->trp, &p->fda, 0, msg, pdulen, NULL); if (cnt <= 0) { pr_err("port %hu: send delay response failed", portnum(p)); err = -1; @@ -782,7 +782,8 @@ static void process_sync(struct port *p, struct ptp_message *m) void port_close(struct port *p) { int i; - p->transport->close(&p->fda); + transport_close(p->trp, &p->fda); + transport_destroy(p->trp); for (i = 0; i < N_TIMER_FDS; i++) { close(p->fda.fd[FD_ANNOUNCE_TIMER + i]); } @@ -915,7 +916,7 @@ enum fsm_event port_event(struct port *p, int fd_index) msg->hwts.type = p->timestamping; - cnt = p->transport->recv(fd, msg, sizeof(*msg), &msg->hwts); + cnt = transport_recv(p->trp, fd, msg, sizeof(*msg), &msg->hwts); if (cnt <= 0) { pr_err("port %hu: recv message failed", portnum(p)); msg_put(msg); @@ -979,8 +980,8 @@ struct port *port_open(struct port_defaults *pod, p->pod = *pod; p->name = name; p->clock = clock; - p->transport = transport_find(transport); - if (!p->transport) { + p->trp = transport_create(transport); + if (!p->trp) { free(p); return NULL; } diff --git a/transport.c b/transport.c index 0947037..13a5300 100644 --- a/transport.c +++ b/transport.c @@ -18,20 +18,37 @@ */ #include "transport.h" +#include "transport_private.h" #include "udp.h" -static struct transport udp = { - .close = udp_close, - .open = udp_open, - .recv = udp_recv, - .send = udp_send, -}; +int transport_close(struct transport *t, struct fdarray *fda) +{ + return t->close(t, fda); +} -struct transport *transport_find(enum transport_type type) +int transport_open(struct transport *t, char *name, + struct fdarray *fda, enum timestamp_type tt) +{ + return t->open(t, name, fda, tt); +} + +int transport_recv(struct transport *t, int fd, + void *buf, int buflen, struct hw_timestamp *hwts) +{ + return t->recv(t, fd, buf, buflen, hwts); +} + +int transport_send(struct transport *t, struct fdarray *fda, int event, + void *buf, int buflen, struct hw_timestamp *hwts) +{ + return t->send(t, fda, event, buf, buflen, hwts); +} + +struct transport *transport_create(enum transport_type type) { switch (type) { case TRANS_UDP_IPV4: - return &udp; + return udp_transport_create(); case TRANS_UDP_IPV6: case TRANS_IEEE_802_3: case TRANS_DEVICENET: @@ -41,3 +58,8 @@ struct transport *transport_find(enum transport_type type) } return NULL; } + +void transport_destroy(struct transport *t) +{ + t->release(t); +} diff --git a/transport.h b/transport.h index 4e9cd70..2a9bda6 100644 --- a/transport.h +++ b/transport.h @@ -44,19 +44,30 @@ struct hw_timestamp { struct timespec ts; }; -struct transport { - int (*close)(struct fdarray *fda); - int (*open)(char *name, struct fdarray *fda, enum timestamp_type tt); - int (*recv)(int fd, void *buf, int buflen, struct hw_timestamp *hwts); - int (*send)(struct fdarray *fda, int event, - void *buf, int buflen, struct hw_timestamp *hwts); -}; +struct transport; + +int transport_close(struct transport *t, struct fdarray *fda); + +int transport_open(struct transport *t, char *name, + struct fdarray *fda, enum timestamp_type tt); + +int transport_recv(struct transport *t, int fd, + void *buf, int buflen, struct hw_timestamp *hwts); + +int transport_send(struct transport *t, struct fdarray *fda, int event, + void *buf, int buflen, struct hw_timestamp *hwts); /** - * Obtain a pointer to the specified transport. + * Allocate an instance of the specified transport. * @param type Which transport to obtain. - * @return Pointer to a static global. + * @return Pointer to a transport instance on success, NULL otherwise. */ -struct transport *transport_find(enum transport_type type); +struct transport *transport_create(enum transport_type type); + +/** + * Free an instance of a transport. + * @param t Pointer obtained by calling transport_create(). + */ +void transport_destroy(struct transport *t); #endif diff --git a/transport_private.h b/transport_private.h new file mode 100644 index 0000000..0791c1d --- /dev/null +++ b/transport_private.h @@ -0,0 +1,43 @@ +/** + * @file transport_private.h + * @brief Defines a private interface for the abstract transport layer. + * @note Copyright (C) 2012 Richard Cochran + * + * 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_TRANSPORT_PRIVATE_H +#define HAVE_TRANSPORT_PRIVATE_H + +#include + +#include "fd.h" +#include "transport.h" + +struct transport { + int (*close)(struct transport *t, struct fdarray *fda); + + int (*open)(struct transport *t, char *name, struct fdarray *fda, + enum timestamp_type tt); + + int (*recv)(struct transport *t, int fd, void *buf, int buflen, + struct hw_timestamp *hwts); + + int (*send)(struct transport *t, struct fdarray *fda, int event, + void *buf, int buflen, struct hw_timestamp *hwts); + + void (*release)(struct transport *t); +}; + +#endif diff --git a/udp.c b/udp.c index d097f98..fc67175 100644 --- a/udp.c +++ b/udp.c @@ -33,6 +33,7 @@ #include #include "print.h" +#include "transport_private.h" #include "udp.h" #define EVENT_PORT 319 @@ -162,7 +163,7 @@ static int mcast_join(int fd, int index, const struct sockaddr *grp, return 0; } -int udp_close(struct fdarray *fda) +static int udp_close(struct transport *t, struct fdarray *fda) { close(fda->fd[0]); close(fda->fd[1]); @@ -216,7 +217,8 @@ no_socket: static struct in_addr mc_addr; -int udp_open(char *name, struct fdarray *fda, enum timestamp_type ts_type) +static int udp_open(struct transport *t, char *name, struct fdarray *fda, + enum timestamp_type ts_type) { int efd, gfd; @@ -316,13 +318,14 @@ static int receive(int fd, void *buf, int buflen, return cnt; } -int udp_recv(int fd, void *buf, int buflen, struct hw_timestamp *hwts) +static int udp_recv(struct transport *t, int fd, void *buf, int buflen, + struct hw_timestamp *hwts) { return receive(fd, buf, buflen, hwts, 0); } -int udp_send(struct fdarray *fda, int event, - void *buf, int len, struct hw_timestamp *hwts) +static int udp_send(struct transport *t, struct fdarray *fda, int event, + void *buf, int len, struct hw_timestamp *hwts) { ssize_t cnt; int fd = event ? fda->fd[FD_EVENT] : fda->fd[FD_GENERAL]; @@ -344,6 +347,24 @@ int udp_send(struct fdarray *fda, int event, return event ? receive(fd, junk, len, hwts, MSG_ERRQUEUE) : cnt; } +static struct transport the_udp_transport = { + .close = udp_close, + .open = udp_open, + .recv = udp_recv, + .send = udp_send, +}; + +struct transport *udp_transport_create(void) +{ + /* No need for any per-instance allocation. */ + return &the_udp_transport; +} + +void udp_transport_destroy(struct transport *t) +{ + /* No need for any per-instance deallocation. */ +} + int udp_interface_macaddr(char *name, unsigned char *mac, int len) { struct ifreq ifreq; diff --git a/udp.h b/udp.h index ad5e034..6506444 100644 --- a/udp.h +++ b/udp.h @@ -23,12 +23,6 @@ #include "fd.h" #include "transport.h" -int udp_close(struct fdarray *fda); -int udp_open(char *name, struct fdarray *fda, enum timestamp_type ts_type); -int udp_recv(int fd, void *buf, int buflen, struct hw_timestamp *hwts); -int udp_send(struct fdarray *fda, int event, - void *buf, int buflen, struct hw_timestamp *hwts); - /** * Obtain the MAC address of a network interface. * @param name The name of the interface @@ -38,4 +32,16 @@ int udp_send(struct fdarray *fda, int event, */ int udp_interface_macaddr(char *name, unsigned char *mac, int len); +/** + * Allocate an instance of a UDP/IPv4 transport. + * @return Pointer to a new transport instance on success, NULL otherwise. + */ +struct transport *udp_transport_create(void); + +/** + * Free an instance of a UDP/IPv4 transport. + * @param t Pointer obtained by calling udp_transport_create(). + */ +void udp_transport_destroy(struct transport *t); + #endif