aboutsummaryrefslogtreecommitdiff
path: root/packages/numap
diff options
context:
space:
mode:
Diffstat (limited to 'packages/numap')
-rw-r--r--packages/numap/README.org47
-rw-r--r--packages/numap/go.mod3
-rw-r--r--packages/numap/internal/hwids/hwids.go148
-rw-r--r--packages/numap/internal/sysfs/parse.go21
-rw-r--r--packages/numap/internal/sysfs/pci.go145
-rw-r--r--packages/numap/numa.go116
-rw-r--r--packages/numap/numap.go31
7 files changed, 0 insertions, 511 deletions
diff --git a/packages/numap/README.org b/packages/numap/README.org
deleted file mode 100644
index c7941b1..0000000
--- a/packages/numap/README.org
+++ /dev/null
@@ -1,47 +0,0 @@
-#+TITLE: numap
-
-Print the NUMA topology of a host.
-
-* Usage
-#+BEGIN_SRC sh
-./numap |jq .
-{
- "node0": {
- "name": "node0",
- "path": "/sys/devices/system/node/node0",
- "cpulist": "0-19,40-59",
- "pci_devices": [
- {
- "vendor": "Mellanox Technologies",
- "name": "MT27710 Family [ConnectX-4 Lx]"
- },
- {
- "vendor": "Mellanox Technologies",
- "name": "MT27710 Family [ConnectX-4 Lx]"
- }
- ]
- },
- "node1": {
- "name": "node1",
- "path": "/sys/devices/system/node/node1",
- "cpulist": "20-39,60-79",
- "pci_devices": [
- {
- "vendor": "Intel Corporation",
- "name": "NVMe Datacenter SSD [3DNAND, Beta Rock Controller]"
- }
- ]
- }
-}
-#+END_SRC
-
-The command will scan the host to find the NUMA nodes, and all the PCI devices, and map the PCI devices back to the NUMA node.
-
-It also provides a way to see the list of CPUs attached to the node.
-
-* Limitations
-** Device class
-For now only the following classes of hardware are cared for:
-- NVMe
-- network
-- GPU
diff --git a/packages/numap/go.mod b/packages/numap/go.mod
deleted file mode 100644
index 92b1885..0000000
--- a/packages/numap/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module golang.fcuny.net/numap
-
-go 1.17
diff --git a/packages/numap/internal/hwids/hwids.go b/packages/numap/internal/hwids/hwids.go
deleted file mode 100644
index 6aa9d8a..0000000
--- a/packages/numap/internal/hwids/hwids.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package hwids
-
-import (
- "bufio"
- "fmt"
- "os"
- "strings"
-)
-
-var pciPath = []string{
- "/usr/share/hwdata/pci.ids",
- "/usr/share/misc/pci.ids",
-}
-
-type PCIType int
-
-const (
- PCIVendor PCIType = iota
- PCIDevice
- PCISubsystem
-)
-
-type PciDevices map[uint16][]PciDevice
-
-// PciDevice represents a PCI device
-type PciDevice struct {
- Type PCIType
- Vendor, Device uint16
- SubVendor, SubDevice uint16
- VendorName, DeviceName string
- SubName string
-}
-
-// Load load the hardware database for PCI devices and return a map of
-// vendor -> list of devices.
-func Load() (PciDevices, error) {
- // if the environment variable HWDATAPATH is set, we add it to the
- // list of paths we check for the hardware database.
- extraPath := os.Getenv("HWDATA")
- if extraPath != "" {
- pciPath = append(pciPath, extraPath)
- }
-
- for _, f := range pciPath {
- fh, err := os.Open(f)
- if err != nil {
- continue
- }
- defer fh.Close()
- return parse(fh)
- }
- return PciDevices{}, fmt.Errorf("hwids: could not find a pci.ids file")
-}
-
-func parse(f *os.File) (PciDevices, error) {
- devices := make(PciDevices)
-
- s := bufio.NewScanner(f)
-
- // this is to keep track of the current device. The format of the
- // file is as follow:
- // vendor vendor_name
- // device device_name <-- single tab
- // subvendor subdevice subsystem_name <-- two tabs
- // the variable is to keep track of the current vendor / device
- cur := PciDevice{}
-
- for s.Scan() {
- l := s.Text()
- // skip empty lines or lines that are a comment
- if len(l) == 0 || l[0] == '#' {
- continue
- }
- // lines starting with a C are the classes definitions, and
- // they are at the end of the file, which means we're done
- // parsing the devices
- if l[0] == 'C' {
- break
- }
-
- parts := strings.SplitN(l, " ", 2)
- if len(parts) != 2 {
- return devices, fmt.Errorf("hwids: malformed PCI ID line (missing ID separator): %s", l)
- }
-
- ids, name := parts[0], parts[1]
- if len(ids) < 2 || len(name) == 0 {
- return devices, fmt.Errorf("hwids: malformed PCI ID line (empty ID or name): %s", l)
- }
-
- cur.Type = PCIVendor
-
- if ids[0] == '\t' {
- if ids[1] == '\t' {
- cur.Type = PCISubsystem
- } else {
- cur.Type = PCIDevice
- }
- }
-
- var err error
- switch cur.Type {
- case PCIVendor:
- _, err = fmt.Sscanf(ids, "%x", &cur.Vendor)
- cur.VendorName = name
- case PCIDevice:
- _, err = fmt.Sscanf(ids, "%x", &cur.Device)
- cur.DeviceName = name
- case PCISubsystem:
- _, err = fmt.Sscanf(ids, "%x %x", &cur.SubVendor, &cur.SubDevice)
- cur.SubName = name
- }
-
- if err != nil {
- return devices, fmt.Errorf("hwids: malformed PCI ID line: %s: %v", l, err)
- }
-
- // This is to reset the state when we are moving to a
- // different vendor or device
- switch cur.Type {
- case PCIVendor:
- cur.Device = 0
- cur.DeviceName = ""
- fallthrough
- case PCIDevice:
- cur.SubVendor = 0
- cur.SubDevice = 0
- cur.SubName = ""
- }
-
- _, ok := devices[cur.Vendor]
- if ok {
- _devices := devices[cur.Vendor]
- _devices = append(_devices, cur)
- devices[cur.Vendor] = _devices
-
- } else {
- _devices := []PciDevice{cur}
- devices[cur.Vendor] = _devices
- }
- }
-
- if err := s.Err(); err != nil {
- return devices, fmt.Errorf("hwids: failed to read PCI ID line: %v", err)
- }
-
- return devices, nil
-}
diff --git a/packages/numap/internal/sysfs/parse.go b/packages/numap/internal/sysfs/parse.go
deleted file mode 100644
index d518653..0000000
--- a/packages/numap/internal/sysfs/parse.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package sysfs
-
-import (
- "io/ioutil"
- "strconv"
- "strings"
-)
-
-// ContentUint64 parses the content of a file in sysfs, and convert
-// from hex to uint64.
-func ContentUint64(path string) (uint64, error) {
- content, err := ioutil.ReadFile(path)
- if err != nil {
- return 0, err
- }
- result, err := strconv.ParseUint(strings.TrimSpace(string(content)), 0, 64)
- if err != nil {
- return 0, err
- }
- return result, nil
-}
diff --git a/packages/numap/internal/sysfs/pci.go b/packages/numap/internal/sysfs/pci.go
deleted file mode 100644
index 9e714b1..0000000
--- a/packages/numap/internal/sysfs/pci.go
+++ /dev/null
@@ -1,145 +0,0 @@
-package sysfs
-
-import (
- "fmt"
- "io/ioutil"
- "path"
- "path/filepath"
- "strconv"
- "strings"
-)
-
-const (
- sysFsPCIDevicesPath = "/sys/bus/pci/devices/"
-)
-
-type PCIDevice struct {
- NumaNode int
- ID string
- Device, Vendor uint64
- SubVendor, SubDevice uint64
- Class uint64
- MSIs []int
-}
-
-func ScanPCIDevices() []PCIDevice {
- devices, err := ioutil.ReadDir(sysFsPCIDevicesPath)
- if err != nil {
- panic(err)
- }
-
- pciDevices := []PCIDevice{}
-
- for _, device := range devices {
- dpath := filepath.Join(sysFsPCIDevicesPath, device.Name())
- pcid, err := NewPCIDevice(dpath, device.Name())
- if err != nil {
- panic(err)
- }
- pciDevices = append(pciDevices, pcid)
- }
- return pciDevices
-}
-
-func getPCIDeviceClass(path string) (uint64, error) {
- return ContentUint64(filepath.Join(path, "class"))
-}
-
-func getPCIDeviceVendor(path string) (uint64, error) {
- return ContentUint64(filepath.Join(path, "vendor"))
-}
-
-func getPCIDeviceId(path string) (uint64, error) {
- return ContentUint64(filepath.Join(path, "device"))
-}
-
-func getPCIDeviceSubsystemDevice(path string) (uint64, error) {
- return ContentUint64(filepath.Join(path, "subsystem_device"))
-}
-
-func getPCIDeviceSubsystemVendor(path string) (uint64, error) {
- return ContentUint64(filepath.Join(path, "subsystem_vendor"))
-}
-
-func getPCIDeviceNumaNode(path string) int {
- content, err := ioutil.ReadFile(filepath.Join(path, "numa_node"))
- if err != nil {
- panic(err)
- }
- nodeNum, err := strconv.Atoi(strings.TrimSpace(string(content)))
- if err != nil {
- panic(err)
- }
- return nodeNum
-}
-
-func getPCIDeviceMSIx(p string) []int {
- g := fmt.Sprintf("%s/*", filepath.Join(p, "msi_irqs"))
- files, err := filepath.Glob(g)
- if err != nil {
- panic(err)
- }
- if len(files) == 0 {
- return []int{}
- }
-
- msix := []int{}
-
- for _, f := range files {
- content, err := ioutil.ReadFile(f)
- if err != nil {
- panic(err)
- }
- if strings.TrimSpace(string(content)) == "msix" {
- base := path.Base(f)
- v, err := strconv.Atoi(base)
- if err != nil {
- panic(err)
- }
- msix = append(msix, v)
- }
- }
- return msix
-}
-
-func NewPCIDevice(path, name string) (PCIDevice, error) {
- nodeNum := getPCIDeviceNumaNode(path)
-
- device, err := getPCIDeviceId(path)
- if err != nil {
- return PCIDevice{}, err
- }
-
- vendor, err := getPCIDeviceVendor(path)
- if err != nil {
- return PCIDevice{}, err
- }
-
- subvendor, err := getPCIDeviceSubsystemVendor(path)
- if err != nil {
- return PCIDevice{}, err
- }
-
- subdevice, err := getPCIDeviceSubsystemDevice(path)
- if err != nil {
- return PCIDevice{}, err
- }
-
- deviceClass, err := getPCIDeviceClass(path)
- if err != nil {
- return PCIDevice{}, err
- }
-
- msix := getPCIDeviceMSIx(path)
-
- return PCIDevice{
- ID: name,
- Device: device,
- Class: deviceClass,
- NumaNode: nodeNum,
- Vendor: vendor,
- SubVendor: subvendor,
- SubDevice: subdevice,
- MSIs: msix,
- }, nil
-}
diff --git a/packages/numap/numa.go b/packages/numap/numa.go
deleted file mode 100644
index 402ea1d..0000000
--- a/packages/numap/numa.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "path"
- "path/filepath"
- "strings"
-
- "golang.fcuny.net/numap/internal/hwids"
- "golang.fcuny.net/numap/internal/sysfs"
-)
-
-const (
- node_root = "/sys/devices/system/node/node*"
- CLASS_NVMe = 67586
- CLASS_ETHERNET = 131072
- CLASS_GPU = 197120
-)
-
-type node struct {
- Name string `json:"name"`
- Path string `json:"path"`
- CpuList string `json:"cpulist"`
- PCIDevices []PCIDevice `json:"pci_devices"`
-}
-
-type PCIDevice struct {
- Vendor string `json:"vendor"`
- Name string `json:"name"`
-}
-
-func findNodes(hwdb hwids.PciDevices) (map[string]node, error) {
- nodes := make(map[string]node)
-
- files, err := filepath.Glob(node_root)
- if err != nil {
- return nil, fmt.Errorf("Failed to find NUMA nodes under %s: %+v", node_root, err)
- }
- if len(files) == 0 {
- return nil, fmt.Errorf("Could not find NUMA node in %s", node_root)
- }
-
- for _, f := range files {
- n, err := newNode(f)
- if err != nil {
- return make(map[string]node), err
- }
- nodes[n.Name] = n
- }
-
- r, err := mapPCIDevicesToNumaNode(hwdb)
- if err != nil {
- panic(err)
- }
- for k, v := range r {
- nodeName := fmt.Sprintf("node%d", k)
- n := nodes[nodeName]
- n.PCIDevices = v
- nodes[nodeName] = n
- }
- return nodes, nil
-}
-
-func mapPCIDevicesToNumaNode(hwdb hwids.PciDevices) (map[int][]PCIDevice, error) {
- devices := sysfs.ScanPCIDevices()
- r := map[int][]PCIDevice{}
-
- for _, d := range devices {
- if d.Class == CLASS_NVMe || d.Class == CLASS_ETHERNET || d.Class == CLASS_GPU {
- _, ok := hwdb[uint16(d.Vendor)]
- if ok {
- desc := hwdb[uint16(d.Vendor)]
- var vendor, name string
- for _, m := range desc {
- if uint64(m.Device) == d.Device && uint64(m.Vendor) == d.Vendor {
- vendor = m.VendorName
- name = m.DeviceName
- break
- }
- }
- pciDevice := PCIDevice{
- Vendor: vendor,
- Name: name,
- }
- r[d.NumaNode] = append(r[d.NumaNode], pciDevice)
- }
- }
- }
- return r, nil
-}
-
-func newNode(p string) (node, error) {
- _, name := path.Split(p)
-
- cpulist, err := cpuList(p)
- if err != nil {
- return node{}, err
- }
-
- return node{
- Name: name,
- Path: p,
- CpuList: cpulist,
- PCIDevices: []PCIDevice{},
- }, nil
-}
-
-func cpuList(p string) (string, error) {
- lpath := filepath.Join(p, "cpulist")
- c, err := ioutil.ReadFile(lpath)
- if err != nil {
- return "", fmt.Errorf("Failed to open %s: %+v", lpath, err)
- }
- return strings.TrimRight(string(c), "\n"), nil
-}
diff --git a/packages/numap/numap.go b/packages/numap/numap.go
deleted file mode 100644
index c65f1f0..0000000
--- a/packages/numap/numap.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "fmt"
- "os"
-
- "golang.fcuny.net/numap/internal/hwids"
-)
-
-func main() {
- hwdb, err := hwids.Load()
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- nodes, err := findNodes(hwdb)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- out, err := json.Marshal(nodes)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-
- fmt.Println(string(out))
-}