#!/bin/bash
# Small Script to determine the nvme pcie gen
# Author: Sebastian Klee, E-Mail: s.klee@timmehosting.de
# Version: 1.0
# Date: 23.09.2024

# Index for arrays
index=0

# Repeat the loop for each line of the output of "lspci | grep 'NV'". The variable "pcie" gets the current line of the output.
IFS=$'\n' && for pcie in $(lspci | grep 'NVM'); do
   # The following arrays get the current value of the variable pcie. 
   nvme_contro[index]="$pcie"
   bus_adr_par[index]=$(echo "$pcie" | awk -F ':' '{print $1}')
   bus_adr_com[index]=$(echo "$pcie" | awk -F ' ' '{print $1}')
   index=$((index + 1))
done

# It the host is an old openvz host
os_release=$(cat /proc/sys/kernel/osrelease)
if [[ $os_release =~ "openvz" ]]; then
  echo -e "NVME PCIe Controller:\n"
  echo "Alter OpenVZ Host, bitte manuell pruefen!!!"
  exit 0
fi

# The Value of the variable "number_adr" is the size of the array "nvme_contro"
number_adr="${#nvme_contro[@]}"
# If the Host has no NVMes
if [[ $number_adr == 0 ]]; then
  echo -e "NVME PCIe Controller:\n"
  echo "Server has no NVMes!!!"
  exit 0
fi

echo -e "NVME PCIe Controller:\n"
for (( c=0; c<number_adr; c++ ))
do
   # Name of the device
   nvme=$(file -h /sys/block/nvme* | awk -F '/|:' -v adre="${bus_adr_com[c]}" '$0 ~ adre {print$4}')
   # Current link speed of the device
   current_link_speed=$(cat  /sys/class/pci_bus/0000:"${bus_adr_par[c]}"/device/0000:"${bus_adr_com[c]}"/current_link_speed)
   # Max link speed of the device
   max_link_speed=$(cat /sys/class/pci_bus/0000:"${bus_adr_par[c]}"/device/0000:"${bus_adr_com[c]}"/max_link_speed)
   # Current link witdth of the device
   current_link_width=$(cat  /sys/class/pci_bus/0000:"${bus_adr_par[c]}"/device/0000:"${bus_adr_com[c]}"/current_link_width)
   # Max link width of the device
   max_link_width=$(cat /sys/class/pci_bus/0000:"${bus_adr_par[c]}"/device/0000:"${bus_adr_com[c]}"/max_link_width)

   # Determining the PCIe gen of the NVMe
   if [[ $max_link_speed =~ 8.0\ GT ]]; then
     echo "${nvme}: PCIe 3 NVMe"
   elif [[ $max_link_speed =~ 16.0\ GT ]]; then
     echo "${nvme}: PCIe 4 NVMe"
   elif [[ $max_link_speed =~ 32.0\ GT ]]; then
     echo "${nvme}: PCIe 5 NVMe"
   elif [[ $max_link_speed =~ 64.0\ GT ]]; then
     echo "${nvme}: PCIe 6 NVMe"
   else
     echo ""
   fi

   # Output additional information
   echo "---------------------"
   echo -e "More information:"
   echo -e "\t${nvme_contro[c]}"
   echo -e "\tCurrent Link Speed: ${current_link_speed}"
   echo -e "\tMax Link Speed: ${max_link_speed}"
   echo -e "\tCurrent Link Width: ${current_link_width}"
   echo -e "\tMax Link Width: ${max_link_width}"
   echo ""

done

exit 0
