1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <linux/can/netlink.h>
6 #include "netlink-util.h"
7 #include "networkd-can.h"
8 #include "networkd-link.h"
9 #include "networkd-manager.h"
10 #include "parse-util.h"
11 #include "string-util.h"
13 #define CAN_TERMINATION_OHM_VALUE 120
15 int config_parse_can_bitrate(
20 unsigned section_line
,
36 r
= parse_size(rvalue
, 1000, &sz
);
38 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
39 "Failed to parse can bitrate '%s', ignoring: %m", rvalue
);
43 /* Linux uses __u32 for bitrates, so the value should not exceed that. */
44 if (sz
<= 0 || sz
> UINT32_MAX
) {
45 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
46 "Bit rate out of permitted range 1...4294967295");
55 static int link_up_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
60 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
63 r
= sd_netlink_message_get_errno(m
);
65 /* we warn but don't fail the link, as it may be brought up later */
66 log_link_message_warning_errno(link
, m
, r
, "Could not bring up interface");
71 static int link_up_can(Link
*link
) {
72 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
77 log_link_debug(link
, "Bringing CAN link up");
79 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
81 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
83 r
= sd_rtnl_message_link_set_flags(req
, IFF_UP
, IFF_UP
);
85 return log_link_error_errno(link
, r
, "Could not set link flags: %m");
87 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, req
, link_up_handler
,
88 link_netlink_destroy_callback
, link
);
90 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
97 static int link_set_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
102 log_link_debug(link
, "Set link");
104 r
= sd_netlink_message_get_errno(m
);
105 if (r
< 0 && r
!= -EEXIST
) {
106 log_link_message_warning_errno(link
, m
, r
, "Failed to configure CAN link");
107 link_enter_failed(link
);
113 static int link_set_can(Link
*link
) {
114 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
115 struct can_ctrlmode cm
= {};
119 assert(link
->network
);
120 assert(link
->manager
);
121 assert(link
->manager
->rtnl
);
123 log_link_debug(link
, "Configuring CAN link.");
125 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &m
, RTM_NEWLINK
, link
->ifindex
);
127 return log_link_error_errno(link
, r
, "Failed to allocate netlink message: %m");
129 r
= sd_netlink_message_set_flags(m
, NLM_F_REQUEST
| NLM_F_ACK
);
131 return log_link_error_errno(link
, r
, "Could not set netlink flags: %m");
133 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
135 return log_link_error_errno(link
, r
, "Failed to open netlink container: %m");
137 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, link
->kind
);
139 return log_link_error_errno(link
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
141 if (link
->network
->can_bitrate
> 0 || link
->network
->can_sample_point
> 0) {
142 struct can_bittiming bt
= {
143 .bitrate
= link
->network
->can_bitrate
,
144 .sample_point
= link
->network
->can_sample_point
,
147 log_link_debug(link
, "Setting bitrate = %d bit/s", bt
.bitrate
);
148 if (link
->network
->can_sample_point
> 0)
149 log_link_debug(link
, "Setting sample point = %d.%d%%", bt
.sample_point
/ 10, bt
.sample_point
% 10);
151 log_link_debug(link
, "Using default sample point");
153 r
= sd_netlink_message_append_data(m
, IFLA_CAN_BITTIMING
, &bt
, sizeof(bt
));
155 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_BITTIMING attribute: %m");
158 if (link
->network
->can_data_bitrate
> 0 || link
->network
->can_data_sample_point
> 0) {
159 struct can_bittiming bt
= {
160 .bitrate
= link
->network
->can_data_bitrate
,
161 .sample_point
= link
->network
->can_data_sample_point
,
164 log_link_debug(link
, "Setting data bitrate = %d bit/s", bt
.bitrate
);
165 if (link
->network
->can_data_sample_point
> 0)
166 log_link_debug(link
, "Setting data sample point = %d.%d%%", bt
.sample_point
/ 10, bt
.sample_point
% 10);
168 log_link_debug(link
, "Using default data sample point");
170 r
= sd_netlink_message_append_data(m
, IFLA_CAN_DATA_BITTIMING
, &bt
, sizeof(bt
));
172 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_DATA_BITTIMING attribute: %m");
175 if (link
->network
->can_fd_mode
>= 0) {
176 cm
.mask
|= CAN_CTRLMODE_FD
;
177 SET_FLAG(cm
.flags
, CAN_CTRLMODE_FD
, link
->network
->can_fd_mode
> 0);
178 log_link_debug(link
, "%sabling FD mode", link
->network
->can_fd_mode
> 0 ? "En" : "Dis");
181 if (link
->network
->can_non_iso
>= 0) {
182 cm
.mask
|= CAN_CTRLMODE_FD_NON_ISO
;
183 SET_FLAG(cm
.flags
, CAN_CTRLMODE_FD_NON_ISO
, link
->network
->can_non_iso
> 0);
184 log_link_debug(link
, "%sabling FD non-ISO mode", link
->network
->can_non_iso
> 0 ? "En" : "Dis");
187 if (link
->network
->can_restart_us
> 0) {
188 char time_string
[FORMAT_TIMESPAN_MAX
];
191 if (link
->network
->can_restart_us
== USEC_INFINITY
)
194 restart_ms
= DIV_ROUND_UP(link
->network
->can_restart_us
, USEC_PER_MSEC
);
196 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, restart_ms
* 1000, MSEC_PER_SEC
);
198 if (restart_ms
> UINT32_MAX
) {
199 log_link_error(link
, "restart timeout (%s) too big.", time_string
);
203 log_link_debug(link
, "Setting restart = %s", time_string
);
205 r
= sd_netlink_message_append_u32(m
, IFLA_CAN_RESTART_MS
, restart_ms
);
207 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
210 if (link
->network
->can_triple_sampling
>= 0) {
211 cm
.mask
|= CAN_CTRLMODE_3_SAMPLES
;
212 SET_FLAG(cm
.flags
, CAN_CTRLMODE_3_SAMPLES
, link
->network
->can_triple_sampling
);
213 log_link_debug(link
, "%sabling triple-sampling", link
->network
->can_triple_sampling
? "En" : "Dis");
216 if (link
->network
->can_listen_only
>= 0) {
217 cm
.mask
|= CAN_CTRLMODE_LISTENONLY
;
218 SET_FLAG(cm
.flags
, CAN_CTRLMODE_LISTENONLY
, link
->network
->can_listen_only
);
219 log_link_debug(link
, "%sabling listen-only mode", link
->network
->can_listen_only
? "En" : "Dis");
223 r
= sd_netlink_message_append_data(m
, IFLA_CAN_CTRLMODE
, &cm
, sizeof(cm
));
225 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
228 if (link
->network
->can_termination
>= 0) {
230 log_link_debug(link
, "%sabling can-termination", link
->network
->can_termination
? "En" : "Dis");
232 r
= sd_netlink_message_append_u16(m
, IFLA_CAN_TERMINATION
,
233 link
->network
->can_termination
? CAN_TERMINATION_OHM_VALUE
: 0);
235 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_TERMINATION attribute: %m");
239 r
= sd_netlink_message_close_container(m
);
241 return log_link_error_errno(link
, r
, "Failed to close netlink container: %m");
243 r
= sd_netlink_message_close_container(m
);
245 return log_link_error_errno(link
, r
, "Failed to close netlink container: %m");
247 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
, link_set_handler
,
248 link_netlink_destroy_callback
, link
);
250 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
254 if (!(link
->flags
& IFF_UP
))
255 return link_up_can(link
);
260 static int link_down_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
265 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
268 r
= sd_netlink_message_get_errno(m
);
270 log_link_message_warning_errno(link
, m
, r
, "Could not bring down interface");
271 link_enter_failed(link
);
275 r
= link_set_can(link
);
277 link_enter_failed(link
);
282 int link_configure_can(Link
*link
) {
285 link_set_state(link
, LINK_STATE_CONFIGURING
);
287 if (streq_ptr(link
->kind
, "can")) {
288 /* The CAN interface must be down to configure bitrate, etc... */
289 if ((link
->flags
& IFF_UP
)) {
290 r
= link_down(link
, link_down_handler
);
292 link_enter_failed(link
);
296 r
= link_set_can(link
);
298 link_enter_failed(link
);
306 if (!(link
->flags
& IFF_UP
)) {
307 r
= link_up_can(link
);
309 link_enter_failed(link
);