594b4be96cab58d18468890bf77d45cacee1b750
[AGL/meta-agl.git] / meta-agl-profile-telematics / recipes-core / systemd / files / 0003-networkd-link-add-support-to-configure-CAN-interface.patch
1 From c855f0b6042516632e4ad2020f8576de54366593 Mon Sep 17 00:00:00 2001
2 From: Hiram van Paassen <hiram.van.paassen@mastervolt.com>
3 Date: Tue, 10 Apr 2018 17:26:20 +0200
4 Subject: [PATCH 3/3] networkd-link: add support to configure CAN interfaces
5
6 This patch adds support for kind "can". Fixes: #4042.
7 ---
8  man/systemd.network.xml                   |  33 ++++++
9  src/libsystemd/sd-netlink/netlink-types.c |  10 ++
10  src/libsystemd/sd-netlink/netlink-types.h |   1 +
11  src/network/networkd-link.c               | 122 +++++++++++++++++++++-
12  src/network/networkd-network-gperf.gperf  |   3 +
13  src/network/networkd-network.c            |   3 +-
14  src/network/networkd-network.h            |   5 +
15  7 files changed, 175 insertions(+), 2 deletions(-)
16
17 diff --git a/man/systemd.network.xml b/man/systemd.network.xml
18 index 6b83a5b851..99ef84ac3d 100644
19 --- a/man/systemd.network.xml
20 +++ b/man/systemd.network.xml
21 @@ -1361,6 +1361,32 @@
22          </varlistentry>
23        </variablelist>
24    </refsect1>
25 +
26 +  <refsect1>
27 +    <title>[CAN] Section Options</title>
28 +      <para>The <literal>[CAN]</literal> section manages the Controller Area Network (CAN bus) and accepts the
29 +      following keys.</para>
30 +      <variablelist class='network-directives'>
31 +        <varlistentry>
32 +          <term><varname>BitRate=</varname></term>
33 +          <listitem>
34 +            <para>The bitrate of CAN device in bits per second. The usual SI prefixes (K, M) with the base of 1000 can
35 +            be used here.</para>
36 +          </listitem>
37 +        </varlistentry>
38 +        <varlistentry>
39 +          <term><varname>RestartSec=</varname></term>
40 +          <listitem>
41 +            <para>Automatic restart delay time. If set to a non-zero value, a restart of the CAN controller will be
42 +            triggered automatically in case of a bus-off condition after the specified delay time. Subsecond delays can
43 +            be specified using decimals (e.g. <literal>0.1s</literal>) or a <literal>ms</literal> or
44 +            <literal>us</literal> postfix. Using <literal>infinity</literal> or <literal>0</literal> will turn the
45 +            automatic restart off. By default automatic restart is disabled.</para>
46 +          </listitem>
47 +        </varlistentry>
48 +      </variablelist>
49 +  </refsect1>
50 +
51    <refsect1>
52      <title>[BridgeVLAN] Section Options</title>
53        <para>The <literal>[BridgeVLAN]</literal> section manages the VLAN ID configuration of a bridge port and accepts
54 diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
55 index 923f7dd10c..978277a2b9 100644
56 --- a/src/libsystemd/sd-netlink/netlink-types.c
57 +++ b/src/libsystemd/sd-netlink/netlink-types.c
58 @@ -300,6 +300,11 @@ static const NLType rtnl_link_info_data_geneve_types[] = {
59          [IFLA_GENEVE_LABEL]             = { .type = NETLINK_TYPE_U32 },
60  };
61  
62 +static const NLType rtnl_link_info_data_can_types[] = {
63 +        [IFLA_CAN_BITTIMING]            = { .size = sizeof(struct can_bittiming) },
64 +        [IFLA_CAN_RESTART_MS]           = { .type = NETLINK_TYPE_U32 },
65 +};
66 +
67  /* these strings must match the .kind entries in the kernel */
68  static const char* const nl_union_link_info_data_table[] = {
69          [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
70 @@ -323,6 +328,7 @@ static const char* const nl_union_link_info_data_table[] = {
71          [NL_UNION_LINK_INFO_DATA_VRF] = "vrf",
72          [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan",
73          [NL_UNION_LINK_INFO_DATA_GENEVE] = "geneve",
74 +        [NL_UNION_LINK_INFO_DATA_CAN] = "can",
75  };
76  
77  DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
78 @@ -366,6 +372,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
79                                                         .types = rtnl_link_info_data_vrf_types },
80          [NL_UNION_LINK_INFO_DATA_GENEVE] =           { .count = ELEMENTSOF(rtnl_link_info_data_geneve_types),
81                                                         .types = rtnl_link_info_data_geneve_types },
82 +        [NL_UNION_LINK_INFO_DATA_CAN] =              { .count = ELEMENTSOF(rtnl_link_info_data_can_types),
83 +                                                       .types = rtnl_link_info_data_can_types },
84  };
85  
86  static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
87 diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
88 index ae65c1d8e4..e7b8a292c2 100644
89 --- a/src/libsystemd/sd-netlink/netlink-types.h
90 +++ b/src/libsystemd/sd-netlink/netlink-types.h
91 @@ -89,6 +89,7 @@ typedef enum NLUnionLinkInfoData {
92          NL_UNION_LINK_INFO_DATA_VRF,
93          NL_UNION_LINK_INFO_DATA_VCAN,
94          NL_UNION_LINK_INFO_DATA_GENEVE,
95 +        NL_UNION_LINK_INFO_DATA_CAN,
96          _NL_UNION_LINK_INFO_DATA_MAX,
97          _NL_UNION_LINK_INFO_DATA_INVALID = -1
98  } NLUnionLinkInfoData;
99 diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
100 index a736dc1a74..73602d60a7 100644
101 --- a/src/network/networkd-link.c
102 +++ b/src/network/networkd-link.c
103 @@ -19,6 +19,7 @@
104  
105  #include <netinet/ether.h>
106  #include <linux/if.h>
107 +#include <linux/can/netlink.h>
108  #include <unistd.h>
109  
110  #include "alloc-util.h"
111 @@ -1805,6 +1806,105 @@ static int link_up_can(Link *link) {
112          return 0;
113  }
114  
115 +static int link_set_can(Link *link) {
116 +        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
117 +        int r;
118 +
119 +        assert(link);
120 +        assert(link->network);
121 +        assert(link->manager);
122 +        assert(link->manager->rtnl);
123 +
124 +        log_link_debug(link, "link_set_can");
125 +
126 +        r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
127 +        if (r < 0)
128 +                return log_link_error_errno(link, r, "Failed to allocate netlink message: %m");
129 +
130 +        r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
131 +        if (r < 0)
132 +                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
133 +
134 +        r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
135 +        if (r < 0)
136 +                return log_link_error_errno(link, r, "Failed to open netlink container: %m");
137 +
138 +        r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
139 +        if (r < 0)
140 +                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
141 +
142 +        if (link->network->can_bitrate > 0 || link->network->can_sample_point > 0) {
143 +                struct can_bittiming bt = {
144 +                        .bitrate = link->network->can_bitrate,
145 +                        .sample_point = link->network->can_sample_point,
146 +                };
147 +
148 +                if (link->network->can_bitrate > UINT32_MAX) {
149 +                        log_link_error(link, "bitrate (%zu) too big.", link->network->can_bitrate);
150 +                        return -ERANGE;
151 +                }
152 +
153 +                log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
154 +                if (link->network->can_sample_point > 0)
155 +                        log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
156 +                else
157 +                        log_link_debug(link, "Using default sample point");
158 +
159 +                r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
160 +                if (r < 0)
161 +                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
162 +        }
163 +
164 +        if (link->network->can_restart_us > 0) {
165 +                char time_string[FORMAT_TIMESPAN_MAX];
166 +                uint64_t restart_ms;
167 +
168 +                if (link->network->can_restart_us == USEC_INFINITY)
169 +                        restart_ms = 0;
170 +                else
171 +                        restart_ms = DIV_ROUND_UP(link->network->can_restart_us, USEC_PER_MSEC);
172 +
173 +                format_timespan(time_string, FORMAT_TIMESPAN_MAX, restart_ms * 1000, MSEC_PER_SEC);
174 +
175 +                if (restart_ms > UINT32_MAX) {
176 +                        log_link_error(link, "restart timeout (%s) too big.", time_string);
177 +                        return -ERANGE;
178 +                }
179 +
180 +                log_link_debug(link, "Setting restart = %s", time_string);
181 +
182 +                r = sd_netlink_message_append_u32(m, IFLA_CAN_RESTART_MS, restart_ms);
183 +                if (r < 0)
184 +                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
185 +        }
186 +
187 +        r = sd_netlink_message_close_container(m);
188 +        if (r < 0)
189 +                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
190 +
191 +        r = sd_netlink_message_close_container(m);
192 +        if (r < 0)
193 +                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
194 +
195 +        r = sd_netlink_call_async(link->manager->rtnl, m, link_set_handler, link,  0, NULL);
196 +        if (r < 0)
197 +                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
198 +
199 +        link_ref(link);
200 +
201 +        if (!(link->flags & IFF_UP)) {
202 +                r = link_up_can(link);
203 +                if (r < 0) {
204 +                        link_enter_failed(link);
205 +                        return r;
206 +                }
207 +        }
208 +
209 +        log_link_debug(link, "link_set_can done");
210 +
211 +        return r;
212 +}
213 +
214  static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
215          _cleanup_link_unref_ Link *link = userdata;
216          int r;
217 @@ -1818,6 +1918,11 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user
218          if (r < 0)
219                  log_link_warning_errno(link, r, "Could not bring down interface: %m");
220  
221 +        if (streq_ptr(link->kind, "can")) {
222 +                link_ref(link);
223 +                link_set_can(link);
224 +        }
225 +
226          return 1;
227  }
228  
229 @@ -2512,6 +2617,21 @@ static int link_update_lldp(Link *link) {
230  static int link_configure_can(Link *link) {
231          int r;
232  
233 +        if (streq_ptr(link->kind, "can")) {
234 +                /* The CAN interface must be down to configure bitrate, etc... */
235 +                if ((link->flags & IFF_UP)) {
236 +                        r = link_down(link);
237 +                        if (r < 0) {
238 +                                link_enter_failed(link);
239 +                                return r;
240 +                        }
241 +
242 +                        return 0;
243 +                }
244 +
245 +                return link_set_can(link);
246 +        }
247 +
248          if (!(link->flags & IFF_UP)) {
249                  r = link_up_can(link);
250                  if (r < 0) {
251 @@ -2530,7 +2650,7 @@ static int link_configure(Link *link) {
252          assert(link->network);
253          assert(link->state == LINK_STATE_PENDING);
254  
255 -        if (streq_ptr(link->kind, "vcan"))
256 +        if (STRPTR_IN_SET(link->kind, "can", "vcan"))
257                  return link_configure_can(link);
258  
259          /* Drop foreign config, but ignore loopback or critical devices.
260 diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
261 index a2d38501a5..95301f16e3 100644
262 --- a/src/network/networkd-network-gperf.gperf
263 +++ b/src/network/networkd-network-gperf.gperf
264 @@ -147,6 +147,8 @@ IPv6Prefix.OnLink,                      config_parse_prefix_flags,
265  IPv6Prefix.AddressAutoconfiguration,    config_parse_prefix_flags,                      0,                             0
266  IPv6Prefix.ValidLifetimeSec,            config_parse_prefix_lifetime,                   0,                             0
267  IPv6Prefix.PreferredLifetimeSec,        config_parse_prefix_lifetime,                   0,                             0
268 +CAN.BitRate,                            config_parse_si_size,                           0,                             offsetof(Network, can_bitrate)
269 +CAN.RestartSec,                         config_parse_sec,                               0,                             offsetof(Network, can_restart_us)
270  /* backwards compatibility: do not add new entries to this section */
271  Network.IPv4LL,                         config_parse_ipv4ll,                            0,                             offsetof(Network, link_local)
272  DHCPv4.UseDNS,                          config_parse_bool,                              0,                             offsetof(Network, dhcp_use_dns)
273 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
274 index 6f2ae66d40..65684e7915 100644
275 --- a/src/network/networkd-network.c
276 +++ b/src/network/networkd-network.c
277 @@ -214,7 +214,8 @@ static int network_load_one(Manager *manager, const char *filename) {
278                                "BridgeFDB\0"
279                                "BridgeVLAN\0"
280                                "IPv6PrefixDelegation\0"
281 -                              "IPv6Prefix\0",
282 +                              "IPv6Prefix\0"
283 +                              "CAN\0",
284                                config_item_perf_lookup, network_network_gperf_lookup,
285                                false, network);
286          if (r < 0)
287 diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
288 index b31921947d..c4e1192cbe 100644
289 --- a/src/network/networkd-network.h
290 +++ b/src/network/networkd-network.h
291 @@ -179,6 +179,11 @@ struct Network {
292          uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN];
293          uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN];
294  
295 +        /* CAN support */
296 +        size_t can_bitrate;
297 +        unsigned can_sample_point;
298 +        usec_t can_restart_us;
299 +
300          AddressFamilyBoolean ip_forward;
301          bool ip_masquerade;
302  
303 -- 
304 2.17.1
305