summaryrefslogtreecommitdiffstats
path: root/netlink/settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'netlink/settings.c')
-rw-r--r--netlink/settings.c269
1 files changed, 168 insertions, 101 deletions
diff --git a/netlink/settings.c b/netlink/settings.c
index a506618..9dd688b 100644
--- a/netlink/settings.c
+++ b/netlink/settings.c
@@ -11,6 +11,8 @@
#include "../internal.h"
#include "../common.h"
+#include "json_print.h"
+#include "json_writer.h"
#include "netlink.h"
#include "strset.h"
#include "bitset.h"
@@ -192,15 +194,21 @@ static bool lm_class_match(unsigned int mode, enum link_mode_class class)
}
static void print_enum(const char *const *info, unsigned int n_info,
- unsigned int val, const char *label)
+ unsigned int val, const char *label, const char *json_key)
{
- if (val >= n_info || !info[val])
- printf("\t%s: Unknown! (%d)\n", label, val);
- else
- printf("\t%s: %s\n", label, info[val]);
+ if (val >= n_info || !info[val]) {
+ if (!is_json_context())
+ printf("\t%s: Unknown! (%d)\n", label, val);
+ } else {
+ if (!is_json_context())
+ printf("\t%s: %s\n", label, info[val]);
+ else
+ print_string(PRINT_JSON, json_key, "%s", info[val]);
+ }
}
-static int dump_pause(const struct nlattr *attr, bool mask, const char *label)
+static int dump_pause(const struct nlattr *attr, bool mask, const char *label,
+ const char *label_json)
{
bool pause, asym;
int ret = 0;
@@ -213,11 +221,13 @@ static int dump_pause(const struct nlattr *attr, bool mask, const char *label)
if (ret < 0)
goto err;
- printf("\t%s", label);
+ if (!is_json_context())
+ printf("\t%s", label);
if (pause)
- printf("%s\n", asym ? "Symmetric Receive-only" : "Symmetric");
+ print_string(PRINT_ANY, label_json, "%s\n",
+ asym ? "Symmetric Receive-only" : "Symmetric");
else
- printf("%s\n", asym ? "Transmit-only" : "No");
+ print_string(PRINT_ANY, label_json, "%s\n", asym ? "Transmit-only" : "No");
return 0;
err:
@@ -229,13 +239,14 @@ static void print_banner(struct nl_context *nlctx)
{
if (nlctx->no_banner)
return;
- printf("Settings for %s:\n", nlctx->devname);
+ print_string(PRINT_ANY, "ifname", "Settings for %s:\n", nlctx->devname);
nlctx->no_banner = true;
}
int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset,
bool mask, unsigned int class, const char *before,
- const char *between, const char *after, const char *if_none)
+ const char *between, const char *after, const char *if_none,
+ const char *json_key)
{
const struct nlattr *bitset_tb[ETHTOOL_A_BITSET_MAX + 1] = {};
DECLARE_ATTR_TB_INFO(bitset_tb);
@@ -260,6 +271,7 @@ int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset,
bits = bitset_tb[ETHTOOL_A_BITSET_BITS];
+ open_json_array(json_key, "");
if (!bits) {
const struct stringset *lm_strings;
unsigned int count;
@@ -280,7 +292,9 @@ int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset,
if (mnl_attr_get_payload_len(bits) / 4 < (count + 31) / 32)
goto err_nonl;
- printf("\t%s", before);
+ if (!is_json_context())
+ printf("\t%s", before);
+
for (idx = 0; idx < count; idx++) {
const uint32_t *raw_data = mnl_attr_get_payload(bits);
char buff[14];
@@ -298,21 +312,27 @@ int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset,
first = false;
/* ugly hack to preserve old output format */
if (class == LM_CLASS_REAL && (idx == prev + 1) &&
- prev < link_modes_count &&
- link_modes[prev].class == LM_CLASS_REAL &&
- link_modes[prev].duplex == DUPLEX_HALF)
- putchar(' ');
- else if (between)
- printf("\t%s", between);
+ prev < link_modes_count &&
+ link_modes[prev].class == LM_CLASS_REAL &&
+ link_modes[prev].duplex == DUPLEX_HALF) {
+ if (!is_json_context())
+ putchar(' ');
+ } else if (between) {
+ if (!is_json_context())
+ printf("\t%s", between);
+ }
else
- printf("\n\t%*s", before_len, "");
- printf("%s", name);
+ if (!is_json_context())
+ printf("\n\t%*s", before_len, "");
+ print_string(PRINT_ANY, NULL, "%s", name);
prev = idx;
}
goto after;
}
- printf("\t%s", before);
+ if (!is_json_context())
+ printf("\t%s", before);
+
mnl_attr_for_each_nested(bit, bits) {
const struct nlattr *tb[ETHTOOL_A_BITSET_BIT_MAX + 1] = {};
DECLARE_ATTR_TB_INFO(tb);
@@ -342,27 +362,31 @@ int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset,
if ((class == LM_CLASS_REAL) && (idx == prev + 1) &&
(prev < link_modes_count) &&
(link_modes[prev].class == LM_CLASS_REAL) &&
- (link_modes[prev].duplex == DUPLEX_HALF))
- putchar(' ');
- else if (between)
- printf("\t%s", between);
+ (link_modes[prev].duplex == DUPLEX_HALF)) {
+ if (!is_json_context())
+ putchar(' ');
+ } else if (between) {
+ if (!is_json_context())
+ printf("\t%s", between);
+ }
else
- printf("\n\t%*s", before_len, "");
+ if (!is_json_context())
+ printf("\n\t%*s", before_len, "");
}
- printf("%s", name);
+ print_string(PRINT_ANY, NULL, "%s", name);
prev = idx;
}
after:
if (first && if_none)
- printf("%s", if_none);
- printf("%s", after);
-
+ print_string(PRINT_FP, NULL, "%s", if_none);
+ close_json_array(after);
return 0;
err:
putchar('\n');
err_nonl:
fflush(stdout);
fprintf(stderr, "malformed netlink message (link_modes)\n");
+ close_json_array("");
return ret;
}
@@ -373,16 +397,16 @@ static int dump_our_modes(struct nl_context *nlctx, const struct nlattr *attr)
print_banner(nlctx);
ret = dump_link_modes(nlctx, attr, true, LM_CLASS_PORT,
- "Supported ports: [ ", " ", " ]\n", NULL);
+ "Supported ports: [ ", " ", " ]\n", NULL, "supported-ports");
if (ret < 0)
return ret;
ret = dump_link_modes(nlctx, attr, true, LM_CLASS_REAL,
"Supported link modes: ", NULL, "\n",
- "Not reported");
+ "Not reported", "supported-link-modes");
if (ret < 0)
return ret;
- ret = dump_pause(attr, true, "Supported pause frame use: ");
+ ret = dump_pause(attr, true, "Supported pause frame use: ", "supported-pause-frame-use");
if (ret < 0)
return ret;
@@ -390,32 +414,40 @@ static int dump_our_modes(struct nl_context *nlctx, const struct nlattr *attr)
&ret);
if (ret < 0)
return ret;
- printf("\tSupports auto-negotiation: %s\n", autoneg ? "Yes" : "No");
+
+ if (is_json_context())
+ print_bool(PRINT_JSON, "supports-auto-negotiation", NULL, autoneg);
+ else
+ printf("\tSupports auto-negotiation: %s\n", autoneg ? "Yes" : "No");
ret = dump_link_modes(nlctx, attr, true, LM_CLASS_FEC,
"Supported FEC modes: ", " ", "\n",
- "Not reported");
+ "Not reported", "supported-fec-modes");
if (ret < 0)
return ret;
ret = dump_link_modes(nlctx, attr, false, LM_CLASS_REAL,
"Advertised link modes: ", NULL, "\n",
- "Not reported");
+ "Not reported", "advertised-link-modes");
if (ret < 0)
return ret;
- ret = dump_pause(attr, false, "Advertised pause frame use: ");
+ ret = dump_pause(attr, false, "Advertised pause frame use: ", "advertised-pause-frame-use");
if (ret < 0)
return ret;
autoneg = bitset_get_bit(attr, false, ETHTOOL_LINK_MODE_Autoneg_BIT,
&ret);
if (ret < 0)
return ret;
- printf("\tAdvertised auto-negotiation: %s\n", autoneg ? "Yes" : "No");
+
+ if (!is_json_context())
+ printf("\tAdvertised auto-negotiation: %s\n", autoneg ? "Yes" : "No");
+ else
+ print_bool(PRINT_JSON, "advertised-auto-negotiation", NULL, autoneg);
ret = dump_link_modes(nlctx, attr, false, LM_CLASS_FEC,
"Advertised FEC modes: ", " ", "\n",
- "Not reported");
+ "Not reported", "advertised-fec-modes");
return ret;
}
@@ -427,12 +459,13 @@ static int dump_peer_modes(struct nl_context *nlctx, const struct nlattr *attr)
print_banner(nlctx);
ret = dump_link_modes(nlctx, attr, false, LM_CLASS_REAL,
"Link partner advertised link modes: ",
- NULL, "\n", "Not reported");
+ NULL, "\n", "Not reported", "link-partner-advertised-link-modes");
if (ret < 0)
return ret;
ret = dump_pause(attr, false,
- "Link partner advertised pause frame use: ");
+ "Link partner advertised pause frame use: ",
+ "link-partner-advertised-pause-frame-use");
if (ret < 0)
return ret;
@@ -440,12 +473,16 @@ static int dump_peer_modes(struct nl_context *nlctx, const struct nlattr *attr)
ETHTOOL_LINK_MODE_Autoneg_BIT, &ret);
if (ret < 0)
return ret;
- printf("\tLink partner advertised auto-negotiation: %s\n",
- autoneg ? "Yes" : "No");
+
+ if (!is_json_context())
+ print_string(PRINT_FP, NULL, "\tLink partner advertised auto-negotiation: %s\n",
+ autoneg ? "Yes" : "No");
+ else
+ print_bool(PRINT_JSON, "link-partner-advertised-auto-negotiation", NULL, autoneg);
ret = dump_link_modes(nlctx, attr, false, LM_CLASS_FEC,
"Link partner advertised FEC modes: ",
- " ", "\n", "Not reported");
+ " ", "\n", "Not reported", "link-partner-advertised-fec-modes");
return ret;
}
@@ -479,30 +516,36 @@ int linkmodes_reply_cb(const struct nlmsghdr *nlhdr, void *data)
uint32_t val = mnl_attr_get_u32(tb[ETHTOOL_A_LINKMODES_SPEED]);
print_banner(nlctx);
- if (val == 0 || val == (uint16_t)(-1) || val == (uint32_t)(-1))
- printf("\tSpeed: Unknown!\n");
- else
- printf("\tSpeed: %uMb/s\n", val);
+ if (val == 0 || val == (uint16_t)(-1) || val == (uint32_t)(-1)) {
+ if (!is_json_context())
+ printf("\tSpeed: Unknown!\n");
+ } else {
+ print_uint(PRINT_ANY, "speed", "\tSpeed: %uMb/s\n", val);
+ }
}
if (tb[ETHTOOL_A_LINKMODES_LANES]) {
uint32_t val = mnl_attr_get_u32(tb[ETHTOOL_A_LINKMODES_LANES]);
print_banner(nlctx);
- printf("\tLanes: %u\n", val);
+ print_uint(PRINT_ANY, "lanes", "\tLanes: %s\n", val);
}
if (tb[ETHTOOL_A_LINKMODES_DUPLEX]) {
uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKMODES_DUPLEX]);
print_banner(nlctx);
print_enum(names_duplex, ARRAY_SIZE(names_duplex), val,
- "Duplex");
+ "Duplex", "duplex");
}
if (tb[ETHTOOL_A_LINKMODES_AUTONEG]) {
int autoneg = mnl_attr_get_u8(tb[ETHTOOL_A_LINKMODES_AUTONEG]);
print_banner(nlctx);
- printf("\tAuto-negotiation: %s\n",
- (autoneg == AUTONEG_DISABLE) ? "off" : "on");
+ if (!is_json_context())
+ printf("\tAuto-negotiation: %s\n",
+ (autoneg == AUTONEG_DISABLE) ? "off" : "on");
+ else
+ print_bool(PRINT_JSON, "auto-negotiation", NULL,
+ autoneg == AUTONEG_DISABLE);
}
if (tb[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG]) {
uint8_t val;
@@ -512,7 +555,7 @@ int linkmodes_reply_cb(const struct nlmsghdr *nlhdr, void *data)
print_banner(nlctx);
print_enum(names_master_slave_cfg,
ARRAY_SIZE(names_master_slave_cfg), val,
- "master-slave cfg");
+ "master-slave cfg", "master-slave-cfg");
}
if (tb[ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE]) {
uint8_t val;
@@ -521,14 +564,14 @@ int linkmodes_reply_cb(const struct nlmsghdr *nlhdr, void *data)
print_banner(nlctx);
print_enum(names_master_slave_state,
ARRAY_SIZE(names_master_slave_state), val,
- "master-slave status");
+ "master-slave status", "master-slave-status");
}
return MNL_CB_OK;
err:
if (nlctx->is_monitor || nlctx->is_dump)
return MNL_CB_OK;
- fputs("No data available\n", stdout);
+ fputs("No data available\n", stderr);
nlctx->exit_code = 75;
return MNL_CB_ERROR;
}
@@ -554,14 +597,14 @@ int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data)
uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKINFO_PORT]);
print_banner(nlctx);
- print_enum(names_port, ARRAY_SIZE(names_port), val, "Port");
+ print_enum(names_port, ARRAY_SIZE(names_port), val, "Port", "port");
port = val;
}
if (tb[ETHTOOL_A_LINKINFO_PHYADDR]) {
uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKINFO_PHYADDR]);
print_banner(nlctx);
- printf("\tPHYAD: %u\n", val);
+ print_uint(PRINT_ANY, "phyad", "\tPHYAD: %x\n", val);
}
if (tb[ETHTOOL_A_LINKINFO_TRANSCEIVER]) {
uint8_t val;
@@ -569,7 +612,7 @@ int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data)
val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKINFO_TRANSCEIVER]);
print_banner(nlctx);
print_enum(names_transceiver, ARRAY_SIZE(names_transceiver),
- val, "Transceiver");
+ val, "Transceiver", "transceiver");
}
if (tb[ETHTOOL_A_LINKINFO_TP_MDIX] && tb[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] &&
port == PORT_TP) {
@@ -714,9 +757,9 @@ static void linkstate_link_ext_substate_print(const struct nlattr *tb[],
link_ext_substate_str = link_ext_substate_get(link_ext_state_val, link_ext_substate_val);
if (!link_ext_substate_str)
- printf(", %u", link_ext_substate_val);
+ print_uint(PRINT_ANY, NULL, ", %u", link_ext_state_val);
else
- printf(", %s", link_ext_substate_str);
+ print_string(PRINT_ANY, NULL, ", %s", link_ext_substate_str);
}
static void linkstate_link_ext_state_print(const struct nlattr *tb[])
@@ -732,13 +775,14 @@ static void linkstate_link_ext_state_print(const struct nlattr *tb[])
link_ext_state_str = get_enum_string(names_link_ext_state,
ARRAY_SIZE(names_link_ext_state),
link_ext_state_val);
+ open_json_array("link-state", "");
if (!link_ext_state_str)
- printf(" (%u", link_ext_state_val);
+ print_uint(PRINT_ANY, NULL, " (%u", link_ext_state_val);
else
- printf(" (%s", link_ext_state_str);
+ print_string(PRINT_ANY, NULL, " (%s", link_ext_state_str);
linkstate_link_ext_substate_print(tb, link_ext_state_val);
- printf(")");
+ close_json_array(")");
}
int linkstate_reply_cb(const struct nlmsghdr *nlhdr, void *data)
@@ -761,24 +805,29 @@ int linkstate_reply_cb(const struct nlmsghdr *nlhdr, void *data)
uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKSTATE_LINK]);
print_banner(nlctx);
- printf("\tLink detected: %s", val ? "yes" : "no");
+ if (!is_json_context())
+ print_string(PRINT_FP, NULL, "\tLink detected: %s", val ? "yes" : "no");
+ else
+ print_bool(PRINT_JSON, "link-detected", NULL, val);
linkstate_link_ext_state_print(tb);
- printf("\n");
+ if (!is_json_context())
+ printf("\n");
}
if (tb[ETHTOOL_A_LINKSTATE_SQI]) {
uint32_t val = mnl_attr_get_u32(tb[ETHTOOL_A_LINKSTATE_SQI]);
print_banner(nlctx);
- printf("\tSQI: %u", val);
+ print_uint(PRINT_ANY, "sqi", "\tSQI: %u", val);
if (tb[ETHTOOL_A_LINKSTATE_SQI_MAX]) {
uint32_t max;
max = mnl_attr_get_u32(tb[ETHTOOL_A_LINKSTATE_SQI_MAX]);
- printf("/%u\n", max);
+ print_uint(PRINT_ANY, "sqi-max", "/%u\n", max);
} else {
- printf("\n");
+ if (!is_json_context())
+ printf("\n");
}
}
@@ -786,7 +835,7 @@ int linkstate_reply_cb(const struct nlmsghdr *nlhdr, void *data)
uint32_t val;
val = mnl_attr_get_u32(tb[ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT]);
- printf("\tLink Down Events: %u\n", val);
+ print_uint(PRINT_ANY, "link-down-events", "\tLink Down Events: %u\n", val);
}
return MNL_CB_OK;
@@ -856,7 +905,7 @@ void msgmask_cb2(unsigned int idx __maybe_unused, const char *name,
bool val, void *data __maybe_unused)
{
if (val)
- printf(" %s", name);
+ print_string(PRINT_FP, NULL, " %s", name);
}
int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data)
@@ -889,13 +938,16 @@ int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data)
print_banner(nlctx);
walk_bitset(tb[ETHTOOL_A_DEBUG_MSGMASK], NULL, msgmask_cb, &msg_mask);
- printf(" Current message level: 0x%08x (%u)\n"
- " ",
- msg_mask, msg_mask);
+
+ print_uint(PRINT_ANY, "current-message-level",
+ " Current message level: 0x%1$08x (%1$u)\n ",
+ msg_mask);
+
walk_bitset(tb[ETHTOOL_A_DEBUG_MSGMASK], msgmask_strings, msgmask_cb2,
- NULL);
- fputc('\n', stdout);
+ NULL);
+ if (!is_json_context())
+ fputc('\n', stdout);
return MNL_CB_OK;
}
@@ -916,18 +968,26 @@ int plca_cfg_reply_cb(const struct nlmsghdr *nlhdr, void *data)
return MNL_CB_OK;
print_banner(nlctx);
- printf("\tPLCA support: ");
+ if (!is_json_context())
+ printf("\tPLCA support: ");
if (tb[ETHTOOL_A_PLCA_VERSION]) {
uint16_t val = mnl_attr_get_u16(tb[ETHTOOL_A_PLCA_VERSION]);
- printf("OPEN Alliance v%u.%u",
- (unsigned int)((val >> 4) & 0xF),
- (unsigned int)(val & 0xF));
- } else
- printf("non-standard");
+ if (!is_json_context()) {
+ printf("OPEN Alliance v%u.%u\n",
+ (unsigned int)((val >> 4) & 0xF),
+ (unsigned int)(val & 0xF));
+ } else {
+ unsigned int length = snprintf(NULL, 0, "%1$u.%1$u", val);
+ char buff[length];
- printf("\n");
+ snprintf(buff, length, "%u.%u", (unsigned int)((val >> 4) & 0xF),
+ (unsigned int)(val & 0xF));
+ print_string(PRINT_JSON, "open-alliance-v", NULL, buff);
+ }
+ } else
+ print_string(PRINT_ANY, "plca-support", "%s\n", "non-standard");
return MNL_CB_OK;
}
@@ -949,16 +1009,14 @@ int plca_status_reply_cb(const struct nlmsghdr *nlhdr, void *data)
return MNL_CB_OK;
print_banner(nlctx);
- printf("\tPLCA status: ");
-
+ const char *status;
if (tb[ETHTOOL_A_PLCA_STATUS]) {
uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_PLCA_STATUS]);
-
- printf(val ? "up" : "down");
- } else
- printf("unknown");
-
- printf("\n");
+ status = val ? "up" : "down";
+ print_string(PRINT_ANY, "plca-status", "PLCA status: %s", status);
+ } else {
+ print_string(PRINT_FP, NULL, "PLCA status: %s", "unknown");
+ }
return MNL_CB_OK;
}
@@ -984,7 +1042,10 @@ static int gset_request(struct cmd_context *ctx, uint8_t msg_type,
int nl_gset(struct cmd_context *ctx)
{
- int ret;
+ int ret = 0;
+
+ new_json_obj(ctx->json);
+ open_json_object(NULL);
/* Check for the base set of commands */
if (netlink_cmd_check(ctx, ETHTOOL_MSG_LINKMODES_GET, true) ||
@@ -999,44 +1060,50 @@ int nl_gset(struct cmd_context *ctx)
ret = gset_request(ctx, ETHTOOL_MSG_LINKMODES_GET,
ETHTOOL_A_LINKMODES_HEADER, linkmodes_reply_cb);
if (ret == -ENODEV)
- return ret;
+ goto out;
ret = gset_request(ctx, ETHTOOL_MSG_LINKINFO_GET,
ETHTOOL_A_LINKINFO_HEADER, linkinfo_reply_cb);
if (ret == -ENODEV)
- return ret;
+ goto out;
ret = gset_request(ctx, ETHTOOL_MSG_WOL_GET, ETHTOOL_A_WOL_HEADER,
wol_reply_cb);
if (ret == -ENODEV)
- return ret;
+ goto out;
ret = gset_request(ctx, ETHTOOL_MSG_PLCA_GET_CFG,
ETHTOOL_A_PLCA_HEADER, plca_cfg_reply_cb);
if (ret == -ENODEV)
- return ret;
+ goto out;
ret = gset_request(ctx, ETHTOOL_MSG_DEBUG_GET, ETHTOOL_A_DEBUG_HEADER,
debug_reply_cb);
if (ret == -ENODEV)
- return ret;
+ goto out;
ret = gset_request(ctx, ETHTOOL_MSG_LINKSTATE_GET,
ETHTOOL_A_LINKSTATE_HEADER, linkstate_reply_cb);
if (ret == -ENODEV)
- return ret;
+ goto out;
ret = gset_request(ctx, ETHTOOL_MSG_PLCA_GET_STATUS,
ETHTOOL_A_PLCA_HEADER, plca_status_reply_cb);
if (ret == -ENODEV)
- return ret;
+ goto out;
if (!ctx->nlctx->no_banner) {
- printf("No data available\n");
- return 75;
+ print_string(PRINT_FP, NULL, "%s", "No data available\n");
+ ret = 75;
+ goto out;
}
- return 0;
+ ret = 0;
+
+out:
+ close_json_object();
+ delete_json_obj();
+ return ret;
}
/* SET_SETTINGS */