]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: can: make Termination= optionally take a raw resistor value
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 15 Aug 2021 17:16:53 +0000 (02:16 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 16 Aug 2021 09:52:24 +0000 (18:52 +0900)
Note that this slightly breaks backward compatibility when
Termination=1. Previously, this is handled as boolean true, then 120 ohm
was used. But now with this commit, it is handled as 1 ohm.

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

index c5c2e48ac751846f5abe18809dfa446c1f1b5b4e..85e4ae09c759b643744bace2e350376db19d8047 100644 (file)
@@ -2996,8 +2996,10 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <varlistentry>
           <term><varname>Termination=</varname></term>
           <listitem>
-            <para>Takes a boolean. When <literal>yes</literal>, the termination resistor will be selected for
-            the bias network. When unset, the kernel's default will be used.</para>
+            <para>Takes a boolean or a termination resistor value in ohm in the range 0–65535. When
+            <literal>yes</literal>, the termination resistor is set to 120 ohm. When
+            <literal>no</literal> or <literal>0</literal> is set, the termination resistor is disabled.
+            When unset, the kernel's default will be used.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index 2bba0c9d3bd582dbdd30df3a6304d80033572409..105a2d64074e198cbc889c9a70b54f410c599e77 100644 (file)
@@ -10,7 +10,7 @@
 #include "parse-util.h"
 #include "string-util.h"
 
-#define CAN_TERMINATION_OHM_VALUE 120
+#define CAN_TERMINATION_DEFAULT_OHM_VALUE 120
 
 int can_set_netlink_message(Link *link, sd_netlink_message *m) {
         int r;
@@ -90,11 +90,10 @@ int can_set_netlink_message(Link *link, sd_netlink_message *m) {
                         return log_link_debug_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
         }
 
-        if (link->network->can_termination >= 0) {
-                log_link_debug(link, "Setting can-termination to '%s'.", yes_no(link->network->can_termination));
+        if (link->network->can_termination_set) {
+                log_link_debug(link, "Setting can-termination to '%u'.", link->network->can_termination);
 
-                r = sd_netlink_message_append_u16(m, IFLA_CAN_TERMINATION,
-                                link->network->can_termination ? CAN_TERMINATION_OHM_VALUE : 0);
+                r = sd_netlink_message_append_u16(m, IFLA_CAN_TERMINATION, link->network->can_termination);
                 if (r < 0)
                         return log_link_debug_errno(link, r, "Could not append IFLA_CAN_TERMINATION attribute: %m");
         }
@@ -227,3 +226,49 @@ int config_parse_can_control_mode(
         SET_FLAG(network->can_control_mode_flags, mask, r);
         return 0;
 }
+
+int config_parse_can_termination(
+                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) {
+
+        Network *network = userdata;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                network->can_termination_set = false;
+                return 0;
+        }
+
+        /* Note that 0 termination ohm value means no termination resistor, and there is no conflict
+         * between parse_boolean() and safe_atou16() when Termination=0. However, Termination=1 must be
+         * treated as 1 ohm, instead of true (and then the default ohm value). So, we need to parse the
+         * string with safe_atou16() at first. */
+
+        r = safe_atou16(rvalue, &network->can_termination);
+        if (r < 0) {
+                r = parse_boolean(rvalue);
+                if (r < 0) {
+                        log_syntax(unit, LOG_WARNING, filename, line, r,
+                                   "Failed to parse CAN termination value, ignoring: %s", rvalue);
+                        return 0;
+                }
+
+                network->can_termination = r ? CAN_TERMINATION_DEFAULT_OHM_VALUE : 0;
+        }
+
+        network->can_termination_set = true;
+        return 0;
+}
index 1efa6c920179af9457ee9d1c7f59da09e4df708a..ff1a014a158518fae40bdfe49d46d11403cf9287 100644 (file)
@@ -14,3 +14,4 @@ int can_set_netlink_message(Link *link, sd_netlink_message *m);
 CONFIG_PARSER_PROTOTYPE(config_parse_can_bitrate);
 CONFIG_PARSER_PROTOTYPE(config_parse_can_restart_usec);
 CONFIG_PARSER_PROTOTYPE(config_parse_can_control_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_can_termination);
index 489d0480563c5e4fceb3aa3d47ad5ad0bf4818a1..077779cc6b2dc488cfdce7237bd82831cf23c7bd 100644 (file)
@@ -358,7 +358,7 @@ CAN.FDMode,                                  config_parse_can_control_mode,
 CAN.PresumeACK,                              config_parse_can_control_mode,                            CAN_CTRLMODE_PRESUME_ACK,      0
 CAN.FDNonISO,                                config_parse_can_control_mode,                            CAN_CTRLMODE_FD_NON_ISO,       0
 CAN.ClassicDataLengthCode,                   config_parse_can_control_mode,                            CAN_CTRLMODE_CC_LEN8_DLC,      0
-CAN.Termination,                             config_parse_tristate,                                    0,                             offsetof(Network, can_termination)
+CAN.Termination,                             config_parse_can_termination,                             0,                             0
 QDisc.Parent,                                config_parse_qdisc_parent,                                _QDISC_KIND_INVALID,           0
 QDisc.Handle,                                config_parse_qdisc_handle,                                _QDISC_KIND_INVALID,           0
 BFIFO.Parent,                                config_parse_qdisc_parent,                                QDISC_KIND_BFIFO,              0
index 1fa223fd73a296164056de9fb4f2508a57f4c012..488d49e3acd90e62f0b6295f3541891565ebcfbf 100644 (file)
@@ -270,7 +270,8 @@ struct Network {
         usec_t can_restart_us;
         uint32_t can_control_mode_mask;
         uint32_t can_control_mode_flags;
-        int can_termination;
+        uint16_t can_termination;
+        bool can_termination_set;
 
         /* sysctl settings */
         AddressFamily ip_forward;