]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: can: allow to specify bit-timing with TimeQuantaNSec= and friends 20442/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 15 Aug 2021 18:36:58 +0000 (03:36 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 16 Aug 2021 13:30:38 +0000 (22:30 +0900)
Closes #19424 and #20435.

man/systemd.network.xml
src/network/networkd-can.c
src/network/networkd-can.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.h
test/fuzz/fuzz-network-parser/directives.network

index c28cbed74f8c70b4572d3b7e8bb8ddb8fa3aec73..fc127b1dba67a5d79b6225e5fdcb0f1120220257 100644 (file)
@@ -2961,6 +2961,25 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
             <varname>BitRate=</varname> is unspecified.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>TimeQuantaNSec=</varname></term>
+          <term><varname>PropagationSegment=</varname></term>
+          <term><varname>PhaseBufferSegment1=</varname></term>
+          <term><varname>PhaseBufferSegment2=</varname></term>
+          <term><varname>SyncJumpWidth=</varname></term>
+          <listitem>
+            <para>Specifies the time quanta, propagation segment, phase buffer segment 1 and 2, and the
+            synchronization jump width, which allow to define the CAN bit-timing in a hardware
+            independent format as proposed by the Bosch CAN 2.0 Specification.
+            <varname>TimeQuantaNSec=</varname> takes a timespan in nanoseconds.
+            <varname>PropagationSegment=</varname>, <varname>PhaseBufferSegment1=</varname>,
+            <varname>PhaseBufferSegment2=</varname>, and <varname>SyncJumpWidth=</varname> take number
+            of time quantum specified in <varname>TimeQuantaNSec=</varname> and must be an unsigned
+            integer in the range 0…4294967295. These settings except for
+            <varname>SyncJumpWidth=</varname> will be ignored when <varname>BitRate=</varname> is
+            specified.</para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>DataBitRate=</varname></term>
           <term><varname>DataSamplePoint=</varname></term>
@@ -2969,12 +2988,25 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
             analogous to the <varname>BitRate=</varname> and <varname>SamplePoint=</varname> keys.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>DataTimeQuantaNSec=</varname></term>
+          <term><varname>DataPropagationSegment=</varname></term>
+          <term><varname>DataPhaseBufferSegment1=</varname></term>
+          <term><varname>DataPhaseBufferSegment2=</varname></term>
+          <term><varname>DataSyncJumpWidth=</varname></term>
+          <listitem>
+            <para>Specifies the time quanta, propagation segment, phase buffer segment 1 and 2, and the
+            synchronization jump width for the data phase, if CAN-FD is used. These settings are
+            analogous to the <varname>TimeQuantaNSec=</varname> or related settings.</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>
+            the <varname>DataBitRate=</varname> and <varname>DataSamplePoint=</varname> keys, or
+            <varname>DataTimeQuanta=</varname> and related settings.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index c4c71b82852c0d780aa6543d8e4afd067ef09f6d..7a0a6e552261349b84b518be3e7610926f1ba48b 100644 (file)
@@ -35,6 +35,7 @@ int can_set_netlink_message(Link *link, sd_netlink_message *m) {
                 struct can_bittiming bt = {
                         .bitrate = link->network->can_bitrate,
                         .sample_point = link->network->can_sample_point,
+                        .sjw = link->network->can_sync_jump_width,
                 };
 
                 log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
@@ -46,12 +47,26 @@ int can_set_netlink_message(Link *link, sd_netlink_message *m) {
                 r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
                 if (r < 0)
                         return log_link_debug_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
+        } else if (link->network->can_time_quanta_ns > 0) {
+                struct can_bittiming bt = {
+                        .tq = link->network->can_time_quanta_ns,
+                        .prop_seg = link->network->can_propagation_segment,
+                        .phase_seg1 = link->network->can_phase_buffer_segment_1,
+                        .phase_seg2 = link->network->can_phase_buffer_segment_2,
+                        .sjw = link->network->can_sync_jump_width,
+                };
+
+                log_link_debug(link, "Setting time quanta = %"PRIu32" nsec", bt.tq);
+                r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
         }
 
         if (link->network->can_data_bitrate > 0) {
                 struct can_bittiming bt = {
                         .bitrate = link->network->can_data_bitrate,
                         .sample_point = link->network->can_data_sample_point,
+                        .sjw = link->network->can_data_sync_jump_width,
                 };
 
                 log_link_debug(link, "Setting data bitrate = %d bit/s", bt.bitrate);
@@ -63,6 +78,19 @@ int can_set_netlink_message(Link *link, sd_netlink_message *m) {
                 r = sd_netlink_message_append_data(m, IFLA_CAN_DATA_BITTIMING, &bt, sizeof(bt));
                 if (r < 0)
                         return log_link_debug_errno(link, r, "Could not append IFLA_CAN_DATA_BITTIMING attribute: %m");
+        } else if (link->network->can_data_time_quanta_ns > 0) {
+                struct can_bittiming bt = {
+                        .tq = link->network->can_data_time_quanta_ns,
+                        .prop_seg = link->network->can_data_propagation_segment,
+                        .phase_seg1 = link->network->can_data_phase_buffer_segment_1,
+                        .phase_seg2 = link->network->can_data_phase_buffer_segment_2,
+                        .sjw = link->network->can_data_sync_jump_width,
+                };
+
+                log_link_debug(link, "Setting data time quanta = %"PRIu32" nsec", bt.tq);
+                r = sd_netlink_message_append_data(m, IFLA_CAN_DATA_BITTIMING, &bt, sizeof(bt));
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not append IFLA_CAN_DATA_BITTIMING attribute: %m");
         }
 
         if (link->network->can_restart_us > 0) {
@@ -149,6 +177,44 @@ int config_parse_can_bitrate(
         return 0;
 }
 
+int config_parse_can_time_quanta(
+                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) {
+
+        nsec_t val, *tq = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = parse_nsec(rvalue, &val);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to parse can time quanta '%s', ignoring: %m", rvalue);
+                return 0;
+        }
+
+        /* Linux uses __u32 for bitrates, so the value should not exceed that. */
+        if (val <= 0 || val > UINT32_MAX) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
+                           "Time quanta out of permitted range 1...4294967295");
+                return 0;
+        }
+
+        *tq = val;
+        return 0;
+}
+
 int config_parse_can_restart_usec(
                 const char* unit,
                 const char *filename,
index ff1a014a158518fae40bdfe49d46d11403cf9287..3945082498f30bf218ff770d749db20fb1ae7265 100644 (file)
@@ -12,6 +12,7 @@ typedef struct Link Link;
 int can_set_netlink_message(Link *link, sd_netlink_message *m);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_can_bitrate);
+CONFIG_PARSER_PROTOTYPE(config_parse_can_time_quanta);
 CONFIG_PARSER_PROTOTYPE(config_parse_can_restart_usec);
 CONFIG_PARSER_PROTOTYPE(config_parse_can_control_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_can_termination);
index 077779cc6b2dc488cfdce7237bd82831cf23c7bd..580347363d80a3aba3a326eea8ccbb39c7ba20bd 100644 (file)
@@ -346,8 +346,18 @@ IPv6RoutePrefix.LifetimeSec,                 config_parse_route_prefix_lifetime,
 LLDP.MUDURL,                                 config_parse_mud_url,                                     0,                             offsetof(Network, lldp_mud)
 CAN.BitRate,                                 config_parse_can_bitrate,                                 0,                             offsetof(Network, can_bitrate)
 CAN.SamplePoint,                             config_parse_permille,                                    0,                             offsetof(Network, can_sample_point)
+CAN.TimeQuantaNSec,                          config_parse_can_time_quanta,                             0,                             offsetof(Network, can_time_quanta_ns)
+CAN.PropagationSegment,                      config_parse_uint32,                                      0,                             offsetof(Network, can_propagation_segment)
+CAN.PhaseBufferSegment1,                     config_parse_uint32,                                      0,                             offsetof(Network, can_phase_buffer_segment_1)
+CAN.PhaseBufferSegment2,                     config_parse_uint32,                                      0,                             offsetof(Network, can_phase_buffer_segment_2)
+CAN.SyncJumpWidth,                           config_parse_uint32,                                      0,                             offsetof(Network, can_sync_jump_width)
 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.DataTimeQuantaNSec,                      config_parse_can_time_quanta,                             0,                             offsetof(Network, can_data_time_quanta_ns)
+CAN.DataPropagationSegment,                  config_parse_uint32,                                      0,                             offsetof(Network, can_data_propagation_segment)
+CAN.DataPhaseBufferSegment1,                 config_parse_uint32,                                      0,                             offsetof(Network, can_data_phase_buffer_segment_1)
+CAN.DataPhaseBufferSegment2,                 config_parse_uint32,                                      0,                             offsetof(Network, can_data_phase_buffer_segment_2)
+CAN.DataSyncJumpWidth,                       config_parse_uint32,                                      0,                             offsetof(Network, can_data_sync_jump_width)
 CAN.RestartSec,                              config_parse_can_restart_usec,                            0,                             offsetof(Network, can_restart_us)
 CAN.Loopback,                                config_parse_can_control_mode,                            CAN_CTRLMODE_LOOPBACK,         0
 CAN.ListenOnly,                              config_parse_can_control_mode,                            CAN_CTRLMODE_LISTENONLY,       0
index 488d49e3acd90e62f0b6295f3541891565ebcfbf..4410683b4a3cfed0e5e57657bfde03a609d87a73 100644 (file)
@@ -265,8 +265,18 @@ struct Network {
         /* CAN support */
         uint32_t can_bitrate;
         unsigned can_sample_point;
+        nsec_t can_time_quanta_ns;
+        uint32_t can_propagation_segment;
+        uint32_t can_phase_buffer_segment_1;
+        uint32_t can_phase_buffer_segment_2;
+        uint32_t can_sync_jump_width;
         uint32_t can_data_bitrate;
         unsigned can_data_sample_point;
+        nsec_t can_data_time_quanta_ns;
+        uint32_t can_data_propagation_segment;
+        uint32_t can_data_phase_buffer_segment_1;
+        uint32_t can_data_phase_buffer_segment_2;
+        uint32_t can_data_sync_jump_width;
         usec_t can_restart_us;
         uint32_t can_control_mode_mask;
         uint32_t can_control_mode_flags;
index 2f96bb8db99f75a6c2e616f20d56e501d8a9cbbc..eb7e699bd31080d0d69f2dd55a90a9c5c3a2afa0 100644 (file)
@@ -257,8 +257,18 @@ MUDURL=
 [CAN]
 SamplePoint=
 BitRate=
+TimeQuantaNSec=
+PropagationSegment=
+PhaseBufferSegment1=
+PhaseBufferSegment2=
+SyncJumpWidth=
 DataSamplePoint=
 DataBitRate=
+DataTimeQuantaNSec=
+DataPropagationSegment=
+DataPhaseBufferSegment1=
+DataPhaseBufferSegment2=
+DataSyncJumpWidth=
 FDMode=
 FDNonISO=
 RestartSec=