Dynamic allocation of interface config entries

Remove the limit of MAX_PORTS ports also when parsing command line
arguments.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
master
Jiri Benc 2014-08-14 15:56:06 +02:00 committed by Richard Cochran
parent c017adc8d1
commit 5e0196d647
5 changed files with 79 additions and 67 deletions

11
clock.c
View File

@ -785,15 +785,16 @@ static void clock_remove_port(struct clock *c, struct port *p)
port_close(p);
}
struct clock *clock_create(int phc_index, struct interface *iface, int count,
struct clock *clock_create(int phc_index, struct interfaces_head *ifaces,
enum timestamp_type timestamping, struct default_ds *dds,
enum servo_type servo)
{
int i, fadj = 0, max_adj = 0.0, sw_ts = timestamping == TS_SOFTWARE ? 1 : 0;
int fadj = 0, max_adj = 0.0, sw_ts = timestamping == TS_SOFTWARE ? 1 : 0;
struct clock *c = &the_clock;
struct port *p;
char phc[32];
struct interface *udsif = &c->uds_interface;
struct interface *iface;
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
@ -909,9 +910,9 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count,
clock_fda_changed(c);
/* Create the ports. */
for (i = 0; i < count; i++) {
if (clock_add_port(c, phc_index, timestamping, &iface[i])) {
pr_err("failed to open port %s", iface[i].name);
STAILQ_FOREACH(iface, ifaces, list) {
if (clock_add_port(c, phc_index, timestamping, iface)) {
pr_err("failed to open port %s", iface->name);
return NULL;
}
}

View File

@ -63,14 +63,13 @@ UInteger8 clock_class(struct clock *c);
*
* @param phc_index PTP hardware clock device to use.
* Pass -1 to select CLOCK_REALTIME.
* @param interface An array of network interfaces.
* @param count The number of elements in @a interfaces.
* @param ifaces A queue of network interfaces.
* @param timestamping The timestamping mode for this clock.
* @param dds A pointer to a default data set for the clock.
* @param servo The servo that this clock will use.
* @return A pointer to the single global clock instance.
*/
struct clock *clock_create(int phc_index, struct interface *iface, int count,
struct clock *clock_create(int phc_index, struct interfaces_head *ifaces,
enum timestamp_type timestamping, struct default_ds *dds,
enum servo_type servo);

View File

@ -20,6 +20,7 @@
#include <float.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "ether.h"
@ -162,40 +163,40 @@ static enum parser_result parse_pod_setting(const char *option,
static enum parser_result parse_port_setting(const char *option,
const char *value,
struct config *cfg,
int p)
struct interface *iface)
{
enum parser_result r;
int val;
r = parse_pod_setting(option, value, &cfg->iface[p].pod);
r = parse_pod_setting(option, value, &iface->pod);
if (r != NOT_PARSED)
return r;
if (!strcmp(option, "network_transport")) {
if (!strcasecmp("L2", value))
cfg->iface[p].transport = TRANS_IEEE_802_3;
iface->transport = TRANS_IEEE_802_3;
else if (!strcasecmp("UDPv4", value))
cfg->iface[p].transport = TRANS_UDP_IPV4;
iface->transport = TRANS_UDP_IPV4;
else if (!strcasecmp("UDPv6", value))
cfg->iface[p].transport = TRANS_UDP_IPV6;
iface->transport = TRANS_UDP_IPV6;
else
return BAD_VALUE;
} else if (!strcmp(option, "delay_mechanism")) {
if (!strcasecmp("Auto", value))
cfg->iface[p].dm = DM_AUTO;
iface->dm = DM_AUTO;
else if (!strcasecmp("E2E", value))
cfg->iface[p].dm = DM_E2E;
iface->dm = DM_E2E;
else if (!strcasecmp("P2P", value))
cfg->iface[p].dm = DM_P2P;
iface->dm = DM_P2P;
else
return BAD_VALUE;
} else if (!strcmp(option, "delay_filter")) {
if (!strcasecmp("moving_average", value))
cfg->iface[p].delay_filter = FILTER_MOVING_AVERAGE;
iface->delay_filter = FILTER_MOVING_AVERAGE;
else if (!strcasecmp("moving_median", value))
cfg->iface[p].delay_filter = FILTER_MOVING_MEDIAN;
iface->delay_filter = FILTER_MOVING_MEDIAN;
else
return BAD_VALUE;
@ -203,7 +204,7 @@ static enum parser_result parse_port_setting(const char *option,
r = get_ranged_int(value, &val, 1, INT_MAX);
if (r != PARSED_OK)
return r;
cfg->iface[p].delay_filter_length = val;
iface->delay_filter_length = val;
} else
return NOT_PARSED;
@ -611,7 +612,8 @@ int config_read(char *name, struct config *cfg)
FILE *fp;
char buf[1024], *line, *c;
const char *option, *value;
int current_port = 0, line_num;
struct interface *current_port = NULL;
int line_num;
fp = 0 == strncmp(name, "-", 2) ? stdin : fopen(name, "r");
@ -647,8 +649,9 @@ int config_read(char *name, struct config *cfg)
goto parse_error;
}
current_port = config_create_interface(port, cfg);
if (current_port < 0)
if (!current_port)
goto parse_error;
config_init_interface(current_port, cfg);
}
continue;
}
@ -660,7 +663,7 @@ int config_read(char *name, struct config *cfg)
fprintf(stderr, "could not parse line %d in %s section\n",
line_num,
current_section == GLOBAL_SECTION ?
"global" : cfg->iface[current_port].name);
"global" : current_port->name);
goto parse_error;
}
@ -678,7 +681,7 @@ int config_read(char *name, struct config *cfg)
fprintf(stderr, "unknown option %s at line %d in %s section\n",
option, line_num,
current_section == GLOBAL_SECTION ?
"global" : cfg->iface[current_port].name);
"global" : current_port->name);
goto parse_error;
case BAD_VALUE:
fprintf(stderr, "%s is a bad value for option %s at line %d\n",
@ -712,36 +715,45 @@ parse_error:
return -2;
}
/* returns the number matching that interface, or -1 on failure */
int config_create_interface(char *name, struct config *cfg)
struct interface *config_create_interface(char *name, struct config *cfg)
{
struct interface *iface;
int i;
if (cfg->nports >= MAX_PORTS) {
fprintf(stderr, "more than %d ports specified\n", MAX_PORTS);
return -1;
}
iface = &cfg->iface[cfg->nports];
/* only create each interface once (by name) */
for(i = 0; i < cfg->nports; i++) {
if (0 == strncmp(name, cfg->iface[i].name, MAX_IFNAME_SIZE))
return i;
STAILQ_FOREACH(iface, &cfg->interfaces, list) {
if (0 == strncmp(name, iface->name, MAX_IFNAME_SIZE))
return iface;
}
iface = calloc(1, sizeof(struct interface));
if (!iface) {
fprintf(stderr, "cannot allocate memory for a port\n");
return NULL;
}
strncpy(iface->name, name, MAX_IFNAME_SIZE);
STAILQ_INSERT_TAIL(&cfg->interfaces, iface, list);
return iface;
}
void config_init_interface(struct interface *iface, struct config *cfg)
{
iface->dm = cfg->dm;
iface->transport = cfg->transport;
memcpy(&iface->pod, &cfg->pod, sizeof(cfg->pod));
sk_get_ts_info(name, &iface->ts_info);
sk_get_ts_info(iface->name, &iface->ts_info);
iface->delay_filter = cfg->dds.delay_filter;
iface->delay_filter_length = cfg->dds.delay_filter_length;
cfg->nports++;
return i;
}
void config_destroy(struct config *cfg)
{
struct interface *iface;
while ((iface = STAILQ_FIRST(&cfg->interfaces))) {
STAILQ_REMOVE_HEAD(&cfg->interfaces, list);
free(iface);
}
}

View File

@ -20,6 +20,8 @@
#ifndef HAVE_CONFIG_H
#define HAVE_CONFIG_H
#include <sys/queue.h>
#include "ds.h"
#include "dm.h"
#include "filter.h"
@ -27,11 +29,11 @@
#include "servo.h"
#include "sk.h"
#define MAX_PORTS 8
#define MAX_IFNAME_SIZE 108 /* = UNIX_PATH_MAX */
/** Defines a network interface, with PTP options. */
struct interface {
STAILQ_ENTRY(interface) list;
char name[MAX_IFNAME_SIZE + 1];
enum delay_mechanism dm;
enum transport_type transport;
@ -62,8 +64,7 @@ struct config {
int cfg_ignore;
/* configured interfaces */
struct interface iface[MAX_PORTS];
int nports;
STAILQ_HEAD(interfaces_head, interface) interfaces;
enum timestamp_type timestamping;
enum transport_type transport;
@ -102,6 +103,8 @@ struct config {
};
int config_read(char *name, struct config *cfg);
int config_create_interface(char *name, struct config *cfg);
struct interface *config_create_interface(char *name, struct config *cfg);
void config_init_interface(struct interface *iface, struct config *cfg);
void config_destroy(struct config *cfg);
#endif

41
ptp4l.c
View File

@ -43,6 +43,8 @@ int assume_two_step = 0;
static int running = 1;
static struct config cfg_settings = {
.interfaces = STAILQ_HEAD_INITIALIZER(cfg_settings.interfaces),
.dds = {
.dds = {
.flags = DDS_TWO_STEP_FLAG,
@ -173,9 +175,7 @@ int main(int argc, char *argv[])
{
char *config = NULL, *req_phc = NULL, *progname;
int c, i;
struct interface *iface = cfg_settings.iface;
char *ports[MAX_PORTS];
int nports = 0;
struct interface *iface;
int *cfg_ignore = &cfg_settings.cfg_ignore;
enum delay_mechanism *dm = &cfg_settings.dm;
enum transport_type *transport = &cfg_settings.transport;
@ -248,8 +248,8 @@ int main(int argc, char *argv[])
config = optarg;
break;
case 'i':
ports[nports] = optarg;
nports++;
if (!config_create_interface(optarg, &cfg_settings))
return -1;
break;
case 'p':
req_phc = optarg;
@ -310,14 +310,7 @@ int main(int argc, char *argv[])
print_set_syslog(cfg_settings.use_syslog);
print_set_level(cfg_settings.print_level);
for (i = 0; i < nports; i++) {
if (config_create_interface(ports[i], &cfg_settings) < 0) {
fprintf(stderr, "too many interfaces\n");
return -1;
}
}
if (!cfg_settings.nports) {
if (STAILQ_EMPTY(&cfg_settings.interfaces)) {
fprintf(stderr, "no interface specified\n");
usage(progname);
return -1;
@ -357,18 +350,21 @@ int main(int argc, char *argv[])
break;
}
/* check whether timestamping mode is supported. */
for (i = 0; i < cfg_settings.nports; i++) {
if (iface[i].ts_info.valid &&
((iface[i].ts_info.so_timestamping & required_modes) != required_modes)) {
/* Init interface configs and check whether timestamping mode is
* supported. */
STAILQ_FOREACH(iface, &cfg_settings.interfaces, list) {
config_init_interface(iface, &cfg_settings);
if (iface->ts_info.valid &&
((iface->ts_info.so_timestamping & required_modes) != required_modes)) {
fprintf(stderr, "interface '%s' does not support "
"requested timestamping mode.\n",
iface[i].name);
iface->name);
return -1;
}
}
/* determine PHC Clock index */
iface = STAILQ_FIRST(&cfg_settings.interfaces);
if (cfg_settings.dds.free_running) {
phc_index = -1;
} else if (*timestamping == TS_SOFTWARE || *timestamping == TS_LEGACY_HW) {
@ -378,8 +374,8 @@ int main(int argc, char *argv[])
fprintf(stderr, "bad ptp device string\n");
return -1;
}
} else if (iface[0].ts_info.valid) {
phc_index = iface[0].ts_info.phc_index;
} else if (iface->ts_info.valid) {
phc_index = iface->ts_info.phc_index;
} else {
fprintf(stderr, "ptp device not specified and\n"
"automatic determination is not\n"
@ -391,12 +387,12 @@ int main(int argc, char *argv[])
pr_info("selected /dev/ptp%d as PTP clock", phc_index);
}
if (generate_clock_identity(&ds->clockIdentity, iface[0].name)) {
if (generate_clock_identity(&ds->clockIdentity, iface->name)) {
fprintf(stderr, "failed to generate a clock identity\n");
return -1;
}
clock = clock_create(phc_index, iface, cfg_settings.nports,
clock = clock_create(phc_index, &cfg_settings.interfaces,
*timestamping, &cfg_settings.dds,
cfg_settings.clock_servo);
if (!clock) {
@ -410,5 +406,6 @@ int main(int argc, char *argv[])
}
clock_destroy(clock);
config_destroy(&cfg_settings);
return 0;
}