#!/bin/bash

# 脚本用途：
# 1. 将 bond0 下所有物理网卡的 RX 和 TX 队列数设置为 4096。
# 2. 为每个物理网卡创建 32 个虚拟函数（VF）。
# 3. 为所有 VF 设置最大传输速率（max_tx_rate）为 1000 Mbps。

# 期望的 VF 数量
DESIRED_VFS=32

# 函数：打印错误信息并退出
error_exit() {
    echo "错误: $1" >&2
    exit 1
}

# 检查是否以 root 身份运行
if [[ $EUID -ne 0 ]]; then
   error_exit "此脚本必须以 root 用户运行。"
fi

# 检查 ethtool 是否安装
if ! command -v ethtool &> /dev/null; then
    error_exit "ethtool 未安装。请使用包管理器安装 ethtool。"
fi

# 检查 lspci 是否安装
if ! command -v lspci &> /dev/null; then
    error_exit "lspci 未安装。请使用包管理器安装 pciutils。"
fi

# 检查 bond0 是否存在
if ! ip link show bond0 &> /dev/null; then
    error_exit "bond0 接口不存在。请确保 bond0 已正确配置。"
fi


# 获取 bond0 的模式
BOND_MODE_FILE="/sys/class/net/bond0/bonding/mode"

if [ ! -f "$BOND_MODE_FILE" ]; then
  error_exit "错误: 文件 $BOND_MODE_FILE 不存在，请确认 bond0 已配置为绑定模式。"
fi

# 读取模式
BOND_MODE=$(cat "$BOND_MODE_FILE" | awk '{print $2}')

echo "开始配置 bond0 下的所有物理网卡..."

# 获取 bond0 的从属物理网卡列表
SLAVE_INTERFACES=$(grep "Slave Interface:" /proc/net/bonding/bond0 | awk '{print $3}')

if [[ -z "$SLAVE_INTERFACES" ]]; then
    error_exit "未找到 bond0 的从属物理网卡。"
fi

echo "发现以下从属物理网卡: $SLAVE_INTERFACES"

# 数组用于存储所有 VF 接口名称
declare -a VF_INTERFACES=()

# 遍历每个从属物理网卡
for IFACE in $SLAVE_INTERFACES; do
    echo "配置网卡: $IFACE"

    # 检查网卡是否存在
    if ! ip link show "$IFACE" &> /dev/null; then
        echo "警告: 网卡 $IFACE 不存在，跳过。"
        continue
    fi

    # 设置 RX 和 TX 队列数为 4096
    echo "设置网卡 $IFACE 的 RX 和 TX 队列数为 4096..."
    ethtool -G "$IFACE" rx 4096 tx 4096
    if [[ $? -ne 0 ]]; then
        echo "错误: 无法设置网卡 $IFACE 的 RX/TX 队列数。请检查网卡是否支持此操作。"
        #continue
    fi

    if [[ "$BOND_MODE" != "6" ]] && [[ "$BOND_MODE" != "1" ]];then
	echo "只有Bond 1|6 模式下才能启动sr-iov"
	continue
    fi

    # 获取当前 SR-IOV 配置路径
    SRIOV_NUMVFS_PATH="/sys/class/net/$IFACE/device/sriov_numvfs"
    SRIOV_TOTALVFS_PATH="/sys/class/net/$IFACE/device/sriov_totalvfs"

    # 检查 SR-IOV 是否支持
    if [[ ! -w "$SRIOV_NUMVFS_PATH" ]]; then
        echo "警告: 无法访问 $SRIOV_NUMVFS_PATH，可能不支持 SR-IOV，跳过 VF 创建。"
        continue
    fi

    # 获取当前启用的 VF 数量
    CURRENT_VFS=$(cat "$SRIOV_NUMVFS_PATH" 2>/dev/null)
    TOTAL_VFS=$(cat "$SRIOV_TOTALVFS_PATH" 2>/dev/null)


    # 检查网卡支持的最大 VF 数量
    if [[ "$DESIRED_VFS" -gt "$TOTAL_VFS" ]]; then
        echo "警告: 网卡 $IFACE 仅支持最多 $TOTAL_VFS 个 VF，无法创建 $DESIRED_VFS 个 VF。"
        DESIRED_VFS="$TOTAL_VFS"
    fi

    # 配置 SR-IOV 并创建 VF
    echo "为网卡 $IFACE 创建 $DESIRED_VFS 个 VF..."
    echo "$DESIRED_VFS" > "$SRIOV_NUMVFS_PATH"
    if [[ $? -ne 0 ]]; then
        echo "错误: 无法为网卡 $IFACE 创建 VF。"
        continue
    fi

    # 验证 VF 是否创建成功
    NEW_VFS=$(cat "$SRIOV_NUMVFS_PATH" 2>/dev/null)
    if [[ "$NEW_VFS" -eq "$DESIRED_VFS" ]]; then
        echo "成功: 网卡 $IFACE 已配置 $DESIRED_VFS 个 VF。"
    else
        echo "警告: 网卡 $IFACE 的 VF 数量为 $NEW_VFS，未达到预期的 $DESIRED_VFS 个。"
    fi

    # 识别并存储 VF 接口名称
    # 方法：
    # 1. 通过 virtfn* 目录获取 VF 的 PCI 地址
    # 2. 通过 lspci 获取对应的网络接口名称
    sleep 2
    for VF_NUM in $(seq 0 $((DESIRED_VFS - 1))); do
	# 设置 VF 接口的最大传输速率为 1000 Mbps
        echo "设置 VF 接口 $VF_IFACE 的最大传输速率为 1000 Mbps..."
        ip link set "$IFACE" vf "$VF_NUM" max_tx_rate 1000
        if [[ $? -eq 0 ]]; then
           echo "成功: 为 VF 接口 $VF_IFACE 设置了最大传输速率 1000 Mbps。"
        else
           echo "警告: 无法为 VF 接口 $VF_IFACE 设置最大传输速率。请检查驱动是否支持该操作。"
        fi
    done
done

echo "所有配置已完成。"

exit 0

