Skip to content

Commit c6a8b6d

Browse files
ethtool: T7730: Add configuration coalesce for interface
This change introduces CLI support for configuring network interface interrupt coalescing parameters via `ethtool --coalesce`. Note: Not all NIC drivers support interrupt coalescing. On unsupported interfaces, `ethtool` returns an error and the VyOS commit will fail.
1 parent 33f1763 commit c6a8b6d

File tree

5 files changed

+570
-0
lines changed

5 files changed

+570
-0
lines changed

interface-definitions/interfaces_ethernet.xml.in

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,313 @@
221221
</leafNode>
222222
</children>
223223
</node>
224+
<node name="coalesce">
225+
<properties>
226+
<help>Interrupt coalescing options for the interface</help>
227+
</properties>
228+
<children>
229+
<leafNode name="adaptive-rx">
230+
<properties>
231+
<help>Enable adaptive receive interrupt moderation</help>
232+
<valueless/>
233+
</properties>
234+
</leafNode>
235+
<leafNode name="adaptive-tx">
236+
<properties>
237+
<help>Enable adaptive transmit interrupt moderation</help>
238+
<valueless/>
239+
</properties>
240+
</leafNode>
241+
<leafNode name="rx-usecs">
242+
<properties>
243+
<help>Delay in microseconds before generating RX interrupt</help>
244+
<valueHelp>
245+
<format>u32:0-16384</format>
246+
<description>RX interrupt coalescing delay</description>
247+
</valueHelp>
248+
<constraint>
249+
<validator name="numeric" argument="--range 0-16384"/>
250+
</constraint>
251+
</properties>
252+
</leafNode>
253+
<leafNode name="rx-frames">
254+
<properties>
255+
<help>Number of RX frames before generating interrupt</help>
256+
<valueHelp>
257+
<format>u32:0-4294967295</format>
258+
<description>RX interrupt coalescing frames threshold</description>
259+
</valueHelp>
260+
<constraint>
261+
<validator name="numeric" argument="--range 0-4294967295"/>
262+
</constraint>
263+
</properties>
264+
</leafNode>
265+
<leafNode name="rx-usecs-irq">
266+
<properties>
267+
<help>Delay in microseconds before generating RX interrupt while servicing IRQ</help>
268+
<valueHelp>
269+
<format>u32:0-16384</format>
270+
<description>RX IRQ interrupt coalescing delay</description>
271+
</valueHelp>
272+
<constraint>
273+
<validator name="numeric" argument="--range 0-16384"/>
274+
</constraint>
275+
</properties>
276+
</leafNode>
277+
<leafNode name="rx-frames-irq">
278+
<properties>
279+
<help>Number of RX frames before generating interrupt while servicing IRQ</help>
280+
<valueHelp>
281+
<format>u32:0-4294967295</format>
282+
<description>RX IRQ interrupt coalescing frames threshold</description>
283+
</valueHelp>
284+
<constraint>
285+
<validator name="numeric" argument="--range 0-4294967295"/>
286+
</constraint>
287+
</properties>
288+
</leafNode>
289+
<leafNode name="tx-usecs">
290+
<properties>
291+
<help>Delay in microseconds before generating TX interrupt</help>
292+
<valueHelp>
293+
<format>u32:0-16384</format>
294+
<description>TX interrupt coalescing delay</description>
295+
</valueHelp>
296+
<constraint>
297+
<validator name="numeric" argument="--range 0-16384"/>
298+
</constraint>
299+
</properties>
300+
</leafNode>
301+
<leafNode name="tx-frames">
302+
<properties>
303+
<help>Number of TX frames before generating interrupt</help>
304+
<valueHelp>
305+
<format>u32:0-4294967295</format>
306+
<description>TX interrupt coalescing frames threshold</description>
307+
</valueHelp>
308+
<constraint>
309+
<validator name="numeric" argument="--range 0-4294967295"/>
310+
</constraint>
311+
</properties>
312+
</leafNode>
313+
<leafNode name="tx-usecs-irq">
314+
<properties>
315+
<help>Delay in microseconds before generating TX interrupt while servicing IRQ</help>
316+
<valueHelp>
317+
<format>u32:0-16384</format>
318+
<description>TX IRQ interrupt coalescing delay</description>
319+
</valueHelp>
320+
<constraint>
321+
<validator name="numeric" argument="--range 0-16384"/>
322+
</constraint>
323+
</properties>
324+
</leafNode>
325+
<leafNode name="tx-frames-irq">
326+
<properties>
327+
<help>Number of TX frames before generating interrupt while servicing IRQ</help>
328+
<valueHelp>
329+
<format>u32:0-4294967295</format>
330+
<description>TX IRQ interrupt coalescing frames threshold</description>
331+
</valueHelp>
332+
<constraint>
333+
<validator name="numeric" argument="--range 0-4294967295"/>
334+
</constraint>
335+
</properties>
336+
</leafNode>
337+
<leafNode name="stats-block-usecs">
338+
<properties>
339+
<help>Time in microseconds between updating coalescing statistics</help>
340+
<valueHelp>
341+
<format>u32:0-4294967295</format>
342+
<description>Statistics block interval</description>
343+
</valueHelp>
344+
<constraint>
345+
<validator name="numeric" argument="--range 0-4294967295"/>
346+
</constraint>
347+
</properties>
348+
</leafNode>
349+
<leafNode name="pkt-rate-low">
350+
<properties>
351+
<help>Lower packet rate threshold for adaptive coalescing</help>
352+
<valueHelp>
353+
<format>u32:0-4294967295</format>
354+
<description>Low packet rate threshold</description>
355+
</valueHelp>
356+
<constraint>
357+
<validator name="numeric" argument="--range 0-4294967295"/>
358+
</constraint>
359+
</properties>
360+
</leafNode>
361+
<leafNode name="rx-usecs-low">
362+
<properties>
363+
<help>RX coalescing delay (usecs) for low packet rate</help>
364+
<valueHelp>
365+
<format>u32:0-16384</format>
366+
<description>Low-rate RX coalescing delay</description>
367+
</valueHelp>
368+
<constraint>
369+
<validator name="numeric" argument="--range 0-16384"/>
370+
</constraint>
371+
</properties>
372+
</leafNode>
373+
<leafNode name="rx-frames-low">
374+
<properties>
375+
<help>RX coalescing frames threshold for low packet rate</help>
376+
<valueHelp>
377+
<format>u32:0-4294967295</format>
378+
<description>Low-rate RX coalescing frames threshold</description>
379+
</valueHelp>
380+
<constraint>
381+
<validator name="numeric" argument="--range 0-4294967295"/>
382+
</constraint>
383+
</properties>
384+
</leafNode>
385+
<leafNode name="tx-usecs-low">
386+
<properties>
387+
<help>TX coalescing delay (usecs) for low packet rate</help>
388+
<valueHelp>
389+
<format>u32:0-16384</format>
390+
<description>Low-rate TX coalescing delay</description>
391+
</valueHelp>
392+
<constraint>
393+
<validator name="numeric" argument="--range 0-16384"/>
394+
</constraint>
395+
</properties>
396+
</leafNode>
397+
<leafNode name="tx-frames-low">
398+
<properties>
399+
<help>TX coalescing frames threshold for low packet rate</help>
400+
<valueHelp>
401+
<format>u32:0-4294967295</format>
402+
<description>Low-rate TX coalescing frames threshold</description>
403+
</valueHelp>
404+
<constraint>
405+
<validator name="numeric" argument="--range 0-4294967295"/>
406+
</constraint>
407+
</properties>
408+
</leafNode>
409+
<leafNode name="pkt-rate-high">
410+
<properties>
411+
<help>Upper packet rate threshold for adaptive coalescing</help>
412+
<valueHelp>
413+
<format>u32:0-4294967295</format>
414+
<description>High packet rate threshold</description>
415+
</valueHelp>
416+
<constraint>
417+
<validator name="numeric" argument="--range 0-4294967295"/>
418+
</constraint>
419+
</properties>
420+
</leafNode>
421+
<leafNode name="rx-usecs-high">
422+
<properties>
423+
<help>RX coalescing delay (usecs) for high packet rate</help>
424+
<valueHelp>
425+
<format>u32:0-16384</format>
426+
<description>High-rate RX coalescing delay</description>
427+
</valueHelp>
428+
<constraint>
429+
<validator name="numeric" argument="--range 0-16384"/>
430+
</constraint>
431+
</properties>
432+
</leafNode>
433+
<leafNode name="rx-frames-high">
434+
<properties>
435+
<help>RX coalescing frames threshold for high packet rate</help>
436+
<valueHelp>
437+
<format>u32:0-4294967295</format>
438+
<description>High-rate RX coalescing frames threshold</description>
439+
</valueHelp>
440+
<constraint>
441+
<validator name="numeric" argument="--range 0-4294967295"/>
442+
</constraint>
443+
</properties>
444+
</leafNode>
445+
<leafNode name="tx-usecs-high">
446+
<properties>
447+
<help>TX coalescing delay (usecs) for high packet rate</help>
448+
<valueHelp>
449+
<format>u32:0-16384</format>
450+
<description>High-rate TX coalescing delay</description>
451+
</valueHelp>
452+
<constraint>
453+
<validator name="numeric" argument="--range 0-16384"/>
454+
</constraint>
455+
</properties>
456+
</leafNode>
457+
<leafNode name="tx-frames-high">
458+
<properties>
459+
<help>TX coalescing frames threshold for high packet rate</help>
460+
<valueHelp>
461+
<format>u32:0-4294967295</format>
462+
<description>High-rate TX coalescing frames threshold</description>
463+
</valueHelp>
464+
<constraint>
465+
<validator name="numeric" argument="--range 0-4294967295"/>
466+
</constraint>
467+
</properties>
468+
</leafNode>
469+
<leafNode name="sample-interval">
470+
<properties>
471+
<help>Sampling interval for adaptive coalescing (in seconds)</help>
472+
<valueHelp>
473+
<format>u32:0-4294967295</format>
474+
<description>Adaptive sampling interval</description>
475+
</valueHelp>
476+
<constraint>
477+
<validator name="numeric" argument="--range 0-4294967295"/>
478+
</constraint>
479+
</properties>
480+
</leafNode>
481+
<leafNode name="cqe-mode-rx">
482+
<properties>
483+
<help>Enable RX CQE (Completion Queue Entry) mode</help>
484+
<valueless/>
485+
</properties>
486+
</leafNode>
487+
<leafNode name="cqe-mode-tx">
488+
<properties>
489+
<help>Enable TX CQE (Completion Queue Entry) mode</help>
490+
<valueless/>
491+
</properties>
492+
</leafNode>
493+
<leafNode name="tx-aggr-max-bytes">
494+
<properties>
495+
<help>Maximum number of bytes to aggregate before transmitting</help>
496+
<valueHelp>
497+
<format>u32:0-4294967295</format>
498+
<description>TX aggregation maximum bytes</description>
499+
</valueHelp>
500+
<constraint>
501+
<validator name="numeric" argument="--range 0-4294967295"/>
502+
</constraint>
503+
</properties>
504+
</leafNode>
505+
<leafNode name="tx-aggr-max-frames">
506+
<properties>
507+
<help>Maximum number of frames to aggregate before transmitting</help>
508+
<valueHelp>
509+
<format>u32:0-4294967295</format>
510+
<description>TX aggregation maximum frames</description>
511+
</valueHelp>
512+
<constraint>
513+
<validator name="numeric" argument="--range 0-4294967295"/>
514+
</constraint>
515+
</properties>
516+
</leafNode>
517+
<leafNode name="tx-aggr-time-usecs">
518+
<properties>
519+
<help>Maximum time in microseconds to wait before transmitting aggregated frames</help>
520+
<valueHelp>
521+
<format>u32:0-16384</format>
522+
<description>TX aggregation timeout</description>
523+
</valueHelp>
524+
<constraint>
525+
<validator name="numeric" argument="--range 0-16384"/>
526+
</constraint>
527+
</properties>
528+
</leafNode>
529+
</children>
530+
</node>
224531
#include <include/interface/redirect.xml.i>
225532
#include <include/interface/vif-s.xml.i>
226533
#include <include/interface/vif.xml.i>

python/vyos/ethtool.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class Ethtool:
6565
_driver_name = None
6666
_flow_control = None
6767
_channels = ''
68+
_coalesce = None
6869

6970
def __init__(self, ifname):
7071
# Get driver used for interface
@@ -122,6 +123,54 @@ def __init__(self, ifname):
122123
if not bool(err):
123124
self._channels = out.lower()
124125

126+
# Get information about NIC coalesce settings
127+
out, err = popen(f'ethtool --show-coalesce {ifname}')
128+
if not bool(err):
129+
self._coalesce = self._parse_ethtool_coalesce(out)
130+
131+
def _parse_ethtool_coalesce(self, output: str) -> dict:
132+
"""
133+
Parse 'ethtool --show-coalesce' command output into a structured dictionary
134+
"""
135+
136+
result = {}
137+
kv_pattern = re.compile(r'([\w\- ]+):\s+([\w/]+)')
138+
139+
for line in output.splitlines():
140+
line = line.strip()
141+
if not line or 'Coalesce parameters' in line:
142+
continue
143+
144+
# Match one or more key-value pairs in the same line
145+
matches = kv_pattern.findall(line)
146+
for key, value in matches:
147+
normalized_key = key.strip().lower().replace(' ', '_').replace('-', '_')
148+
149+
# Convert line which has two parameters in one line
150+
if normalized_key == 'tx':
151+
# 'Adaptive RX: n/a TX: n/a' -> 'adaptive_rx' and 'adaptive_tx'
152+
if line.startswith('Adaptive RX:'):
153+
normalized_key = 'adaptive_tx'
154+
155+
# 'CQE mode RX: n/a TX: n/a' -> 'cqe_mode_rx' and 'cqe_mode_tx'
156+
if line.startswith('CQE mode RX:'):
157+
normalized_key = 'cqe_mode_tx'
158+
159+
# Normalize and typecast value
160+
val_lower = value.lower()
161+
if val_lower == 'n/a':
162+
parsed_val = None
163+
elif val_lower in ('on', 'off'):
164+
parsed_val = val_lower == 'on'
165+
elif value.isdigit():
166+
parsed_val = int(value)
167+
else:
168+
parsed_val = value
169+
170+
result[normalized_key] = parsed_val
171+
172+
return result
173+
125174
def check_auto_negotiation_supported(self):
126175
""" Check if the NIC supports changing auto-negotiation """
127176
return self._base_settings['supports-auto-negotiation']
@@ -235,3 +284,16 @@ def check_mac_change(self) -> bool:
235284
def check_bonding(self) -> bool:
236285
""" Check if ethernet drivers supports bonding """
237286
return bool(self.get_driver_name() not in _drivers_without_bonding_support)
287+
288+
def check_coalesce(self, setting_name=None):
289+
"""Check if the NIC supports 'coalesce' setting(s)"""
290+
291+
if not self._coalesce:
292+
return False
293+
294+
return self._coalesce.get(setting_name) is not None if setting_name else True
295+
296+
def get_coalesce(self):
297+
"""Get all 'coalesce' settings for the interface"""
298+
299+
return self._coalesce.copy() if self._coalesce else {}

0 commit comments

Comments
 (0)