sk: change sk_interface_phc to sk_get_ts_info

this patch changes sk_interface_phc to sk_get_ts_info, by allowing the function
to store all the data returned by Ethtool's get_ts_info IOCTL in a struct. A new
struct "sk_ts_info" contains the same data as well as a field for specifying the
structure as valid (in order to support old kernels without the IOCTL). The
valid field should be set only when the IOCTL successfully populates the fields.

A follow-on patch will add new functionality possible because of these
changes. This patch only updates the programs which use the call to perform the
minimum they already do, using the new interface.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
master
Jacob Keller 2012-11-13 13:35:04 -08:00 committed by Richard Cochran
parent 4e81072589
commit 004b62d22b
7 changed files with 50 additions and 22 deletions

View File

@ -464,6 +464,8 @@ int config_create_interface(char *name, struct config *cfg)
iface->transport = cfg->transport; iface->transport = cfg->transport;
memcpy(&iface->pod, &cfg->pod, sizeof(cfg->pod)); memcpy(&iface->pod, &cfg->pod, sizeof(cfg->pod));
sk_get_ts_info(name, &iface->ts_info);
cfg->nports++; cfg->nports++;
return i; return i;

View File

@ -24,6 +24,7 @@
#include "dm.h" #include "dm.h"
#include "transport.h" #include "transport.h"
#include "servo.h" #include "servo.h"
#include "sk.h"
#define MAX_PORTS 8 #define MAX_PORTS 8
#define MAX_IFNAME_SIZE 16 #define MAX_IFNAME_SIZE 16
@ -34,6 +35,7 @@ struct interface {
enum delay_mechanism dm; enum delay_mechanism dm;
enum transport_type transport; enum transport_type transport;
struct port_defaults pod; struct port_defaults pod;
struct sk_ts_info ts_info;
}; };
#define CFG_IGNORE_DM (1 << 0) #define CFG_IGNORE_DM (1 << 0)

View File

@ -298,13 +298,13 @@ int main(int argc, char *argv[])
} }
if (src == CLOCK_INVALID && ethdev) { if (src == CLOCK_INVALID && ethdev) {
int phc_index = -1; struct sk_ts_info ts_info;
char phc_device[16]; char phc_device[16];
if (sk_interface_phc(ethdev, &phc_index) || phc_index < 0) { if (sk_get_ts_info(ethdev, &ts_info) || !ts_info.valid) {
fprintf(stderr, "can't autodiscover PHC device\n"); fprintf(stderr, "can't autodiscover PHC device\n");
return -1; return -1;
} }
sprintf(phc_device, "/dev/ptp%d", phc_index); sprintf(phc_device, "/dev/ptp%d", ts_info.phc_index);
src = clock_open(phc_device); src = clock_open(phc_device);
} }
if (!(device || src != CLOCK_INVALID) || dst == CLOCK_INVALID) { if (!(device || src != CLOCK_INVALID) || dst == CLOCK_INVALID) {

7
port.c
View File

@ -1663,7 +1663,6 @@ struct port *port_open(int phc_index,
struct clock *clock) struct clock *clock)
{ {
struct port *p = malloc(sizeof(*p)); struct port *p = malloc(sizeof(*p));
int checked_phc_index = -1;
if (!p) if (!p)
return NULL; return NULL;
@ -1672,12 +1671,12 @@ struct port *port_open(int phc_index,
if (interface->transport == TRANS_UDS) if (interface->transport == TRANS_UDS)
; /* UDS cannot have a PHC. */ ; /* UDS cannot have a PHC. */
else if (sk_interface_phc(interface->name, &checked_phc_index)) else if (!interface->ts_info.valid)
pr_warning("port %d: get_ts_info not supported", number); pr_warning("port %d: get_ts_info not supported", number);
else if (phc_index >= 0 && phc_index != checked_phc_index) { else if (phc_index >= 0 && phc_index != interface->ts_info.phc_index) {
pr_err("port %d: PHC device mismatch", number); pr_err("port %d: PHC device mismatch", number);
pr_err("port %d: /dev/ptp%d requested, but /dev/ptp%d attached", pr_err("port %d: /dev/ptp%d requested, but /dev/ptp%d attached",
number, phc_index, checked_phc_index); number, phc_index, interface->ts_info.phc_index);
free(p); free(p);
return NULL; return NULL;
} }

View File

@ -263,9 +263,12 @@ int main(int argc, char *argv[])
fprintf(stderr, "bad ptp device string\n"); fprintf(stderr, "bad ptp device string\n");
return -1; return -1;
} }
} else if (sk_interface_phc(iface[0].name, &phc_index)) { } else if (iface[0].ts_info.valid) {
fprintf(stderr, "get_ts_info not supported\n" phc_index = iface[0].ts_info.phc_index;
"please specify ptp device\n"); } else {
fprintf(stderr, "ptp device not specified and\n"
"automatic determination is not\n"
"supported. please specify ptp device\n");
return -1; return -1;
} }

25
sk.c
View File

@ -88,7 +88,7 @@ int sk_interface_index(int fd, char *name)
return ifreq.ifr_ifindex; return ifreq.ifr_ifindex;
} }
int sk_interface_phc(char *name, int *index) int sk_get_ts_info(char *name, struct sk_ts_info *sk_info)
{ {
#ifdef ETHTOOL_GET_TS_INFO #ifdef ETHTOOL_GET_TS_INFO
struct ethtool_ts_info info; struct ethtool_ts_info info;
@ -98,29 +98,38 @@ int sk_interface_phc(char *name, int *index)
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
info.cmd = ETHTOOL_GET_TS_INFO; info.cmd = ETHTOOL_GET_TS_INFO;
strcpy(ifr.ifr_name, name); strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
ifr.ifr_data = (char *) &info; ifr.ifr_data = (char *) &info;
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) { if (fd < 0) {
pr_err("socket failed: %m"); pr_err("socket failed: %m");
return -1; goto failed;
} }
err = ioctl(fd, SIOCETHTOOL, &ifr); err = ioctl(fd, SIOCETHTOOL, &ifr);
if (err < 0) { if (err < 0) {
pr_err("ioctl SIOCETHTOOL failed: %m"); pr_err("ioctl SIOCETHTOOL failed: %m");
close(fd); close(fd);
return -1; goto failed;
} }
close(fd); close(fd);
*index = info.phc_index;
return info.phc_index < 0 ? -1 : 0; /* copy the necessary data to sk_info */
#else memset(sk_info, 0, sizeof(struct sk_ts_info));
return -1; sk_info->valid = 1;
sk_info->phc_index = info.phc_index;
sk_info->so_timestamping = info.so_timestamping;
sk_info->tx_types = info.tx_types;
sk_info->rx_filters = info.rx_filters;
return 0;
#endif #endif
failed:
/* clear data and ensure it is not marked valid */
memset(sk_info, 0, sizeof(struct sk_ts_info));
return -1;
} }
int sk_interface_macaddr(char *name, unsigned char *mac, int len) int sk_interface_macaddr(char *name, unsigned char *mac, int len)

21
sk.h
View File

@ -22,6 +22,19 @@
#include "transport.h" #include "transport.h"
/**
* struct sk_ts_info - supported timestamping information
* @valid: set to non-zero when the info struct contains valid data
* @info: structure containing the values returned by GET_TS_INFO
*/
struct sk_ts_info {
int valid;
int phc_index;
unsigned int so_timestamping;
unsigned int tx_types;
unsigned int rx_filters;
};
/** /**
* Obtain the numerical index from a network interface by name. * Obtain the numerical index from a network interface by name.
* @param fd An open socket. * @param fd An open socket.
@ -31,12 +44,12 @@
int sk_interface_index(int fd, char *device); int sk_interface_index(int fd, char *device);
/** /**
* Obtain the PHC device index of a network interface. * Obtain supported timestamping information
* @param name The name of the interface * @param name The name of the interface
* @return index The non-negative phc index associated with this iface. * @param info Struct containing obtained timestamping information.
* On error a negative integer is returned. * @return zero on success, negative on failure.
*/ */
int sk_interface_phc(char *name, int *index); int sk_get_ts_info(char *name, struct sk_ts_info *sk_info);
/** /**
* Obtain the MAC address of a network interface. * Obtain the MAC address of a network interface.