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
parent
c017adc8d1
commit
5e0196d647
11
clock.c
11
clock.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
5
clock.h
5
clock.h
|
@ -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);
|
||||
|
||||
|
|
78
config.c
78
config.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
11
config.h
11
config.h
|
@ -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
41
ptp4l.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue