Merge pull request #15238 from rpls/canfd

network: can: add support for CAN-FD related properties
This commit is contained in:
Lennart Poettering 2020-04-02 10:13:24 +02:00 committed by GitHub
commit e7b0ea5440
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 113 additions and 8 deletions

View file

@ -2350,7 +2350,7 @@
<term><varname>BitRate=</varname></term>
<listitem>
<para>The bitrate of CAN device in bits per second. The usual SI prefixes (K, M) with the base of 1000 can
be used here.</para>
be used here. Takes a number in the range 1..4294967295.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -2360,6 +2360,29 @@
<literal>87.5%</literal>) or permille (e.g. <literal>875‰</literal>).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>DataBitRate=</varname></term>
<term><varname>DataSamplePoint=</varname></term>
<listitem>
<para>The bitrate and sample point for the data phase, if CAN-FD is used. These settings are
analogous to the <varname>BitRate=</varname> and <varname>SamplePoint=</varname> keys.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FDMode=</varname></term>
<listitem>
<para>Takes a boolean. When <literal>yes</literal>, CAN-FD mode is enabled for the interface.
Note, that a bitrate and optional sample point should also be set for the CAN-FD data phase using
the <varname>DataBitRate=</varname> and <varname>DataSamplePoint=</varname> keys.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FDNonISO=</varname></term>
<listitem>
<para>Takes a boolean. When <literal>yes</literal>, non-ISO CAN-FD mode is enabled for the
interface. When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RestartSec=</varname></term>
<listitem>

View file

@ -7,10 +7,51 @@
#include "networkd-can.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "parse-util.h"
#include "string-util.h"
#define CAN_TERMINATION_OHM_VALUE 120
int config_parse_can_bitrate(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint32_t *br = data;
uint64_t sz;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = parse_size(rvalue, 1000, &sz);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse can bitrate '%s', ignoring: %m", rvalue);
return 0;
}
/* Linux uses __u32 for bitrates, so the value should not exceed that. */
if (sz <= 0 || sz > UINT32_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Bit rate out of permitted range 1...4294967295");
return 0;
}
*br = (uint32_t) sz;
return 0;
}
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
@ -103,11 +144,6 @@ static int link_set_can(Link *link) {
.sample_point = link->network->can_sample_point,
};
if (link->network->can_bitrate > UINT32_MAX) {
log_link_error(link, "bitrate (%" PRIu64 ") too big.", link->network->can_bitrate);
return -ERANGE;
}
log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
if (link->network->can_sample_point > 0)
log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
@ -119,6 +155,35 @@ static int link_set_can(Link *link) {
return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
}
if (link->network->can_data_bitrate > 0 || link->network->can_data_sample_point > 0) {
struct can_bittiming bt = {
.bitrate = link->network->can_data_bitrate,
.sample_point = link->network->can_data_sample_point,
};
log_link_debug(link, "Setting data bitrate = %d bit/s", bt.bitrate);
if (link->network->can_data_sample_point > 0)
log_link_debug(link, "Setting data sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
else
log_link_debug(link, "Using default data sample point");
r = sd_netlink_message_append_data(m, IFLA_CAN_DATA_BITTIMING, &bt, sizeof(bt));
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_CAN_DATA_BITTIMING attribute: %m");
}
if (link->network->can_fd_mode >= 0) {
cm.mask |= CAN_CTRLMODE_FD;
SET_FLAG(cm.flags, CAN_CTRLMODE_FD, link->network->can_fd_mode > 0);
log_link_debug(link, "%sabling FD mode", link->network->can_fd_mode > 0 ? "En" : "Dis");
}
if (link->network->can_non_iso >= 0) {
cm.mask |= CAN_CTRLMODE_FD_NON_ISO;
SET_FLAG(cm.flags, CAN_CTRLMODE_FD_NON_ISO, link->network->can_non_iso > 0);
log_link_debug(link, "%sabling FD non-ISO mode", link->network->can_non_iso > 0 ? "En" : "Dis");
}
if (link->network->can_restart_us > 0) {
char time_string[FORMAT_TIMESPAN_MAX];
uint64_t restart_ms;

View file

@ -1,6 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "conf-parser.h"
typedef struct Link Link;
int link_configure_can(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_can_bitrate);

View file

@ -6,6 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "conf-parser.h"
#include "netem.h"
#include "network-internal.h"
#include "networkd-can.h"
#include "networkd-conf.h"
#include "networkd-dhcp-common.h"
#include "networkd-dhcp-server.h"
@ -257,8 +258,12 @@ IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime,
IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0
IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0
CAN.BitRate, config_parse_si_uint64, 0, offsetof(Network, can_bitrate)
CAN.BitRate, config_parse_can_bitrate, 0, offsetof(Network, can_bitrate)
CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point)
CAN.DataBitRate, config_parse_can_bitrate, 0, offsetof(Network, can_data_bitrate)
CAN.DataSamplePoint, config_parse_permille, 0, offsetof(Network, can_data_sample_point)
CAN.FDMode, config_parse_tristate, 0, offsetof(Network, can_fd_mode)
CAN.FDNonISO, config_parse_tristate, 0, offsetof(Network, can_non_iso)
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)

View file

@ -205,12 +205,16 @@ struct Network {
uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN];
/* CAN support */
uint64_t can_bitrate;
uint32_t can_bitrate;
unsigned can_sample_point;
uint32_t can_data_bitrate;
unsigned can_data_sample_point;
usec_t can_restart_us;
int can_triple_sampling;
int can_termination;
int can_listen_only;
int can_fd_mode;
int can_non_iso;
AddressFamily ip_forward;
bool ip_masquerade;

View file

@ -201,6 +201,10 @@ PVID=
[CAN]
SamplePoint=
BitRate=
DataSamplePoint=
DataBitRate=
FDMode=
FDNonISO=
RestartSec=
TripleSampling=
Termination=