Repository: prometheus/procfs
Pull request #549 (2023-07-11 14:42:25)

Add `hw_counters` for infiniband device.
This change adds `hw_counters` to the existing infiniband class so that additional counter information for infiniband devices can be obtained.

In preparing this PR, I have confirmed that `hw_counters` for Infiniband devices can be obtained from the `mlx5_core` kernel module included in multiple Linux distributions and multiple OS versions.
I have also confirmed that it is possible to get `hw_counters` from the `mlx5_core` kernel module included in the [OFED driver](https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/).
However, I have not checked for other cases (e.g. mlx4_core), so this implementation is limited to mlx5 only.



Patch:
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index 100cf93..8ace97b 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -1,3 +1,5 @@
+---
+# This action is synced from https://github.com/prometheus/prometheus
 name: golangci-lint
 on:
   push:
@@ -16,15 +18,15 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v3
+        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
       - name: install Go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
         with:
           go-version: 1.20.x
       - name: Install snmp_exporter/generator dependencies
         run: sudo apt-get update && sudo apt-get -y install libsnmp-dev
         if: github.repository == 'prometheus/snmp_exporter'
       - name: Lint
-        uses: golangci/golangci-lint-action@v3.4.0
+        uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
         with:
-          version: v1.51.2
+          version: v1.54.2
diff --git a/Makefile.common b/Makefile.common
index 787feff..062a281 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -55,13 +55,13 @@ ifneq ($(shell command -v gotestsum > /dev/null),)
 endif
 endif
 
-PROMU_VERSION ?= 0.14.0
+PROMU_VERSION ?= 0.15.0
 PROMU_URL     := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
 
 SKIP_GOLANGCI_LINT :=
 GOLANGCI_LINT :=
 GOLANGCI_LINT_OPTS ?=
-GOLANGCI_LINT_VERSION ?= v1.53.3
+GOLANGCI_LINT_VERSION ?= v1.54.2
 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64.
 # windows isn't included here because of the path separator being different.
 ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
diff --git a/btrfs/get.go b/btrfs/get.go
index 8c5149a..77c72e1 100644
--- a/btrfs/get.go
+++ b/btrfs/get.go
@@ -207,7 +207,7 @@ func (r *reader) calcRatio(p string) float64 {
 
 // readDeviceInfo returns the information for all devices associated with this filesystem.
 func (r *reader) readDeviceInfo(d string) map[string]*Device {
-	devs := r.listFiles("devices")
+	devs := r.listFiles(d)
 	info := make(map[string]*Device, len(devs))
 	for _, n := range devs {
 		info[n] = &Device{
diff --git a/fs.go b/fs.go
index 60c551e..4980c87 100644
--- a/fs.go
+++ b/fs.go
@@ -20,8 +20,8 @@ import (
 // FS represents the pseudo-filesystem sys, which provides an interface to
 // kernel data structures.
 type FS struct {
-	proc fs.FS
-	real bool
+	proc   fs.FS
+	isReal bool
 }
 
 // DefaultMountPoint is the common mount point of the proc filesystem.
@@ -41,10 +41,10 @@ func NewFS(mountPoint string) (FS, error) {
 		return FS{}, err
 	}
 
-	real, err := isRealProc(mountPoint)
+	isReal, err := isRealProc(mountPoint)
 	if err != nil {
 		return FS{}, err
 	}
 
-	return FS{fs, real}, nil
+	return FS{fs, isReal}, nil
 }
diff --git a/fs_statfs_notype.go b/fs_statfs_notype.go
index 8005769..134767d 100644
--- a/fs_statfs_notype.go
+++ b/fs_statfs_notype.go
@@ -11,8 +11,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//go:build netbsd || openbsd || solaris || windows
-// +build netbsd openbsd solaris windows
+//go:build !freebsd && !linux
+// +build !freebsd,!linux
 
 package procfs
 
diff --git a/fs_statfs_type.go b/fs_statfs_type.go
index 6233217..80df79c 100644
--- a/fs_statfs_type.go
+++ b/fs_statfs_type.go
@@ -11,8 +11,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//go:build !netbsd && !openbsd && !solaris && !windows
-// +build !netbsd,!openbsd,!solaris,!windows
+//go:build freebsd || linux
+// +build freebsd linux
 
 package procfs
 
diff --git a/go.mod b/go.mod
index d582993..95cd65f 100644
--- a/go.mod
+++ b/go.mod
@@ -5,5 +5,5 @@ go 1.19
 require (
 	github.com/google/go-cmp v0.5.9
 	golang.org/x/sync v0.3.0
-	golang.org/x/sys v0.9.0
+	golang.org/x/sys v0.11.0
 )
diff --git a/go.sum b/go.sum
index 8f019b2..4d2f8b9 100644
--- a/go.sum
+++ b/go.sum
@@ -2,5 +2,5 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
-golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/iscsi/get.go b/iscsi/get.go
index bee3193..1a77c8c 100644
--- a/iscsi/get.go
+++ b/iscsi/get.go
@@ -195,9 +195,8 @@ func (fs FS) GetRBDMatch(rbdNumber string, poolImage string) (*RBD, error) {
 		bSystemPool, err := os.ReadFile(systemPoolPath)
 		if err != nil {
 			continue
-		} else {
-			systemPool = strings.TrimSpace(string(bSystemPool))
 		}
+		systemPool = strings.TrimSpace(string(bSystemPool))
 
 		systemImagePath := filepath.Join(systemRbdPath, "name")
 		if _, err := os.Stat(systemImagePath); os.IsNotExist(err) {
@@ -206,9 +205,8 @@ func (fs FS) GetRBDMatch(rbdNumber string, poolImage string) (*RBD, error) {
 		bSystemImage, err := os.ReadFile(systemImagePath)
 		if err != nil {
 			continue
-		} else {
-			systemImage = strings.TrimSpace(string(bSystemImage))
 		}
+		systemImage = strings.TrimSpace(string(bSystemImage))
 
 		if strings.Compare(strconv.FormatInt(int64(systemRbdNumber), 10), rbdNumber) == 0 &&
 			matchPoolImage(systemPool, systemImage, poolImage) {
diff --git a/mountstats.go b/mountstats.go
index 852c8c4..9d8af6d 100644
--- a/mountstats.go
+++ b/mountstats.go
@@ -44,6 +44,14 @@ const (
 
 	fieldTransport11TCPLen = 13
 	fieldTransport11UDPLen = 10
+
+	// kernel version >= 4.14 MaxLen
+	// See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393
+	fieldTransport11RDMAMaxLen = 28
+
+	// kernel version <= 4.2 MinLen
+	// See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331
+	fieldTransport11RDMAMinLen = 20
 )
 
 // A Mount is a device mount parsed from /proc/[pid]/mountstats.
@@ -233,6 +241,33 @@ type NFSTransportStats struct {
 	// A running counter, incremented on each request as the current size of the
 	// pending queue.
 	CumulativePendingQueue uint64
+
+	// Stats below only available with stat version 1.1.
+	// Transport over RDMA
+
+	// accessed when sending a call
+	ReadChunkCount   uint64
+	WriteChunkCount  uint64
+	ReplyChunkCount  uint64
+	TotalRdmaRequest uint64
+
+	// rarely accessed error counters
+	PullupCopyCount      uint64
+	HardwayRegisterCount uint64
+	FailedMarshalCount   uint64
+	BadReplyCount        uint64
+	MrsRecovered         uint64
+	MrsOrphaned          uint64
+	MrsAllocated         uint64
+	EmptySendctxQ        uint64
+
+	// accessed when receiving a reply
+	TotalRdmaReply    uint64
+	FixupCopyCount    uint64
+	ReplyWaitsForSend uint64
+	LocalInvNeeded    uint64
+	NomsgCallCount    uint64
+	BcallCount        uint64
 }
 
 // parseMountStats parses a /proc/[pid]/mountstats file and returns a slice
@@ -587,14 +622,17 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 			expectedLength = fieldTransport11TCPLen
 		} else if protocol == "udp" {
 			expectedLength = fieldTransport11UDPLen
+		} else if protocol == "rdma" {
+			expectedLength = fieldTransport11RDMAMinLen
 		} else {
 			return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss)
 		}
-		if len(ss) != expectedLength {
-			return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v", ErrFileParse, ss)
+		if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) ||
+			(protocol == "rdma" && len(ss) < expectedLength) {
+			return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v, protocol: %v", ErrFileParse, ss, protocol)
 		}
 	default:
-		return nil, fmt.Errorf("%s: Unrecognized NFS transport stats version: %q", ErrFileParse, statVersion)
+		return nil, fmt.Errorf("%s: Unrecognized NFS transport stats version: %q, protocol: %v", ErrFileParse, statVersion, protocol)
 	}
 
 	// Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay
@@ -604,7 +642,9 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	// Note: slice length must be set to length of v1.1 stats to avoid a panic when
 	// only v1.0 stats are present.
 	// See: https://github.com/prometheus/node_exporter/issues/571.
-	ns := make([]uint64, fieldTransport11TCPLen)
+	//
+	// Note: NFS Over RDMA slice length is fieldTransport11RDMAMaxLen
+	ns := make([]uint64, fieldTransport11RDMAMaxLen+3)
 	for i, s := range ss {
 		n, err := strconv.ParseUint(s, 10, 64)
 		if err != nil {
@@ -622,9 +662,14 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 	// we set them to 0 here.
 	if protocol == "udp" {
 		ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...)
+	} else if protocol == "tcp" {
+		ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...)
+	} else if protocol == "rdma" {
+		ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...)
 	}
 
 	return &NFSTransportStats{
+		// NFS xprt over tcp or udp
 		Protocol:                 protocol,
 		Port:                     ns[0],
 		Bind:                     ns[1],
@@ -636,8 +681,32 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
 		BadTransactionIDs:        ns[7],
 		CumulativeActiveRequests: ns[8],
 		CumulativeBacklog:        ns[9],
-		MaximumRPCSlotsUsed:      ns[10],
-		CumulativeSendingQueue:   ns[11],
-		CumulativePendingQueue:   ns[12],
+
+		// NFS xprt over tcp or udp
+		// And statVersion 1.1
+		MaximumRPCSlotsUsed:    ns[10],
+		CumulativeSendingQueue: ns[11],
+		CumulativePendingQueue: ns[12],
+
+		// NFS xprt over rdma
+		// And stat Version 1.1
+		ReadChunkCount:       ns[13],
+		WriteChunkCount:      ns[14],
+		ReplyChunkCount:      ns[15],
+		TotalRdmaRequest:     ns[16],
+		PullupCopyCount:      ns[17],
+		HardwayRegisterCount: ns[18],
+		FailedMarshalCount:   ns[19],
+		BadReplyCount:        ns[20],
+		MrsRecovered:         ns[21],
+		MrsOrphaned:          ns[22],
+		MrsAllocated:         ns[23],
+		EmptySendctxQ:        ns[24],
+		TotalRdmaReply:       ns[25],
+		FixupCopyCount:       ns[26],
+		ReplyWaitsForSend:    ns[27],
+		LocalInvNeeded:       ns[28],
+		NomsgCallCount:       ns[29],
+		BcallCount:           ns[30],
 	}, nil
 }
diff --git a/nfs/nfs.go b/nfs/nfs.go
index 7292102..f17fa51 100644
--- a/nfs/nfs.go
+++ b/nfs/nfs.go
@@ -201,51 +201,56 @@ type ServerV4Stats struct {
 // V4Ops models the "proc4ops" line: NFSv4 operations
 // Variable list.
 // See:
-// - v4.0 https://tools.ietf.org/html/rfc3010 (38 operations)
+// - v4.0 https://tools.ietf.org/html/rfc3010 (38/39 operations)
+//   - nfs == v2.5.x 38 field : https://elixir.bootlin.com/linux/v2.5.75/source/include/linux/nfs4.h#L52
+//   - nfs >= v2.6.x 39 field : https://elixir.bootlin.com/linux/v2.6.39.4/source/include/linux/nfs4.h#L233
+//
 // - v4.1 https://tools.ietf.org/html/rfc5661 (58 operations)
 // - v4.2 https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41 (71 operations)
 //
 //nolint:godot
 type V4Ops struct {
 	//Values       uint64 // Variable depending on v4.x sub-version. TODO: Will this always at least include the fields in this struct?
-	Op0Unused    uint64
-	Op1Unused    uint64
-	Op2Future    uint64
-	Access       uint64
-	Close        uint64
-	Commit       uint64
-	Create       uint64
-	DelegPurge   uint64
-	DelegReturn  uint64
-	GetAttr      uint64
-	GetFH        uint64
-	Link         uint64
-	Lock         uint64
-	Lockt        uint64
-	Locku        uint64
-	Lookup       uint64
-	LookupRoot   uint64
-	Nverify      uint64
-	Open         uint64
-	OpenAttr     uint64
-	OpenConfirm  uint64
-	OpenDgrd     uint64
-	PutFH        uint64
-	PutPubFH     uint64
-	PutRootFH    uint64
-	Read         uint64
-	ReadDir      uint64
-	ReadLink     uint64
-	Remove       uint64
-	Rename       uint64
-	Renew        uint64
-	RestoreFH    uint64
-	SaveFH       uint64
-	SecInfo      uint64
-	SetAttr      uint64
-	Verify       uint64
-	Write        uint64
-	RelLockOwner uint64
+	Op0Unused          uint64
+	Op1Unused          uint64
+	Op2Future          uint64
+	Access             uint64
+	Close              uint64
+	Commit             uint64
+	Create             uint64
+	DelegPurge         uint64
+	DelegReturn        uint64
+	GetAttr            uint64
+	GetFH              uint64
+	Link               uint64
+	Lock               uint64
+	Lockt              uint64
+	Locku              uint64
+	Lookup             uint64
+	LookupRoot         uint64
+	Nverify            uint64
+	Open               uint64
+	OpenAttr           uint64
+	OpenConfirm        uint64
+	OpenDgrd           uint64
+	PutFH              uint64
+	PutPubFH           uint64
+	PutRootFH          uint64
+	Read               uint64
+	ReadDir            uint64
+	ReadLink           uint64
+	Remove             uint64
+	Rename             uint64
+	Renew              uint64
+	RestoreFH          uint64
+	SaveFH             uint64
+	SecInfo            uint64
+	SetAttr            uint64
+	SetClientID        uint64
+	SetClientIDConfirm uint64
+	Verify             uint64
+	Write              uint64
+	RelLockOwner       uint64
 }
 
 // ClientRPCStats models all stats from /proc/net/rpc/nfs.
@@ -270,6 +275,7 @@ type ServerRPCStats struct {
 	V3Stats        V3Stats
 	ServerV4Stats  ServerV4Stats
 	V4Ops          V4Ops
+	WdelegGetattr  uint64
 }
 
 // FS represents the pseudo-filesystem proc, which provides an interface to
diff --git a/nfs/parse.go b/nfs/parse.go
index 5e78c54..76e74cb 100644
--- a/nfs/parse.go
+++ b/nfs/parse.go
@@ -272,45 +272,53 @@ func parseV4Ops(v []uint64) (V4Ops, error) {
 		return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v)
 	}
 
+	// nfs v2.5.x 39field and >=v2.6.x 40 field;
+	v40 := uint64(0)
+	if values > 39 {
+		v40 = v[40]
+	}
+
 	stats := V4Ops{
-		Op0Unused:    v[1],
-		Op1Unused:    v[2],
-		Op2Future:    v[3],
-		Access:       v[4],
-		Close:        v[5],
-		Commit:       v[6],
-		Create:       v[7],
-		DelegPurge:   v[8],
-		DelegReturn:  v[9],
-		GetAttr:      v[10],
-		GetFH:        v[11],
-		Link:         v[12],
-		Lock:         v[13],
-		Lockt:        v[14],
-		Locku:        v[15],
-		Lookup:       v[16],
-		LookupRoot:   v[17],
-		Nverify:      v[18],
-		Open:         v[19],
-		OpenAttr:     v[20],
-		OpenConfirm:  v[21],
-		OpenDgrd:     v[22],
-		PutFH:        v[23],
-		PutPubFH:     v[24],
-		PutRootFH:    v[25],
-		Read:         v[26],
-		ReadDir:      v[27],
-		ReadLink:     v[28],
-		Remove:       v[29],
-		Rename:       v[30],
-		Renew:        v[31],
-		RestoreFH:    v[32],
-		SaveFH:       v[33],
-		SecInfo:      v[34],
-		SetAttr:      v[35],
-		Verify:       v[36],
-		Write:        v[37],
-		RelLockOwner: v[38],
+		Op0Unused:          v[1],
+		Op1Unused:          v[2],
+		Op2Future:          v[3],
+		Access:             v[4],
+		Close:              v[5],
+		Commit:             v[6],
+		Create:             v[7],
+		DelegPurge:         v[8],
+		DelegReturn:        v[9],
+		GetAttr:            v[10],
+		GetFH:              v[11],
+		Link:               v[12],
+		Lock:               v[13],
+		Lockt:              v[14],
+		Locku:              v[15],
+		Lookup:             v[16],
+		LookupRoot:         v[17],
+		Nverify:            v[18],
+		Open:               v[19],
+		OpenAttr:           v[20],
+		OpenConfirm:        v[21],
+		OpenDgrd:           v[22],
+		PutFH:              v[23],
+		PutPubFH:           v[24],
+		PutRootFH:          v[25],
+		Read:               v[26],
+		ReadDir:            v[27],
+		ReadLink:           v[28],
+		Remove:             v[29],
+		Rename:             v[30],
+		Renew:              v[31],
+		RestoreFH:          v[32],
+		SaveFH:             v[33],
+		SecInfo:            v[34],
+		SetAttr:            v[35],
+		SetClientID:        v[36],
+		SetClientIDConfirm: v[37],
+		Verify:             v[38],
+		Write:              v[39],
+		RelLockOwner:       v40,
 	}
 
 	return stats, nil
diff --git a/nfs/parse_nfsd.go b/nfs/parse_nfsd.go
index 857ae3b..66828e5 100644
--- a/nfs/parse_nfsd.go
+++ b/nfs/parse_nfsd.go
@@ -73,6 +73,8 @@ func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) {
 			stats.ServerV4Stats, err = parseServerV4Stats(values)
 		case "proc4ops":
 			stats.V4Ops, err = parseV4Ops(values)
+		case "wdeleg_getattr":
+			stats.WdelegGetattr = values[0]
 		default:
 			return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine)
 		}
diff --git a/proc.go b/proc.go
index e159996..d1f71ca 100644
--- a/proc.go
+++ b/proc.go
@@ -244,7 +244,7 @@ func (p Proc) FileDescriptorTargets() ([]string, error) {
 // a process.
 func (p Proc) FileDescriptorsLen() (int, error) {
 	// Use fast path if available (Linux v6.2): https://github.com/torvalds/linux/commit/f1f1f2569901
-	if p.fs.real {
+	if p.fs.isReal {
 		stat, err := os.Stat(p.path("fd"))
 		if err != nil {
 			return 0, err
diff --git a/proc_fdinfo.go b/proc_fdinfo.go
index 4b7933e..fa761b3 100644
--- a/proc_fdinfo.go
+++ b/proc_fdinfo.go
@@ -26,6 +26,7 @@ var (
 	rPos          = regexp.MustCompile(`^pos:\s+(\d+)$`)
 	rFlags        = regexp.MustCompile(`^flags:\s+(\d+)$`)
 	rMntID        = regexp.MustCompile(`^mnt_id:\s+(\d+)$`)
+	rIno          = regexp.MustCompile(`^ino:\s+(\d+)$`)
 	rInotify      = regexp.MustCompile(`^inotify`)
 	rInotifyParts = regexp.MustCompile(`^inotify\s+wd:([0-9a-f]+)\s+ino:([0-9a-f]+)\s+sdev:([0-9a-f]+)(?:\s+mask:([0-9a-f]+))?`)
 )
@@ -40,6 +41,8 @@ type ProcFDInfo struct {
 	Flags string
 	// Mount point ID
 	MntID string
+	// Inode number
+	Ino string
 	// List of inotify lines (structured) in the fdinfo file (kernel 3.8+ only)
 	InotifyInfos []InotifyInfo
 }
@@ -51,7 +54,7 @@ func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) {
 		return nil, err
 	}
 
-	var text, pos, flags, mntid string
+	var text, pos, flags, mntid, ino string
 	var inotify []InotifyInfo
 
 	scanner := bufio.NewScanner(bytes.NewReader(data))
@@ -63,6 +66,8 @@ func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) {
 			flags = rFlags.FindStringSubmatch(text)[1]
 		} else if rMntID.MatchString(text) {
 			mntid = rMntID.FindStringSubmatch(text)[1]
+		} else if rIno.MatchString(text) {
+			ino = rIno.FindStringSubmatch(text)[1]
 		} else if rInotify.MatchString(text) {
 			newInotify, err := parseInotifyInfo(text)
 			if err != nil {
@@ -77,6 +82,7 @@ func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) {
 		Pos:          pos,
 		Flags:        flags,
 		MntID:        mntid,
+		Ino:          ino,
 		InotifyInfos: inotify,
 	}
 
diff --git a/proc_maps.go b/proc_maps.go
index 727549a..7e75c28 100644
--- a/proc_maps.go
+++ b/proc_maps.go
@@ -63,17 +63,17 @@ type ProcMap struct {
 // parseDevice parses the device token of a line and converts it to a dev_t
 // (mkdev) like structure.
 func parseDevice(s string) (uint64, error) {
-	toks := strings.Split(s, ":")
-	if len(toks) < 2 {
-		return 0, fmt.Errorf("%w: unexpected number of fields, expected: 2, got: %q", ErrFileParse, len(toks))
+	i := strings.Index(s, ":")
+	if i == -1 {
+		return 0, fmt.Errorf("%w: expected separator `:` in %s", ErrFileParse, s)
 	}
 
-	major, err := strconv.ParseUint(toks[0], 16, 0)
+	major, err := strconv.ParseUint(s[0:i], 16, 0)
 	if err != nil {
 		return 0, err
 	}
 
-	minor, err := strconv.ParseUint(toks[1], 16, 0)
+	minor, err := strconv.ParseUint(s[i+1:], 16, 0)
 	if err != nil {
 		return 0, err
 	}
@@ -93,17 +93,17 @@ func parseAddress(s string) (uintptr, error) {
 
 // parseAddresses parses the start-end address.
 func parseAddresses(s string) (uintptr, uintptr, error) {
-	toks := strings.Split(s, "-")
-	if len(toks) < 2 {
-		return 0, 0, fmt.Errorf("%w: invalid address", ErrFileParse)
+	idx := strings.Index(s, "-")
+	if idx == -1 {
+		return 0, 0, fmt.Errorf("%w: expected separator `-` in %s", ErrFileParse, s)
 	}
 
-	saddr, err := parseAddress(toks[0])
+	saddr, err := parseAddress(s[0:idx])
 	if err != nil {
 		return 0, 0, err
 	}
 
-	eaddr, err := parseAddress(toks[1])
+	eaddr, err := parseAddress(s[idx+1:])
 	if err != nil {
 		return 0, 0, err
 	}
diff --git a/proc_psi.go b/proc_psi.go
index 152539d..fe9dbb4 100644
--- a/proc_psi.go
+++ b/proc_psi.go
@@ -64,11 +64,11 @@ func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) {
 		return PSIStats{}, fmt.Errorf("%s: psi_stats: unavailable for %q: %w", ErrFileRead, resource, err)
 	}
 
-	return parsePSIStats(resource, bytes.NewReader(data))
+	return parsePSIStats(bytes.NewReader(data))
 }
 
 // parsePSIStats parses the specified file for pressure stall information.
-func parsePSIStats(resource string, r io.Reader) (PSIStats, error) {
+func parsePSIStats(r io.Reader) (PSIStats, error) {
 	psiStats := PSIStats{}
 
 	scanner := bufio.NewScanner(r)
diff --git a/proc_smaps.go b/proc_smaps.go
index 0e97d99..ad8785a 100644
--- a/proc_smaps.go
+++ b/proc_smaps.go
@@ -135,12 +135,12 @@ func (s *ProcSMapsRollup) parseLine(line string) error {
 	}
 	vBytes := vKBytes * 1024
 
-	s.addValue(k, v, vKBytes, vBytes)
+	s.addValue(k, vBytes)
 
 	return nil
 }
 
-func (s *ProcSMapsRollup) addValue(k string, vString string, vUint uint64, vUintBytes uint64) {
+func (s *ProcSMapsRollup) addValue(k string, vUintBytes uint64) {
 	switch k {
 	case "Rss":
 		s.Rss += vUintBytes
diff --git a/proc_status.go b/proc_status.go
index c055d07..46307f5 100644
--- a/proc_status.go
+++ b/proc_status.go
@@ -23,7 +23,7 @@ import (
 )
 
 // ProcStatus provides status information about the process,
-// read from /proc/[pid]/stat.
+// read from /proc/[pid]/status.
 type ProcStatus struct {
 	// The process ID.
 	PID int
@@ -32,6 +32,8 @@ type ProcStatus struct {
 
 	// Thread group ID.
 	TGID int
+	// List of Pid namespace.
+	NSpids []uint64
 
 	// Peak virtual memory size.
 	VmPeak uint64 // nolint:revive
@@ -127,6 +129,8 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
 		copy(s.UIDs[:], strings.Split(vString, "\t"))
 	case "Gid":
 		copy(s.GIDs[:], strings.Split(vString, "\t"))
+	case "NSpid":
+		s.NSpids = calcNSPidsList(vString)
 	case "VmPeak":
 		s.VmPeak = vUintBytes
 	case "VmSize":
@@ -200,3 +204,18 @@ func calcCpusAllowedList(cpuString string) []uint64 {
 	sort.Slice(g, func(i, j int) bool { return g[i] < g[j] })
 	return g
 }
+
+func calcNSPidsList(nspidsString string) []uint64 {
+	s := strings.Split(nspidsString, " ")
+	var nspids []uint64
+
+	for _, nspid := range s {
+		nspid, _ := strconv.ParseUint(nspid, 10, 64)
+		if nspid == 0 {
+			continue
+		}
+		nspids = append(nspids, nspid)
+	}
+
+	return nspids
+}
diff --git a/sysfs/class_infiniband.go b/sysfs/class_infiniband.go
index 652b544..90dc0d0 100644
--- a/sysfs/class_infiniband.go
+++ b/sysfs/class_infiniband.go
@@ -67,6 +67,42 @@ type InfiniBandCounters struct {
 	VL15Dropped                  *uint64 // counters/VL15_dropped
 }
 
+// InfiniBandHwCounters contains counter value from files in
+// /sys/class/infiniband/<Name>/ports/<Port>/hw_counters
+// for a single port of one InfiniBand device.
+type InfiniBandHwCounters struct {
+	DuplicateRequest        *uint64 // hw_counters/duplicate_request
+	ImpliedNakSeqErr        *uint64 // hw_counters/implied_nak_seq_err
+	Lifespan                *uint64 // hw_counters/lifespan
+	LocalAckTimeoutErr      *uint64 // hw_counters/local_ack_timeout_err
+	NpCnpSent               *uint64 // hw_counters/np_cnp_sent
+	NpEcnMarkedRocePackets  *uint64 // hw_counters/np_ecn_marked_roce_packets
+	OutOfBuffer             *uint64 // hw_counters/out_of_buffer
+	OutOfSequence           *uint64 // hw_counters/out_of_sequence
+	PacketSeqErr            *uint64 // hw_counters/packet_seq_err
+	ReqCqeError             *uint64 // hw_counters/req_cqe_error
+	ReqCqeFlushError        *uint64 // hw_counters/req_cqe_flush_error
+	ReqRemoteAccessErrors   *uint64 // hw_counters/req_remote_access_errors
+	ReqRemoteInvalidRequest *uint64 // hw_counters/req_remote_invalid_request
+	RespCqeError            *uint64 // hw_counters/resp_cqe_error
+	RespCqeFlushError       *uint64 // hw_counters/resp_cqe_flush_error
+	RespLocalLengthError    *uint64 // hw_counters/resp_local_length_error
+	RespRemoteAccessErrors  *uint64 // hw_counters/resp_remote_access_errors
+	RnrNakRetryErr          *uint64 // hw_counters/rnr_nak_retry_err
+	RoceAdpRetrans          *uint64 // hw_counters/roce_adp_retrans
+	RoceAdpRetransTo        *uint64 // hw_counters/roce_adp_retrans_to
+	RoceSlowRestart         *uint64 // hw_counters/roce_slow_restart
+	RoceSlowRestartCnps     *uint64 // hw_counters/roce_slow_restart_cnps
+	RoceSlowRestartTrans    *uint64 // hw_counters/roce_slow_restart_trans
+	RpCnpHandled            *uint64 // hw_counters/rp_cnp_handled
+	RpCnpIgnored            *uint64 // hw_counters/rp_cnp_ignored
+	RxAtomicRequests        *uint64 // hw_counters/rx_atomic_requests
+	RxDctConnect            *uint64 // hw_counters/rx_dct_connect
+	RxIcrcEncapsulated      *uint64 // hw_counters/rx_icrc_encapsulated
+	RxReadRequests          *uint64 // hw_counters/rx_read_requests
+	RxWriteRequests         *uint64 // hw_counters/rx_write_requests
+}
+
 // InfiniBandPort contains info from files in
 // /sys/class/infiniband/<Name>/ports/<Port>
 // for a single port of one InfiniBand device.
@@ -79,6 +115,7 @@ type InfiniBandPort struct {
 	PhysStateID uint   // String representation from /sys/class/infiniband/<Name>/ports/<Port>/phys_state
 	Rate        uint64 // in bytes/second from /sys/class/infiniband/<Name>/ports/<Port>/rate
 	Counters    InfiniBandCounters
+	HwCounters  InfiniBandHwCounters
 }
 
 // InfiniBandDevice contains info from files in /sys/class/infiniband for a
@@ -121,16 +158,24 @@ func (fs FS) InfiniBandClass() (InfiniBandClass, error) {
 }
 
 // Parse one InfiniBand device.
+// Refer to https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-infiniband
 func (fs FS) parseInfiniBandDevice(name string) (*InfiniBandDevice, error) {
 	path := fs.sys.Path(infinibandClassPath, name)
 	device := InfiniBandDevice{Name: name}
 
-	for _, f := range [...]string{"board_id", "fw_ver", "hca_type"} {
+	// fw_ver is exposed by all InfiniBand drivers since kernel version 4.10.
+	value, err := util.SysReadFile(filepath.Join(path, "fw_ver"))
+	if err != nil {
+		return nil, fmt.Errorf("failed to read HCA firmware version: %w", err)
+	}
+	device.FirmwareVersion = value
+
+	// Not all InfiniBand drivers expose all of these.
+	for _, f := range [...]string{"board_id", "hca_type"} {
 		name := filepath.Join(path, f)
 		value, err := util.SysReadFile(name)
 		if err != nil {
-			// Not all InfiniBand drivers provide hca_type.
-			if os.IsNotExist(err) && (f == "hca_type") {
+			if os.IsNotExist(err) {
 				continue
 			}
 			return nil, fmt.Errorf("failed to read file %q: %w", name, err)
@@ -139,8 +184,6 @@ func (fs FS) parseInfiniBandDevice(name string) (*InfiniBandDevice, error) {
 		switch f {
 		case "board_id":
 			device.BoardID = value
-		case "fw_ver":
-			device.FirmwareVersion = value
 		case "hca_type":
 			device.HCAType = value
 		}
@@ -242,6 +285,14 @@ func (fs FS) parseInfiniBandPort(name string, port string) (*InfiniBandPort, err
 	}
 	ibp.Counters = *counters
 
+	if strings.Contains(ibp.Name, "mlx5") {
+		hwCounters, err := parseInfiniBandHwCounters(portPath)
+		if err != nil {
+			return nil, err
+		}
+		ibp.HwCounters = *hwCounters
+	}
+
 	return &ibp, nil
 }
 
@@ -405,3 +456,106 @@ func parseInfiniBandCounters(portPath string) (*InfiniBandCounters, error) {
 
 	return &counters, nil
 }
+
+func parseInfiniBandHwCounters(portPath string) (*InfiniBandHwCounters, error) {
+	var hwCounters InfiniBandHwCounters
+
+	path := filepath.Join(portPath, "hw_counters")
+	files, err := os.ReadDir(path)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, f := range files {
+		if !f.Type().IsRegular() {
+			continue
+		}
+
+		name := filepath.Join(path, f.Name())
+		value, err := util.SysReadFile(name)
+		if err != nil {
+			if os.IsNotExist(err) || os.IsPermission(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) {
+				continue
+			}
+			return nil, fmt.Errorf("failed to read file %q: %w", name, err)
+		}
+
+		vp := util.NewValueParser(value)
+
+		switch f.Name() {
+		case "duplicate_request":
+			hwCounters.DuplicateRequest = vp.PUInt64()
+		case "implied_nak_seq_err":
+			hwCounters.ImpliedNakSeqErr = vp.PUInt64()
+		case "lifespan":
+			hwCounters.Lifespan = vp.PUInt64()
+		case "local_ack_timeout_err":
+			hwCounters.LocalAckTimeoutErr = vp.PUInt64()
+		case "np_cnp_sent":
+			hwCounters.NpCnpSent = vp.PUInt64()
+		case "np_ecn_marked_roce_packets":
+			hwCounters.NpEcnMarkedRocePackets = vp.PUInt64()
+		case "out_of_buffer":
+			hwCounters.OutOfBuffer = vp.PUInt64()
+		case "out_of_sequence":
+			hwCounters.OutOfSequence = vp.PUInt64()
+		case "packet_seq_err":
+			hwCounters.PacketSeqErr = vp.PUInt64()
+		case "req_cqe_error":
+			hwCounters.ReqCqeError = vp.PUInt64()
+		case "req_cqe_flush_error":
+			hwCounters.ReqCqeFlushError = vp.PUInt64()
+		case "req_remote_access_errors":
+			hwCounters.ReqRemoteAccessErrors = vp.PUInt64()
+		case "req_remote_invalid_request":
+			hwCounters.ReqRemoteInvalidRequest = vp.PUInt64()
+		case "resp_cqe_error":
+			hwCounters.RespCqeError = vp.PUInt64()
+		case "resp_cqe_flush_error":
+			hwCounters.RespCqeFlushError = vp.PUInt64()
+		case "resp_local_length_error":
+			hwCounters.RespLocalLengthError = vp.PUInt64()
+		case "resp_remote_access_errors":
+			hwCounters.RespRemoteAccessErrors = vp.PUInt64()
+		case "rnr_nak_retry_err":
+			hwCounters.RnrNakRetryErr = vp.PUInt64()
+		case "roce_adp_retrans":
+			hwCounters.RoceAdpRetrans = vp.PUInt64()
+		case "roce_adp_retrans_to":
+			hwCounters.RoceAdpRetransTo = vp.PUInt64()
+		case "roce_slow_restart":
+			hwCounters.RoceSlowRestart = vp.PUInt64()
+		case "roce_slow_restart_cnps":
+			hwCounters.RoceSlowRestartCnps = vp.PUInt64()
+		case "roce_slow_restart_trans":
+			hwCounters.RoceSlowRestartTrans = vp.PUInt64()
+		case "rp_cnp_handled":
+			hwCounters.RpCnpHandled = vp.PUInt64()
+		case "rp_cnp_ignored":
+			hwCounters.RpCnpIgnored = vp.PUInt64()
+		case "rx_atomic_requests":
+			hwCounters.RxAtomicRequests = vp.PUInt64()
+		case "rx_dct_connect":
+			hwCounters.RxDctConnect = vp.PUInt64()
+		case "rx_icrc_encapsulated":
+			hwCounters.RxIcrcEncapsulated = vp.PUInt64()
+		case "rx_read_requests":
+			hwCounters.RxReadRequests = vp.PUInt64()
+		case "rx_write_requests":
+			hwCounters.RxWriteRequests = vp.PUInt64()
+		}
+
+		if err := vp.Err(); err != nil {
+			// Ugly workaround for handling https://github.com/prometheus/node_exporter/issues/966
+			// when counters are `N/A (not available)`.
+			// This was already patched and submitted, see
+			// https://www.spinics.net/lists/linux-rdma/msg68596.html
+			// Remove this as soon as the fix lands in the enterprise distros.
+			if strings.Contains(value, "N/A (no PMA)") {
+				continue
+			}
+			return nil, err
+		}
+	}
+	return &hwCounters, nil
+}
diff --git a/sysfs/class_sas_device.go b/sysfs/class_sas_device.go
index 14014a7..644cdc0 100644
--- a/sysfs/class_sas_device.go
+++ b/sysfs/class_sas_device.go
@@ -163,9 +163,8 @@ func (fs FS) blockSASDeviceBlockDevices(name string) ([]string, error) {
 				if err != nil {
 					if os.IsNotExist(err) {
 						continue
-					} else {
-						return nil, err
 					}
+					return nil, err
 				}
 
 				for _, blockdevice := range blocks {
diff --git a/sysfs/class_sas_phy.go b/sysfs/class_sas_phy.go
index e0e3a31..67bd7a6 100644
--- a/sysfs/class_sas_phy.go
+++ b/sysfs/class_sas_phy.go
@@ -99,9 +99,8 @@ func (fs FS) parseSASPhy(name string) (*SASPhy, error) {
 			if err != nil {
 				if os.IsPermission(err) {
 					continue
-				} else {
-					return nil, fmt.Errorf("failed to read file %q: %w", name, err)
 				}
+				return nil, fmt.Errorf("failed to read file %q: %w", name, err)
 			}
 
 			vp := util.NewValueParser(value)
diff --git a/sysfs/vulnerability.go b/sysfs/vulnerability.go
index 08927a2..5a14a3e 100644
--- a/sysfs/vulnerability.go
+++ b/sysfs/vulnerability.go
@@ -17,7 +17,6 @@
 package sysfs
 
 import (
-	"fmt"
 	"os"
 	"path/filepath"
 	"strings"
@@ -27,12 +26,14 @@ const (
 	notAffected = "not affected" // based on: https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu
 	vulnerable  = "vulnerable"
 	mitigation  = "mitigation"
+	unknown     = "unknown"
 )
 
 const (
 	VulnerabilityStateNotAffected = iota
 	VulnerabilityStateVulnerable
 	VulnerabilityStateMitigation
+	VulnerabilityStateUnknown
 )
 
 var (
@@ -42,6 +43,7 @@ var (
 		VulnerabilityStateNotAffected: notAffected,
 		VulnerabilityStateVulnerable:  vulnerable,
 		VulnerabilityStateMitigation:  mitigation,
+		VulnerabilityStateUnknown:     unknown,
 	}
 )
 
@@ -98,9 +100,17 @@ func parseVulnerability(name, rawContent string) (*Vulnerability, error) {
 		if len(m) > 1 {
 			v.Mitigation = strings.Join(m[1:], " ")
 		}
+	case strings.HasPrefix(rawContentLower, unknown):
+		v.State = VulnerabilityStateUnknown
+		m := strings.Fields(rawContent)
+		if len(m) > 1 {
+			v.Mitigation = strings.Join(m[1:], " ")
+		}
 	default:
-		return nil, fmt.Errorf("unknown vulnerability state for %s: %s", name, rawContent)
-
+		// Output the raw data obtained from the vulnerability, with state
+		// unknown, rather than erroring out
+		v.State = VulnerabilityStateUnknown
+		v.Mitigation = rawContent
 	}
 	return v, nil
 }
diff --git a/thread.go b/thread.go
index 394762c..df2215e 100644
--- a/thread.go
+++ b/thread.go
@@ -55,7 +55,7 @@ func (fs FS) AllThreads(pid int) (Procs, error) {
 			continue
 		}
 
-		t = append(t, Proc{PID: int(tid), fs: FS{fsi.FS(taskPath), fs.real}})
+		t = append(t, Proc{PID: int(tid), fs: FS{fsi.FS(taskPath), fs.isReal}})
 	}
 
 	return t, nil
@@ -67,12 +67,12 @@ func (fs FS) Thread(pid, tid int) (Proc, error) {
 	if _, err := os.Stat(taskPath); err != nil {
 		return Proc{}, err
 	}
-	return Proc{PID: tid, fs: FS{fsi.FS(taskPath), fs.real}}, nil
+	return Proc{PID: tid, fs: FS{fsi.FS(taskPath), fs.isReal}}, nil
 }
 
 // Thread returns a process for a given TID of Proc.
 func (proc Proc) Thread(tid int) (Proc, error) {
-	tfs := FS{fsi.FS(proc.path("task")), proc.fs.real}
+	tfs := FS{fsi.FS(proc.path("task")), proc.fs.isReal}
 	if _, err := os.Stat(tfs.proc.Path(strconv.Itoa(tid))); err != nil {
 		return Proc{}, err
 	}


Test patch:
diff --git a/mountstats_test.go b/mountstats_test.go
index 3d23671..43903e9 100644
--- a/mountstats_test.go
+++ b/mountstats_test.go
@@ -372,6 +372,102 @@ func TestMountStats(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "NFS xprt over rdma proto",
+			s: `device <nfsserver>:<nfsmount> mounted on <mountpoint> with fstype nfs statvers=1.1
+        opts:   ro,vers=3,rsize=1048576,wsize=1048576,namlen=255,acregmin=120,acregmax=120,acdirmin=120,acdirmax=120,hard,nocto,forcerdirplus,proto=rdma,nconnect=16,port=20049,timeo=600,retrans=2,sec=sys,mountaddr=172.16.40.20,mountvers=3,mountport=0,mountproto=tcp,local_lock=none
+        age:    1270876
+        caps:   caps=0xf,wtmult=4096,dtsize=131072,bsize=0,namlen=255
+        sec:    flavor=1,pseudoflavor=1
+        events: 512052 36601115 0 68 1498583 16514 38815015 0 41584 2654459933 0 0 0 0 1527715 0 0 1498575 0 0 0 0 0 0 0 0 0
+        bytes:  3104202770327296 0 0 0 2013200952170479 0 491504202537 0
+        RPC iostats version: 1.1  p/v: 100003/3 (nfs)
+        xprt:   rdma 0 0 5808 62 0 494490723 494490687 36 10032963746 1282789 107150285 1226637531 2673889 135120843409861 135119397156505 266368832 75716996 0 7853 0 0 0 0 119328 1336431717 0 96
+        per-op statistics
+                NULL: 16 16 0 640 384 320 11 331 0
+`,
+			mounts: []*Mount{{
+				Device: "<nfsserver>:<nfsmount>",
+				Mount:  "<mountpoint>",
+				Type:   "nfs",
+				Stats: &MountStatsNFS{
+					StatVersion: "1.1",
+					Opts: map[string]string{"acdirmax": "120", "acdirmin": "120", "acregmax": "120",
+						"acregmin": "120", "forcerdirplus": "", "hard": "", "local_lock": "none",
+						"mountaddr": "172.16.40.20", "mountport": "0", "mountproto": "tcp", "mountvers": "3",
+						"namlen": "255", "nconnect": "16", "nocto": "", "port": "20049", "proto": "rdma",
+						"retrans": "2", "ro": "", "rsize": "1048576", "sec": "sys", "timeo": "600",
+						"vers": "3", "wsize": "1048576"},
+					Age: 1270876 * time.Second,
+					Bytes: NFSBytesStats{
+						Read:      3104202770327296,
+						ReadTotal: 2013200952170479,
+						ReadPages: 491504202537,
+					},
+					Events: NFSEventsStats{
+						InodeRevalidate:     512052,
+						DnodeRevalidate:     36601115,
+						AttributeInvalidate: 68,
+						VFSOpen:             1498583,
+						VFSLookup:           16514,
+						VFSAccess:           38815015,
+						VFSReadPage:         41584,
+						VFSReadPages:        2654459933,
+						VFSFlush:            1527715,
+						VFSFileRelease:      1498575,
+					},
+					Operations: []NFSOperationStats{
+						{
+							Operation:                           "NULL",
+							Requests:                            16,
+							Transmissions:                       16,
+							MajorTimeouts:                       0,
+							BytesSent:                           640,
+							BytesReceived:                       384,
+							CumulativeQueueMilliseconds:         320,
+							CumulativeTotalResponseMilliseconds: 11,
+							CumulativeTotalRequestMilliseconds:  331,
+							AverageRTTMilliseconds:              0.6875,
+							Errors:                              0,
+						},
+					},
+					Transport: NFSTransportStats{
+						Protocol:                 "rdma",
+						Port:                     0,
+						Bind:                     0,
+						Connect:                  5808,
+						ConnectIdleTime:          62,
+						IdleTimeSeconds:          0,
+						Sends:                    494490723,
+						Receives:                 494490687,
+						BadTransactionIDs:        36,
+						CumulativeActiveRequests: 10032963746,
+						CumulativeBacklog:        1282789,
+						MaximumRPCSlotsUsed:      0,
+						CumulativeSendingQueue:   0,
+						CumulativePendingQueue:   0,
+						ReadChunkCount:           107150285,
+						WriteChunkCount:          1226637531,
+						ReplyChunkCount:          2673889,
+						TotalRdmaRequest:         135120843409861,
+						PullupCopyCount:          135119397156505,
+						HardwayRegisterCount:     266368832,
+						FailedMarshalCount:       75716996,
+						BadReplyCount:            0,
+						MrsRecovered:             7853,
+						MrsOrphaned:              0,
+						MrsAllocated:             0,
+						EmptySendctxQ:            0,
+						TotalRdmaReply:           0,
+						FixupCopyCount:           119328,
+						ReplyWaitsForSend:        1336431717,
+						LocalInvNeeded:           0,
+						NomsgCallCount:           96,
+						BcallCount:               0,
+					},
+				},
+			}},
+		},
 	}
 
 	for i, tt := range tests {
@@ -518,4 +614,61 @@ device fs.example.com:/volume4/apps/home-automation/node-red-data mounted on /va
 			LOOKUPP: 0 0 0 0 0 0 0 0 0
 		LAYOUTERROR: 0 0 0 0 0 0 0 0 0
 `
+
+	extendedRDMAExampleALLMountstats = `device <nfsserver>:<nfsmount> mounted on <mountpoint> with fstype nfs statvers=1.1
+        opts:   ro,vers=3,rsize=1048576,wsize=1048576,namlen=255,acregmin=120,acregmax=120,acdirmin=120,acdirmax=120,hard,nocto,forcerdirplus,proto=rdma,nconnect=16,port=20049,timeo=600,retrans=2,sec=sys,mountaddr=172.16.40.20,mountvers=3,mountport=0,mountproto=tcp,local_lock=none
+        age:    1270876
+        caps:   caps=0xf,wtmult=4096,dtsize=131072,bsize=0,namlen=255
+        sec:    flavor=1,pseudoflavor=1
+        events: 512052 36601115 0 68 1498583 16514 38815015 0 41584 2654459933 0 0 0 0 1527715 0 0 1498575 0 0 0 0 0 0 0 0 0
+        bytes:  3104202770327296 0 0 0 2013200952170479 0 491504202537 0
+        RPC iostats version: 1.1  p/v: 100003/3 (nfs)
+        xprt:   rdma 0 0 5808 62 0 494490723 494490687 36 10032963746 1282789 107150285 1226637531 2673889 135120843409861 135119397156505 266368832 75716996 0 7853 0 0 0 0 119328 1336431717 0 96
+        xprt:   rdma 0 0 14094 145 0 492392334 492392307 27 7078693624 2509627 105561370 1280878332 2659446 142218924010291 142217463504063 276368040 94761838 0 7610 0 0 0 0 207977 1389069860 0 103
+        xprt:   rdma 0 0 16107 156 0 522755125 522755092 33 9119562599 1147699 109077860 1491898147 2566003 167152062826463 167149287506014 284931680 83011025 0 6229 0 0 0 0 221408 1603518232 0 82
+        xprt:   rdma 0 0 7808 82 0 441542046 441542010 36 7226132207 2519174 111096004 955223347 2676765 105741904708009 105740125663595 275613584 80373159 0 8893 0 0 0 0 149479 1068962768 0 76
+        xprt:   rdma 0 0 15018 167 0 508091827 508091764 63 19817677255 36702583 108265928 1258185459 2438516 138247436686102 138246196289594 270162080 74962306 0 13328 0 0 0 0 268433 1368837472 0 66
+        xprt:   rdma 0 0 14321 149 0 530246310 530246275 35 9723190432 2392024 111099700 1494204555 2589805 166691166581904 166689567426908 289995492 85067377 0 8010 0 0 0 0 214511 1607864447 0 100
+        xprt:   rdma 0 0 7863 84 0 459019689 459019642 47 11809253102 1716688 111825219 1032758664 2564226 114416685286438 114414936423706 290494252 73702102 0 6927 0 0 0 0 134453 1147121864 0 79
+        xprt:   rdma 0 0 7702 84 3 497598986 497598931 55 11816221496 3924722 106922130 1382063307 2506108 153967067193941 153965665472218 286222584 84094006 0 5875 0 0 0 0 127347 1491469045 0 66
+        xprt:   rdma 0 0 18341 202 0 477721151 477721073 78 15204400959 40562626 106645745 1291616653 3091375 144533696686651 144529688231163 278135800 73821525 0 6795 0 0 0 0 251097 1401327563 0 64
+        xprt:   rdma 0 0 8228 90 4 453155092 453155063 29 7884786894 1591225 112197590 1026006338 2742688 114591819605673 114590175821191 275541944 85857259 0 7487 0 0 0 0 143044 1140917892 0 76
+        xprt:   rdma 0 0 7843 83 0 446480377 446480324 53 12267986428 2958997 111971246 963162784 2693433 107176282309753 107174637802555 290269096 101100410 0 7825 0 0 0 0 141735 1077797328 0 83
+        xprt:   rdma 0 0 7582 86 0 423315608 423315567 41 10197484604 2076993 109207538 785978455 2650354 86090211449474 86088475571312 279912524 87676008 0 7491 0 0 0 0 137533 897807641 0 101
+        xprt:   rdma 0 0 7767 84 0 482538465 482538424 41 8935200479 1344778 112200583 1192341640 2644896 132860698423762 132858881459050 273354060 75337030 0 5941 0 0 0 0 127842 1307164736 0 97
+        xprt:   rdma 0 0 14526 148 2 537745063 537745007 56 20756072620 3970332320 109539564 1363647371 2503250 148793734936250 148791264145401 291888720 90344151 0 7471 0 0 0 0 211057 1475661285 0 82
+        xprt:   rdma 0 0 14300 151 0 495357347 495357316 31 8703101643 1451809 112315311 1303804607 2620502 145680743007170 145678880292235 288046696 98018259 0 7241 0 0 0 0 209396 1418712657 0 139
+        xprt:   rdma 0 0 7700 82 0 466611083 466611050 33 8540498291 4082864 114740300 1059770596 2523155 117376668239921 117375375683167 260927576 78437075 0 6691 0 0 0 0 130878 1177008175 1 76
+        per-op statistics
+                NULL: 16 16 0 640 384 320 11 331 0
+             GETATTR: 512052 512052 0 79823516 57349824 107131 612667 751847 0
+             SETATTR: 0 0 0 0 0 0 0 0 0
+              LOOKUP: 16713 16713 0 3040536 3706344 560 17488 20232 346
+              ACCESS: 211705 211705 0 33860920 25404600 37059 229754 283822 0
+            READLINK: 0 0 0 0 0 0 0 0 0
+                READ: 2654501510 2654501510 0 445911966900 2013540728551504 6347457114 31407021389 37927280438 0
+               WRITE: 0 0 0 0 0 0 0 0 0
+              CREATE: 0 0 0 0 0 0 0 0 0
+               MKDIR: 0 0 0 0 0 0 0 0 0
+             SYMLINK: 0 0 0 0 0 0 0 0 0
+               MKNOD: 0 0 0 0 0 0 0 0 0
+              REMOVE: 0 0 0 0 0 0 0 0 0
+               RMDIR: 0 0 0 0 0 0 0 0 0
+              RENAME: 0 0 0 0 0 0 0 0 0
+                LINK: 0 0 0 0 0 0 0 0 0
+             READDIR: 0 0 0 0 0 0 0 0 0
+         READDIRPLUS: 0 0 0 0 0 0 0 0 0
+              FSSTAT: 56356 56356 0 6243572 9467808 82068 74356 159001 0
+              FSINFO: 2 2 0 184 328 0 0 0 0
+            PATHCONF: 1 1 0 92 140 0 0 0 0
+              COMMIT: 0 0 0 0 0 0 0 0 0
+`
 )
+
+func TestMountStatsExtendedRDMAStats(t *testing.T) {
+	r := strings.NewReader(extendedRDMAExampleALLMountstats)
+	_, err := parseMountStats(r)
+	if err != nil {
+		t.Errorf("failed to parse mount stats with extended RDMA statistics: %v", err)
+	}
+}
diff --git a/nfs/parse_nfsd_test.go b/nfs/parse_nfsd_test.go
index b09b3b5..a7e9689 100644
--- a/nfs/parse_nfsd_test.go
+++ b/nfs/parse_nfsd_test.go
@@ -33,7 +33,7 @@ func TestNewNFSdServerRPCStats(t *testing.T) {
 			content: "invalid",
 			invalid: true,
 		}, {
-			name: "good file",
+			name: "good file, proc4ops 72",
 			content: `rc 0 6 18622
 fh 0 0 0 0 0
 io 157286400 0
@@ -45,6 +45,7 @@ proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2
 proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0
 proc4 2 2 10853
 proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+wdeleg_getattr 16
 `,
 			stats: &nfs.ServerRPCStats{
 				ReplyCache: nfs.ReplyCache{
@@ -134,45 +135,485 @@ proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150
 					Compound: 10853,
 				},
 				V4Ops: nfs.V4Ops{
-					Op0Unused:    0,
-					Op1Unused:    0,
-					Op2Future:    0,
-					Access:       1098,
-					Close:        2,
-					Commit:       0,
-					Create:       0,
-					DelegPurge:   0,
-					DelegReturn:  0,
-					GetAttr:      8179,
-					GetFH:        5896,
-					Link:         0,
-					Lock:         0,
-					Lockt:        0,
-					Locku:        0,
-					Lookup:       5900,
-					LookupRoot:   0,
-					Nverify:      0,
-					Open:         2,
-					OpenAttr:     0,
-					OpenConfirm:  2,
-					OpenDgrd:     0,
-					PutFH:        9609,
-					PutPubFH:     0,
-					PutRootFH:    2,
-					Read:         150,
-					ReadDir:      1272,
-					ReadLink:     0,
-					Remove:       0,
-					Rename:       0,
-					Renew:        1236,
-					RestoreFH:    0,
-					SaveFH:       0,
-					SecInfo:      0,
-					SetAttr:      0,
-					Verify:       3,
-					Write:        3,
-					RelLockOwner: 0,
+					Op0Unused:          0,
+					Op1Unused:          0,
+					Op2Future:          0,
+					Access:             1098,
+					Close:              2,
+					Commit:             0,
+					Create:             0,
+					DelegPurge:         0,
+					DelegReturn:        0,
+					GetAttr:            8179,
+					GetFH:              5896,
+					Link:               0,
+					Lock:               0,
+					Lockt:              0,
+					Locku:              0,
+					Lookup:             5900,
+					LookupRoot:         0,
+					Nverify:            0,
+					Open:               2,
+					OpenAttr:           0,
+					OpenConfirm:        2,
+					OpenDgrd:           0,
+					PutFH:              9609,
+					PutPubFH:           0,
+					PutRootFH:          2,
+					Read:               150,
+					ReadDir:            1272,
+					ReadLink:           0,
+					Remove:             0,
+					Rename:             0,
+					Renew:              1236,
+					RestoreFH:          0,
+					SaveFH:             0,
+					SecInfo:            0,
+					SetAttr:            0,
+					SetClientID:        3,
+					SetClientIDConfirm: 3,
+					Verify:             0,
+					Write:              0,
+					RelLockOwner:       0,
 				},
+				WdelegGetattr: 16,
+			},
+		}, {
+			name: "good file, proc4ops 40",
+			content: `rc 0 25020854 19157796
+fh 276 0 0 0 0
+io 899844043 2470085989
+th 1024 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
+ra 2048 4250593 118232 55926 31504 20253 13815 9875 7028 5546 3991 171551
+net 44179842 1 44179026 3092
+rpc 44177753 0 0 0 0
+proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+proc3 22 747 7259760 1383711 1570520 3464939 8436 4688207 21668847 1173194 6457 2127 172 213538 1253 556401 14950 1101 56245 90790 742 367 1989658
+proc4 2 0 0
+proc4ops 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+wdeleg_getattr 9`,
+
+			stats: &nfs.ServerRPCStats{
+				ReplyCache: nfs.ReplyCache{
+					Hits:    0,
+					Misses:  25020854,
+					NoCache: 19157796,
+				},
+				FileHandles: nfs.FileHandles{
+					Stale:        276,
+					TotalLookups: 0,
+					AnonLookups:  0,
+					DirNoCache:   0,
+					NoDirNoCache: 0,
+				},
+				InputOutput: nfs.InputOutput{
+					Read:  899844043,
+					Write: 2470085989,
+				},
+				Threads: nfs.Threads{
+					Threads: 1024,
+					FullCnt: 0,
+				},
+				ReadAheadCache: nfs.ReadAheadCache{
+					CacheSize:      2048,
+					CacheHistogram: []uint64{4250593, 118232, 55926, 31504, 20253, 13815, 9875, 7028, 5546, 3991},
+					NotFound:       171551,
+				},
+				Network: nfs.Network{
+					NetCount:   44179842,
+					UDPCount:   1,
+					TCPCount:   44179026,
+					TCPConnect: 3092,
+				},
+				ServerRPC: nfs.ServerRPC{
+					RPCCount: 44177753,
+					BadCnt:   0,
+					BadFmt:   0,
+					BadAuth:  0,
+					BadcInt:  0,
+				},
+				V2Stats: nfs.V2Stats{
+					Null:     0,
+					GetAttr:  0,
+					SetAttr:  0,
+					Root:     0,
+					Lookup:   0,
+					ReadLink: 0,
+					Read:     0,
+					WrCache:  0,
+					Write:    0,
+					Create:   0,
+					Remove:   0,
+					Rename:   0,
+					Link:     0,
+					SymLink:  0,
+					MkDir:    0,
+					RmDir:    0,
+					ReadDir:  0,
+					FsStat:   0,
+				},
+				V3Stats: nfs.V3Stats{
+					Null:        747,
+					GetAttr:     7259760,
+					SetAttr:     1383711,
+					Lookup:      1570520,
+					Access:      3464939,
+					ReadLink:    8436,
+					Read:        4688207,
+					Write:       21668847,
+					Create:      1173194,
+					MkDir:       6457,
+					SymLink:     2127,
+					MkNod:       172,
+					Remove:      213538,
+					RmDir:       1253,
+					Rename:      556401,
+					Link:        14950,
+					ReadDir:     1101,
+					ReadDirPlus: 56245,
+					FsStat:      90790,
+					FsInfo:      742,
+					PathConf:    367,
+					Commit:      1989658,
+				},
+				ServerV4Stats: nfs.ServerV4Stats{
+					Null:     0,
+					Compound: 0,
+				},
+				V4Ops: nfs.V4Ops{
+					Op0Unused:          0,
+					Op1Unused:          0,
+					Op2Future:          0,
+					Access:             0,
+					Close:              0,
+					Commit:             0,
+					Create:             0,
+					DelegPurge:         0,
+					DelegReturn:        0,
+					GetAttr:            0,
+					GetFH:              0,
+					Link:               0,
+					Lock:               0,
+					Lockt:              0,
+					Locku:              0,
+					Lookup:             0,
+					LookupRoot:         0,
+					Nverify:            0,
+					Open:               0,
+					OpenAttr:           0,
+					OpenConfirm:        0,
+					OpenDgrd:           0,
+					PutFH:              0,
+					PutPubFH:           0,
+					PutRootFH:          0,
+					Read:               0,
+					ReadDir:            0,
+					ReadLink:           0,
+					Remove:             0,
+					Rename:             0,
+					Renew:              0,
+					RestoreFH:          0,
+					SaveFH:             0,
+					SecInfo:            0,
+					SetAttr:            0,
+					SetClientID:        0,
+					SetClientIDConfirm: 0,
+					Verify:             0,
+					Write:              0,
+					RelLockOwner:       0,
+				},
+				WdelegGetattr: 9,
+			},
+		},
+		{
+			name: "good file, proc4ops 59",
+			content: `rc 0 268 742119
+fh 0 0 0 0 0
+io 2476981939 0
+th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
+ra 32 30104 0 0 0 0 0 0 0 0 0 71174
+net 742701 314 742393 10103960
+rpc 742406 310 310 0 0
+proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+proc3 22 105 71158 0 175642 184711 17103 101277 0 0 0 0 0 0 0 0 0 0 8916 102 202 0 0
+proc4 2 101 182991
+proc4ops 59 0 0 0 18112 8341 0 0 0 3239 71595 11834 0 0 0 0 107097 0 0 8344 0 5100 0 181968 0 235 5735 4406 0 0 0 652 8342 8344 0 0 134 134 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+wdeleg_getattr 10`,
+			stats: &nfs.ServerRPCStats{
+				ReplyCache: nfs.ReplyCache{
+					Hits:    0,
+					Misses:  268,
+					NoCache: 742119,
+				},
+				FileHandles: nfs.FileHandles{
+					Stale:        0,
+					TotalLookups: 0,
+					AnonLookups:  0,
+					DirNoCache:   0,
+					NoDirNoCache: 0,
+				},
+				InputOutput: nfs.InputOutput{
+					Read:  2476981939,
+					Write: 0,
+				},
+				Threads: nfs.Threads{
+					Threads: 8,
+					FullCnt: 0,
+				},
+				ReadAheadCache: nfs.ReadAheadCache{
+					CacheSize:      32,
+					CacheHistogram: []uint64{30104, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+					NotFound:       71174,
+				},
+				Network: nfs.Network{
+					NetCount:   742701,
+					UDPCount:   314,
+					TCPCount:   742393,
+					TCPConnect: 10103960,
+				},
+				ServerRPC: nfs.ServerRPC{
+					RPCCount: 742406,
+					BadCnt:   310,
+					BadFmt:   310,
+					BadAuth:  0,
+					BadcInt:  0,
+				},
+				V2Stats: nfs.V2Stats{
+					Null:     0,
+					GetAttr:  0,
+					SetAttr:  0,
+					Root:     0,
+					Lookup:   0,
+					ReadLink: 0,
+					Read:     0,
+					WrCache:  0,
+					Write:    0,
+					Create:   0,
+					Remove:   0,
+					Rename:   0,
+					Link:     0,
+					SymLink:  0,
+					MkDir:    0,
+					RmDir:    0,
+					ReadDir:  0,
+					FsStat:   0,
+				},
+				V3Stats: nfs.V3Stats{
+					Null:        105,
+					GetAttr:     71158,
+					SetAttr:     0,
+					Lookup:      175642,
+					Access:      184711,
+					ReadLink:    17103,
+					Read:        101277,
+					Write:       0,
+					Create:      0,
+					MkDir:       0,
+					SymLink:     0,
+					MkNod:       0,
+					Remove:      0,
+					RmDir:       0,
+					Rename:      0,
+					Link:        0,
+					ReadDir:     0,
+					ReadDirPlus: 8916,
+					FsStat:      102,
+					FsInfo:      202,
+					PathConf:    0,
+					Commit:      0,
+				},
+				ServerV4Stats: nfs.ServerV4Stats{
+					Null:     101,
+					Compound: 182991,
+				},
+				V4Ops: nfs.V4Ops{
+					Op0Unused:          0,
+					Op1Unused:          0,
+					Op2Future:          0,
+					Access:             18112,
+					Close:              8341,
+					Commit:             0,
+					Create:             0,
+					DelegPurge:         0,
+					DelegReturn:        3239,
+					GetAttr:            71595,
+					GetFH:              11834,
+					Link:               0,
+					Lock:               0,
+					Lockt:              0,
+					Locku:              0,
+					Lookup:             107097,
+					LookupRoot:         0,
+					Nverify:            0,
+					Open:               8344,
+					OpenAttr:           0,
+					OpenConfirm:        5100,
+					OpenDgrd:           0,
+					PutFH:              181968,
+					PutPubFH:           0,
+					PutRootFH:          235,
+					Read:               5735,
+					ReadDir:            4406,
+					ReadLink:           0,
+					Remove:             0,
+					Rename:             0,
+					Renew:              652,
+					RestoreFH:          8342,
+					SaveFH:             8344,
+					SecInfo:            0,
+					SetAttr:            0,
+					SetClientID:        134,
+					SetClientIDConfirm: 134,
+					Verify:             0,
+					Write:              0,
+					RelLockOwner:       0,
+				},
+				WdelegGetattr: 10,
+			},
+		}, {
+			name: "good file, proc4ops 39",
+			content: `rc 0 25020854 19157796
+fh 276 0 0 0 0
+io 899844043 2470085989
+th 1024 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
+ra 2048 4250593 118232 55926 31504 20253 13815 9875 7028 5546 3991 171551
+net 44179842 1 44179026 3092
+rpc 44177753 0 0 0 0
+proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+proc3 22 747 7259760 1383711 1570520 3464939 8436 4688207 21668847 1173194 6457 2127 172 213538 1253 556401 14950 1101 56245 90790 742 367 1989658
+proc4 2 0 0
+proc4ops 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39
+wdeleg_getattr 765432`,
+			stats: &nfs.ServerRPCStats{
+				ReplyCache: nfs.ReplyCache{
+					Hits:    0,
+					Misses:  25020854,
+					NoCache: 19157796,
+				},
+				FileHandles: nfs.FileHandles{
+					Stale:        276,
+					TotalLookups: 0,
+					AnonLookups:  0,
+					DirNoCache:   0,
+					NoDirNoCache: 0,
+				},
+				InputOutput: nfs.InputOutput{
+					Read:  899844043,
+					Write: 2470085989,
+				},
+				Threads: nfs.Threads{
+					Threads: 1024,
+					FullCnt: 0,
+				},
+				ReadAheadCache: nfs.ReadAheadCache{
+					CacheSize:      2048,
+					CacheHistogram: []uint64{4250593, 118232, 55926, 31504, 20253, 13815, 9875, 7028, 5546, 3991},
+					NotFound:       171551,
+				},
+				Network: nfs.Network{
+					NetCount:   44179842,
+					UDPCount:   1,
+					TCPCount:   44179026,
+					TCPConnect: 3092,
+				},
+				ServerRPC: nfs.ServerRPC{
+					RPCCount: 44177753,
+					BadCnt:   0,
+					BadFmt:   0,
+					BadAuth:  0,
+					BadcInt:  0,
+				},
+				V2Stats: nfs.V2Stats{
+					Null:     0,
+					GetAttr:  0,
+					SetAttr:  0,
+					Root:     0,
+					Lookup:   0,
+					ReadLink: 0,
+					Read:     0,
+					WrCache:  0,
+					Write:    0,
+					Create:   0,
+					Remove:   0,
+					Rename:   0,
+					Link:     0,
+					SymLink:  0,
+					MkDir:    0,
+					RmDir:    0,
+					ReadDir:  0,
+					FsStat:   0,
+				},
+				V3Stats: nfs.V3Stats{
+					Null:        747,
+					GetAttr:     7259760,
+					SetAttr:     1383711,
+					Lookup:      1570520,
+					Access:      3464939,
+					ReadLink:    8436,
+					Read:        4688207,
+					Write:       21668847,
+					Create:      1173194,
+					MkDir:       6457,
+					SymLink:     2127,
+					MkNod:       172,
+					Remove:      213538,
+					RmDir:       1253,
+					Rename:      556401,
+					Link:        14950,
+					ReadDir:     1101,
+					ReadDirPlus: 56245,
+					FsStat:      90790,
+					FsInfo:      742,
+					PathConf:    367,
+					Commit:      1989658,
+				},
+				ServerV4Stats: nfs.ServerV4Stats{
+					Null:     0,
+					Compound: 0,
+				},
+				V4Ops: nfs.V4Ops{
+					Op0Unused:          0,
+					Op1Unused:          0,
+					Op2Future:          0,
+					Access:             0,
+					Close:              0,
+					Commit:             0,
+					Create:             0,
+					DelegPurge:         0,
+					DelegReturn:        0,
+					GetAttr:            0,
+					GetFH:              0,
+					Link:               0,
+					Lock:               0,
+					Lockt:              0,
+					Locku:              0,
+					Lookup:             0,
+					LookupRoot:         0,
+					Nverify:            0,
+					Open:               0,
+					OpenAttr:           0,
+					OpenConfirm:        0,
+					OpenDgrd:           0,
+					PutFH:              0,
+					PutPubFH:           0,
+					PutRootFH:          0,
+					Read:               0,
+					ReadDir:            0,
+					ReadLink:           0,
+					Remove:             0,
+					Rename:             0,
+					Renew:              0,
+					RestoreFH:          0,
+					SaveFH:             0,
+					SecInfo:            0,
+					SetAttr:            0,
+					SetClientID:        0,
+					SetClientIDConfirm: 0,
+					Verify:             0,
+					Write:              39,
+					RelLockOwner:       0,
+				},
+				WdelegGetattr: 765432,
 			},
 		},
 	}
diff --git a/proc_maps64_test.go b/proc_maps64_test.go
index 66ef134..44ec68c 100644
--- a/proc_maps64_test.go
+++ b/proc_maps64_test.go
@@ -138,3 +138,40 @@ func TestProcMaps(t *testing.T) {
 	}
 
 }
+
+var start, end uintptr
+
+func BenchmarkParseAddress(b *testing.B) {
+	b.ReportAllocs()
+	var (
+		s, e uintptr
+		err  error
+	)
+	for i := 0; i < b.N; i++ {
+		s, e, err = parseAddresses("7f7d7469e000-7f7d746a0000")
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+	// Prevent the compiler from optimizing away benchmark code.
+	start = s
+	end = e
+}
+
+var device uint64
+
+func BenchmarkParseDevice(b *testing.B) {
+	b.ReportAllocs()
+	var (
+		d   uint64
+		err error
+	)
+	for i := 0; i < b.N; i++ {
+		d, err = parseDevice("00:22")
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+	// Prevent the compiler from optimizing away benchmark code.
+	device = d
+}
diff --git a/proc_psi_test.go b/proc_psi_test.go
index da674dc..de1fd31 100644
--- a/proc_psi_test.go
+++ b/proc_psi_test.go
@@ -111,7 +111,7 @@ func TestPSIStats(t *testing.T) {
 func TestParsePSIStats(t *testing.T) {
 	t.Run("unknown measurement type", func(t *testing.T) {
 		raw := "nonsense haha test=fake"
-		_, err := parsePSIStats("fake", strings.NewReader(raw))
+		_, err := parsePSIStats(strings.NewReader(raw))
 		if err != nil {
 			t.Error("unknown measurement type must be ignored")
 		}
@@ -121,7 +121,7 @@ func TestParsePSIStats(t *testing.T) {
 		t.Run("some", func(t *testing.T) {
 			raw := `some avg10=0.10 avg60=2.00 avg300=3.85 total=oops
 full avg10=0.20 avg60=3.00 avg300=teddy total=25`
-			stats, err := parsePSIStats("fake", strings.NewReader(raw))
+			stats, err := parsePSIStats(strings.NewReader(raw))
 			if err == nil {
 				t.Error("a malformed line must result in a parse error")
 			}
@@ -133,7 +133,7 @@ full avg10=0.20 avg60=3.00 avg300=teddy total=25`
 		t.Run("full", func(t *testing.T) {
 			raw := `some avg10=0.10 avg60=2.00 avg300=3.85 total=1
 full avg10=0.20 avg60=3.00 avg300=test total=25`
-			stats, err := parsePSIStats("fake", strings.NewReader(raw))
+			stats, err := parsePSIStats(strings.NewReader(raw))
 			t.Log(err)
 			t.Log(stats)
 			if err == nil {
diff --git a/proc_status_test.go b/proc_status_test.go
index 2f0884f..9d22a48 100644
--- a/proc_status_test.go
+++ b/proc_status_test.go
@@ -36,6 +36,7 @@ func TestProcStatus(t *testing.T) {
 	}{
 		{name: "Pid", want: 26231, have: s.PID},
 		{name: "Tgid", want: 26231, have: s.TGID},
+		{name: "NSpid", want: 1, have: int(s.NSpids[0])},
 		{name: "VmPeak", want: 58472 * 1024, have: int(s.VmPeak)},
 		{name: "VmSize", want: 58440 * 1024, have: int(s.VmSize)},
 		{name: "VmLck", want: 0 * 1024, have: int(s.VmLck)},
diff --git a/sysfs/class_infiniband_test.go b/sysfs/class_infiniband_test.go
index acb6263..461e280 100644
--- a/sysfs/class_infiniband_test.go
+++ b/sysfs/class_infiniband_test.go
@@ -117,6 +117,53 @@ func TestInfiniBandClass(t *testing.T) {
 		mlx4Port2PortXmitWait                 uint64 = 3846
 		mlx4Port2SymbolError                  uint64
 		mlx4Port2VL15Dropped                  uint64
+
+		mlx5Port1ExcessiveBufferOverrunErrors uint64
+		mlx5Port1LinkDowned                   uint64
+		mlx5Port1LinkErrorRecovery            uint64
+		mlx5Port1LocalLinkIntegrityErrors     uint64
+		mlx5Port1MulticastRcvPackets          uint64
+		mlx5Port1MulticastXmitPackets         uint64
+		mlx5Port1PortRcvConstraintErrors      uint64
+		mlx5Port1PortRcvData                  uint64 = 72505381512
+		mlx5Port1PortRcvErrors                uint64
+		mlx5Port1PortRcvPackets               uint64 = 541889824
+		mlx5Port1PortRcvRemotePhysicalErrors  uint64
+		mlx5Port1PortRcvSwitchRelayErrors     uint64
+		mlx5Port1PortXmitConstraintErrors     uint64
+		mlx5Port1PortXmitData                 uint64 = 11523046035392
+		mlx5Port1PortXmitDiscards             uint64
+		mlx5Port1PortXmitPackets              uint64 = 10907922116
+		mlx5Port1PortXmitWait                 uint64
+		mlx5Port1SymbolError                  uint64
+		mlx5Port1UnicastRcvPackets            uint64 = 541889824
+		mlx5Port1UnicastXmitPackets           uint64 = 10907922116
+		mlx5Port1VL15Dropped                  uint64
+		mlx5Port1DuplicateRequest             uint64 = 41
+		mlx5Port1ImpliedNakSeqErr             uint64
+		mlx5Port1Lifespan                     uint64 = 10
+		mlx5Port1LocalAckTimeoutErr           uint64 = 131
+		mlx5Port1OutOfBuffer                  uint64
+		mlx5Port1OutOfSequence                uint64 = 1
+		mlx5Port1PacketSeqErr                 uint64 = 1
+		mlx5Port1ReqCqeError                  uint64 = 3481
+		mlx5Port1ReqCqeFlushError             uint64 = 80
+		mlx5Port1ReqRemoteAccessErrors        uint64
+		mlx5Port1ReqRemoteInvalidRequest      uint64
+		mlx5Port1RespCqeError                 uint64 = 8109
+		mlx5Port1RespCqeFlushError            uint64 = 4708
+		mlx5Port1RespLocalLengthError         uint64
+		mlx5Port1RespRemoteAccessErrors       uint64
+		mlx5Port1RnrNakRetryErr               uint64
+		mlx5Port1RoceAdpRetrans               uint64 = 99
+		mlx5Port1RoceAdpRetransTo             uint64 = 4
+		mlx5Port1RoceSlowRestart              uint64
+		mlx5Port1RoceSlowRestartCnps          uint64 = 131
+		mlx5Port1RoceSlowRestartTrans         uint64
+		mlx5Port1RxAtomicRequests             uint64
+		mlx5Port1RxDctConnect                 uint64
+		mlx5Port1RxReadRequests               uint64 = 175528982
+		mlx5Port1RxWriteRequests              uint64 = 742114
 	)
 
 	want := InfiniBandClass{
@@ -220,6 +267,73 @@ func TestInfiniBandClass(t *testing.T) {
 				},
 			},
 		},
+		"mlx5_0": InfiniBandDevice{
+			Name:            "mlx5_0",
+			BoardID:         "SM_2001000001034",
+			FirmwareVersion: "14.28.2006",
+			HCAType:         "MT4118",
+			Ports: map[uint]InfiniBandPort{
+				1: {
+					Name:        "mlx5_0",
+					Port:        1,
+					State:       "ACTIVE",
+					StateID:     4,
+					PhysState:   "ACTIVE",
+					PhysStateID: 4,
+					Rate:        3125000000,
+					Counters: InfiniBandCounters{
+						ExcessiveBufferOverrunErrors: &mlx5Port1ExcessiveBufferOverrunErrors,
+						LinkDowned:                   &mlx5Port1LinkDowned,
+						LinkErrorRecovery:            &mlx5Port1LinkErrorRecovery,
+						LocalLinkIntegrityErrors:     &mlx5Port1LocalLinkIntegrityErrors,
+						MulticastRcvPackets:          &mlx5Port1MulticastRcvPackets,
+						MulticastXmitPackets:         &mlx5Port1MulticastXmitPackets,
+						PortRcvConstraintErrors:      &mlx5Port1PortRcvConstraintErrors,
+						PortRcvData:                  &mlx5Port1PortRcvData,
+						PortRcvErrors:                &mlx5Port1PortRcvErrors,
+						PortRcvPackets:               &mlx5Port1PortRcvPackets,
+						PortRcvRemotePhysicalErrors:  &mlx5Port1PortRcvRemotePhysicalErrors,
+						PortRcvSwitchRelayErrors:     &mlx5Port1PortRcvSwitchRelayErrors,
+						PortXmitConstraintErrors:     &mlx5Port1PortXmitConstraintErrors,
+						PortXmitData:                 &mlx5Port1PortXmitData,
+						PortXmitDiscards:             &mlx5Port1PortXmitDiscards,
+						PortXmitPackets:              &mlx5Port1PortXmitPackets,
+						PortXmitWait:                 &mlx5Port1PortXmitWait,
+						SymbolError:                  &mlx5Port1SymbolError,
+						UnicastRcvPackets:            &mlx5Port1UnicastRcvPackets,
+						UnicastXmitPackets:           &mlx5Port1UnicastXmitPackets,
+						VL15Dropped:                  &mlx5Port1VL15Dropped,
+					},
+					HwCounters: InfiniBandHwCounters{
+						DuplicateRequest:        &mlx5Port1DuplicateRequest,
+						ImpliedNakSeqErr:        &mlx5Port1ImpliedNakSeqErr,
+						Lifespan:                &mlx5Port1Lifespan,
+						LocalAckTimeoutErr:      &mlx5Port1LocalAckTimeoutErr,
+						OutOfBuffer:             &mlx5Port1OutOfBuffer,
+						OutOfSequence:           &mlx5Port1OutOfSequence,
+						PacketSeqErr:            &mlx5Port1PacketSeqErr,
+						ReqCqeError:             &mlx5Port1ReqCqeError,
+						ReqCqeFlushError:        &mlx5Port1ReqCqeFlushError,
+						ReqRemoteAccessErrors:   &mlx5Port1ReqRemoteAccessErrors,
+						ReqRemoteInvalidRequest: &mlx5Port1ReqRemoteInvalidRequest,
+						RespCqeError:            &mlx5Port1RespCqeError,
+						RespCqeFlushError:       &mlx5Port1RespCqeFlushError,
+						RespLocalLengthError:    &mlx5Port1RespLocalLengthError,
+						RespRemoteAccessErrors:  &mlx5Port1RespRemoteAccessErrors,
+						RnrNakRetryErr:          &mlx5Port1RnrNakRetryErr,
+						RoceAdpRetrans:          &mlx5Port1RoceAdpRetrans,
+						RoceAdpRetransTo:        &mlx5Port1RoceAdpRetransTo,
+						RoceSlowRestart:         &mlx5Port1RoceSlowRestart,
+						RoceSlowRestartCnps:     &mlx5Port1RoceSlowRestartCnps,
+						RoceSlowRestartTrans:    &mlx5Port1RoceSlowRestartTrans,
+						RxAtomicRequests:        &mlx5Port1RxAtomicRequests,
+						RxDctConnect:            &mlx5Port1RxDctConnect,
+						RxReadRequests:          &mlx5Port1RxReadRequests,
+						RxWriteRequests:         &mlx5Port1RxWriteRequests,
+					},
+				},
+			},
+		},
 	}
 
 	if diff := cmp.Diff(want, got); diff != "" {
diff --git a/sysfs/vulnerability_test.go b/sysfs/vulnerability_test.go
index 255586d..ec9cafc 100644
--- a/sysfs/vulnerability_test.go
+++ b/sysfs/vulnerability_test.go
@@ -38,14 +38,15 @@ func TestFS_CPUVulnerabilities(t *testing.T) {
 		want              *Vulnerability
 		wantErr           bool
 	}{
-		{"Not affected", "itlb_multihit", &Vulnerability{CodeName: "itlb_multihit", State: VulnerabilityStateNotAffected, Mitigation: ""}, false},
-		{"Not affected with underscores", "tsx_async_abort", &Vulnerability{CodeName: "tsx_async_abort", State: VulnerabilityStateNotAffected, Mitigation: ""}, false},
+		{"Not affected", "tsx_async_abort", &Vulnerability{CodeName: "tsx_async_abort", State: VulnerabilityStateNotAffected, Mitigation: ""}, false},
 		{"Mitigation simple string", "spec_store_bypass", &Vulnerability{CodeName: "spec_store_bypass", State: VulnerabilityStateMitigation, Mitigation: "Speculative Store Bypass disabled via prctl"}, false},
 		{"Mitigation special chars", "retbleed", &Vulnerability{CodeName: "retbleed", State: VulnerabilityStateMitigation, Mitigation: "untrained return thunk; SMT enabled with STIBP protection"}, false},
 		{"Mitigation more special chars", "spectre_v1", &Vulnerability{CodeName: "spectre_v1", State: VulnerabilityStateMitigation, Mitigation: "usercopy/swapgs barriers and __user pointer sanitization"}, false},
 		{"Mitigation with multiple subsections", "spectre_v2", &Vulnerability{CodeName: "spectre_v2", State: VulnerabilityStateMitigation, Mitigation: "Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected"}, false},
 		{"Vulnerable", "mds", &Vulnerability{CodeName: "mds", State: VulnerabilityStateVulnerable, Mitigation: ""}, false},
 		{"Vulnerable with mitigation available", "mmio_stale_data", &Vulnerability{CodeName: "mmio_stale_data", State: VulnerabilityStateVulnerable, Mitigation: "Clear CPU buffers attempted, no microcode"}, false},
+		{"Unknown", "srbds", &Vulnerability{CodeName: "srbds", State: VulnerabilityStateUnknown, Mitigation: "Dependent on hypervisor status"}, false},
+		{"Unknown with unparseable mitigation", "itlb_multihit", &Vulnerability{CodeName: "itlb_multihit", State: VulnerabilityStateUnknown, Mitigation: "KVM: Mitigation: VMX unsupported"}, false},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/testdata/fixtures.ttar b/testdata/fixtures.ttar
index ae2e0f0..92f72fa 100644
--- a/testdata/fixtures.ttar
+++ b/testdata/fixtures.ttar
@@ -5409,6 +5409,281 @@ Lines: 1
 4: ACTIVE
 Mode: 644
 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Directory: fixtures/sys/class/infiniband/mlx5_0
+Mode: 755
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/board_id
+Lines: 1
+SM_2001000001034
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/fw_ver
+Lines: 1
+14.28.2006
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/hca_type
+Lines: 1
+MT4118
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Directory: fixtures/sys/class/infiniband/mlx5_0/ports
+Mode: 755
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Directory: fixtures/sys/class/infiniband/mlx5_0/ports/1
+Mode: 755
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Directory: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters
+Mode: 755
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/VL15_dropped
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/excessive_buffer_overrun_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/link_downed
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/link_error_recovery
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/local_link_integrity_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/multicast_rcv_packets
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/multicast_xmit_packets
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_constraint_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_data
+Lines: 1
+18126345378
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_packets
+Lines: 1
+541889824
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_remote_physical_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_switch_relay_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_constraint_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_data
+Lines: 1
+2880761508848
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_discards
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_packets
+Lines: 1
+10907922116
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_wait
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/symbol_error
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/unicast_rcv_packets
+Lines: 1
+541889824
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/unicast_xmit_packets
+Lines: 1
+10907922116
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Directory: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters
+Mode: 755
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/duplicate_request
+Lines: 1
+41
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/implied_nak_seq_err
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/lifespan
+Lines: 1
+10
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/local_ack_timeout_err
+Lines: 1
+131
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/out_of_buffer
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/out_of_sequence
+Lines: 1
+1
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/packet_seq_err
+Lines: 1
+1
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_cqe_error
+Lines: 1
+3481
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_cqe_flush_error
+Lines: 1
+80
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_remote_access_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_remote_invalid_request
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_cqe_error
+Lines: 1
+8109
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_cqe_flush_error
+Lines: 1
+4708
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_local_length_error
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_remote_access_errors
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rnr_nak_retry_err
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_adp_retrans
+Lines: 1
+99
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_adp_retrans_to
+Lines: 1
+4
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_slow_restart
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_slow_restart_cnps
+Lines: 1
+131
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_slow_restart_trans
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_atomic_requests
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_dct_connect
+Lines: 1
+0
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_read_requests
+Lines: 1
+175528982
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_write_requests
+Lines: 1
+742114
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/phys_state
+Lines: 1
+4: ACTIVE
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/rate
+Lines: 1
+25 Gb/sec (1X EDR)
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/state
+Lines: 1
+4: ACTIVE
+Mode: 644
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Directory: fixtures/sys/class/net
 Mode: 775
 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -13239,7 +13514,7 @@ Mode: 755
 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Path: fixtures/sys/devices/system/cpu/vulnerabilities/itlb_multihit
 Lines: 1
-Not affected
+KVM: Mitigation: VMX unsupported
 Mode: 444
 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Path: fixtures/sys/devices/system/cpu/vulnerabilities/mds
@@ -13272,6 +13547,11 @@ Lines: 1
 Mitigation: Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected
 Mode: 444
 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Path: fixtures/sys/devices/system/cpu/vulnerabilities/srbds
+Lines: 1
+Unknown: Dependent on hypervisor status
+Mode: 444
+# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Path: fixtures/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
 Lines: 1
 Not affected