pmc: Move new common funtionality into pmc_common
Code from pmc.c will be reused by new snmpd.c in later commit. Signed-off-by: Anders Selhammer <anders.selhammer@est.tech>master
parent
763a7ecdb2
commit
d85c592993
299
pmc.c
299
pmc.c
|
@ -35,88 +35,8 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#define BAD_ACTION -1
|
|
||||||
#define BAD_ID -1
|
|
||||||
#define AMBIGUOUS_ID -2
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
||||||
#define P41 ((double)(1ULL << 41))
|
|
||||||
|
|
||||||
static struct pmc *pmc;
|
static struct pmc *pmc;
|
||||||
|
|
||||||
static void do_get_action(int action, int index, char *str);
|
|
||||||
static void do_set_action(int action, int index, char *str);
|
|
||||||
static void not_supported(int action, int index, char *str);
|
|
||||||
static void null_management(int action, int index, char *str);
|
|
||||||
|
|
||||||
struct management_id {
|
|
||||||
char name[64];
|
|
||||||
int code;
|
|
||||||
void (*func)(int action, int index, char *str);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct management_id idtab[] = {
|
|
||||||
/* Clock management ID values */
|
|
||||||
{ "USER_DESCRIPTION", TLV_USER_DESCRIPTION, do_get_action },
|
|
||||||
{ "SAVE_IN_NON_VOLATILE_STORAGE", TLV_SAVE_IN_NON_VOLATILE_STORAGE, not_supported },
|
|
||||||
{ "RESET_NON_VOLATILE_STORAGE", TLV_RESET_NON_VOLATILE_STORAGE, not_supported },
|
|
||||||
{ "INITIALIZE", TLV_INITIALIZE, not_supported },
|
|
||||||
{ "FAULT_LOG", TLV_FAULT_LOG, not_supported },
|
|
||||||
{ "FAULT_LOG_RESET", TLV_FAULT_LOG_RESET, not_supported },
|
|
||||||
{ "DEFAULT_DATA_SET", TLV_DEFAULT_DATA_SET, do_get_action },
|
|
||||||
{ "CURRENT_DATA_SET", TLV_CURRENT_DATA_SET, do_get_action },
|
|
||||||
{ "PARENT_DATA_SET", TLV_PARENT_DATA_SET, do_get_action },
|
|
||||||
{ "TIME_PROPERTIES_DATA_SET", TLV_TIME_PROPERTIES_DATA_SET, do_get_action },
|
|
||||||
{ "PRIORITY1", TLV_PRIORITY1, do_set_action },
|
|
||||||
{ "PRIORITY2", TLV_PRIORITY2, do_set_action },
|
|
||||||
{ "DOMAIN", TLV_DOMAIN, do_get_action },
|
|
||||||
{ "SLAVE_ONLY", TLV_SLAVE_ONLY, do_get_action },
|
|
||||||
{ "TIME", TLV_TIME, not_supported },
|
|
||||||
{ "CLOCK_ACCURACY", TLV_CLOCK_ACCURACY, do_get_action },
|
|
||||||
{ "UTC_PROPERTIES", TLV_UTC_PROPERTIES, not_supported },
|
|
||||||
{ "TRACEABILITY_PROPERTIES", TLV_TRACEABILITY_PROPERTIES, do_get_action },
|
|
||||||
{ "TIMESCALE_PROPERTIES", TLV_TIMESCALE_PROPERTIES, do_get_action },
|
|
||||||
{ "PATH_TRACE_LIST", TLV_PATH_TRACE_LIST, not_supported },
|
|
||||||
{ "PATH_TRACE_ENABLE", TLV_PATH_TRACE_ENABLE, not_supported },
|
|
||||||
{ "GRANDMASTER_CLUSTER_TABLE", TLV_GRANDMASTER_CLUSTER_TABLE, not_supported },
|
|
||||||
{ "ACCEPTABLE_MASTER_TABLE", TLV_ACCEPTABLE_MASTER_TABLE, not_supported },
|
|
||||||
{ "ACCEPTABLE_MASTER_MAX_TABLE_SIZE", TLV_ACCEPTABLE_MASTER_MAX_TABLE_SIZE, not_supported },
|
|
||||||
{ "ALTERNATE_TIME_OFFSET_ENABLE", TLV_ALTERNATE_TIME_OFFSET_ENABLE, not_supported },
|
|
||||||
{ "ALTERNATE_TIME_OFFSET_NAME", TLV_ALTERNATE_TIME_OFFSET_NAME, not_supported },
|
|
||||||
{ "ALTERNATE_TIME_OFFSET_MAX_KEY", TLV_ALTERNATE_TIME_OFFSET_MAX_KEY, not_supported },
|
|
||||||
{ "ALTERNATE_TIME_OFFSET_PROPERTIES", TLV_ALTERNATE_TIME_OFFSET_PROPERTIES, not_supported },
|
|
||||||
{ "TRANSPARENT_CLOCK_DEFAULT_DATA_SET", TLV_TRANSPARENT_CLOCK_DEFAULT_DATA_SET, not_supported },
|
|
||||||
{ "PRIMARY_DOMAIN", TLV_PRIMARY_DOMAIN, not_supported },
|
|
||||||
{ "TIME_STATUS_NP", TLV_TIME_STATUS_NP, do_get_action },
|
|
||||||
{ "GRANDMASTER_SETTINGS_NP", TLV_GRANDMASTER_SETTINGS_NP, do_set_action },
|
|
||||||
/* Port management ID values */
|
|
||||||
{ "NULL_MANAGEMENT", TLV_NULL_MANAGEMENT, null_management },
|
|
||||||
{ "CLOCK_DESCRIPTION", TLV_CLOCK_DESCRIPTION, do_get_action },
|
|
||||||
{ "PORT_DATA_SET", TLV_PORT_DATA_SET, do_get_action },
|
|
||||||
{ "LOG_ANNOUNCE_INTERVAL", TLV_LOG_ANNOUNCE_INTERVAL, do_get_action },
|
|
||||||
{ "ANNOUNCE_RECEIPT_TIMEOUT", TLV_ANNOUNCE_RECEIPT_TIMEOUT, do_get_action },
|
|
||||||
{ "LOG_SYNC_INTERVAL", TLV_LOG_SYNC_INTERVAL, do_get_action },
|
|
||||||
{ "VERSION_NUMBER", TLV_VERSION_NUMBER, do_get_action },
|
|
||||||
{ "ENABLE_PORT", TLV_ENABLE_PORT, not_supported },
|
|
||||||
{ "DISABLE_PORT", TLV_DISABLE_PORT, not_supported },
|
|
||||||
{ "UNICAST_NEGOTIATION_ENABLE", TLV_UNICAST_NEGOTIATION_ENABLE, not_supported },
|
|
||||||
{ "UNICAST_MASTER_TABLE", TLV_UNICAST_MASTER_TABLE, not_supported },
|
|
||||||
{ "UNICAST_MASTER_MAX_TABLE_SIZE", TLV_UNICAST_MASTER_MAX_TABLE_SIZE, not_supported },
|
|
||||||
{ "ACCEPTABLE_MASTER_TABLE_ENABLED", TLV_ACCEPTABLE_MASTER_TABLE_ENABLED, not_supported },
|
|
||||||
{ "ALTERNATE_MASTER", TLV_ALTERNATE_MASTER, not_supported },
|
|
||||||
{ "TRANSPARENT_CLOCK_PORT_DATA_SET", TLV_TRANSPARENT_CLOCK_PORT_DATA_SET, not_supported },
|
|
||||||
{ "DELAY_MECHANISM", TLV_DELAY_MECHANISM, do_get_action },
|
|
||||||
{ "LOG_MIN_PDELAY_REQ_INTERVAL", TLV_LOG_MIN_PDELAY_REQ_INTERVAL, do_get_action },
|
|
||||||
{ "PORT_DATA_SET_NP", TLV_PORT_DATA_SET_NP, do_set_action },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *action_string[] = {
|
|
||||||
"GET",
|
|
||||||
"SET",
|
|
||||||
"RESPONSE",
|
|
||||||
"COMMAND",
|
|
||||||
"ACKNOWLEDGE",
|
|
||||||
};
|
|
||||||
|
|
||||||
#define IFMT "\n\t\t"
|
#define IFMT "\n\t\t"
|
||||||
|
|
||||||
static char *text2str(struct PTPText *text)
|
static char *text2str(struct PTPText *text)
|
||||||
|
@ -159,7 +79,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
|
||||||
}
|
}
|
||||||
fprintf(fp, "\t%s seq %hu %s ",
|
fprintf(fp, "\t%s seq %hu %s ",
|
||||||
pid2str(&msg->header.sourcePortIdentity),
|
pid2str(&msg->header.sourcePortIdentity),
|
||||||
msg->header.sequenceId, action_string[action]);
|
msg->header.sequenceId, pmc_action_string(action));
|
||||||
if (msg->tlv_count != 1) {
|
if (msg->tlv_count != 1) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -438,221 +358,6 @@ out:
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_get_action(int action, int index, char *str)
|
|
||||||
{
|
|
||||||
if (action == GET)
|
|
||||||
pmc_send_get_action(pmc, idtab[index].code);
|
|
||||||
else
|
|
||||||
fprintf(stderr, "%s only allows GET\n", idtab[index].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_set_action(int action, int index, char *str)
|
|
||||||
{
|
|
||||||
struct grandmaster_settings_np gsn;
|
|
||||||
struct management_tlv_datum mtd;
|
|
||||||
struct port_ds_np pnp;
|
|
||||||
int cnt, code = idtab[index].code;
|
|
||||||
int leap_61, leap_59, utc_off_valid;
|
|
||||||
int ptp_timescale, time_traceable, freq_traceable;
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case GET:
|
|
||||||
pmc_send_get_action(pmc, code);
|
|
||||||
return;
|
|
||||||
case SET:
|
|
||||||
break;
|
|
||||||
case RESPONSE:
|
|
||||||
case COMMAND:
|
|
||||||
case ACKNOWLEDGE:
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "%s only allows GET or SET\n",
|
|
||||||
idtab[index].name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (code) {
|
|
||||||
case TLV_PRIORITY1:
|
|
||||||
case TLV_PRIORITY2:
|
|
||||||
cnt = sscanf(str, " %*s %*s %hhu", &mtd.val);
|
|
||||||
if (cnt != 1) {
|
|
||||||
fprintf(stderr, "%s SET needs 1 value\n",
|
|
||||||
idtab[index].name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pmc_send_set_action(pmc, code, &mtd, sizeof(mtd));
|
|
||||||
break;
|
|
||||||
case TLV_GRANDMASTER_SETTINGS_NP:
|
|
||||||
cnt = sscanf(str, " %*s %*s "
|
|
||||||
"clockClass %hhu "
|
|
||||||
"clockAccuracy %hhx "
|
|
||||||
"offsetScaledLogVariance %hx "
|
|
||||||
"currentUtcOffset %hd "
|
|
||||||
"leap61 %d "
|
|
||||||
"leap59 %d "
|
|
||||||
"currentUtcOffsetValid %d "
|
|
||||||
"ptpTimescale %d "
|
|
||||||
"timeTraceable %d "
|
|
||||||
"frequencyTraceable %d "
|
|
||||||
"timeSource %hhx ",
|
|
||||||
&gsn.clockQuality.clockClass,
|
|
||||||
&gsn.clockQuality.clockAccuracy,
|
|
||||||
&gsn.clockQuality.offsetScaledLogVariance,
|
|
||||||
&gsn.utc_offset,
|
|
||||||
&leap_61,
|
|
||||||
&leap_59,
|
|
||||||
&utc_off_valid,
|
|
||||||
&ptp_timescale,
|
|
||||||
&time_traceable,
|
|
||||||
&freq_traceable,
|
|
||||||
&gsn.time_source);
|
|
||||||
if (cnt != 11) {
|
|
||||||
fprintf(stderr, "%s SET needs 11 values\n",
|
|
||||||
idtab[index].name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gsn.time_flags = 0;
|
|
||||||
if (leap_61)
|
|
||||||
gsn.time_flags |= LEAP_61;
|
|
||||||
if (leap_59)
|
|
||||||
gsn.time_flags |= LEAP_59;
|
|
||||||
if (utc_off_valid)
|
|
||||||
gsn.time_flags |= UTC_OFF_VALID;
|
|
||||||
if (ptp_timescale)
|
|
||||||
gsn.time_flags |= PTP_TIMESCALE;
|
|
||||||
if (time_traceable)
|
|
||||||
gsn.time_flags |= TIME_TRACEABLE;
|
|
||||||
if (freq_traceable)
|
|
||||||
gsn.time_flags |= FREQ_TRACEABLE;
|
|
||||||
pmc_send_set_action(pmc, code, &gsn, sizeof(gsn));
|
|
||||||
break;
|
|
||||||
case TLV_PORT_DATA_SET_NP:
|
|
||||||
cnt = sscanf(str, " %*s %*s "
|
|
||||||
"neighborPropDelayThresh %u "
|
|
||||||
"asCapable %d ",
|
|
||||||
&pnp.neighborPropDelayThresh,
|
|
||||||
&pnp.asCapable);
|
|
||||||
if (cnt != 2) {
|
|
||||||
fprintf(stderr, "%s SET needs 2 values\n",
|
|
||||||
idtab[index].name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pmc_send_set_action(pmc, code, &pnp, sizeof(pnp));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void not_supported(int action, int index, char *str)
|
|
||||||
{
|
|
||||||
fprintf(stdout, "sorry, %s not supported yet\n", idtab[index].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void null_management(int action, int index, char *str)
|
|
||||||
{
|
|
||||||
if (action == GET)
|
|
||||||
pmc_send_get_action(pmc, idtab[index].code);
|
|
||||||
else
|
|
||||||
puts("non-get actions still todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_action(char *s)
|
|
||||||
{
|
|
||||||
int len = strlen(s);
|
|
||||||
if (0 == strncasecmp(s, "GET", len))
|
|
||||||
return GET;
|
|
||||||
else if (0 == strncasecmp(s, "SET", len))
|
|
||||||
return SET;
|
|
||||||
else if (0 == strncasecmp(s, "CMD", len))
|
|
||||||
return COMMAND;
|
|
||||||
else if (0 == strncasecmp(s, "COMMAND", len))
|
|
||||||
return COMMAND;
|
|
||||||
return BAD_ACTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_id(char *s)
|
|
||||||
{
|
|
||||||
int i, index = BAD_ID, len = strlen(s);
|
|
||||||
/* check for exact match */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(idtab); i++) {
|
|
||||||
if (strcasecmp(s, idtab[i].name) == 0) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* look for a unique prefix match */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(idtab); i++) {
|
|
||||||
if (0 == strncasecmp(s, idtab[i].name, len)) {
|
|
||||||
if (index == BAD_ID)
|
|
||||||
index = i;
|
|
||||||
else
|
|
||||||
return AMBIGUOUS_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_target(const char *str)
|
|
||||||
{
|
|
||||||
struct PortIdentity pid;
|
|
||||||
|
|
||||||
if (str[0] == '*') {
|
|
||||||
memset(&pid, 0xff, sizeof(pid));
|
|
||||||
} else if (str2pid(str, &pid)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pmc_target(pmc, &pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_help(FILE *fp)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
for (i = 0; i < ARRAY_SIZE(idtab); i++) {
|
|
||||||
if (idtab[i].func != not_supported)
|
|
||||||
fprintf(fp, "\t[action] %s\n", idtab[i].name);
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
fprintf(fp, "\tThe [action] can be GET, SET, CMD, or COMMAND\n");
|
|
||||||
fprintf(fp, "\tCommands are case insensitive and may be abbreviated.\n");
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
fprintf(fp, "\tTARGET [portIdentity]\n");
|
|
||||||
fprintf(fp, "\tTARGET *\n");
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_command(char *str)
|
|
||||||
{
|
|
||||||
int action, id;
|
|
||||||
char action_str[10+1] = {0}, id_str[64+1] = {0};
|
|
||||||
|
|
||||||
if (0 == strncasecmp(str, "HELP", strlen(str))) {
|
|
||||||
print_help(stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (2 != sscanf(str, " %10s %64s", action_str, id_str))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (0 == strncasecmp(action_str, "TARGET", strlen(action_str)))
|
|
||||||
return parse_target(id_str);
|
|
||||||
|
|
||||||
action = parse_action(action_str);
|
|
||||||
id = parse_id(id_str);
|
|
||||||
|
|
||||||
if (action == BAD_ACTION || id == BAD_ID)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (id == AMBIGUOUS_ID) {
|
|
||||||
fprintf(stdout, "id %s is too ambiguous\n", id_str);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "sending: %s %s\n",
|
|
||||||
action_string[action], idtab[id].name);
|
|
||||||
|
|
||||||
idtab[id].func(action, id, str);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(char *progname)
|
static void usage(char *progname)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -881,7 +586,7 @@ int main(int argc, char *argv[])
|
||||||
command = line;
|
command = line;
|
||||||
}
|
}
|
||||||
if (pollfd[1].revents & POLLOUT) {
|
if (pollfd[1].revents & POLLOUT) {
|
||||||
if (do_command(command)) {
|
if (pmc_do_command(pmc, command)) {
|
||||||
fprintf(stderr, "bad command: %s\n", command);
|
fprintf(stderr, "bad command: %s\n", command);
|
||||||
}
|
}
|
||||||
command = NULL;
|
command = NULL;
|
||||||
|
|
294
pmc_common.c
294
pmc_common.c
|
@ -48,6 +48,260 @@
|
||||||
/* Includes one extra byte to make length even. */
|
/* Includes one extra byte to make length even. */
|
||||||
#define EMPTY_PTP_TEXT 2
|
#define EMPTY_PTP_TEXT 2
|
||||||
|
|
||||||
|
static void do_get_action(struct pmc *pmc, int action, int index, char *str);
|
||||||
|
static void do_set_action(struct pmc *pmc, int action, int index, char *str);
|
||||||
|
static void not_supported(struct pmc *pmc, int action, int index, char *str);
|
||||||
|
static void null_management(struct pmc *pmc, int action, int index, char *str);
|
||||||
|
|
||||||
|
static const char *action_string[] = {
|
||||||
|
"GET",
|
||||||
|
"SET",
|
||||||
|
"RESPONSE",
|
||||||
|
"COMMAND",
|
||||||
|
"ACKNOWLEDGE",
|
||||||
|
};
|
||||||
|
|
||||||
|
struct management_id {
|
||||||
|
char name[64];
|
||||||
|
int code;
|
||||||
|
void (*func)(struct pmc *pmc, int action, int index, char *str);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct management_id idtab[] = {
|
||||||
|
/* Clock management ID values */
|
||||||
|
{ "USER_DESCRIPTION", TLV_USER_DESCRIPTION, do_get_action },
|
||||||
|
{ "SAVE_IN_NON_VOLATILE_STORAGE", TLV_SAVE_IN_NON_VOLATILE_STORAGE, not_supported },
|
||||||
|
{ "RESET_NON_VOLATILE_STORAGE", TLV_RESET_NON_VOLATILE_STORAGE, not_supported },
|
||||||
|
{ "INITIALIZE", TLV_INITIALIZE, not_supported },
|
||||||
|
{ "FAULT_LOG", TLV_FAULT_LOG, not_supported },
|
||||||
|
{ "FAULT_LOG_RESET", TLV_FAULT_LOG_RESET, not_supported },
|
||||||
|
{ "DEFAULT_DATA_SET", TLV_DEFAULT_DATA_SET, do_get_action },
|
||||||
|
{ "CURRENT_DATA_SET", TLV_CURRENT_DATA_SET, do_get_action },
|
||||||
|
{ "PARENT_DATA_SET", TLV_PARENT_DATA_SET, do_get_action },
|
||||||
|
{ "TIME_PROPERTIES_DATA_SET", TLV_TIME_PROPERTIES_DATA_SET, do_get_action },
|
||||||
|
{ "PRIORITY1", TLV_PRIORITY1, do_set_action },
|
||||||
|
{ "PRIORITY2", TLV_PRIORITY2, do_set_action },
|
||||||
|
{ "DOMAIN", TLV_DOMAIN, do_get_action },
|
||||||
|
{ "SLAVE_ONLY", TLV_SLAVE_ONLY, do_get_action },
|
||||||
|
{ "TIME", TLV_TIME, not_supported },
|
||||||
|
{ "CLOCK_ACCURACY", TLV_CLOCK_ACCURACY, do_get_action },
|
||||||
|
{ "UTC_PROPERTIES", TLV_UTC_PROPERTIES, not_supported },
|
||||||
|
{ "TRACEABILITY_PROPERTIES", TLV_TRACEABILITY_PROPERTIES, do_get_action },
|
||||||
|
{ "TIMESCALE_PROPERTIES", TLV_TIMESCALE_PROPERTIES, do_get_action },
|
||||||
|
{ "PATH_TRACE_LIST", TLV_PATH_TRACE_LIST, not_supported },
|
||||||
|
{ "PATH_TRACE_ENABLE", TLV_PATH_TRACE_ENABLE, not_supported },
|
||||||
|
{ "GRANDMASTER_CLUSTER_TABLE", TLV_GRANDMASTER_CLUSTER_TABLE, not_supported },
|
||||||
|
{ "ACCEPTABLE_MASTER_TABLE", TLV_ACCEPTABLE_MASTER_TABLE, not_supported },
|
||||||
|
{ "ACCEPTABLE_MASTER_MAX_TABLE_SIZE", TLV_ACCEPTABLE_MASTER_MAX_TABLE_SIZE, not_supported },
|
||||||
|
{ "ALTERNATE_TIME_OFFSET_ENABLE", TLV_ALTERNATE_TIME_OFFSET_ENABLE, not_supported },
|
||||||
|
{ "ALTERNATE_TIME_OFFSET_NAME", TLV_ALTERNATE_TIME_OFFSET_NAME, not_supported },
|
||||||
|
{ "ALTERNATE_TIME_OFFSET_MAX_KEY", TLV_ALTERNATE_TIME_OFFSET_MAX_KEY, not_supported },
|
||||||
|
{ "ALTERNATE_TIME_OFFSET_PROPERTIES", TLV_ALTERNATE_TIME_OFFSET_PROPERTIES, not_supported },
|
||||||
|
{ "TRANSPARENT_CLOCK_DEFAULT_DATA_SET", TLV_TRANSPARENT_CLOCK_DEFAULT_DATA_SET, not_supported },
|
||||||
|
{ "PRIMARY_DOMAIN", TLV_PRIMARY_DOMAIN, not_supported },
|
||||||
|
{ "TIME_STATUS_NP", TLV_TIME_STATUS_NP, do_get_action },
|
||||||
|
{ "GRANDMASTER_SETTINGS_NP", TLV_GRANDMASTER_SETTINGS_NP, do_set_action },
|
||||||
|
/* Port management ID values */
|
||||||
|
{ "NULL_MANAGEMENT", TLV_NULL_MANAGEMENT, null_management },
|
||||||
|
{ "CLOCK_DESCRIPTION", TLV_CLOCK_DESCRIPTION, do_get_action },
|
||||||
|
{ "PORT_DATA_SET", TLV_PORT_DATA_SET, do_get_action },
|
||||||
|
{ "LOG_ANNOUNCE_INTERVAL", TLV_LOG_ANNOUNCE_INTERVAL, do_get_action },
|
||||||
|
{ "ANNOUNCE_RECEIPT_TIMEOUT", TLV_ANNOUNCE_RECEIPT_TIMEOUT, do_get_action },
|
||||||
|
{ "LOG_SYNC_INTERVAL", TLV_LOG_SYNC_INTERVAL, do_get_action },
|
||||||
|
{ "VERSION_NUMBER", TLV_VERSION_NUMBER, do_get_action },
|
||||||
|
{ "ENABLE_PORT", TLV_ENABLE_PORT, not_supported },
|
||||||
|
{ "DISABLE_PORT", TLV_DISABLE_PORT, not_supported },
|
||||||
|
{ "UNICAST_NEGOTIATION_ENABLE", TLV_UNICAST_NEGOTIATION_ENABLE, not_supported },
|
||||||
|
{ "UNICAST_MASTER_TABLE", TLV_UNICAST_MASTER_TABLE, not_supported },
|
||||||
|
{ "UNICAST_MASTER_MAX_TABLE_SIZE", TLV_UNICAST_MASTER_MAX_TABLE_SIZE, not_supported },
|
||||||
|
{ "ACCEPTABLE_MASTER_TABLE_ENABLED", TLV_ACCEPTABLE_MASTER_TABLE_ENABLED, not_supported },
|
||||||
|
{ "ALTERNATE_MASTER", TLV_ALTERNATE_MASTER, not_supported },
|
||||||
|
{ "TRANSPARENT_CLOCK_PORT_DATA_SET", TLV_TRANSPARENT_CLOCK_PORT_DATA_SET, not_supported },
|
||||||
|
{ "DELAY_MECHANISM", TLV_DELAY_MECHANISM, do_get_action },
|
||||||
|
{ "LOG_MIN_PDELAY_REQ_INTERVAL", TLV_LOG_MIN_PDELAY_REQ_INTERVAL, do_get_action },
|
||||||
|
{ "PORT_DATA_SET_NP", TLV_PORT_DATA_SET_NP, do_set_action },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void do_get_action(struct pmc *pmc, int action, int index, char *str)
|
||||||
|
{
|
||||||
|
if (action == GET)
|
||||||
|
pmc_send_get_action(pmc, idtab[index].code);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s only allows GET\n", idtab[index].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_set_action(struct pmc *pmc, int action, int index, char *str)
|
||||||
|
{
|
||||||
|
struct grandmaster_settings_np gsn;
|
||||||
|
struct management_tlv_datum mtd;
|
||||||
|
struct port_ds_np pnp;
|
||||||
|
int cnt, code = idtab[index].code;
|
||||||
|
int leap_61, leap_59, utc_off_valid;
|
||||||
|
int ptp_timescale, time_traceable, freq_traceable;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case GET:
|
||||||
|
pmc_send_get_action(pmc, code);
|
||||||
|
return;
|
||||||
|
case SET:
|
||||||
|
break;
|
||||||
|
case RESPONSE:
|
||||||
|
case COMMAND:
|
||||||
|
case ACKNOWLEDGE:
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s only allows GET or SET\n",
|
||||||
|
idtab[index].name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (code) {
|
||||||
|
case TLV_PRIORITY1:
|
||||||
|
case TLV_PRIORITY2:
|
||||||
|
cnt = sscanf(str, " %*s %*s %hhu", &mtd.val);
|
||||||
|
if (cnt != 1) {
|
||||||
|
fprintf(stderr, "%s SET needs 1 value\n",
|
||||||
|
idtab[index].name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pmc_send_set_action(pmc, code, &mtd, sizeof(mtd));
|
||||||
|
break;
|
||||||
|
case TLV_GRANDMASTER_SETTINGS_NP:
|
||||||
|
cnt = sscanf(str, " %*s %*s "
|
||||||
|
"clockClass %hhu "
|
||||||
|
"clockAccuracy %hhx "
|
||||||
|
"offsetScaledLogVariance %hx "
|
||||||
|
"currentUtcOffset %hd "
|
||||||
|
"leap61 %d "
|
||||||
|
"leap59 %d "
|
||||||
|
"currentUtcOffsetValid %d "
|
||||||
|
"ptpTimescale %d "
|
||||||
|
"timeTraceable %d "
|
||||||
|
"frequencyTraceable %d "
|
||||||
|
"timeSource %hhx ",
|
||||||
|
&gsn.clockQuality.clockClass,
|
||||||
|
&gsn.clockQuality.clockAccuracy,
|
||||||
|
&gsn.clockQuality.offsetScaledLogVariance,
|
||||||
|
&gsn.utc_offset,
|
||||||
|
&leap_61,
|
||||||
|
&leap_59,
|
||||||
|
&utc_off_valid,
|
||||||
|
&ptp_timescale,
|
||||||
|
&time_traceable,
|
||||||
|
&freq_traceable,
|
||||||
|
&gsn.time_source);
|
||||||
|
if (cnt != 11) {
|
||||||
|
fprintf(stderr, "%s SET needs 11 values\n",
|
||||||
|
idtab[index].name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gsn.time_flags = 0;
|
||||||
|
if (leap_61)
|
||||||
|
gsn.time_flags |= LEAP_61;
|
||||||
|
if (leap_59)
|
||||||
|
gsn.time_flags |= LEAP_59;
|
||||||
|
if (utc_off_valid)
|
||||||
|
gsn.time_flags |= UTC_OFF_VALID;
|
||||||
|
if (ptp_timescale)
|
||||||
|
gsn.time_flags |= PTP_TIMESCALE;
|
||||||
|
if (time_traceable)
|
||||||
|
gsn.time_flags |= TIME_TRACEABLE;
|
||||||
|
if (freq_traceable)
|
||||||
|
gsn.time_flags |= FREQ_TRACEABLE;
|
||||||
|
pmc_send_set_action(pmc, code, &gsn, sizeof(gsn));
|
||||||
|
break;
|
||||||
|
case TLV_PORT_DATA_SET_NP:
|
||||||
|
cnt = sscanf(str, " %*s %*s "
|
||||||
|
"neighborPropDelayThresh %u "
|
||||||
|
"asCapable %d ",
|
||||||
|
&pnp.neighborPropDelayThresh,
|
||||||
|
&pnp.asCapable);
|
||||||
|
if (cnt != 2) {
|
||||||
|
fprintf(stderr, "%s SET needs 2 values\n",
|
||||||
|
idtab[index].name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pmc_send_set_action(pmc, code, &pnp, sizeof(pnp));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void not_supported(struct pmc *pmc, int action, int index, char *str)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "sorry, %s not supported yet\n", idtab[index].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void null_management(struct pmc *pmc, int action, int index, char *str)
|
||||||
|
{
|
||||||
|
if (action == GET)
|
||||||
|
pmc_send_get_action(pmc, idtab[index].code);
|
||||||
|
else
|
||||||
|
puts("non-get actions still todo");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_action(char *s)
|
||||||
|
{
|
||||||
|
int len = strlen(s);
|
||||||
|
if (0 == strncasecmp(s, "GET", len))
|
||||||
|
return GET;
|
||||||
|
else if (0 == strncasecmp(s, "SET", len))
|
||||||
|
return SET;
|
||||||
|
else if (0 == strncasecmp(s, "CMD", len))
|
||||||
|
return COMMAND;
|
||||||
|
else if (0 == strncasecmp(s, "COMMAND", len))
|
||||||
|
return COMMAND;
|
||||||
|
return BAD_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_id(char *s)
|
||||||
|
{
|
||||||
|
int i, index = BAD_ID, len = strlen(s);
|
||||||
|
/* check for exact match */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(idtab); i++) {
|
||||||
|
if (strcasecmp(s, idtab[i].name) == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* look for a unique prefix match */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(idtab); i++) {
|
||||||
|
if (0 == strncasecmp(s, idtab[i].name, len)) {
|
||||||
|
if (index == BAD_ID)
|
||||||
|
index = i;
|
||||||
|
else
|
||||||
|
return AMBIGUOUS_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_target(struct pmc *pmc, const char *str)
|
||||||
|
{
|
||||||
|
struct PortIdentity pid;
|
||||||
|
|
||||||
|
if (str[0] == '*') {
|
||||||
|
memset(&pid, 0xff, sizeof(pid));
|
||||||
|
} else if (str2pid(str, &pid)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pmc_target(pmc, &pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_help(FILE *fp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
for (i = 0; i < ARRAY_SIZE(idtab); i++) {
|
||||||
|
if (idtab[i].func != not_supported)
|
||||||
|
fprintf(fp, "\t[action] %s\n", idtab[i].name);
|
||||||
|
}
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
fprintf(fp, "\tThe [action] can be GET, SET, CMD, or COMMAND\n");
|
||||||
|
fprintf(fp, "\tCommands are case insensitive and may be abbreviated.\n");
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
fprintf(fp, "\tTARGET [portIdentity]\n");
|
||||||
|
fprintf(fp, "\tTARGET *\n");
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct pmc {
|
struct pmc {
|
||||||
UInteger16 sequence_id;
|
UInteger16 sequence_id;
|
||||||
UInteger8 boundary_hops;
|
UInteger8 boundary_hops;
|
||||||
|
@ -359,3 +613,43 @@ void pmc_target_all(struct pmc *pmc)
|
||||||
{
|
{
|
||||||
memset(&pmc->target, 0xff, sizeof(pmc->target));
|
memset(&pmc->target, 0xff, sizeof(pmc->target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *pmc_action_string(int action)
|
||||||
|
{
|
||||||
|
return action_string[action];
|
||||||
|
}
|
||||||
|
|
||||||
|
int pmc_do_command(struct pmc *pmc, char *str)
|
||||||
|
{
|
||||||
|
int action, id;
|
||||||
|
char action_str[10+1] = {0}, id_str[64+1] = {0};
|
||||||
|
|
||||||
|
if (0 == strncasecmp(str, "HELP", strlen(str))) {
|
||||||
|
print_help(stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (2 != sscanf(str, " %10s %64s", action_str, id_str))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (0 == strncasecmp(action_str, "TARGET", strlen(action_str)))
|
||||||
|
return parse_target(pmc, id_str);
|
||||||
|
|
||||||
|
action = parse_action(action_str);
|
||||||
|
id = parse_id(id_str);
|
||||||
|
|
||||||
|
if (action == BAD_ACTION || id == BAD_ID)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (id == AMBIGUOUS_ID) {
|
||||||
|
fprintf(stdout, "id %s is too ambiguous\n", id_str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "sending: %s %s\n",
|
||||||
|
action_string[action], idtab[id].name);
|
||||||
|
|
||||||
|
idtab[id].func(pmc, action, id, str);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,12 @@
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
|
#define BAD_ACTION -1
|
||||||
|
#define BAD_ID -1
|
||||||
|
#define AMBIGUOUS_ID -2
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
#define P41 ((double)(1ULL << 41))
|
||||||
|
|
||||||
struct pmc;
|
struct pmc;
|
||||||
|
|
||||||
struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type,
|
struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type,
|
||||||
|
@ -46,4 +52,7 @@ int pmc_target(struct pmc *pmc, struct PortIdentity *pid);
|
||||||
void pmc_target_port(struct pmc *pmc, UInteger16 portNumber);
|
void pmc_target_port(struct pmc *pmc, UInteger16 portNumber);
|
||||||
void pmc_target_all(struct pmc *pmc);
|
void pmc_target_all(struct pmc *pmc);
|
||||||
|
|
||||||
|
const char *pmc_action_string(int action);
|
||||||
|
int pmc_do_command(struct pmc *pmc, char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue