common: has-quirk: Add support for matching based on "ethtool -i"

In addition to matching on interface names, add support for matching
on ethtool information.

Example:

    {
        "@ethtool:driver=st_gmac": {
	    "broken-mqprio": true
	}
    }

This would mark any interface using the "st_gmac" driver as having a
broken mqprio implementation. Whereas this:

    {
        "@ethtool:driver=st_gmac;bus-info:30bf0000.ethernet": {
	    "broken-mqprio": true
	}
    }

Only matches an st_gmac-backed interface at the specified location.

As matching becomes more complicated, use the shell implementation
from confd as well, to make sure that they are always in agreement.
This commit is contained in:
Tobias Waldekranz
2025-10-02 14:51:29 +02:00
parent 7c019190c8
commit 39b4101d19
2 changed files with 45 additions and 18 deletions
@@ -1,12 +1,49 @@
#!/bin/sh
#!/bin/bash
IFQUIRKSFILE=${IFQUIRKSFILE:-/etc/product/interface-quirks.json}
if [ $# -lt 2 ]; then
echo "usage: $0 <quirk-name> <ifname>"
exit 1
fi
quirk=$1
ifname=$2
if [ -f "/etc/product/interface-quirks.json" ]; then
echo "$(jq -r --arg iface "$ifname" --arg quirk "$quirk" '.[$iface][$quirk] // "false"' /etc/product/interface-quirks.json)"
else
echo "false"
fi
[ -f "$IFQUIRKSFILE" ] || { echo false && exit; }
match()
{
jq -e \
--arg quirk "$quirk" --arg pattern "$1" \
'.[$pattern][$quirk]' "$IFQUIRKSFILE" >/dev/null || return
echo true
exit 0
}
ethtoolmatch()
{
local pattern="${1#@ethtool:}"
grep -qFxvf \
<(ethtool -i "$ifname") \
<(echo -n "$pattern" | awk -v FS="=" -v RS=";" '{ printf("%s: %s\n", $1, $2); }') \
&& return
match "@ethtool:$pattern"
}
for pattern in $(jq -r 'keys[]' "$IFQUIRKSFILE"); do
case "$pattern" in
@ethtool:*)
ethtoolmatch "$pattern"
;;
"$ifname")
match "$ifname"
;;
esac
done
echo "false"
+2 -12
View File
@@ -17,18 +17,8 @@
bool iface_has_quirk(const char *ifname, const char *quirkname)
{
struct json_t *iface, *quirk;
if (!confd.ifquirks)
return false;
iface = json_object_get(confd.ifquirks, ifname);
if (!iface)
return false;
quirk = json_object_get(iface, quirkname);
return quirk ? json_is_true(quirk) : false;
return systemf("[ $(/usr/libexec/infix/has-quirk %s %s) = true ]",
quirkname, ifname) == 0;
}
static bool iface_is_phys(const char *ifname)