#!/bin/sh
# enumerate-nics.sh — JSON array of NIC facts via /sys (no classification)

FIRST=true
printf '['

for P in /sys/class/net/*; do
  IF=$(basename "$P")
  [ -e "/sys/class/net/$IF/device" ] || continue

  DEV=$(readlink -f "/sys/class/net/$IF/device") || continue
  BDF=${DEV##*/}

  DRIVER_PATH=$(readlink -f "/sys/class/net/$IF/device/driver" 2>/dev/null || true)
  DRIVER=${DRIVER_PATH##*/}; [ "$DRIVER" = "/driver" ] && DRIVER=""

  MAC=$(cat "/sys/class/net/$IF/address" 2>/dev/null || echo "")
  MTU=$(cat "/sys/class/net/$IF/mtu" 2>/dev/null || echo 0)
  OPER=$(cat "/sys/class/net/$IF/operstate" 2>/dev/null || echo unknown)
  SPEED=$(cat "/sys/class/net/$IF/speed" 2>/dev/null || echo -1)
  DUPLEX=$(cat "/sys/class/net/$IF/duplex" 2>/dev/null || echo unknown)
  NUMA=$(cat "/sys/class/net/$IF/device/numa_node" 2>/dev/null || echo -1)

  RXQ=0; TXQ=0
  QDIR="/sys/class/net/$IF/queues"
  if [ -d "$QDIR" ]; then
    for q in "$QDIR"/rx-*; do [ -d "$q" ] || continue; RXQ=$((RXQ+1)); done
    for q in "$QDIR"/tx-*; do [ -d "$q" ] || continue; TXQ=$((TXQ+1)); done
  fi

  # PHC / PTP
  PHC_INDEX=""
  PTP_SUPPORTED=false
  if [ -d "$DEV/ptp" ]; then
    for p in "$DEV"/ptp/ptp*; do
      [ -d "$p" ] || continue
      base=$(basename "$p")
      case "$base" in ptp*) PHC_INDEX=${base#ptp}; PTP_SUPPORTED=true; break ;; esac
    done
  fi

  # PCI IDs / class / IOMMU
  VENDOR=$(cat "/sys/bus/pci/devices/$BDF/vendor" 2>/dev/null || echo "")
  DEVICE=$(cat "/sys/bus/pci/devices/$BDF/device" 2>/dev/null || echo "")
  SUBV=$(cat "/sys/bus/pci/devices/$BDF/subsystem_vendor" 2>/dev/null || echo "")
  SUBD=$(cat "/sys/bus/pci/devices/$BDF/subsystem_device" 2>/dev/null || echo "")
  IOMMU_PATH=$(readlink -f "/sys/bus/pci/devices/$BDF/iommu_group" 2>/dev/null || true)
  IOMMU_GROUP=
  if [ -n "$IOMMU_PATH" ]; then
    base=${IOMMU_PATH##*/}
    case "$base" in
      ''|*[!0-9]*) IOMMU_GROUP= ;;
      *) IOMMU_GROUP="$base" ;;
    esac
  fi

  # SR-IOV flags
  IS_VF=false
  [ -e "/sys/bus/pci/devices/$BDF/physfn" ] && IS_VF=true
  SRIOV_TOTAL=0
  [ -e "/sys/bus/pci/devices/$BDF/sriov_totalvfs" ] && SRIOV_TOTAL=$(cat "/sys/bus/pci/devices/$BDF/sriov_totalvfs")
  SRIOV_NUM=0
  [ -e "/sys/bus/pci/devices/$BDF/sriov_numvfs" ] && SRIOV_NUM=$(cat "/sys/bus/pci/devices/$BDF/sriov_numvfs")

  # IPv4 addresses. /sys doesn't expose these — use iproute2's `ip`
  # which is universally available on modern Linux. Emit as a JSON
  # string array; empty array if `ip` is missing or no IPs are bound.
  IPS_JSON='[]'
  if command -v ip >/dev/null 2>&1; then
    IPS_RAW=$(ip -o -4 addr show dev "$IF" 2>/dev/null | awk '{print $4}' | awk -F/ '{print $1}')
    if [ -n "$IPS_RAW" ]; then
      IPS_JSON="[$(printf '%s\n' "$IPS_RAW" | awk 'NF{printf("%s\"%s\"", sep, $0); sep=","}')]"
    fi
  fi

  # emit
  if [ "$FIRST" = false ]; then printf ','; fi
  FIRST=false

  printf '{'
  printf '"ifname":"%s",' "$IF"
  printf '"pciBdf":"%s",' "$BDF"
  printf '"driver":"%s",' "$DRIVER"
  printf '"mac":"%s",' "$MAC"
  printf '"mtu":%s,' "$MTU"
  printf '"operstate":"%s",' "$OPER"
  printf '"speedMbps":%s,' "$SPEED"
  printf '"duplex":"%s",' "$DUPLEX"
  printf '"numa":%s,' "$NUMA"
  printf '"rxQueues":%s,' "$RXQ"
  printf '"txQueues":%s,' "$TXQ"
  printf '"ptpSupported":%s,' "$PTP_SUPPORTED"
  if [ -n "$PHC_INDEX" ]; then
    printf '"phcIndex":%s,' "$PHC_INDEX"
  else
    printf '"phcIndex":null,'
  fi
  printf '"vendor":"%s",' "$VENDOR"
  printf '"device":"%s",' "$DEVICE"
  printf '"subvendor":"%s",' "$SUBV"
  printf '"subdevice":"%s",' "$SUBD"
  if [ -n "$IOMMU_GROUP" ]; then
    printf '"iommuGroup":%s,' "$IOMMU_GROUP"
  else
    printf '"iommuGroup":null,'
  fi
  printf '"isSriovVf":%s,' "$IS_VF"
  printf '"sriovTotalVfs":%s,' "$SRIOV_TOTAL"
  printf '"sriovNumVfs":%s,' "$SRIOV_NUM"
  printf '"ipAddresses":%s' "$IPS_JSON"
  printf '}'
done

printf ']\n'
