Skip to content

Commit 245f31c

Browse files
authored
Merge pull request #1288 from kernelkit/misc
Fix 'show dhcp-server' output in CLI and operational
2 parents bd2f346 + fdb0289 commit 245f31c

File tree

6 files changed

+80
-6
lines changed

6 files changed

+80
-6
lines changed

board/aarch64/bananapi-bpi-r3/rootfs/usr/share/product/bananapi,bpi-r3/etc/factory-config.cfg

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@
113113
{"id": "vendor-class", "value": "Banana Pi BPI-R3"}
114114
]
115115
}
116+
},
117+
"ietf-ip:ipv6": {
118+
"infix-dhcpv6-client:dhcp": {
119+
"option": [
120+
{"id": "ntp-server"},
121+
{"id": "client-fqdn"},
122+
{"id": "domain-search"},
123+
{"id": "dns-server"}
124+
]
125+
}
116126
}
117127
},
118128
{
@@ -284,6 +294,7 @@
284294
"policy": [
285295
{
286296
"name": "lan-to-wan",
297+
"action": "accept",
287298
"ingress": [
288299
"lan"
289300
],

board/aarch64/friendlyarm-nanopi-r2s/rootfs/usr/share/product/friendlyarm,nanopi-r2s/etc/factory-config.cfg

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@
7272
{"id": "vendor-class", "value": "NanoPi R2S"}
7373
]
7474
}
75+
},
76+
"ietf-ip:ipv6": {
77+
"infix-dhcpv6-client:dhcp": {
78+
"option": [
79+
{"id": "ntp-server"},
80+
{"id": "client-fqdn"},
81+
{"id": "domain-search"},
82+
{"id": "dns-server"}
83+
]
84+
}
7585
}
7686
}
7787
]
@@ -235,6 +245,7 @@
235245
"policy": [
236246
{
237247
"name": "lan-to-wan",
248+
"action": "accept",
238249
"ingress": [
239250
"lan"
240251
],

doc/ChangeLog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ All notable changes to the project are documented in this file.
6868
- Add support for property-based filtering with operators (contains, isequal,
6969
startswith, regex, ereregex) on message properties (msg, msgid, programname,
7070
hostname, source, data), with optional case-insensitive and negate modifiers
71+
- Update factory configuration for BPi-R3 and NanoPi R2S boards to enable
72+
DHCPv6 client on WAN interface and allow traffic forwarding from LAN to WAN
73+
zone in the firewall (this is what most users expect)
7174

7275
### Fixes
7376

@@ -80,6 +83,12 @@ All notable changes to the project are documented in this file.
8083
- Fix #1255: serious regression in boot time, introduced in v25.10, delays the
8184
boot step "Mounting filesystems ...", from 30 seconds up to five minutes!
8285
- Fix broken intra-document links in container and tunnel documentation
86+
- Fix `show dhcp-server` command crashing with invalid timestamp format.
87+
DHCP lease expiry timestamps had double timezone suffix causing libyang
88+
validation errors
89+
- Fix `show dhcp-server` output alignment. The EXPIRES column was misaligned
90+
when CLIENT ID field was empty, and CLIENT ID column was too narrow for
91+
typical 20-character client IDs
8392

8493
[latest-boot]: https://github.com/kernelkit/infix/releases/latest-boot
8594
[bpi-r3-emmc-documentation]: https://github.com/kernelkit/infix/blob/main/board/aarch64/bananapi-bpi-r3/README.md

src/statd/python/cli_pretty/cli_pretty.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class PadDhcpServer:
154154
ip = 17
155155
mac = 19
156156
host = 21
157-
cid = 19
157+
cid = 22
158158
exp = 10
159159

160160

@@ -652,7 +652,20 @@ def get_formatted_value(self):
652652
else:
653653
return f"{self.value} W"
654654

655+
# Handle PWM fan sensors (reported as "other" type with milli scale)
656+
# PWM duty cycle is reported as percentage (0-100)
657+
elif self.value_type == 'other' and self.value_scale == 'milli':
658+
# Check if this is likely a PWM sensor based on description or name
659+
name_lower = self.name.lower()
660+
desc_lower = (self.description or "").lower()
661+
if 'pwm' in desc_lower or 'fan' in name_lower or 'fan' in desc_lower:
662+
percent = self.value / 1000.0
663+
return f"{percent:.1f}%"
664+
# Fall through for other "other" type sensors
665+
655666
# For unknown sensor types, show raw value
667+
if self.value_type in ['other', 'unknown']:
668+
return f"{self.value}"
656669
else:
657670
return f"{self.value} {self.value_type}"
658671

@@ -720,11 +733,11 @@ def __init__(self, data):
720733
now = datetime.now(timezone.utc)
721734
for lease in get_json_data([], self.data, 'leases', 'lease'):
722735
if lease["expires"] == "never":
723-
exp = " never"
736+
exp = "never"
724737
else:
725738
dt = datetime.strptime(lease['expires'], '%Y-%m-%dT%H:%M:%S%z')
726739
seconds = int((dt - now).total_seconds())
727-
exp = f" {self.format_duration(seconds)}"
740+
exp = self.format_duration(seconds)
728741
self.leases.append({
729742
"ip": lease["address"],
730743
"mac": lease["phys-address"],
@@ -775,7 +788,7 @@ def print(self):
775788
row += f"{mac:<{PadDhcpServer.mac}}"
776789
row += f"{host:<{PadDhcpServer.host}}"
777790
row += f"{cid:<{PadDhcpServer.cid}}"
778-
row += f"{exp:>{PadDhcpServer.exp - 1}}"
791+
row += f"{exp:>{PadDhcpServer.exp}}"
779792
print(row)
780793

781794
def print_stats(self):

src/statd/python/yanger/ietf_hardware.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def create_sensor(sensor_name, value, value_type, value_scale, label=None):
297297
except (FileNotFoundError, ValueError, IOError):
298298
continue
299299

300-
# Fan sensors
300+
# Fan sensors (RPM from tachometer)
301301
for fan_file in glob.glob(os.path.join(hwmon_path, "fan*_input")):
302302
try:
303303
sensor_num = os.path.basename(fan_file).split('_')[0].replace('fan', '')
@@ -314,6 +314,36 @@ def create_sensor(sensor_name, value, value_type, value_scale, label=None):
314314
except (FileNotFoundError, ValueError, IOError):
315315
continue
316316

317+
# PWM fan sensors (duty cycle percentage)
318+
# Only add if no fan*_input exists for this device (avoid duplicates)
319+
has_rpm_sensor = bool(glob.glob(os.path.join(hwmon_path, "fan*_input")))
320+
if not has_rpm_sensor:
321+
for pwm_file in glob.glob(os.path.join(hwmon_path, "pwm[0-9]*")):
322+
# Skip pwm*_enable, pwm*_mode, etc. - only process pwm1, pwm2, etc.
323+
pwm_basename = os.path.basename(pwm_file)
324+
if not pwm_basename.replace('pwm', '').isdigit():
325+
continue
326+
try:
327+
sensor_num = pwm_basename.replace('pwm', '')
328+
pwm_raw = int(HOST.read(pwm_file).strip())
329+
# Convert PWM duty cycle (0-255) to percentage (0-100)
330+
# Note: Some devices are inverted (255=off, 0=max), but we report as-is
331+
# The value represents duty cycle, not necessarily fan speed
332+
# Use "other" value-type since PWM duty cycle isn't a standard IETF type
333+
value = int((pwm_raw / 255.0) * 100 * 1000) # Convert to milli-percent (0-100000)
334+
label_file = os.path.join(hwmon_path, f"pwm{sensor_num}_label")
335+
raw_label = None
336+
if HOST.exists(label_file):
337+
raw_label = HOST.read(label_file).strip()
338+
label = normalize_sensor_name(raw_label)
339+
sensor_name = f"{base_name}-{label}"
340+
else:
341+
sensor_name = base_name if sensor_num == '1' else f"{base_name}{sensor_num}"
342+
# Use "PWM Fan" as description so it displays nicely in show hardware
343+
add_sensor(base_name, create_sensor(sensor_name, value, "other", "milli", raw_label or "PWM Fan"))
344+
except (FileNotFoundError, ValueError, IOError):
345+
continue
346+
317347
# Voltage sensors
318348
for voltage_file in glob.glob(os.path.join(hwmon_path, "in*_input")):
319349
try:

src/statd/python/yanger/infix_dhcp_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def leases(leases_file):
2323
else:
2424
dt = datetime.fromtimestamp(int(tokens[0]),
2525
tz=timezone.utc)
26-
expires = dt.isoformat() + "+00:00"
26+
expires = dt.isoformat()
2727

2828
row = {
2929
"expires": expires,

0 commit comments

Comments
 (0)