config: Introduce a unicast master table.
This patch adds configuration file support for a table of unicast masters. Each table lives in its own section and has a unique, positive numerical ID. Entries in the table are a pair of transport type and protocol address. Each port may specify a table id to be used for unicast negotiation. Tables may not be shared between ports, but nothing prevents table entries from appearing in more than table. Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
parent
1d450540c7
commit
e22dc6b113
152
config.c
152
config.c
|
@ -33,6 +33,7 @@
|
|||
|
||||
enum config_section {
|
||||
GLOBAL_SECTION,
|
||||
UC_MTAB_SECTION,
|
||||
PORT_SECTION,
|
||||
UNKNOWN_SECTION,
|
||||
};
|
||||
|
@ -264,12 +265,16 @@ struct config_item config_tab[] = {
|
|||
PORT_ITEM_INT("udp_ttl", 1, 1, 255),
|
||||
PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F),
|
||||
GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
|
||||
PORT_ITEM_INT("unicast_master_table", 0, 0, INT_MAX),
|
||||
PORT_ITEM_INT("unicast_req_duration", 3600, 10, INT_MAX),
|
||||
GLOB_ITEM_INT("use_syslog", 1, 0, 1),
|
||||
GLOB_ITEM_STR("userDescription", ""),
|
||||
GLOB_ITEM_INT("utc_offset", CURRENT_UTC_OFFSET, 0, INT_MAX),
|
||||
GLOB_ITEM_INT("verbose", 0, 0, 1),
|
||||
};
|
||||
|
||||
static struct unicast_master_table *current_uc_mtab;
|
||||
|
||||
static enum parser_result
|
||||
parse_fault_interval(struct config *cfg, const char *section,
|
||||
const char *option, const char *value);
|
||||
|
@ -340,10 +345,103 @@ static void config_item_free(void *ptr)
|
|||
free(ci);
|
||||
}
|
||||
|
||||
static int config_switch_unicast_mtab(struct config *cfg, int idx, int line_num)
|
||||
{
|
||||
struct unicast_master_table *table;
|
||||
|
||||
if (idx < 1) {
|
||||
fprintf(stderr, "line %d: table_id %d is out of range. "
|
||||
"Must be in the range %d to %d\n",
|
||||
line_num, idx, 1, INT_MAX);
|
||||
return -1;
|
||||
}
|
||||
STAILQ_FOREACH(table, &cfg->unicast_master_tables, list) {
|
||||
if (table->table_index == idx) {
|
||||
fprintf(stderr, "line %d: table_id %d already taken\n",
|
||||
line_num, idx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
table = calloc(1, sizeof(*table));
|
||||
if (!table) {
|
||||
fprintf(stderr, "low memory\n");
|
||||
return -1;
|
||||
}
|
||||
STAILQ_INIT(&table->addrs);
|
||||
table->table_index = idx;
|
||||
memset(&table->peer_addr.portIdentity, 0xff,
|
||||
sizeof(table->peer_addr.portIdentity));
|
||||
STAILQ_INSERT_TAIL(&cfg->unicast_master_tables, table, list);
|
||||
current_uc_mtab = table;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_unicast_mtab_address(enum transport_type type, char *address,
|
||||
int line_num)
|
||||
{
|
||||
struct unicast_master_address *item;
|
||||
|
||||
if (!current_uc_mtab) {
|
||||
fprintf(stderr, "line %d: missing table_id\n", line_num);
|
||||
return -1;
|
||||
}
|
||||
item = calloc(1, sizeof(*item));
|
||||
if (!item) {
|
||||
fprintf(stderr, "low memory\n");
|
||||
return -1;
|
||||
}
|
||||
if (str2addr(type, address, &item->address)) {
|
||||
fprintf(stderr, "line %d: bad address\n", line_num);
|
||||
free(item);
|
||||
return -1;
|
||||
}
|
||||
memset(&item->portIdentity, 0xff, sizeof(item->portIdentity));
|
||||
item->type = type;
|
||||
STAILQ_INSERT_TAIL(¤t_uc_mtab->addrs, item, list);
|
||||
current_uc_mtab->count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_unicast_mtab_peer(char *address, int line_num)
|
||||
{
|
||||
if (!current_uc_mtab) {
|
||||
fprintf(stderr, "line %d: missing table_id\n", line_num);
|
||||
return -1;
|
||||
}
|
||||
if (current_uc_mtab->peer_name) {
|
||||
free(current_uc_mtab->peer_name);
|
||||
}
|
||||
current_uc_mtab->peer_name = strdup(address);
|
||||
if (!current_uc_mtab->peer_name) {
|
||||
fprintf(stderr, "low memory\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_unicast_mtab_query_interval(int lqi, int line_num)
|
||||
{
|
||||
if (!current_uc_mtab) {
|
||||
fprintf(stderr, "line %d: missing table_id\n", line_num);
|
||||
return -1;
|
||||
}
|
||||
if (lqi < INT8_MIN || lqi > INT8_MAX) {
|
||||
fprintf(stderr, "line %d: logQueryInterval %d out of range\n",
|
||||
line_num, lqi);
|
||||
return -1;
|
||||
}
|
||||
current_uc_mtab->logQueryInterval = lqi;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum parser_result parse_section_line(char *s, enum config_section *section)
|
||||
{
|
||||
if (!strcasecmp(s, "[global]")) {
|
||||
*section = GLOBAL_SECTION;
|
||||
} else if (!strcasecmp(s, "[unicast_master_table]")) {
|
||||
*section = UC_MTAB_SECTION;
|
||||
current_uc_mtab = NULL;
|
||||
} else if (s[0] == '[') {
|
||||
char c;
|
||||
*section = PORT_SECTION;
|
||||
|
@ -484,6 +582,39 @@ static enum parser_result parse_fault_interval(struct config *cfg,
|
|||
return NOT_PARSED;
|
||||
}
|
||||
|
||||
static int parse_unicast_mtab_line(struct config *cfg, char *line, int line_num)
|
||||
{
|
||||
char address[64 + 1] = {0}, transport[16 + 1] = {0};
|
||||
enum transport_type type = TRANS_UDS;
|
||||
struct config_enum *cte;
|
||||
int cnt, lqi, table_id;
|
||||
|
||||
cnt = sscanf(line, " table_id %d", &table_id);
|
||||
if (cnt == 1) {
|
||||
return config_switch_unicast_mtab(cfg, table_id, line_num);
|
||||
}
|
||||
cnt = sscanf(line, " logQueryInterval %d", &lqi);
|
||||
if (cnt == 1) {
|
||||
return config_unicast_mtab_query_interval(lqi, line_num);
|
||||
}
|
||||
cnt = sscanf(line, " peer_address %64s", address);
|
||||
if (cnt == 1) {
|
||||
return config_unicast_mtab_peer(address, line_num);
|
||||
}
|
||||
cnt = sscanf(line, " %16s %64s", transport, address);
|
||||
if (cnt != 2) {
|
||||
fprintf(stderr, "bad master table at line %d\n", line_num);
|
||||
return -1;
|
||||
}
|
||||
for (cte = nw_trans_enu; cte->label; cte++) {
|
||||
if (!strcasecmp(cte->label, transport)) {
|
||||
type = cte->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return config_unicast_mtab_address(type, address, line_num);
|
||||
}
|
||||
|
||||
static enum parser_result parse_setting_line(char *line,
|
||||
const char **option,
|
||||
const char **value)
|
||||
|
@ -594,6 +725,13 @@ int config_read(char *name, struct config *cfg)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (current_section == UC_MTAB_SECTION) {
|
||||
if (parse_unicast_mtab_line(cfg, line, line_num)) {
|
||||
goto parse_error;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_section == UNKNOWN_SECTION) {
|
||||
fprintf(stderr, "line %d is not in a section\n", line_num);
|
||||
goto parse_error;
|
||||
|
@ -679,6 +817,7 @@ struct config *config_create(void)
|
|||
return NULL;
|
||||
}
|
||||
STAILQ_INIT(&cfg->interfaces);
|
||||
STAILQ_INIT(&cfg->unicast_master_tables);
|
||||
|
||||
cfg->opts = config_alloc_longopts();
|
||||
if (!cfg->opts) {
|
||||
|
@ -724,12 +863,25 @@ fail:
|
|||
|
||||
void config_destroy(struct config *cfg)
|
||||
{
|
||||
struct unicast_master_address *address;
|
||||
struct unicast_master_table *table;
|
||||
struct interface *iface;
|
||||
|
||||
while ((iface = STAILQ_FIRST(&cfg->interfaces))) {
|
||||
STAILQ_REMOVE_HEAD(&cfg->interfaces, list);
|
||||
free(iface);
|
||||
}
|
||||
while ((table = STAILQ_FIRST(&cfg->unicast_master_tables))) {
|
||||
while ((address = STAILQ_FIRST(&table->addrs))) {
|
||||
STAILQ_REMOVE_HEAD(&table->addrs, list);
|
||||
free(address);
|
||||
}
|
||||
if (table->peer_name) {
|
||||
free(table->peer_name);
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&cfg->unicast_master_tables, list);
|
||||
free(table);
|
||||
}
|
||||
hash_destroy(cfg->htab, config_item_free);
|
||||
free(cfg->opts);
|
||||
free(cfg);
|
||||
|
|
4
config.h
4
config.h
|
@ -26,6 +26,7 @@
|
|||
#include "ds.h"
|
||||
#include "dm.h"
|
||||
#include "filter.h"
|
||||
#include "mtab.h"
|
||||
#include "transport.h"
|
||||
#include "servo.h"
|
||||
#include "sk.h"
|
||||
|
@ -54,6 +55,9 @@ struct config {
|
|||
|
||||
/* hash of all non-legacy items */
|
||||
struct hash *htab;
|
||||
|
||||
/* unicast master tables */
|
||||
STAILQ_HEAD(ucmtab_head, unicast_master_table) unicast_master_tables;
|
||||
};
|
||||
|
||||
int config_read(char *name, struct config *cfg);
|
||||
|
|
|
@ -42,6 +42,8 @@ hybrid_e2e 0
|
|||
net_sync_monitor 0
|
||||
tc_spanning_tree 0
|
||||
tx_timestamp_timeout 1
|
||||
unicast_master_table 0
|
||||
unicast_req_duration 3600
|
||||
use_syslog 1
|
||||
verbose 0
|
||||
summary_interval 0
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* @file mtab.h
|
||||
* @brief master table implementation
|
||||
* @note Copyright (C) 2018 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-1335 USA.
|
||||
*/
|
||||
#ifndef HAVE_MTAB_H
|
||||
#define HAVE_MTAB_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "pdt.h"
|
||||
#include "transport.h"
|
||||
|
||||
struct unicast_master_address {
|
||||
STAILQ_ENTRY(unicast_master_address) list;
|
||||
struct PortIdentity portIdentity;
|
||||
enum transport_type type;
|
||||
struct address address;
|
||||
unsigned int granted;
|
||||
unsigned int sydymsk;
|
||||
time_t renewal_tmo;
|
||||
};
|
||||
|
||||
struct unicast_master_table {
|
||||
STAILQ_HEAD(addrs_head, unicast_master_address) addrs;
|
||||
STAILQ_ENTRY(unicast_master_table) list;
|
||||
Integer8 logQueryInterval;
|
||||
int table_index;
|
||||
int count;
|
||||
int port;
|
||||
/* for use with P2P delay mechanism: */
|
||||
struct unicast_master_address peer_addr;
|
||||
char *peer_name;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -123,6 +123,7 @@ struct port {
|
|||
int tc_spanning_tree;
|
||||
Integer64 rx_timestamp_offset;
|
||||
Integer64 tx_timestamp_offset;
|
||||
int unicast_req_duration;
|
||||
enum link_state link_status;
|
||||
struct fault_interval flt_interval_pertype[FT_CNT];
|
||||
enum fault_type last_fault_type;
|
||||
|
@ -131,6 +132,8 @@ struct port {
|
|||
LIST_HEAD(fm, foreign_clock) foreign_masters;
|
||||
/* TC book keeping */
|
||||
TAILQ_HEAD(tct, tc_txd) tc_transmitted;
|
||||
/* unicast client mode */
|
||||
struct unicast_master_table *unicast_master_table;
|
||||
};
|
||||
|
||||
#define portnum(p) (p->portIdentity.portNumber)
|
||||
|
|
Loading…
Reference in New Issue