Make the transport layer more opaque.

Although the UDP/IPv4 layer does not need any state per instance (other
than the two file descriptors), the raw Ethernet layer will need this.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Richard Cochran 2012-03-13 08:28:37 +01:00
parent 7421e74aca
commit 29463cd306
6 changed files with 145 additions and 41 deletions

25
port.c
View File

@ -40,7 +40,7 @@
struct port { struct port {
char *name; char *name;
struct clock *clock; struct clock *clock;
struct transport *transport; struct transport *trp;
enum timestamp_type timestamping; enum timestamp_type timestamping;
struct fdarray fda; struct fdarray fda;
struct foreign_clock *best; struct foreign_clock *best;
@ -351,7 +351,7 @@ static int port_delay_request(struct port *p)
if (msg_pre_send(msg)) if (msg_pre_send(msg))
goto out; 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) { if (cnt <= 0) {
pr_err("port %hu: send delay request failed", portnum(p)); pr_err("port %hu: send delay request failed", portnum(p));
goto out; goto out;
@ -420,7 +420,7 @@ static int port_tx_announce(struct port *p)
err = -1; err = -1;
goto out; 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) { if (cnt <= 0) {
pr_err("port %hu: send announce failed", portnum(p)); pr_err("port %hu: send announce failed", portnum(p));
err = -1; err = -1;
@ -464,7 +464,7 @@ static int port_tx_sync(struct port *p)
err = -1; err = -1;
goto out; 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) { if (cnt <= 0) {
pr_err("port %hu: send sync failed", portnum(p)); pr_err("port %hu: send sync failed", portnum(p));
err = -1; err = -1;
@ -497,7 +497,7 @@ static int port_tx_sync(struct port *p)
err = -1; err = -1;
goto out; 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) { if (cnt <= 0) {
pr_err("port %hu: send follow up failed", portnum(p)); pr_err("port %hu: send follow up failed", portnum(p));
err = -1; err = -1;
@ -531,7 +531,7 @@ static int port_initialize(struct port *p)
goto no_timers; 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; goto no_tropen;
for (i = 0; i < N_TIMER_FDS; i++) { for (i = 0; i < N_TIMER_FDS; i++) {
@ -546,7 +546,7 @@ static int port_initialize(struct port *p)
return 0; return 0;
no_tmo: no_tmo:
p->transport->close(&p->fda); transport_close(p->trp, &p->fda);
no_tropen: no_tropen:
no_timers: no_timers:
for (i = 0; i < N_TIMER_FDS; i++) { 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; err = -1;
goto out; 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) { if (cnt <= 0) {
pr_err("port %hu: send delay response failed", portnum(p)); pr_err("port %hu: send delay response failed", portnum(p));
err = -1; err = -1;
@ -782,7 +782,8 @@ static void process_sync(struct port *p, struct ptp_message *m)
void port_close(struct port *p) void port_close(struct port *p)
{ {
int i; 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++) { for (i = 0; i < N_TIMER_FDS; i++) {
close(p->fda.fd[FD_ANNOUNCE_TIMER + 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; 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) { if (cnt <= 0) {
pr_err("port %hu: recv message failed", portnum(p)); pr_err("port %hu: recv message failed", portnum(p));
msg_put(msg); msg_put(msg);
@ -979,8 +980,8 @@ struct port *port_open(struct port_defaults *pod,
p->pod = *pod; p->pod = *pod;
p->name = name; p->name = name;
p->clock = clock; p->clock = clock;
p->transport = transport_find(transport); p->trp = transport_create(transport);
if (!p->transport) { if (!p->trp) {
free(p); free(p);
return NULL; return NULL;
} }

View File

@ -18,20 +18,37 @@
*/ */
#include "transport.h" #include "transport.h"
#include "transport_private.h"
#include "udp.h" #include "udp.h"
static struct transport udp = { int transport_close(struct transport *t, struct fdarray *fda)
.close = udp_close, {
.open = udp_open, return t->close(t, fda);
.recv = udp_recv, }
.send = udp_send,
};
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) { switch (type) {
case TRANS_UDP_IPV4: case TRANS_UDP_IPV4:
return &udp; return udp_transport_create();
case TRANS_UDP_IPV6: case TRANS_UDP_IPV6:
case TRANS_IEEE_802_3: case TRANS_IEEE_802_3:
case TRANS_DEVICENET: case TRANS_DEVICENET:
@ -41,3 +58,8 @@ struct transport *transport_find(enum transport_type type)
} }
return NULL; return NULL;
} }
void transport_destroy(struct transport *t)
{
t->release(t);
}

View File

@ -44,19 +44,30 @@ struct hw_timestamp {
struct timespec ts; struct timespec ts;
}; };
struct transport { struct transport;
int (*close)(struct fdarray *fda);
int (*open)(char *name, struct fdarray *fda, enum timestamp_type tt); int transport_close(struct transport *t, struct fdarray *fda);
int (*recv)(int fd, void *buf, int buflen, struct hw_timestamp *hwts);
int (*send)(struct fdarray *fda, int event, 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); 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. * @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 #endif

View File

@ -0,0 +1,43 @@
/**
* @file transport_private.h
* @brief Defines a private interface for the abstract transport layer.
* @note Copyright (C) 2012 Richard Cochran <richardcochran@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_TRANSPORT_PRIVATE_H
#define HAVE_TRANSPORT_PRIVATE_H
#include <time.h>
#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

29
udp.c
View File

@ -33,6 +33,7 @@
#include <linux/sockios.h> #include <linux/sockios.h>
#include "print.h" #include "print.h"
#include "transport_private.h"
#include "udp.h" #include "udp.h"
#define EVENT_PORT 319 #define EVENT_PORT 319
@ -162,7 +163,7 @@ static int mcast_join(int fd, int index, const struct sockaddr *grp,
return 0; 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[0]);
close(fda->fd[1]); close(fda->fd[1]);
@ -216,7 +217,8 @@ no_socket:
static struct in_addr mc_addr; 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; int efd, gfd;
@ -316,12 +318,13 @@ static int receive(int fd, void *buf, int buflen,
return cnt; 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); return receive(fd, buf, buflen, hwts, 0);
} }
int udp_send(struct fdarray *fda, int event, static int udp_send(struct transport *t, struct fdarray *fda, int event,
void *buf, int len, struct hw_timestamp *hwts) void *buf, int len, struct hw_timestamp *hwts)
{ {
ssize_t cnt; ssize_t cnt;
@ -344,6 +347,24 @@ int udp_send(struct fdarray *fda, int event,
return event ? receive(fd, junk, len, hwts, MSG_ERRQUEUE) : cnt; 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) int udp_interface_macaddr(char *name, unsigned char *mac, int len)
{ {
struct ifreq ifreq; struct ifreq ifreq;

18
udp.h
View File

@ -23,12 +23,6 @@
#include "fd.h" #include "fd.h"
#include "transport.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. * Obtain the MAC address of a network interface.
* @param name The name of the 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); 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 #endif