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 "string-util.h"
12 static int link_up_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
17 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
20 r
= sd_netlink_message_get_errno(m
);
22 /* we warn but don't fail the link, as it may be brought up later */
23 log_link_warning_errno(link
, r
, "Could not bring up interface: %m");
28 static int link_up_can(Link
*link
) {
29 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
34 log_link_debug(link
, "Bringing CAN link up");
36 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
38 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
40 r
= sd_rtnl_message_link_set_flags(req
, IFF_UP
, IFF_UP
);
42 return log_link_error_errno(link
, r
, "Could not set link flags: %m");
44 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, req
, link_up_handler
,
45 link_netlink_destroy_callback
, link
);
47 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
54 static int link_set_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
59 log_link_debug(link
, "Set link");
61 r
= sd_netlink_message_get_errno(m
);
62 if (r
< 0 && r
!= -EEXIST
) {
63 log_link_error_errno(link
, r
, "Failed to configure CAN link: %m");
64 link_enter_failed(link
);
70 static int link_set_can(Link
*link
) {
71 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
75 assert(link
->network
);
76 assert(link
->manager
);
77 assert(link
->manager
->rtnl
);
79 log_link_debug(link
, "Configuring CAN link.");
81 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &m
, RTM_NEWLINK
, link
->ifindex
);
83 return log_link_error_errno(link
, r
, "Failed to allocate netlink message: %m");
85 r
= sd_netlink_message_set_flags(m
, NLM_F_REQUEST
| NLM_F_ACK
);
87 return log_link_error_errno(link
, r
, "Could not set netlink flags: %m");
89 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
91 return log_link_error_errno(link
, r
, "Failed to open netlink container: %m");
93 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, link
->kind
);
95 return log_link_error_errno(link
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
97 if (link
->network
->can_bitrate
> 0 || link
->network
->can_sample_point
> 0) {
98 struct can_bittiming bt
= {
99 .bitrate
= link
->network
->can_bitrate
,
100 .sample_point
= link
->network
->can_sample_point
,
103 if (link
->network
->can_bitrate
> UINT32_MAX
) {
104 log_link_error(link
, "bitrate (%zu) too big.", link
->network
->can_bitrate
);
108 log_link_debug(link
, "Setting bitrate = %d bit/s", bt
.bitrate
);
109 if (link
->network
->can_sample_point
> 0)
110 log_link_debug(link
, "Setting sample point = %d.%d%%", bt
.sample_point
/ 10, bt
.sample_point
% 10);
112 log_link_debug(link
, "Using default sample point");
114 r
= sd_netlink_message_append_data(m
, IFLA_CAN_BITTIMING
, &bt
, sizeof(bt
));
116 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_BITTIMING attribute: %m");
119 if (link
->network
->can_restart_us
> 0) {
120 char time_string
[FORMAT_TIMESPAN_MAX
];
123 if (link
->network
->can_restart_us
== USEC_INFINITY
)
126 restart_ms
= DIV_ROUND_UP(link
->network
->can_restart_us
, USEC_PER_MSEC
);
128 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, restart_ms
* 1000, MSEC_PER_SEC
);
130 if (restart_ms
> UINT32_MAX
) {
131 log_link_error(link
, "restart timeout (%s) too big.", time_string
);
135 log_link_debug(link
, "Setting restart = %s", time_string
);
137 r
= sd_netlink_message_append_u32(m
, IFLA_CAN_RESTART_MS
, restart_ms
);
139 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
142 if (link
->network
->can_triple_sampling
>= 0) {
143 struct can_ctrlmode cm
= {
144 .mask
= CAN_CTRLMODE_3_SAMPLES
,
145 .flags
= link
->network
->can_triple_sampling
? CAN_CTRLMODE_3_SAMPLES
: 0,
148 log_link_debug(link
, "%sabling triple-sampling", link
->network
->can_triple_sampling
? "En" : "Dis");
150 r
= sd_netlink_message_append_data(m
, IFLA_CAN_CTRLMODE
, &cm
, sizeof(cm
));
152 return log_link_error_errno(link
, r
, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
155 r
= sd_netlink_message_close_container(m
);
157 return log_link_error_errno(link
, r
, "Failed to close netlink container: %m");
159 r
= sd_netlink_message_close_container(m
);
161 return log_link_error_errno(link
, r
, "Failed to close netlink container: %m");
163 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, m
, link_set_handler
,
164 link_netlink_destroy_callback
, link
);
166 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
170 if (!(link
->flags
& IFF_UP
))
171 return link_up_can(link
);
176 static int link_down_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
181 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
184 r
= sd_netlink_message_get_errno(m
);
186 log_link_warning_errno(link
, r
, "Could not bring down interface: %m");
187 link_enter_failed(link
);
191 r
= link_set_can(link
);
193 link_enter_failed(link
);
198 int link_configure_can(Link
*link
) {
201 if (streq_ptr(link
->kind
, "can")) {
202 /* The CAN interface must be down to configure bitrate, etc... */
203 if ((link
->flags
& IFF_UP
)) {
204 r
= link_down(link
, link_down_handler
);
206 link_enter_failed(link
);
210 r
= link_set_can(link
);
212 link_enter_failed(link
);
220 if (!(link
->flags
& IFF_UP
)) {
221 r
= link_up_can(link
);
223 link_enter_failed(link
);