diff --git a/man/systemd.network.xml b/man/systemd.network.xml index a174a1fb24..8df79e08cd 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2317,6 +2317,16 @@ the value of a received bit by majority rule. When unset, the kernel's default will be used. + + ListenOnly= + + Takes a boolean. When yes, listen-only mode is enabled. When the + interface is in listen-only mode, the interface neither transmit CAN frames nor send ACK + bit. Listen-only mode is important to debug CAN networks without interfering with the + communication or acknowledge the CAN frame. When unset, the kernel's default will be used. + + + diff --git a/src/network/networkd-can.c b/src/network/networkd-can.c index c703f94f3a..18533843e3 100644 --- a/src/network/networkd-can.c +++ b/src/network/networkd-can.c @@ -71,6 +71,7 @@ static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) static int link_set_can(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + struct can_ctrlmode cm = {}; int r; assert(link); @@ -142,13 +143,18 @@ static int link_set_can(Link *link) { } if (link->network->can_triple_sampling >= 0) { - struct can_ctrlmode cm = { - .mask = CAN_CTRLMODE_3_SAMPLES, - .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0, - }; - + cm.mask |= CAN_CTRLMODE_3_SAMPLES; + SET_FLAG(cm.flags, CAN_CTRLMODE_3_SAMPLES, link->network->can_triple_sampling); log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis"); + } + if (link->network->can_listen_only >= 0) { + cm.mask |= CAN_CTRLMODE_LISTENONLY; + SET_FLAG(cm.flags, CAN_CTRLMODE_LISTENONLY, link->network->can_listen_only); + log_link_debug(link, "%sabling listen-only mode", link->network->can_listen_only ? "En" : "Dis"); + } + + if (cm.mask != 0) { r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m"); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index e1b9b5687a..d6259a41bf 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -256,6 +256,7 @@ CAN.SamplePoint, config_parse_permille, CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us) CAN.TripleSampling, config_parse_tristate, 0, offsetof(Network, can_triple_sampling) CAN.Termination, config_parse_tristate, 0, offsetof(Network, can_termination) +CAN.ListenOnly, config_parse_tristate, 0, offsetof(Network, can_listen_only) QDisc.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0 QDisc.Handle, config_parse_qdisc_handle, _QDISC_KIND_INVALID, 0 BFIFO.Parent, config_parse_qdisc_parent, QDISC_KIND_BFIFO, 0 diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index f8ecb1f687..693f018385 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -200,6 +200,7 @@ struct Network { usec_t can_restart_us; int can_triple_sampling; int can_termination; + int can_listen_only; AddressFamily ip_forward; bool ip_masquerade; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index a729adcc86..630abafdcf 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -201,6 +201,7 @@ BitRate= RestartSec= TripleSampling= Termination= +ListenOnly= [Address] DuplicateAddressDetection= AutoJoin=