chiark / gitweb /
core: clean up some confusing regarding SI decimal and IEC binary suffixes for sizes
authorLennart Poettering <lennart@poettering.net>
Sun, 23 Feb 2014 02:13:54 +0000 (03:13 +0100)
committerLennart Poettering <lennart@poettering.net>
Sun, 23 Feb 2014 02:19:04 +0000 (03:19 +0100)
According to Wikipedia it is customary to specify hardware metrics and
transfer speeds to the basis 1000 (SI decimal), while software metrics
and physical volatile memory (RAM) sizes to the basis 1024 (IEC binary).
So far we specified everything in IEC, let's fix that and be more
true to what's otherwise customary. Since we don't want to parse "Mi"
instead of "M" we document each time what the context used is.

13 files changed:
man/systemd.resource-control.xml
man/systemd.socket.xml
man/udev.xml
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/journal/journald-gperf.gperf
src/shared/conf-parser.c
src/shared/conf-parser.h
src/shared/util.c
src/shared/util.h
src/systemctl/systemctl.c
src/test/test-util.c
src/udev/net/link-config-gperf.gperf

index 0ee983b1c3d5d213a8879c219e1ecf44ee3b5ef2..e923b6da867cf1363a13a725bb8e25174792b157 100644 (file)
@@ -226,14 +226,15 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
           case the backing block device of the file system of the file
           is used. If the bandwidth is suffixed with K, M, G, or T,
           the specified bandwidth is parsed as Kilobytes, Megabytes,
-          Gigabytes, or Terabytes, respectively (Example:
+          Gigabytes, or Terabytes, respectively, to the base of
+          1000. (Example:
           "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This
           controls the <literal>blkio.read_bps_device</literal> and
           <literal>blkio.write_bps_device</literal> control group
           attributes. Use this option multiple times to set bandwidth
           limits for multiple devices. For details about these control
-          group attributes, see
-          <ulink url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
+          group attributes, see <ulink
+          url="https://www.kernel.org/doc/Documentation/cgroups/blkio-controller.txt">blkio-controller.txt</ulink>.
           </para>
 
           <para>Implies
index 5e9b39f38f1856370cada543a4dc099c6e16d53d..d645de45e10ae074a1c64412c9c29450d045edd1 100644 (file)
                                 <term><varname>ReceiveBuffer=</varname></term>
                                 <term><varname>SendBuffer=</varname></term>
                                 <listitem><para>Takes an integer
-                                argument controlling the receive
-                                or send buffer sizes of this
-                                socket, respectively. This controls the SO_RCVBUF
-                                and SO_SNDBUF socket options (see
+                                argument controlling the receive or
+                                send buffer sizes of this socket,
+                                respectively. This controls the
+                                SO_RCVBUF and SO_SNDBUF socket options
+                                (see
                                 <citerefentry><refentrytitle>socket</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-                                for details.).</para></listitem>
+                                for details.). The usual suffixes K,
+                                M, G are supported and are understood
+                                to the base of 1024.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
 
                         <varlistentry>
                                 <term><varname>PipeSize=</varname></term>
-                                <listitem><para>Takes an integer
-                                value. Controls the pipe buffer size
+                                <listitem><para>Takes an size in
+                                bytes. Controls the pipe buffer size
                                 of FIFOs configured in this socket
                                 unit. See
                                 <citerefentry><refentrytitle>fcntl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-                                for details.</para></listitem>
+                                for details. The usual suffixes K, M,
+                                G are supported and are understood to
+                                the base of 1024.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
index 9733b85760569a429455c4ea672d9b38cf44ffc1..95b37fd0cfdee7e5d5cb819baa25ac7631b54fd9 100644 (file)
         <varlistentry>
           <term><varname>MTUBytes=</varname></term>
           <listitem>
-            <para>The maximum transmission unit in bytes to set for the device.</para>
+            <para>The maximum transmission unit in bytes to set for
+            the device. The usual suffixes K, M, G, are supported and
+            are understood to the base of 1024.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
           <term><varname>BitsPerSecond=</varname></term>
           <listitem>
-            <para>The speed to set for the device, the value is rounded down
-            to the nearest Mbps.</para>
+            <para>The speed to set for the device, the value is
+            rounded down to the nearest Mbps. The usual suffixes K, M,
+            G, are supported and are understood to the base of
+            1000.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index e1bab7a2643be18003ebb80cae1dd4fdb2f85c65..26146b192784d74826fad42a728b4d7fd238e229 100644 (file)
@@ -219,12 +219,12 @@ Socket.Accept,                   config_parse_bool,                  0,
 Socket.MaxConnections,           config_parse_unsigned,              0,                             offsetof(Socket, max_connections)
 Socket.KeepAlive,                config_parse_bool,                  0,                             offsetof(Socket, keep_alive)
 Socket.Priority,                 config_parse_int,                   0,                             offsetof(Socket, priority)
-Socket.ReceiveBuffer,            config_parse_bytes_size,            0,                             offsetof(Socket, receive_buffer)
-Socket.SendBuffer,               config_parse_bytes_size,            0,                             offsetof(Socket, send_buffer)
+Socket.ReceiveBuffer,            config_parse_iec_size,              0,                             offsetof(Socket, receive_buffer)
+Socket.SendBuffer,               config_parse_iec_size,              0,                             offsetof(Socket, send_buffer)
 Socket.IPTOS,                    config_parse_ip_tos,                0,                             offsetof(Socket, ip_tos)
 Socket.IPTTL,                    config_parse_int,                   0,                             offsetof(Socket, ip_ttl)
 Socket.Mark,                     config_parse_int,                   0,                             offsetof(Socket, mark)
-Socket.PipeSize,                 config_parse_bytes_size,            0,                             offsetof(Socket, pipe_size)
+Socket.PipeSize,                 config_parse_iec_size,              0,                             offsetof(Socket, pipe_size)
 Socket.FreeBind,                 config_parse_bool,                  0,                             offsetof(Socket, free_bind)
 Socket.Transparent,              config_parse_bool,                  0,                             offsetof(Socket, transparent)
 Socket.Broadcast,                config_parse_bool,                  0,                             offsetof(Socket, broadcast)
index 5b1e99092115215363f2b4dcc02ba20fab7d2e13..82aed1eb92c08e9805b7292df1eaae64f2d02bb4 100644 (file)
@@ -2327,10 +2327,9 @@ int config_parse_memory_limit(
 
         assert_cc(sizeof(uint64_t) == sizeof(off_t));
 
-        r = parse_bytes(rvalue, &bytes);
+        r = parse_size(rvalue, 1024, &bytes);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Memory limit '%s' invalid. Ignoring.", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue);
                 return 0;
         }
 
@@ -2563,10 +2562,9 @@ int config_parse_blockio_bandwidth(
                 return 0;
         }
 
-        r = parse_bytes(bandwidth, &bytes);
+        r = parse_size(bandwidth, 1000, &bytes);
         if (r < 0 || bytes <= 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
                 return 0;
         }
 
@@ -2964,7 +2962,9 @@ void unit_dump_config_items(FILE *f) {
 #endif
                 { config_parse_int,                   "INTEGER" },
                 { config_parse_unsigned,              "UNSIGNED" },
-                { config_parse_bytes_size,            "SIZE" },
+                { config_parse_iec_size,              "SIZE" },
+                { config_parse_iec_off,               "SIZE" },
+                { config_parse_si_size,               "SIZE" },
                 { config_parse_bool,                  "BOOLEAN" },
                 { config_parse_string,                "STRING" },
                 { config_parse_path,                  "PATH" },
index 2ecba3bd0e90e955a51663b62928dd5a52759f85..84efee317683aa0839711b7a6a537310523e311d 100644 (file)
@@ -21,12 +21,12 @@ Journal.Seal,               config_parse_bool,      0, offsetof(Server, seal)
 Journal.SyncIntervalSec,    config_parse_sec,       0, offsetof(Server, sync_interval_usec)
 Journal.RateLimitInterval,  config_parse_sec,       0, offsetof(Server, rate_limit_interval)
 Journal.RateLimitBurst,     config_parse_unsigned,  0, offsetof(Server, rate_limit_burst)
-Journal.SystemMaxUse,       config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_use)
-Journal.SystemMaxFileSize,  config_parse_bytes_off, 0, offsetof(Server, system_metrics.max_size)
-Journal.SystemKeepFree,     config_parse_bytes_off, 0, offsetof(Server, system_metrics.keep_free)
-Journal.RuntimeMaxUse,      config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_use)
-Journal.RuntimeMaxFileSize, config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.max_size)
-Journal.RuntimeKeepFree,    config_parse_bytes_off, 0, offsetof(Server, runtime_metrics.keep_free)
+Journal.SystemMaxUse,       config_parse_iec_off,   0, offsetof(Server, system_metrics.max_use)
+Journal.SystemMaxFileSize,  config_parse_iec_off,   0, offsetof(Server, system_metrics.max_size)
+Journal.SystemKeepFree,     config_parse_iec_off,   0, offsetof(Server, system_metrics.keep_free)
+Journal.RuntimeMaxUse,      config_parse_iec_off,   0, offsetof(Server, runtime_metrics.max_use)
+Journal.RuntimeMaxFileSize, config_parse_iec_off,   0, offsetof(Server, runtime_metrics.max_size)
+Journal.RuntimeKeepFree,    config_parse_iec_off,   0, offsetof(Server, runtime_metrics.keep_free)
 Journal.MaxRetentionSec,    config_parse_sec,       0, offsetof(Server, max_retention_usec)
 Journal.MaxFileSec,         config_parse_sec,       0, offsetof(Server, max_file_usec)
 Journal.ForwardToSyslog,    config_parse_bool,      0, offsetof(Server, forward_to_syslog)
index dde62b575501d66c04e2880b01e8058a34b79278..cfa669b1139bd416bbb4d1aec1c5a5da46e8c5cd 100644 (file)
@@ -447,8 +447,7 @@ DEFINE_PARSER(double, double, safe_atod)
 DEFINE_PARSER(nsec, nsec_t, parse_nsec)
 DEFINE_PARSER(sec, usec_t, parse_sec)
 
-
-int config_parse_bytes_size(const char* unit,
+int config_parse_iec_size(const char* unit,
                             const char *filename,
                             unsigned line,
                             const char *section,
@@ -468,10 +467,9 @@ int config_parse_bytes_size(const char* unit,
         assert(rvalue);
         assert(data);
 
-        r = parse_bytes(rvalue, &o);
+        r = parse_size(rvalue, 1024, &o);
         if (r < 0 || (off_t) (size_t) o != o) {
-                log_syntax(unit, LOG_ERR, filename, line, -r,
-                           "Failed to parse byte value, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -479,8 +477,37 @@ int config_parse_bytes_size(const char* unit,
         return 0;
 }
 
+int config_parse_si_size(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) {
+
+        size_t *sz = data;
+        off_t o;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = parse_size(rvalue, 1000, &o);
+        if (r < 0 || (off_t) (size_t) o != o) {
+                log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        *sz = (size_t) o;
+        return 0;
+}
 
-int config_parse_bytes_off(const char* unit,
+int config_parse_iec_off(const char* unit,
                            const char *filename,
                            unsigned line,
                            const char *section,
@@ -501,10 +528,9 @@ int config_parse_bytes_off(const char* unit,
 
         assert_cc(sizeof(off_t) == sizeof(uint64_t));
 
-        r = parse_bytes(rvalue, bytes);
+        r = parse_size(rvalue, 1024, bytes);
         if (r < 0)
-                log_syntax(unit, LOG_ERR, filename, line, -r,
-                           "Failed to parse bytes value, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse size value, ignoring: %s", rvalue);
 
         return 0;
 }
index ebbcaa54fe14a205328c296485e4fbf6892f5368..4ccdaddd296284460dc11c5e5cd877ec5e15322e 100644 (file)
@@ -97,8 +97,9 @@ int config_parse_unsigned(const char *unit, const char *filename, unsigned line,
 int config_parse_long(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);
 int config_parse_uint64(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);
 int config_parse_double(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);
-int config_parse_bytes_size(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);
-int config_parse_bytes_off(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);
+int config_parse_iec_size(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);
+int config_parse_si_size(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);
+int config_parse_iec_off(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);
 int config_parse_bool(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);
 int config_parse_show_status(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);
 int config_parse_string(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);
index b33f1203e672f5c99fe6904e36d30484dc910b90..5cb598c4c56169365f448a925180937ed5f2da0c 100644 (file)
@@ -2135,11 +2135,28 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
         return n;
 }
 
-int parse_bytes(const char *t, off_t *bytes) {
-        static const struct {
+int parse_size(const char *t, off_t base, off_t *size) {
+
+        /* Soo, sometimes we want to parse IEC binary suffxies, and
+         * sometimes SI decimal suffixes. This function can parse
+         * both. Which one is the right way depends on the
+         * context. Wikipedia suggests that SI is customary for
+         * hardrware metrics and network speeds, while IEC is
+         * customary for most data sizes used by software and volatile
+         * (RAM) memory. Hence be careful which one you pick!
+         *
+         * In either case we use just K, M, G as suffix, and not Ki,
+         * Mi, Gi or so (as IEC would suggest). That's because that's
+         * frickin' ugly. But this means you really need to make sure
+         * to document which base you are parsing when you use this
+         * call. */
+
+        struct table {
                 const char *suffix;
                 unsigned long long factor;
-        } table[] = {
+        };
+
+        static const struct table iec[] = {
                 { "B", 1 },
                 { "K", 1024ULL },
                 { "M", 1024ULL*1024ULL },
@@ -2150,11 +2167,33 @@ int parse_bytes(const char *t, off_t *bytes) {
                 { "", 1 },
         };
 
+        static const struct table si[] = {
+                { "B", 1 },
+                { "K", 1000ULL },
+                { "M", 1000ULL*1000ULL },
+                { "G", 1000ULL*1000ULL*1000ULL },
+                { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
+                { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
+                { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
+                { "", 1 },
+        };
+
+        const struct table *table;
         const char *p;
         unsigned long long r = 0;
+        unsigned n_entries;
 
         assert(t);
-        assert(bytes);
+        assert(base == 1000 || base == 1024);
+        assert(size);
+
+        if (base == 1000) {
+                table = si;
+                n_entries = ELEMENTSOF(si);
+        } else {
+                table = iec;
+                n_entries = ELEMENTSOF(iec);
+        }
 
         p = t;
         do {
@@ -2176,7 +2215,7 @@ int parse_bytes(const char *t, off_t *bytes) {
 
                 e += strspn(e, WHITESPACE);
 
-                for (i = 0; i < ELEMENTSOF(table); i++)
+                for (i = 0; i < n_entries; i++)
                         if (startswith(e, table[i].suffix)) {
                                 unsigned long long tmp;
                                 if ((unsigned long long) l > ULLONG_MAX / table[i].factor)
@@ -2193,12 +2232,12 @@ int parse_bytes(const char *t, off_t *bytes) {
                                 break;
                         }
 
-                if (i >= ELEMENTSOF(table))
+                if (i >= n_entries)
                         return -EINVAL;
 
         } while (*p);
 
-        *bytes = r;
+        *size = r;
 
         return 0;
 }
index d1230d2b64cd65be71f97d7524cd22f40e41504b..9913fcefaeba3ff6a4bfd16aaf0cec0cd2fa5828 100644 (file)
@@ -144,8 +144,9 @@ int close_nointr(int fd);
 void close_nointr_nofail(int fd);
 void close_many(const int fds[], unsigned n_fd);
 
+int parse_size(const char *t, off_t base, off_t *size);
+
 int parse_boolean(const char *v) _pure_;
-int parse_bytes(const char *t, off_t *bytes);
 int parse_pid(const char *s, pid_t* ret_pid);
 int parse_uid(const char *s, uid_t* ret_uid);
 #define parse_gid(s, ret_uid) parse_uid(s, ret_uid)
index 3375bac985566dc6b3d8ebb9f8e33a6712193c2f..c5ca8dc11d19e5bd7195fa9885e12bc697dc909a 100644 (file)
@@ -4045,7 +4045,7 @@ static int append_assignment(sd_bus_message *m, const char *assignment) {
         } else if (streq(field, "MemoryLimit")) {
                 off_t bytes;
 
-                r = parse_bytes(eq, &bytes);
+                r = parse_size(eq, 1024, &bytes);
                 if (r < 0) {
                         log_error("Failed to parse bytes specification %s", assignment);
                         return -EINVAL;
@@ -4115,7 +4115,7 @@ static int append_assignment(sd_bus_message *m, const char *assignment) {
                                 return -EINVAL;
                         }
 
-                        r = parse_bytes(bandwidth, &bytes);
+                        r = parse_size(bandwidth, 1000, &bytes);
                         if (r < 0) {
                                 log_error("Failed to parse byte value %s.", bandwidth);
                                 return -EINVAL;
index 1ac4a1edd1192127106acdfd29a32905f1fcc69b..b718206e86141d43d7ace2fb842090daf9e32432 100644 (file)
@@ -435,42 +435,42 @@ static void test_protect_errno(void) {
         assert(errno == 12);
 }
 
-static void test_parse_bytes(void) {
+static void test_parse_size(void) {
         off_t bytes;
 
-        assert_se(parse_bytes("111", &bytes) == 0);
+        assert_se(parse_size("111", 1024, &bytes) == 0);
         assert_se(bytes == 111);
 
-        assert_se(parse_bytes(" 112 B", &bytes) == 0);
+        assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
         assert_se(bytes == 112);
 
-        assert_se(parse_bytes("3 K", &bytes) == 0);
+        assert_se(parse_size("3 K", 1024, &bytes) == 0);
         assert_se(bytes == 3*1024);
 
-        assert_se(parse_bytes(" 4 M 11K", &bytes) == 0);
+        assert_se(parse_size(" 4 M 11K", 1024, &bytes) == 0);
         assert_se(bytes == 4*1024*1024 + 11 * 1024);
 
-        assert_se(parse_bytes("3B3G", &bytes) == 0);
+        assert_se(parse_size("3B3G", 1024, &bytes) == 0);
         assert_se(bytes == 3ULL*1024*1024*1024 + 3);
 
-        assert_se(parse_bytes("3B3G4T", &bytes) == 0);
+        assert_se(parse_size("3B3G4T", 1024, &bytes) == 0);
         assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
 
-        assert_se(parse_bytes("12P", &bytes) == 0);
+        assert_se(parse_size("12P", 1024, &bytes) == 0);
         assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
 
-        assert_se(parse_bytes("3E 2P", &bytes) == 0);
+        assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
         assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
 
-        assert_se(parse_bytes("12X", &bytes) == -EINVAL);
+        assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
 
-        assert_se(parse_bytes("1024E", &bytes) == -ERANGE);
-        assert_se(parse_bytes("-1", &bytes) == -ERANGE);
-        assert_se(parse_bytes("-1024E", &bytes) == -ERANGE);
+        assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
+        assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
+        assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
 
-        assert_se(parse_bytes("-1024P", &bytes) == -ERANGE);
+        assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
 
-        assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE);
+        assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
 }
 
 static void test_strextend(void) {
@@ -617,7 +617,7 @@ int main(int argc, char *argv[]) {
         test_u64log2();
         test_get_process_comm();
         test_protect_errno();
-        test_parse_bytes();
+        test_parse_size();
         test_strextend();
         test_strrep();
         test_split_pair();
index 3384ca0418b3e22229c6049158ce75c85f179b0b..819e93c4d78ad987cb86dfa0a2a309ce9ccb1ecc 100644 (file)
@@ -30,7 +30,7 @@ Link.MACAddress,           config_parse_hwaddr,        0,
 Link.NamePolicy,           config_parse_name_policy,   0,                             offsetof(link_config, name_policy)
 Link.Name,                 config_parse_ifname,        0,                             offsetof(link_config, name)
 Link.Alias,                config_parse_ifalias,       0,                             offsetof(link_config, alias)
-Link.MTUBytes,             config_parse_bytes_size,    0,                             offsetof(link_config, mtu)
-Link.BitsPerSecond,        config_parse_bytes_size,    0,                             offsetof(link_config, speed)
+Link.MTUBytes,             config_parse_iec_size,      0,                             offsetof(link_config, mtu)
+Link.BitsPerSecond,        config_parse_si_size,       0,                             offsetof(link_config, speed)
 Link.Duplex,               config_parse_duplex,        0,                             offsetof(link_config, duplex)
 Link.WakeOnLan,            config_parse_wol,           0,                             offsetof(link_config, wol)