Merge branch 'can-tdc-plus-cleanups' into next
Vincent Mailhol says: ==================== The main purpose is to add commandline support for Transmitter Delay Compensation (TDC) in iproute. Other issues found during the development of this feature also get addressed. This patch series contains four patches which respectively: 1. Correct the bittiming ranges in the print_usage function and add the units to give more clarity: some parameters are in milliseconds, some in nano seconds, some in time quantum and the newly TDC parameters introduced in this series would be in clock period. 2. Do some code refactoring on function print_ctrlmode(). 3. factorize the many print_*(PRINT_JSON, ...) and fprintf occurrences in a single print_*(PRINT_ANY, ...) call and fix the signedness while doing that. 4. report the value of the bitrate prescalers (brp and dbrp). 5. adds command line support for the TDC in iproute and goes together with below series in the kernel: https://lore.kernel.org/linux-can/20210814091750.73931-1-mailhol.vincent@wanadoo.fr/T/#t ** Changelog ** >From RFC v5 to v6: * Dropped the RFC tag because the related patch series on the kernel side were pulled into net-next. * Remove the changes in include/uapi/linux/can/netlink.h because these should be pulled separately. * Add another patch (the second of this series) to do some cleanup on function print_ctrlmode(). * Minor fixes in the patch comments (grammar, rephrasing). >From RFC v4 to RFC v5: * Add the unit (bps, tq, ns or ms) in print_usage() * Rewrote void can_print_timing_min_max() to better factorize the code. * Rewrote the commit message of the two last patches (those related to TDC) to either add clarification of fix inacurracies. >From v3 to RFC v4: * Reflect the changes made on the kernel side. >From RFC v2 to v3: * Dropped the RFC tag. Now that the kernel patch reach the testing branch, I am finaly ready. * Regression fix: configuring a link with only nominal bittiming returned -EOPNOTSUPP * Added two more patches to the series: - iplink_can: fix configuration ranges in print_usage() - iplink_can: print brp and dbrp bittiming variables * Other small fixes on formatting. >From RFC v1 to RFC v2: * Add an additional patch to the series to fix the issues reported by Stephen Hemminger Ref: https://lore.kernel.org/linux-can/20210506112007.1666738-1-mailhol.vincent@wanadoo.fr/T/#t ==================== Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
commit
9c56d693f6
504
ip/iplink_can.c
504
ip/iplink_can.c
|
|
@ -28,6 +28,7 @@ static void print_usage(FILE *f)
|
|||
"\n"
|
||||
"\t[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |\n"
|
||||
"\t[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]\n"
|
||||
"\t[ tdcv TDCV tdco TDCO tdcf TDCF ]\n"
|
||||
"\n"
|
||||
"\t[ loopback { on | off } ]\n"
|
||||
"\t[ listen-only { on | off } ]\n"
|
||||
|
|
@ -38,20 +39,24 @@ static void print_usage(FILE *f)
|
|||
"\t[ fd-non-iso { on | off } ]\n"
|
||||
"\t[ presume-ack { on | off } ]\n"
|
||||
"\t[ cc-len8-dlc { on | off } ]\n"
|
||||
"\t[ tdc-mode { auto | manual | off } ]\n"
|
||||
"\n"
|
||||
"\t[ restart-ms TIME-MS ]\n"
|
||||
"\t[ restart ]\n"
|
||||
"\n"
|
||||
"\t[ termination { 0..65535 } ]\n"
|
||||
"\n"
|
||||
"\tWhere: BITRATE := { 1..1000000 }\n"
|
||||
"\tWhere: BITRATE := { NUMBER in bps }\n"
|
||||
"\t SAMPLE-POINT := { 0.000..0.999 }\n"
|
||||
"\t TQ := { NUMBER }\n"
|
||||
"\t PROP-SEG := { 1..8 }\n"
|
||||
"\t PHASE-SEG1 := { 1..8 }\n"
|
||||
"\t PHASE-SEG2 := { 1..8 }\n"
|
||||
"\t SJW := { 1..4 }\n"
|
||||
"\t RESTART-MS := { 0 | NUMBER }\n"
|
||||
"\t TQ := { NUMBER in ns }\n"
|
||||
"\t PROP-SEG := { NUMBER in tq }\n"
|
||||
"\t PHASE-SEG1 := { NUMBER in tq }\n"
|
||||
"\t PHASE-SEG2 := { NUMBER in tq }\n"
|
||||
"\t SJW := { NUMBER in tq }\n"
|
||||
"\t TDCV := { NUMBER in tc}\n"
|
||||
"\t TDCO := { NUMBER in tc}\n"
|
||||
"\t TDCF := { NUMBER in tc}\n"
|
||||
"\t RESTART-MS := { 0 | NUMBER in ms }\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -88,34 +93,47 @@ static void set_ctrlmode(char *name, char *arg,
|
|||
cm->mask |= flags;
|
||||
}
|
||||
|
||||
static void print_ctrlmode(FILE *f, __u32 cm)
|
||||
static void print_flag(enum output_type t, __u32 *flags, __u32 flag,
|
||||
const char* name)
|
||||
{
|
||||
open_json_array(PRINT_ANY, is_json_context() ? "ctrlmode" : "<");
|
||||
#define _PF(cmflag, cmname) \
|
||||
if (cm & cmflag) { \
|
||||
cm &= ~cmflag; \
|
||||
print_string(PRINT_ANY, NULL, cm ? "%s," : "%s", cmname); \
|
||||
if (*flags & flag) {
|
||||
*flags &= ~flag;
|
||||
print_string(t, NULL, *flags ? "%s," : "%s", name);
|
||||
}
|
||||
_PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
|
||||
_PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
|
||||
_PF(CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING");
|
||||
_PF(CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT");
|
||||
_PF(CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING");
|
||||
_PF(CAN_CTRLMODE_FD, "FD");
|
||||
_PF(CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO");
|
||||
_PF(CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
|
||||
_PF(CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC");
|
||||
#undef _PF
|
||||
if (cm)
|
||||
print_hex(PRINT_ANY, NULL, "%x", cm);
|
||||
close_json_array(PRINT_ANY, "> ");
|
||||
}
|
||||
|
||||
static void print_ctrlmode(enum output_type t, __u32 flags, const char* key)
|
||||
{
|
||||
if (!flags)
|
||||
return;
|
||||
|
||||
open_json_array(t, is_json_context() ? key : "<");
|
||||
|
||||
print_flag(t, &flags, CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_FD, "FD");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_TDC_AUTO, "TDC-AUTO");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_TDC_MANUAL, "TDC-MANUAL");
|
||||
|
||||
if (flags)
|
||||
print_hex(t, NULL, "%x", flags);
|
||||
|
||||
close_json_array(t, "> ");
|
||||
}
|
||||
|
||||
static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
struct can_bittiming bt = {}, dbt = {};
|
||||
struct can_ctrlmode cm = {0, 0};
|
||||
struct can_ctrlmode cm = { 0 };
|
||||
struct rtattr *tdc;
|
||||
__u32 tdcv = -1, tdco = -1, tdcf = -1;
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "bitrate") == 0) {
|
||||
|
|
@ -181,6 +199,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
NEXT_ARG();
|
||||
if (get_u32(&dbt.sjw, *argv, 0))
|
||||
invarg("invalid \"dsjw\" value\n", *argv);
|
||||
} else if (matches(*argv, "tdcv") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&tdcv, *argv, 0))
|
||||
invarg("invalid \"tdcv\" value\n", *argv);
|
||||
} else if (matches(*argv, "tdco") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&tdco, *argv, 0))
|
||||
invarg("invalid \"tdco\" value\n", *argv);
|
||||
} else if (matches(*argv, "tdcf") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&tdcf, *argv, 0))
|
||||
invarg("invalid \"tdcf\" value\n", *argv);
|
||||
} else if (matches(*argv, "loopback") == 0) {
|
||||
NEXT_ARG();
|
||||
set_ctrlmode("loopback", *argv, &cm,
|
||||
|
|
@ -217,6 +247,23 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
NEXT_ARG();
|
||||
set_ctrlmode("cc-len8-dlc", *argv, &cm,
|
||||
CAN_CTRLMODE_CC_LEN8_DLC);
|
||||
} else if (matches(*argv, "tdc-mode") == 0) {
|
||||
NEXT_ARG();
|
||||
if (strcmp(*argv, "auto") == 0) {
|
||||
cm.flags |= CAN_CTRLMODE_TDC_AUTO;
|
||||
cm.mask |= CAN_CTRLMODE_TDC_AUTO;
|
||||
} else if (strcmp(*argv, "manual") == 0) {
|
||||
cm.flags |= CAN_CTRLMODE_TDC_MANUAL;
|
||||
cm.mask |= CAN_CTRLMODE_TDC_MANUAL;
|
||||
} else if (strcmp(*argv, "off") == 0) {
|
||||
cm.mask |= CAN_CTRLMODE_TDC_AUTO |
|
||||
CAN_CTRLMODE_TDC_MANUAL;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: argument of \"tdc-mode\" must be \"auto\", \"manual\" or \"off\", not \"%s\"\n",
|
||||
*argv);
|
||||
exit (-1);
|
||||
}
|
||||
} else if (matches(*argv, "restart") == 0) {
|
||||
__u32 val = 1;
|
||||
|
||||
|
|
@ -254,6 +301,17 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
if (cm.mask)
|
||||
addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
|
||||
|
||||
if (tdcv != -1 || tdco != -1 || tdcf != -1) {
|
||||
tdc = addattr_nest(n, 1024, IFLA_CAN_TDC | NLA_F_NESTED);
|
||||
if (tdcv != -1)
|
||||
addattr32(n, 1024, IFLA_CAN_TDC_TDCV, tdcv);
|
||||
if (tdco != -1)
|
||||
addattr32(n, 1024, IFLA_CAN_TDC_TDCO, tdco);
|
||||
if (tdcf != -1)
|
||||
addattr32(n, 1024, IFLA_CAN_TDC_TDCF, tdcf);
|
||||
addattr_nest_end(n, tdc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -266,11 +324,75 @@ static const char *can_state_names[CAN_STATE_MAX] = {
|
|||
[CAN_STATE_SLEEPING] = "SLEEPING"
|
||||
};
|
||||
|
||||
static void can_print_json_timing_min_max(const char *attr, int min, int max)
|
||||
static void can_print_nl_indent(void)
|
||||
{
|
||||
open_json_object(attr);
|
||||
print_int(PRINT_JSON, "min", NULL, min);
|
||||
print_int(PRINT_JSON, "max", NULL, max);
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, "%s", "\t ");
|
||||
}
|
||||
|
||||
static void can_print_timing_min_max(const char *json_attr, const char *fp_attr,
|
||||
int min, int max)
|
||||
{
|
||||
print_null(PRINT_FP, NULL, fp_attr, NULL);
|
||||
open_json_object(json_attr);
|
||||
print_uint(PRINT_ANY, "min", " %d", min);
|
||||
print_uint(PRINT_ANY, "max", "..%d", max);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
static void can_print_tdc_opt(FILE *f, struct rtattr *tdc_attr)
|
||||
{
|
||||
struct rtattr *tb[IFLA_CAN_TDC_MAX + 1];
|
||||
|
||||
parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr);
|
||||
if (tb[IFLA_CAN_TDC_TDCV] || tb[IFLA_CAN_TDC_TDCO] ||
|
||||
tb[IFLA_CAN_TDC_TDCF]) {
|
||||
open_json_object("tdc");
|
||||
can_print_nl_indent();
|
||||
if (tb[IFLA_CAN_TDC_TDCV]) {
|
||||
__u32 *tdcv = RTA_DATA(tb[IFLA_CAN_TDC_TDCV]);
|
||||
|
||||
print_uint(PRINT_ANY, "tdcv", " tdcv %u", *tdcv);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCO]) {
|
||||
__u32 *tdco = RTA_DATA(tb[IFLA_CAN_TDC_TDCO]);
|
||||
|
||||
print_uint(PRINT_ANY, "tdco", " tdco %u", *tdco);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCF]) {
|
||||
__u32 *tdcf = RTA_DATA(tb[IFLA_CAN_TDC_TDCF]);
|
||||
|
||||
print_uint(PRINT_ANY, "tdcf", " tdcf %u", *tdcf);
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
}
|
||||
|
||||
static void can_print_tdc_const_opt(FILE *f, struct rtattr *tdc_attr)
|
||||
{
|
||||
struct rtattr *tb[IFLA_CAN_TDC_MAX + 1];
|
||||
|
||||
parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr);
|
||||
open_json_object("tdc");
|
||||
can_print_nl_indent();
|
||||
if (tb[IFLA_CAN_TDC_TDCV_MIN] && tb[IFLA_CAN_TDC_TDCV_MAX]) {
|
||||
__u32 *tdcv_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MIN]);
|
||||
__u32 *tdcv_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MAX]);
|
||||
|
||||
can_print_timing_min_max("tdcv", " tdcv", *tdcv_min, *tdcv_max);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCO_MIN] && tb[IFLA_CAN_TDC_TDCO_MAX]) {
|
||||
__u32 *tdco_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MIN]);
|
||||
__u32 *tdco_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MAX]);
|
||||
|
||||
can_print_timing_min_max("tdco", " tdco", *tdco_min, *tdco_max);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCF_MIN] && tb[IFLA_CAN_TDC_TDCF_MAX]) {
|
||||
__u32 *tdcf_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MIN]);
|
||||
__u32 *tdcf_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MAX]);
|
||||
|
||||
can_print_timing_min_max("tdcf", " tdcf", *tdcf_min, *tdcf_max);
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
|
|
@ -282,8 +404,7 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
if (tb[IFLA_CAN_CTRLMODE]) {
|
||||
struct can_ctrlmode *cm = RTA_DATA(tb[IFLA_CAN_CTRLMODE]);
|
||||
|
||||
if (cm->flags)
|
||||
print_ctrlmode(f, cm->flags);
|
||||
print_ctrlmode(PRINT_ANY, cm->flags, "ctrlmode");
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_STATE]) {
|
||||
|
|
@ -297,56 +418,39 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
struct can_berr_counter *bc =
|
||||
RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]);
|
||||
|
||||
if (is_json_context()) {
|
||||
open_json_object("berr_counter");
|
||||
print_int(PRINT_JSON, "tx", NULL, bc->txerr);
|
||||
print_int(PRINT_JSON, "rx", NULL, bc->rxerr);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "(berr-counter tx %d rx %d) ",
|
||||
bc->txerr, bc->rxerr);
|
||||
}
|
||||
open_json_object("berr_counter");
|
||||
print_uint(PRINT_ANY, "tx", "(berr-counter tx %u", bc->txerr);
|
||||
print_uint(PRINT_ANY, "rx", " rx %u) ", bc->rxerr);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_RESTART_MS]) {
|
||||
__u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]);
|
||||
|
||||
print_int(PRINT_ANY,
|
||||
"restart_ms",
|
||||
"restart-ms %d ",
|
||||
*restart_ms);
|
||||
print_uint(PRINT_ANY, "restart_ms", "restart-ms %u ",
|
||||
*restart_ms);
|
||||
}
|
||||
|
||||
/* bittiming is irrelevant if fixed bitrate is defined */
|
||||
if (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) {
|
||||
struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
|
||||
char sp[6];
|
||||
|
||||
if (is_json_context()) {
|
||||
json_writer_t *jw;
|
||||
|
||||
open_json_object("bittiming");
|
||||
print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
|
||||
jw = get_json_writer();
|
||||
jsonw_name(jw, "sample_point");
|
||||
jsonw_printf(jw, "%.3f",
|
||||
(float) bt->sample_point / 1000);
|
||||
print_int(PRINT_ANY, "tq", NULL, bt->tq);
|
||||
print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
|
||||
print_int(PRINT_ANY, "phase_seg1",
|
||||
NULL, bt->phase_seg1);
|
||||
print_int(PRINT_ANY, "phase_seg2",
|
||||
NULL, bt->phase_seg2);
|
||||
print_int(PRINT_ANY, "sjw", NULL, bt->sjw);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n bitrate %d sample-point %.3f ",
|
||||
bt->bitrate, (float) bt->sample_point / 1000.);
|
||||
fprintf(f,
|
||||
"\n tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
|
||||
bt->tq, bt->prop_seg,
|
||||
bt->phase_seg1, bt->phase_seg2,
|
||||
bt->sjw);
|
||||
}
|
||||
open_json_object("bittiming");
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "bitrate", " bitrate %u", bt->bitrate);
|
||||
snprintf(sp, sizeof(sp), "%.3f", bt->sample_point / 1000.);
|
||||
print_string(PRINT_ANY, "sample_point", " sample-point %s", sp);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "tq", " tq %u", bt->tq);
|
||||
print_uint(PRINT_ANY, "prop_seg", " prop-seg %u", bt->prop_seg);
|
||||
print_uint(PRINT_ANY, "phase_seg1", " phase-seg1 %u",
|
||||
bt->phase_seg1);
|
||||
print_uint(PRINT_ANY, "phase_seg2", " phase-seg2 %u",
|
||||
bt->phase_seg2);
|
||||
print_uint(PRINT_ANY, "sjw", " sjw %u", bt->sjw);
|
||||
print_uint(PRINT_ANY, "brp", " brp %u", bt->brp);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
/* bittiming const is irrelevant if fixed bitrate is defined */
|
||||
|
|
@ -354,28 +458,18 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
struct can_bittiming_const *btc =
|
||||
RTA_DATA(tb[IFLA_CAN_BITTIMING_CONST]);
|
||||
|
||||
if (is_json_context()) {
|
||||
open_json_object("bittiming_const");
|
||||
print_string(PRINT_JSON, "name", NULL, btc->name);
|
||||
can_print_json_timing_min_max("tseg1",
|
||||
btc->tseg1_min,
|
||||
btc->tseg1_max);
|
||||
can_print_json_timing_min_max("tseg2",
|
||||
btc->tseg2_min,
|
||||
btc->tseg2_max);
|
||||
can_print_json_timing_min_max("sjw", 1, btc->sjw_max);
|
||||
can_print_json_timing_min_max("brp",
|
||||
btc->brp_min,
|
||||
btc->brp_max);
|
||||
print_int(PRINT_JSON, "brp_inc", NULL, btc->brp_inc);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n %s: tseg1 %d..%d tseg2 %d..%d "
|
||||
"sjw 1..%d brp %d..%d brp-inc %d",
|
||||
btc->name, btc->tseg1_min, btc->tseg1_max,
|
||||
btc->tseg2_min, btc->tseg2_max, btc->sjw_max,
|
||||
btc->brp_min, btc->brp_max, btc->brp_inc);
|
||||
}
|
||||
open_json_object("bittiming_const");
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_ANY, "name", " %s:", btc->name);
|
||||
can_print_timing_min_max("tseg1", " tseg1",
|
||||
btc->tseg1_min, btc->tseg1_max);
|
||||
can_print_timing_min_max("tseg2", " tseg2",
|
||||
btc->tseg2_min, btc->tseg2_max);
|
||||
can_print_timing_min_max("sjw", " sjw", 1, btc->sjw_max);
|
||||
can_print_timing_min_max("brp", " brp",
|
||||
btc->brp_min, btc->brp_max);
|
||||
print_uint(PRINT_ANY, "brp_inc", " brp_inc %u", btc->brp_inc);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_BITRATE_CONST]) {
|
||||
|
|
@ -391,64 +485,52 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
bitrate = bt->bitrate;
|
||||
}
|
||||
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON,
|
||||
"bittiming_bitrate",
|
||||
NULL, bitrate);
|
||||
open_json_array(PRINT_JSON, "bitrate_const");
|
||||
for (i = 0; i < bitrate_cnt; ++i)
|
||||
print_uint(PRINT_JSON, NULL, NULL,
|
||||
bitrate_const[i]);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
} else {
|
||||
fprintf(f, "\n bitrate %u", bitrate);
|
||||
fprintf(f, "\n [");
|
||||
|
||||
for (i = 0; i < bitrate_cnt - 1; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
|
||||
fprintf(f, "%8u, ", bitrate_const[i]);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "bittiming_bitrate", " bitrate %u",
|
||||
bitrate);
|
||||
can_print_nl_indent();
|
||||
open_json_array(PRINT_ANY, is_json_context() ?
|
||||
"bitrate_const" : " [");
|
||||
for (i = 0; i < bitrate_cnt; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i) {
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_FP, NULL, "%s", " ");
|
||||
}
|
||||
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
fprintf(f, "%8u ]", bitrate_const[i]);
|
||||
print_uint(PRINT_ANY, NULL,
|
||||
i < bitrate_cnt - 1 ? "%8u, " : "%8u",
|
||||
bitrate_const[i]);
|
||||
}
|
||||
close_json_array(PRINT_JSON, " ]");
|
||||
}
|
||||
|
||||
/* data bittiming is irrelevant if fixed bitrate is defined */
|
||||
if (tb[IFLA_CAN_DATA_BITTIMING] && !tb[IFLA_CAN_DATA_BITRATE_CONST]) {
|
||||
struct can_bittiming *dbt =
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
|
||||
char dsp[6];
|
||||
|
||||
if (is_json_context()) {
|
||||
json_writer_t *jw;
|
||||
open_json_object("data_bittiming");
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "bitrate", " dbitrate %u", dbt->bitrate);
|
||||
snprintf(dsp, sizeof(dsp), "%.3f", dbt->sample_point / 1000.);
|
||||
print_string(PRINT_ANY, "sample_point", " dsample-point %s",
|
||||
dsp);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "tq", " dtq %u", dbt->tq);
|
||||
print_uint(PRINT_ANY, "prop_seg", " dprop-seg %u",
|
||||
dbt->prop_seg);
|
||||
print_uint(PRINT_ANY, "phase_seg1", " dphase-seg1 %u",
|
||||
dbt->phase_seg1);
|
||||
print_uint(PRINT_ANY, "phase_seg2", " dphase-seg2 %u",
|
||||
dbt->phase_seg2);
|
||||
print_uint(PRINT_ANY, "sjw", " dsjw %u", dbt->sjw);
|
||||
print_uint(PRINT_ANY, "brp", " dbrp %u", dbt->brp);
|
||||
|
||||
open_json_object("data_bittiming");
|
||||
print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
|
||||
jw = get_json_writer();
|
||||
jsonw_name(jw, "sample_point");
|
||||
jsonw_printf(jw, "%.3f",
|
||||
(float) dbt->sample_point / 1000.);
|
||||
print_int(PRINT_JSON, "tq", NULL, dbt->tq);
|
||||
print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
|
||||
print_int(PRINT_JSON, "phase_seg1",
|
||||
NULL, dbt->phase_seg1);
|
||||
print_int(PRINT_JSON, "phase_seg2",
|
||||
NULL, dbt->phase_seg2);
|
||||
print_int(PRINT_JSON, "sjw", NULL, dbt->sjw);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n dbitrate %d dsample-point %.3f ",
|
||||
dbt->bitrate,
|
||||
(float) dbt->sample_point / 1000.);
|
||||
fprintf(f, "\n dtq %d dprop-seg %d dphase-seg1 %d "
|
||||
"dphase-seg2 %d dsjw %d",
|
||||
dbt->tq, dbt->prop_seg, dbt->phase_seg1,
|
||||
dbt->phase_seg2, dbt->sjw);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC])
|
||||
can_print_tdc_opt(f, tb[IFLA_CAN_TDC]);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
/* data bittiming const is irrelevant if fixed bitrate is defined */
|
||||
|
|
@ -457,29 +539,22 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
struct can_bittiming_const *dbtc =
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING_CONST]);
|
||||
|
||||
if (is_json_context()) {
|
||||
open_json_object("data_bittiming_const");
|
||||
print_string(PRINT_JSON, "name", NULL, dbtc->name);
|
||||
can_print_json_timing_min_max("tseg1",
|
||||
dbtc->tseg1_min,
|
||||
dbtc->tseg1_max);
|
||||
can_print_json_timing_min_max("tseg2",
|
||||
dbtc->tseg2_min,
|
||||
dbtc->tseg2_max);
|
||||
can_print_json_timing_min_max("sjw", 1, dbtc->sjw_max);
|
||||
can_print_json_timing_min_max("brp",
|
||||
dbtc->brp_min,
|
||||
dbtc->brp_max);
|
||||
open_json_object("data_bittiming_const");
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_ANY, "name", " %s:", dbtc->name);
|
||||
can_print_timing_min_max("tseg1", " dtseg1",
|
||||
dbtc->tseg1_min, dbtc->tseg1_max);
|
||||
can_print_timing_min_max("tseg2", " dtseg2",
|
||||
dbtc->tseg2_min, dbtc->tseg2_max);
|
||||
can_print_timing_min_max("sjw", " dsjw", 1, dbtc->sjw_max);
|
||||
can_print_timing_min_max("brp", " dbrp",
|
||||
dbtc->brp_min, dbtc->brp_max);
|
||||
print_uint(PRINT_ANY, "brp_inc", " dbrp_inc %u", dbtc->brp_inc);
|
||||
|
||||
print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n %s: dtseg1 %d..%d dtseg2 %d..%d "
|
||||
"dsjw 1..%d dbrp %d..%d dbrp-inc %d",
|
||||
dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max,
|
||||
dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max,
|
||||
dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC])
|
||||
can_print_tdc_const_opt(f, tb[IFLA_CAN_TDC]);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
|
||||
|
|
@ -497,30 +572,23 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
dbitrate = dbt->bitrate;
|
||||
}
|
||||
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON, "data_bittiming_bitrate",
|
||||
NULL, dbitrate);
|
||||
open_json_array(PRINT_JSON, "data_bitrate_const");
|
||||
for (i = 0; i < dbitrate_cnt; ++i)
|
||||
print_uint(PRINT_JSON, NULL, NULL,
|
||||
dbitrate_const[i]);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
} else {
|
||||
fprintf(f, "\n dbitrate %u", dbitrate);
|
||||
fprintf(f, "\n [");
|
||||
|
||||
for (i = 0; i < dbitrate_cnt - 1; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
|
||||
fprintf(f, "%8u, ", dbitrate_const[i]);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "data_bittiming_bitrate", " dbitrate %u",
|
||||
dbitrate);
|
||||
can_print_nl_indent();
|
||||
open_json_array(PRINT_ANY, is_json_context() ?
|
||||
"data_bitrate_const" : " [");
|
||||
for (i = 0; i < dbitrate_cnt; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i) {
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_FP, NULL, "%s", " ");
|
||||
}
|
||||
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
fprintf(f, "%8u ]", dbitrate_const[i]);
|
||||
print_uint(PRINT_ANY, NULL,
|
||||
i < dbitrate_cnt - 1 ? "%8u, " : "%8u",
|
||||
dbitrate_const[i]);
|
||||
}
|
||||
close_json_array(PRINT_JSON, " ]");
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
|
||||
|
|
@ -530,29 +598,21 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
sizeof(*trm_const);
|
||||
int i;
|
||||
|
||||
if (is_json_context()) {
|
||||
print_hu(PRINT_JSON, "termination", NULL, *trm);
|
||||
open_json_array(PRINT_JSON, "termination_const");
|
||||
for (i = 0; i < trm_cnt; ++i)
|
||||
print_hu(PRINT_JSON, NULL, NULL, trm_const[i]);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
} else {
|
||||
fprintf(f, "\n termination %hu [ ", *trm);
|
||||
|
||||
for (i = 0; i < trm_cnt - 1; ++i)
|
||||
fprintf(f, "%hu, ", trm_const[i]);
|
||||
|
||||
fprintf(f, "%hu ]", trm_const[i]);
|
||||
}
|
||||
can_print_nl_indent();
|
||||
print_hu(PRINT_ANY, "termination", " termination %hu [ ", *trm);
|
||||
open_json_array(PRINT_JSON, "termination_const");
|
||||
for (i = 0; i < trm_cnt; ++i)
|
||||
print_hu(PRINT_ANY, NULL,
|
||||
i < trm_cnt - 1 ? "%hu, " : "%hu",
|
||||
trm_const[i]);
|
||||
close_json_array(PRINT_JSON, " ]");
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_CLOCK]) {
|
||||
struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]);
|
||||
|
||||
print_int(PRINT_ANY,
|
||||
"clock",
|
||||
"\n clock %d ",
|
||||
clock->freq);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "clock", " clock %u ", clock->freq);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -565,31 +625,23 @@ static void can_print_xstats(struct link_util *lu,
|
|||
if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) {
|
||||
stats = RTA_DATA(xstats);
|
||||
|
||||
if (is_json_context()) {
|
||||
print_int(PRINT_JSON, "restarts",
|
||||
NULL, stats->restarts);
|
||||
print_int(PRINT_JSON, "bus_error",
|
||||
NULL, stats->bus_error);
|
||||
print_int(PRINT_JSON, "arbitration_lost",
|
||||
NULL, stats->arbitration_lost);
|
||||
print_int(PRINT_JSON, "error_warning",
|
||||
NULL, stats->error_warning);
|
||||
print_int(PRINT_JSON, "error_passive",
|
||||
NULL, stats->error_passive);
|
||||
print_int(PRINT_JSON, "bus_off", NULL, stats->bus_off);
|
||||
} else {
|
||||
fprintf(f, "\n re-started bus-errors arbit-lost "
|
||||
"error-warn error-pass bus-off");
|
||||
fprintf(f, "\n %-10d %-10d %-10d %-10d %-10d %-10d",
|
||||
stats->restarts, stats->bus_error,
|
||||
stats->arbitration_lost, stats->error_warning,
|
||||
stats->error_passive, stats->bus_off);
|
||||
}
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_FP, NULL, "%s",
|
||||
" re-started bus-errors arbit-lost error-warn error-pass bus-off");
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "restarts", " %-10u", stats->restarts);
|
||||
print_uint(PRINT_ANY, "bus_error", " %-10u", stats->bus_error);
|
||||
print_uint(PRINT_ANY, "arbitration_lost", " %-10u",
|
||||
stats->arbitration_lost);
|
||||
print_uint(PRINT_ANY, "error_warning", " %-10u",
|
||||
stats->error_warning);
|
||||
print_uint(PRINT_ANY, "error_passive", " %-10u",
|
||||
stats->error_passive);
|
||||
print_uint(PRINT_ANY, "bus_off", " %-10u", stats->bus_off);
|
||||
}
|
||||
}
|
||||
|
||||
static void can_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
static void can_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
|
||||
{
|
||||
print_usage(f);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue