From 6049ddcca2e723cd92ef5c5b335c4461342dd23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 30 May 2023 12:15:28 +0200 Subject: [PATCH 1/3] shared/ethtool-util: autogenerate table of link mode names We updated this table manually, but the kernel adds new modes periodically and we forget to do that. So let that happen automatically whenever we import new kernel headers. C.f. 72dda93acba95a330daae45bd85be8abc788df1c. Effectively, this adds: [ETHTOOL_LINK_MODE_10baseT1L_Full_BIT] = "10baset1l-full", [ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT] = "800000basecr8-full", [ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT] = "800000basekr8-full", [ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT] = "800000basedr8-full", [ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT] = "800000basedr8-2-full", [ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT] = "800000basesr8-full", [ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT] = "800000basevr8-full", N_ADVERTISE needed to be increased because we need more bits. --- src/shared/ethtool-link-mode.py | 33 ++++++++++++ src/shared/ethtool-util.c | 93 +-------------------------------- src/shared/ethtool-util.h | 2 +- src/shared/meson.build | 9 ++++ 4 files changed, 44 insertions(+), 93 deletions(-) create mode 100644 src/shared/ethtool-link-mode.py diff --git a/src/shared/ethtool-link-mode.py b/src/shared/ethtool-link-mode.py new file mode 100644 index 00000000000..a113177de12 --- /dev/null +++ b/src/shared/ethtool-link-mode.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1-or-later + +import re +import sys + +OVERRIDES = { + 'autoneg' : 'autonegotiation', +} +count = 0 + +f = open(sys.argv[1]) +for line in f: + if line.startswith('enum ethtool_link_mode_bit_indices {'): + break +for line in f: + if line.startswith('}'): + break + # ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, + m = re.match(r'^\s*(ETHTOOL_LINK_MODE_(.*)_BIT)\s*=\s*(\d+),', line) + if not m: + continue + enum, name, value = m.groups() + + name = name.lower().replace('_', '-') + name = OVERRIDES.get(name, name) + + enum = f'[{enum}]' + + print(f' {enum:50} = "{name}",') + count += 1 + +assert count >= 99 diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index e978b8bf7ea..dce9e005fee 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -151,98 +151,7 @@ static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = { }; static const char* const ethtool_link_mode_bit_table[] = { - [ETHTOOL_LINK_MODE_10baseT_Half_BIT] = "10baset-half", - [ETHTOOL_LINK_MODE_10baseT_Full_BIT] = "10baset-full", - [ETHTOOL_LINK_MODE_100baseT_Half_BIT] = "100baset-half", - [ETHTOOL_LINK_MODE_100baseT_Full_BIT] = "100baset-full", - [ETHTOOL_LINK_MODE_1000baseT_Half_BIT] = "1000baset-half", - [ETHTOOL_LINK_MODE_1000baseT_Full_BIT] = "1000baset-full", - [ETHTOOL_LINK_MODE_Autoneg_BIT] = "autonegotiation", - [ETHTOOL_LINK_MODE_TP_BIT] = "tp", - [ETHTOOL_LINK_MODE_AUI_BIT] = "aui", - [ETHTOOL_LINK_MODE_MII_BIT] = "mii", - [ETHTOOL_LINK_MODE_FIBRE_BIT] = "fibre", - [ETHTOOL_LINK_MODE_BNC_BIT] = "bnc", - [ETHTOOL_LINK_MODE_10000baseT_Full_BIT] = "10000baset-full", - [ETHTOOL_LINK_MODE_Pause_BIT] = "pause", - [ETHTOOL_LINK_MODE_Asym_Pause_BIT] = "asym-pause", - [ETHTOOL_LINK_MODE_2500baseX_Full_BIT] = "2500basex-full", - [ETHTOOL_LINK_MODE_Backplane_BIT] = "backplane", - [ETHTOOL_LINK_MODE_1000baseKX_Full_BIT] = "1000basekx-full", - [ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT] = "10000basekx4-full", - [ETHTOOL_LINK_MODE_10000baseKR_Full_BIT] = "10000basekr-full", - [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = "10000baser-fec", - [ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT] = "20000basemld2-full", - [ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT] = "20000basekr2-full", - [ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT] = "40000basekr4-full", - [ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT] = "40000basecr4-full", - [ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT] = "40000basesr4-full", - [ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT] = "40000baselr4-full", - [ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT] = "56000basekr4-full", - [ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT] = "56000basecr4-full", - [ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT] = "56000basesr4-full", - [ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT] = "56000baselr4-full", - [ETHTOOL_LINK_MODE_25000baseCR_Full_BIT] = "25000basecr-full", - [ETHTOOL_LINK_MODE_25000baseKR_Full_BIT] = "25000basekr-full", - [ETHTOOL_LINK_MODE_25000baseSR_Full_BIT] = "25000basesr-full", - [ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT] = "50000basecr2-full", - [ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT] = "50000basekr2-full", - [ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT] = "100000basekr4-full", - [ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT] = "100000basesr4-full", - [ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT] = "100000basecr4-full", - [ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT] = "100000baselr4-er4-full", - [ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT] = "50000basesr2-full", - [ETHTOOL_LINK_MODE_1000baseX_Full_BIT] = "1000basex-full", - [ETHTOOL_LINK_MODE_10000baseCR_Full_BIT] = "10000basecr-full", - [ETHTOOL_LINK_MODE_10000baseSR_Full_BIT] = "10000basesr-full", - [ETHTOOL_LINK_MODE_10000baseLR_Full_BIT] = "10000baselr-full", - [ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT] = "10000baselrm-full", - [ETHTOOL_LINK_MODE_10000baseER_Full_BIT] = "10000baseer-full", - [ETHTOOL_LINK_MODE_2500baseT_Full_BIT] = "2500baset-full", - [ETHTOOL_LINK_MODE_5000baseT_Full_BIT] = "5000baset-full", - [ETHTOOL_LINK_MODE_FEC_NONE_BIT] = "fec-none", - [ETHTOOL_LINK_MODE_FEC_RS_BIT] = "fec-rs", - [ETHTOOL_LINK_MODE_FEC_BASER_BIT] = "fec-baser", - [ETHTOOL_LINK_MODE_50000baseKR_Full_BIT] = "50000basekr-full", - [ETHTOOL_LINK_MODE_50000baseSR_Full_BIT] = "50000basesr-full", - [ETHTOOL_LINK_MODE_50000baseCR_Full_BIT] = "50000basecr-full", - [ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT] = "50000baselr-er-fr-full", - [ETHTOOL_LINK_MODE_50000baseDR_Full_BIT] = "50000basedr-full", - [ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT] = "100000basekr2-full", - [ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT] = "100000basesr2-full", - [ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT] = "100000basecr2-full", - [ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT] = "100000baselr2-er2-fr2-full", - [ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT] = "100000basedr2-full", - [ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT] = "200000basekr4-full", - [ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT] = "200000basesr4-full", - [ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT] = "200000baselr4-er4-fr4-full", - [ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT] = "200000basedr4-full", - [ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT] = "200000basecr4-full", - [ETHTOOL_LINK_MODE_100baseT1_Full_BIT] = "100baset1-full", - [ETHTOOL_LINK_MODE_1000baseT1_Full_BIT] = "1000baset1-full", - [ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT] = "400000basekr8-full", - [ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT] = "400000basesr8-full", - [ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT] = "400000baselr8-er8-fr8-full", - [ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT] = "400000basedr8-full", - [ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT] = "400000basecr8-full", - [ETHTOOL_LINK_MODE_FEC_LLRS_BIT] = "fec-llrs", - [ETHTOOL_LINK_MODE_100000baseKR_Full_BIT] = "100000basekr-full", - [ETHTOOL_LINK_MODE_100000baseSR_Full_BIT] = "100000basesr-full", - [ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT] = "100000baselr-er-fr-full", - [ETHTOOL_LINK_MODE_100000baseCR_Full_BIT] = "100000basecr-full", - [ETHTOOL_LINK_MODE_100000baseDR_Full_BIT] = "100000basedr-full", - [ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT] = "200000basekr2-full", - [ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT] = "200000basesr2-full", - [ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT] = "200000baselr2-er2-fr2-full", - [ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT] = "200000basedr2-full", - [ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT] = "200000basecr2-full", - [ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT] = "400000basekr4-full", - [ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT] = "400000basesr4-full", - [ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT] = "400000baselr4-er4-fr4-full", - [ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT] = "400000basedr4-full", - [ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT] = "400000basecr4-full", - [ETHTOOL_LINK_MODE_100baseFX_Half_BIT] = "100basefx-half", - [ETHTOOL_LINK_MODE_100baseFX_Full_BIT] = "100basefx-full", +# include "ethtool-link-mode.h" }; /* Make sure the array is large enough to fit all bits */ assert_cc((ELEMENTSOF(ethtool_link_mode_bit_table)-1) / 32 < N_ADVERTISE); diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h index 84dd444d338..5303cd75046 100644 --- a/src/shared/ethtool-util.h +++ b/src/shared/ethtool-util.h @@ -8,7 +8,7 @@ #include "conf-parser.h" #include "ether-addr-util.h" -#define N_ADVERTISE 3 +#define N_ADVERTISE 4 /* we can't use DUPLEX_ prefix, as it * clashes with */ diff --git a/src/shared/meson.build b/src/shared/meson.build index 021ba517f8a..5a40d09bd51 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -270,6 +270,15 @@ target2 = custom_target( shared_generated_gperf_headers = [target1, target2] shared_sources += shared_generated_gperf_headers +fname = 'ethtool-link-mode.h' +ethtool_link_mode_h = custom_target( + fname, + input : ['ethtool-link-mode.py', 'linux/ethtool.h'], + output : fname, + command : [python, '@INPUT0@', '@INPUT1@'], + capture : true) +shared_sources += ethtool_link_mode_h + libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag) libshared_deps = [threads, From c18dde32e5b6c6f523fb312668c6fb4f87236978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 30 May 2023 13:02:57 +0200 Subject: [PATCH 2/3] man: generate link mode list dynamically The entries are sorted by speed. Some fields are left empty when there is no clear value to use. The table is much longer now, but I think it's better to document the allowed values, even if some are not terribly useful. Fixes #26256. --- man/meson.build | 16 ++++++----- man/systemd.link.xml | 47 +++------------------------------ meson.build | 2 ++ src/shared/ethtool-link-mode.py | 38 ++++++++++++++++++++------ src/shared/meson.build | 10 +++++++ tools/xml_helper.py | 2 ++ 6 files changed, 57 insertions(+), 58 deletions(-) diff --git a/man/meson.build b/man/meson.build index e6724a53f4a..4dc5fabd6de 100644 --- a/man/meson.build +++ b/man/meson.build @@ -20,7 +20,9 @@ xsltproc_flags = [ '--stringparam', 'man.copyright.section.enabled', '0', '--stringparam', 'systemd.version', '@0@'.format(meson.project_version()), '--path', - '@0@:@1@'.format(meson.current_build_dir(), meson.current_source_dir())] + '@0@:@1@:@2@'.format(meson.current_build_dir(), + meson.current_source_dir(), + libshared_build_dir)] custom_man_xsl = files('custom-man.xsl') custom_html_xsl = files('custom-html.xsl') @@ -32,6 +34,8 @@ custom_entities_ent = custom_target( output : 'custom-entities.ent', command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@']) +man_page_depends += custom_entities_ent + man_pages = [] html_pages = [] source_xml_files = [] @@ -68,7 +72,7 @@ foreach tuple : manpages input : xml, output : [man] + manaliases, command : xslt_cmd + [custom_man_xsl, '@INPUT@'], - depends : custom_entities_ent, + depends : man_page_depends, install : want_man, install_dir : mandirn) man_pages += p1 @@ -93,7 +97,7 @@ foreach tuple : manpages input : xml, output : html, command : xslt_cmd + [custom_html_xsl, '@INPUT@'], - depends : [custom_entities_ent, p2], + depends : [man_page_depends, p2], install : want_html, install_dir : docdir / 'html') html_pages += p3 @@ -114,7 +118,7 @@ systemd_directives_xml = custom_target( 'systemd.directives.xml', input : ['directives-template.xml', source_xml_files], output : 'systemd.directives.xml', - depends : custom_entities_ent, + depends : man_page_depends, command : [make_directive_index_py, '@OUTPUT@', '@INPUT@']) nonindex_xml_files = source_xml_files + [systemd_directives_xml] @@ -166,7 +170,7 @@ foreach tuple : xsltproc.found() ? [['systemd.directives', '7', systemd_directiv input : xml, output : html, command : xslt_cmd + [custom_html_xsl, '@INPUT@'], - depends : [custom_entities_ent, p2], + depends : [man_page_depends, p2], install : want_html and have_lxml, install_dir : docdir / 'html') html_pages += p3 @@ -237,4 +241,4 @@ update_man_rules = custom_target( command : [update_man_rules_py, '@0@/man/*.xml'.format(project_source_root), '@0@/rules/meson.build'.format(meson.current_source_dir())], - depends : custom_entities_ent) + depends : man_page_depends) diff --git a/man/systemd.link.xml b/man/systemd.link.xml index cc851d31f98..af9e247fc4d 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -3,7 +3,8 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - + systemd.link systemd @@ -709,49 +710,7 @@ Speed (Mbps) Duplex Mode - - - 10half - - - 10full - - - 100half - - - 100full - - - 1000half - - - 1000full - - - 10000full - - - 2500full - - - 1000full - - - 10000full - - - 10000full - - - 10000full - - - 20000full - - - 20000full - + diff --git a/meson.build b/meson.build index 97622b6d973..3919a4a9b05 100644 --- a/meson.build +++ b/meson.build @@ -2172,6 +2172,8 @@ userspace = declare_dependency( link_args : userspace_c_ld_args, ) +man_page_depends = [] + ############################################################ # binaries that have --help and are intended for use by humans, diff --git a/src/shared/ethtool-link-mode.py b/src/shared/ethtool-link-mode.py index a113177de12..03ea1b1fd88 100644 --- a/src/shared/ethtool-link-mode.py +++ b/src/shared/ethtool-link-mode.py @@ -7,27 +7,49 @@ import sys OVERRIDES = { 'autoneg' : 'autonegotiation', } -count = 0 -f = open(sys.argv[1]) +xml = sys.argv[1] == '--xml' + +f = open(sys.argv[-1]) for line in f: if line.startswith('enum ethtool_link_mode_bit_indices {'): break + +entries = [] for line in f: if line.startswith('}'): break # ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, - m = re.match(r'^\s*(ETHTOOL_LINK_MODE_(.*)_BIT)\s*=\s*(\d+),', line) + m = re.match(r'^\s*(ETHTOOL_LINK_MODE_((\d*).*)_BIT)\s*=\s*(\d+),', line) if not m: continue - enum, name, value = m.groups() + enum, name, speed, value = m.groups() name = name.lower().replace('_', '-') name = OVERRIDES.get(name, name) - enum = f'[{enum}]' + duplex = name.split('-')[-1].lower() + if duplex not in {'half', 'full'}: + duplex = '' - print(f' {enum:50} = "{name}",') - count += 1 + entries += [(enum, name, speed, value, duplex)] -assert count >= 99 +if xml: + print(' ') + + entries.sort(key=lambda entry: (int(entry[2]) if entry[2] else 1e20, entry[4], entry[1], entry[3])) + +for enum, name, speed, value, duplex in entries: + if xml: + print(f'''\ + + {speed}{duplex} + ''') + else: + enum = f'[{enum}]' + print(f' {enum:50} = "{name}",') + +if xml: + print(' ') + +assert len(entries) >= 99 diff --git a/src/shared/meson.build b/src/shared/meson.build index 5a40d09bd51..d78b9176c0c 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -279,6 +279,15 @@ ethtool_link_mode_h = custom_target( capture : true) shared_sources += ethtool_link_mode_h +fname = 'ethtool-link-mode.xml' +ethtool_link_mode_xml = custom_target( + fname, + input : ['ethtool-link-mode.py', 'linux/ethtool.h'], + output : fname, + command : [python, '@INPUT0@', '--xml', '@INPUT1@'], + capture : true) +man_page_depends += ethtool_link_mode_xml + libshared_name = 'systemd-shared-@0@'.format(shared_lib_tag) libshared_deps = [threads, @@ -304,6 +313,7 @@ libshared_deps = [threads, versiondep] libshared_sym_path = '@0@/libshared.sym'.format(meson.current_source_dir()) +libshared_build_dir = meson.current_build_dir() libshared_static = static_library( libshared_name, diff --git a/tools/xml_helper.py b/tools/xml_helper.py index 0361358bec2..bc14298653d 100755 --- a/tools/xml_helper.py +++ b/tools/xml_helper.py @@ -7,6 +7,8 @@ class CustomResolver(tree.Resolver): def resolve(self, url, id, context): if 'custom-entities.ent' in url: return self.resolve_filename('man/custom-entities.ent', context) + if 'ethtool-link-mode' in url: + return self.resolve_filename('src/shared/ethtool-link-mode.xml', context) _parser = tree.XMLParser() _parser.resolvers.add(CustomResolver()) From 1e473c2ebbcfd510238ea9d031ca7d73a9591a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 6 Jun 2023 09:54:20 +0200 Subject: [PATCH 3/3] meson: use "cpp -E -dM" to process header file This was requested in review: https://github.com/systemd/systemd/pull/27846#discussion_r1210383265 I kept this as separate commit because the change would impact both of the previous commits and splitting it up seems like unnecessary work. The result is unchanged. v2: - use universal_newlines=True to keep compat with Python 3.6 on C8S. --- src/shared/ethtool-link-mode.py | 14 ++++++++++---- src/shared/meson.build | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/shared/ethtool-link-mode.py b/src/shared/ethtool-link-mode.py index 03ea1b1fd88..aac1576145e 100644 --- a/src/shared/ethtool-link-mode.py +++ b/src/shared/ethtool-link-mode.py @@ -2,21 +2,27 @@ # SPDX-License-Identifier: LGPL-2.1-or-later import re +import shlex +import subprocess import sys OVERRIDES = { 'autoneg' : 'autonegotiation', } -xml = sys.argv[1] == '--xml' +mode, cpp, header = sys.argv[1:] +xml = mode == '--xml' -f = open(sys.argv[-1]) -for line in f: +command = [*shlex.split(cpp), '-include', header, '-'] +out = subprocess.check_output(command, stdin=subprocess.DEVNULL, universal_newlines=True) + +lines = iter(out.splitlines()) +for line in lines: if line.startswith('enum ethtool_link_mode_bit_indices {'): break entries = [] -for line in f: +for line in lines: if line.startswith('}'): break # ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, diff --git a/src/shared/meson.build b/src/shared/meson.build index d78b9176c0c..f2ed6b17743 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -275,7 +275,7 @@ ethtool_link_mode_h = custom_target( fname, input : ['ethtool-link-mode.py', 'linux/ethtool.h'], output : fname, - command : [python, '@INPUT0@', '@INPUT1@'], + command : [python, '@INPUT0@', '--header', cpp, '@INPUT1@'], capture : true) shared_sources += ethtool_link_mode_h @@ -284,7 +284,7 @@ ethtool_link_mode_xml = custom_target( fname, input : ['ethtool-link-mode.py', 'linux/ethtool.h'], output : fname, - command : [python, '@INPUT0@', '--xml', '@INPUT1@'], + command : [python, '@INPUT0@', '--xml', cpp, '@INPUT1@'], capture : true) man_page_depends += ethtool_link_mode_xml