1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 /* Make sure the net/if.h header is included before any linux/ one */
5 #include <linux/can/netlink.h>
7 #include "networkd-can.h"
8 #include "networkd-link.h"
9 #include "networkd-network.h"
10 #include "networkd-setlink.h"
11 #include "parse-util.h"
12 #include "string-util.h"
14 #define CAN_TERMINATION_DEFAULT_OHM_VALUE 120
16 int can_set_netlink_message(Link
*link
, sd_netlink_message
*m
) {
20 assert(link
->network
);
23 r
= sd_netlink_message_set_flags(m
, NLM_F_REQUEST
| NLM_F_ACK
);
27 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
31 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, link
->kind
);
35 if (link
->network
->can_bitrate
> 0) {
36 struct can_bittiming bt
= {
37 .bitrate
= link
->network
->can_bitrate
,
38 .sample_point
= link
->network
->can_sample_point
,
39 .sjw
= link
->network
->can_sync_jump_width
,
42 log_link_debug(link
, "Setting bitrate = %u bit/s", bt
.bitrate
);
43 if (link
->network
->can_sample_point
> 0)
44 log_link_debug(link
, "Setting sample point = %u.%u%%", bt
.sample_point
/ 10, bt
.sample_point
% 10);
46 log_link_debug(link
, "Using default sample point");
48 r
= sd_netlink_message_append_data(m
, IFLA_CAN_BITTIMING
, &bt
, sizeof(bt
));
51 } else if (link
->network
->can_time_quanta_ns
> 0) {
52 struct can_bittiming bt
= {
53 .tq
= link
->network
->can_time_quanta_ns
,
54 .prop_seg
= link
->network
->can_propagation_segment
,
55 .phase_seg1
= link
->network
->can_phase_buffer_segment_1
,
56 .phase_seg2
= link
->network
->can_phase_buffer_segment_2
,
57 .sjw
= link
->network
->can_sync_jump_width
,
60 log_link_debug(link
, "Setting time quanta = %"PRIu32
" nsec", bt
.tq
);
61 r
= sd_netlink_message_append_data(m
, IFLA_CAN_BITTIMING
, &bt
, sizeof(bt
));
66 if (link
->network
->can_data_bitrate
> 0) {
67 struct can_bittiming bt
= {
68 .bitrate
= link
->network
->can_data_bitrate
,
69 .sample_point
= link
->network
->can_data_sample_point
,
70 .sjw
= link
->network
->can_data_sync_jump_width
,
73 log_link_debug(link
, "Setting data bitrate = %u bit/s", bt
.bitrate
);
74 if (link
->network
->can_data_sample_point
> 0)
75 log_link_debug(link
, "Setting data sample point = %u.%u%%", bt
.sample_point
/ 10, bt
.sample_point
% 10);
77 log_link_debug(link
, "Using default data sample point");
79 r
= sd_netlink_message_append_data(m
, IFLA_CAN_DATA_BITTIMING
, &bt
, sizeof(bt
));
82 } else if (link
->network
->can_data_time_quanta_ns
> 0) {
83 struct can_bittiming bt
= {
84 .tq
= link
->network
->can_data_time_quanta_ns
,
85 .prop_seg
= link
->network
->can_data_propagation_segment
,
86 .phase_seg1
= link
->network
->can_data_phase_buffer_segment_1
,
87 .phase_seg2
= link
->network
->can_data_phase_buffer_segment_2
,
88 .sjw
= link
->network
->can_data_sync_jump_width
,
91 log_link_debug(link
, "Setting data time quanta = %"PRIu32
" nsec", bt
.tq
);
92 r
= sd_netlink_message_append_data(m
, IFLA_CAN_DATA_BITTIMING
, &bt
, sizeof(bt
));
97 if (link
->network
->can_restart_us
> 0) {
100 if (link
->network
->can_restart_us
== USEC_INFINITY
)
103 restart_ms
= DIV_ROUND_UP(link
->network
->can_restart_us
, USEC_PER_MSEC
);
105 log_link_debug(link
, "Setting restart = %s", FORMAT_TIMESPAN(restart_ms
* 1000, MSEC_PER_SEC
));
106 r
= sd_netlink_message_append_u32(m
, IFLA_CAN_RESTART_MS
, restart_ms
);
111 if (link
->network
->can_control_mode_mask
!= 0) {
112 struct can_ctrlmode cm
= {
113 .mask
= link
->network
->can_control_mode_mask
,
114 .flags
= link
->network
->can_control_mode_flags
,
117 r
= sd_netlink_message_append_data(m
, IFLA_CAN_CTRLMODE
, &cm
, sizeof(cm
));
122 if (link
->network
->can_termination_set
) {
123 log_link_debug(link
, "Setting can-termination to '%u'.", link
->network
->can_termination
);
125 r
= sd_netlink_message_append_u16(m
, IFLA_CAN_TERMINATION
, link
->network
->can_termination
);
130 r
= sd_netlink_message_close_container(m
);
134 r
= sd_netlink_message_close_container(m
);
141 int config_parse_can_bitrate(
143 const char *filename
,
146 unsigned section_line
,
153 uint32_t *br
= ASSERT_PTR(data
);
161 r
= parse_size(rvalue
, 1000, &sz
);
163 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
164 "Failed to parse can bitrate '%s', ignoring: %m", rvalue
);
168 /* Linux uses __u32 for bitrates, so the value should not exceed that. */
169 if (sz
<= 0 || sz
> UINT32_MAX
) {
170 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
171 "Bit rate out of permitted range 1...4294967295");
180 int config_parse_can_time_quanta(
182 const char *filename
,
185 unsigned section_line
,
192 nsec_t val
, *tq
= ASSERT_PTR(data
);
199 r
= parse_nsec(rvalue
, &val
);
201 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
202 "Failed to parse can time quanta '%s', ignoring: %m", rvalue
);
206 /* Linux uses __u32 for bitrates, so the value should not exceed that. */
207 if (val
<= 0 || val
> UINT32_MAX
) {
208 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
209 "Time quanta out of permitted range 1...4294967295");
217 int config_parse_can_restart_usec(
219 const char *filename
,
222 unsigned section_line
,
229 usec_t usec
, *restart_usec
= ASSERT_PTR(data
);
236 r
= parse_sec(rvalue
, &usec
);
238 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
239 "Failed to parse CAN restart sec '%s', ignoring: %m", rvalue
);
243 if (usec
!= USEC_INFINITY
&&
244 DIV_ROUND_UP(usec
, USEC_PER_MSEC
) > UINT32_MAX
) {
245 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
246 "CAN RestartSec= must be in the range 0...%"PRIu32
"ms, ignoring: %s", UINT32_MAX
, rvalue
);
250 *restart_usec
= usec
;
254 int config_parse_can_control_mode(
256 const char *filename
,
259 unsigned section_line
,
266 Network
*network
= ASSERT_PTR(userdata
);
267 uint32_t mask
= ltype
;
275 if (isempty(rvalue
)) {
276 network
->can_control_mode_mask
&= ~mask
;
277 network
->can_control_mode_flags
&= ~mask
;
281 r
= parse_boolean(rvalue
);
283 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
284 "Failed to parse CAN control mode '%s', ignoring: %s", lvalue
, rvalue
);
288 network
->can_control_mode_mask
|= mask
;
289 SET_FLAG(network
->can_control_mode_flags
, mask
, r
);
293 int config_parse_can_termination(
295 const char *filename
,
298 unsigned section_line
,
305 Network
*network
= userdata
;
313 if (isempty(rvalue
)) {
314 network
->can_termination_set
= false;
318 /* Note that 0 termination ohm value means no termination resistor, and there is no conflict
319 * between parse_boolean() and safe_atou16() when Termination=0. However, Termination=1 must be
320 * treated as 1 ohm, instead of true (and then the default ohm value). So, we need to parse the
321 * string with safe_atou16() at first. */
323 r
= safe_atou16(rvalue
, &network
->can_termination
);
325 r
= parse_boolean(rvalue
);
327 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
328 "Failed to parse CAN termination value, ignoring: %s", rvalue
);
332 network
->can_termination
= r
? CAN_TERMINATION_DEFAULT_OHM_VALUE
: 0;
335 network
->can_termination_set
= true;