@@ -11,6 +11,7 @@ import (
1111 "log/slog"
1212 "regexp"
1313 "slices"
14+ "sort"
1415 "strconv"
1516 "strings"
1617 "time"
@@ -94,6 +95,7 @@ const (
9495 NICTableName = "NIC"
9596 NetworkIRQMappingTableName = "Network IRQ Mapping"
9697 NetworkConfigTableName = "Network Configuration"
98+ NICPacketSteeringTableName = "NIC Packet Steering"
9799 DiskTableName = "Disk"
98100 FilesystemTableName = "Filesystem"
99101 GPUTableName = "GPU"
@@ -380,6 +382,13 @@ var tableDefinitions = map[string]TableDefinition{
380382 script .SysctlScriptName ,
381383 },
382384 FieldsFunc : networkConfigTableValues },
385+ NICPacketSteeringTableName : {
386+ Name : NICPacketSteeringTableName ,
387+ HasRows : true ,
388+ ScriptNames : []string {
389+ script .NicInfoScriptName ,
390+ },
391+ FieldsFunc : nicPacketSteeringTableValues },
383392 NetworkIRQMappingTableName : {
384393 Name : NetworkIRQMappingTableName ,
385394 HasRows : true ,
@@ -1625,6 +1634,9 @@ func nicTableValues(outputs map[string]script.ScriptOutput) []Field {
16251634 {Name : "Driver" },
16261635 {Name : "Driver Version" },
16271636 {Name : "Firmware Version" },
1637+ {Name : "MTU" , Description : "Maximum Transmission Unit. The largest size packet or frame, specified in octets (eight-bit bytes), that can be sent in a packet- or frame-based network such as the Internet." },
1638+ {Name : "TX Queues" },
1639+ {Name : "RX Queues" },
16281640 {Name : "IRQBalance" , Description : "System level setting. Dynamically monitors system activity and spreads IRQs across available cores, aiming to balance CPU load, improve throughput, and reduce latency for interrupt-heavy workloads." },
16291641 {Name : "Adaptive RX" , Description : "Enables dynamic adjustment of receive interrupt coalescing based on traffic patterns." },
16301642 {Name : "Adaptive TX" , Description : "Enables dynamic adjustment of transmit interrupt coalescing based on traffic patterns." },
@@ -1660,15 +1672,80 @@ func nicTableValues(outputs map[string]script.ScriptOutput) []Field {
16601672 fields [9 ].Values = append (fields [9 ].Values , nicInfo .Driver )
16611673 fields [10 ].Values = append (fields [10 ].Values , nicInfo .DriverVersion )
16621674 fields [11 ].Values = append (fields [11 ].Values , nicInfo .FirmwareVersion )
1663- fields [12 ].Values = append (fields [12 ].Values , nicInfo .IRQBalance )
1664- fields [13 ].Values = append (fields [13 ].Values , nicInfo .AdaptiveRX )
1665- fields [14 ].Values = append (fields [14 ].Values , nicInfo .AdaptiveTX )
1666- fields [15 ].Values = append (fields [15 ].Values , nicInfo .RxUsecs )
1667- fields [16 ].Values = append (fields [16 ].Values , nicInfo .TxUsecs )
1675+ fields [12 ].Values = append (fields [12 ].Values , nicInfo .MTU )
1676+ fields [13 ].Values = append (fields [13 ].Values , nicInfo .TXQueues )
1677+ fields [14 ].Values = append (fields [14 ].Values , nicInfo .RXQueues )
1678+ fields [15 ].Values = append (fields [15 ].Values , nicInfo .IRQBalance )
1679+ fields [16 ].Values = append (fields [16 ].Values , nicInfo .AdaptiveRX )
1680+ fields [17 ].Values = append (fields [17 ].Values , nicInfo .AdaptiveTX )
1681+ fields [18 ].Values = append (fields [18 ].Values , nicInfo .RxUsecs )
1682+ fields [19 ].Values = append (fields [19 ].Values , nicInfo .TxUsecs )
16681683 }
16691684 return fields
16701685}
16711686
1687+ func nicPacketSteeringTableValues (outputs map [string ]script.ScriptOutput ) []Field {
1688+ allNicsInfo := parseNicInfo (outputs [script .NicInfoScriptName ].Stdout )
1689+ if len (allNicsInfo ) == 0 {
1690+ return []Field {}
1691+ }
1692+
1693+ fields := []Field {
1694+ {Name : "Interface" },
1695+ {Name : "Type" , Description : "XPS (Transmit Packet Steering) and RPS (Receive Packet Steering) are software-based mechanisms that allow the selection of a specific logical CPU core to handle the transmission or processing of network packets for a given queue." },
1696+ {Name : "Queue:CPU(s) | Queue|CPU(s) | ..." },
1697+ }
1698+
1699+ for _ , nicInfo := range allNicsInfo {
1700+ // XPS row
1701+ if nicInfo .TXQueues != "0" {
1702+ fields [0 ].Values = append (fields [0 ].Values , nicInfo .Name )
1703+ fields [1 ].Values = append (fields [1 ].Values , "xps_cpus" )
1704+ fields [2 ].Values = append (fields [2 ].Values , formatQueueCPUMappings (nicInfo .XPSCPUs , "tx-" ))
1705+ }
1706+
1707+ // RPS row
1708+ if nicInfo .RXQueues != "0" {
1709+ fields [0 ].Values = append (fields [0 ].Values , nicInfo .Name )
1710+ fields [1 ].Values = append (fields [1 ].Values , "rps_cpus" )
1711+ fields [2 ].Values = append (fields [2 ].Values , formatQueueCPUMappings (nicInfo .RPSCPUs , "rx-" ))
1712+ }
1713+ }
1714+
1715+ if len (fields [0 ].Values ) == 0 {
1716+ return []Field {}
1717+ }
1718+ return fields
1719+ }
1720+
1721+ func formatQueueCPUMappings (mappings map [string ]string , prefix string ) string {
1722+ var queueMappings []string
1723+
1724+ // Extract and sort queue numbers to ensure consistent output
1725+ var queues []int
1726+ for queueStr := range mappings {
1727+ queueNum , err := strconv .Atoi (strings .TrimPrefix (queueStr , prefix ))
1728+ if err == nil {
1729+ queues = append (queues , queueNum )
1730+ }
1731+ }
1732+ sort .Ints (queues )
1733+
1734+ for _ , queueNum := range queues {
1735+ queueStr := fmt .Sprintf ("%s%d" , prefix , queueNum )
1736+ cpus := mappings [queueStr ]
1737+ // a nil value can be returned from the map if the key does not exist, so check for that
1738+ if cpus != "" {
1739+ queueMappings = append (queueMappings , fmt .Sprintf ("%d:%s" , queueNum , cpus ))
1740+ }
1741+ }
1742+
1743+ if len (queueMappings ) == 0 {
1744+ return "N/A"
1745+ }
1746+ return strings .Join (queueMappings , " | " )
1747+ }
1748+
16721749func networkIRQMappingTableValues (outputs map [string ]script.ScriptOutput ) []Field {
16731750 nicIRQMappings := nicIRQMappingsFromOutput (outputs )
16741751 if len (nicIRQMappings ) == 0 {
0 commit comments