SRIOV 分离 VF 网口

SRIOV.sh

#!/bin/bash

__FileName__=""
__Author__="ShiWei"
__Time__="/2021/05/08"
__Version__="V1"

# 打印命令  并且  执行命令  函数
execute_and_pirnt_cmd() {
    # 第二个 参数 所执行命令 的注释
#    echo -e "\n $2 "
    printf "\n%12s %-s\n" " " $2
    echo  "[root@shiwei ~]# ${1}"
    res=-1  # 无 特殊字符命令的 输出状态
    result=0  # 有特殊字符命令的 输出结果
    echo $1 | grep -E  ['!'@#\$%^\&*\(\)\>\<\|_+] &> /dev/zero
    # 0 : 有 特殊字符 ;  1 : 无 特殊字符
    if [ $? -ne 0 ];then
        $1
        res=$?
    else
        # 命令之后包含 管道符
        echo $1 > cmd_script
        chmod 777 cmd_script
        bash cmd_script
#        ./cmd_script > result_file
#        result=`cat result_file`
#        rm -rf result_file
        rm -rf cmd_script
#        return ${result}
#        res=$?   # 此种方式 获取命令 执行结果 失败
    fi

    return ${res}
}


# 自动判断 该参数是否 配置,
read_or_config () {
    # 必须保证两个参数
    # 先判断 该参数是否已 配置
    if [ -z `eval 'echo $'"${2}"` ]; then
        read -p "$1" "$2"
    fi
}

# 优化网口
optim_net_card () {
    # 优化 物理网口
    ip link set ${1// /} mtu 9000
    combined=`ethtool  -l  ${1} | grep "Combined" | head -1 | awk -F ":" '{print $2}'`
    ethtool -L ${1} combined  ${combined// /}
        # 设置网卡最大缓存
    rx_num=`ethtool -g ${1} | grep -i rx:  | sed -n  '1p' | cut -d: -f2`
    tx_num=`ethtool -g ${1} | grep -i tx:  | sed -n  '1p' | cut -d: -f2`
    ethtool -G ${1} rx  ${rx_num// /}  tx  ${tx_num// }
} &> /dev/zero


bus () {
    echo '[root@Num_eigth_46 ~]# lspci -vvv | grep -i  ether'
    lspci -vvv | grep -i ether

    printf "%-15s %-8s %-15s %-15s %-20s %-32s %18s\n"  "网口名"  "  状态"  "      Bus 号"  "   驱动名"  "     驱动版本" "             固件版本"  "  槽位号"
    for i in `cat /proc/net/dev | egrep -iv 'lo:|virbr|vnet|face|inter' | cut -d: -f1 | sort`
    do

        printf "%-15s" $i
        state=`ip addr  show $i | sed '1p' -n  | awk -F state '{print $2}' | awk '{print $1}'`
        printf "%-8s" $state
        bus=`ethtool -i $i | grep -i bus | awk -F info: '{print $2}'`
        printf "%-15s" $bus
        driver_name=`ethtool -i $i | sed '1p' -n | awk -F river: '{print $2}'`
        printf "%-15s" $driver_name
        driver_ver=`ethtool -i $i | sed '2p' -n | awk -F sion: '{print $2}'`
        printf "%-20s" $driver_ver
        fw_version=`ethtool -i $i | sed '3p' -n | cut -d: -f2`
        printf "%-32s" "$fw_version"
        slots=`lspci -v -s ${bus} | grep 'Physical Slot' | cut -d ':' -f2 | grep -v 'Input/output'`
        printf "%-6s\n" $slots
    done
}


# [[ ${arr[@]/ens4f0/} != ${arr[@]} ]] && echo "Yes" || echo "No"
echo "#############################################################################################"
echo "#####################             SRIOV  自动化脚本                  ########################"
echo "#############################################################################################"
echo
printf "******  若当前为 SSH 链接机器, 则链接 IP 不可为当前所要配置SRIOV的网卡的IP   ******** \n"
printf "******  若该卡的是1G 电口卡,且驱动为 igb, 则SRIOV 的配置方法为 modprobe igb max_vfs=2,2,2,2 \n 当同时存在多个驱动为 igb 的1G电口卡时, 默认优先分离板载的,  ****\n"
printf "******  到当前为止 , 对 intel , mellanox, wangxun 卡 均有效   *****\n"
printf "******  需要打 VF 驱动的网卡请自行先把 VF  驱动打好,否则即使分离 VF 口成功了, \n 由于不存在 VF 驱动的拉起, 你是看不到 VF 网口名的,但是各个 VF 口的 PCI 设备是存在的 \n"
echo "#############################################################################################"
echo




PLATFORM='intel'
VIRT_BIOS='yes'
int_name=""
BUS=""
VF_NUM="0"
CURR_VF_NUM="0"
VF_ROOT=""
MAX_VF=""
TP_1G_SPEED="0"

echo
echo
# <1. 判断 CPU 平台
lscpu | sed '19p' -n | grep -i "VT-x"      # intel
if [ $? -eq 0 ]; then
    echo "该系统 CPU 为 Intel 平台"
else
    lscpu | sed '19p' -n | grep -i "amd-v" # amd
    if [ $? -eq 0 ]; then
        PLATFORM="amd"
        echo "*********** 该系统 CPU 为 AMD 平台"
    else
        PLATFORM="other"
        echo "*********** 该系统 CPU 为未知 平台"
        exit
    fi
fi


# <2.  判断 系统是否 开启 IOMMU, Intel 平台 在 /etc/default/grub 文件中添加 "intel_iommu=on iommu=pt",
    # Intel 平台 开启 IOMMU
    # 判断 Intel 平台 是否开启 IOMMU
if [ "$PLATFORM" == "intel" ]; then
    virt-host-validate | grep -i warn
    if [ $? -eq 0 ]; then
        grubby --update-kernel=`grubby --default-kernel` --args="intel_iommu=on iommu=pt"
        grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
        echo "*********** 该 Intel 平台系统内核已配置 IOMMU, 请重启就好 ......."
    fi
fi

    # 提示 要重启, 使其新添加的内核 参数 生效
    # AMD  平台 无需开启 IOMMU, 自动开启

# <3. 判断 系统 BIOS 是否开启 SRIOV 虚拟化开关
    # Intel 平台在 Bios 下开启 VT-D 虚拟化开关
    # AMD 平台需要在 Bios 下开启 SRIOV 和 SVM 两个 开关
virt-host-validate | grep "/dev/kvm exists" | grep -i "fail"
if [ $? -eq 0 ]; then
    VIRT_BIOS="no"
fi

if [ "$VIRT_BIOS" == "no" ];then
    if [ "$PLATFORM" == "amd" ]; then
        modprobe kvm
        modprobe ccp
        modprode kvm_amd
        echo "*********** 该 AMD 平台系统在 BIOS 下 未 开启虚拟化 SRIOV 和 SVM 开关, 请开启........."
        exit
    elif [ "$PLATFORM" == "intel" ]; then
        modprobe kvm
        mobprobe kvm_intel
        echo "*********** 该 Intel 平台系统在 BIOS 下 未 开启虚拟化 VT-D 开关, 请开启........."
        exit
    fi
else
    echo "*********** 该 ${PLATFORM} 平台系统在 BIOS 下已开启虚拟化开关。"
fi

echo
# 展示 SRIOV  vF 信息
bus
echo


# 输入待测网口名
while :
do
    read_or_config "请输入本机待测网口名:" int_name

    cat /proc/net/dev | egrep -iv 'lo:|virbr|vnet|face|inter' | cut -d: -f1 | grep ${int_name// /} &> /dev/zero
    if [ $? -eq 0 ];then
        break
    else
        echo "Sorry !本机无此网口,  请重新输入.........."
        int_name=""
    fi
done
echo
# 获取网卡 品牌 信息
bus_str=`ethtool -i ${int_name} | grep 'bus-info' | awk '{print $2}' | sed 's# ##g'`
driver_name=`ethtool -i ${int_name} | grep 'driver:' | awk '{print $2}' | sed 's# ##g'`
type_str=`lspci -vvv | grep 'Ethernet controller' | grep "${bus_str#*:}" | awk '{print $4,$5}' | tr A-Z a-z `
# 获取网卡是电口还是 光口(TP: 电口;  FIBRE: 光口)
cable_type=`ethtool ${int_name} | grep 'Supported ports:' | sed -r  's#.*\[(.*)\]$#\1#g' | sed 's/ //g'`
# 获取网卡当前速率
net_curr_speed=`ethtool ${int_name} | grep 'Speed:' | awk '{print $2}'`
# 判断该网卡是 几 P 的(几个接口的)
net_port_total=`ls -al "/sys/bus/pci/drivers/${driver_name}/" | grep ${bus_str%.*} | wc -l`
# 判断当前 网口是 该网卡的 第几个 接口
net_port_num=${bus_str##*.}
# 当前 该网卡所有 网口的 vf 数量
declare -a every_curr_vfs

for num in $(seq 0 $(echo $((4-1))))
do
    every_curr_vfs[${num}]=`cd  /sys/bus/pci/drivers/${driver_name} && cat ${bus_str%.*}.${num}/sriov_numvfs`
done


if [ "${cable_type}" == "TP" -a "${driver_name}" == "igb" ]; then
    echo "******** 该网卡接口为电口, 且速率为 ${net_curr_speed}"
    TP_1G_SPEED="1"

elif [ "${cable_type}" == "FIBRE" ]; then
    echo "******** 该网卡接口为光口 "
fi


#*	表示任意字符串。
#[abc]	表示 a、b、c 三个字符中的任意一个。比如,[15ZH] 表示 1、5、Z、H 四个字符中的任意一个。
#[m-n]	表示从 m 到 n 的任意一个字符。比如,[0-9] 表示任意一个数字,[0-9a-zA-Z] 表示字母或数字。
#|	表示多重选择,类似逻辑运算中的或运算。比如,abc | xyz 表示匹配字符串 "abc" 或者 "xyz"。

case ${type_str} in
    *intel*)
        brand="intel"
    ;;
    *mellanox*)
        brand="mellanox"
    ;;
    *wangxun*)
        brand="wangxun"
    ;;
    *)
        brand="no"
    ;;
esac

echo "******** 网卡品牌为: ${brand}"


cd "/sys/bus/pci/devices/"
	# 等价地址
#	/sys/class/net/<网口名>/device

# 获取 Bus 号
BUS=`ethtool -i ${int_name} | grep -i bus | awk -F info: '{print $2}'`
BUS=${BUS// /}
echo "*********** ${int_name} 网口的 BUS 号为: $BUS"
#VF_ROOT="/sys/bus/pci/devices/${BUS}"
#cd VF_ROOT
# 展示 可分离的 最大 VF 口数量
MAX_VF=`cat   ${BUS// /}/sriov_totalvfs`
CURR_VF_NUM=`cat   ${BUS// /}/sriov_numvfs`
echo "*********** ${int_name} 网口可分离的最大 VF 数量为: ${MAX_VF}"
echo "*********** ${int_name} 网口当前已分离的 VF 口数量为: ${CURR_VF_NUM}"
echo

# 设置 VF
while :
do
    read -p "请输入${int_name} 网口要分离的 VF 口数量:" VF_NUM
        # 判断输入得是否有效
    if [[ ${VF_NUM// /} -gt $MAX_VF || ${VF_NUM// /} -lt 0 ]];then
        echo "              可分离 VF 口有效范围为: (0 <= VF <= ${MAX_VF})"
    else
        # 判断是否不为 1G 电口卡
        if [ "${TP_1G_SPEED}" == "0" ]; then
            echo ${VF_NUM} > ${BUS// /}/sriov_numvfs
        else
            modprobe -r igb
            sleep 1
            # 给该网卡所有网口
            every_curr_vfs[${net_port_num}]=${VF_NUM}
            config_str="${every_curr_vfs[0]},${every_curr_vfs[1]},${every_curr_vfs[2]},${every_curr_vfs[3]}"
            modprobe igb max_vfs=${config_str}
#            modprobe igb max_vfs=2,2,2,2
            echo
        fi
        echo "*********** VF 口分离完成。"
        wait
        sleep 1
        break
    fi
done

sleep 7
# 展示 所有 创建的 VF 口
if [[ "${VF_NUM}" -ne "0" ]]; then
    #bus | grep "${int_name}v"
    echo "在 ${int_name} 物理网口上所创建的所有 VF 口如下:"
    all_vf=($(cat /proc/net/dev | egrep -iv 'lo:|virbr|vnet|face|inter' | cut -d: -f1 | egrep -i "${int_name}.{1,}" | sort --field-separator=" " --key=3))
    for vf in $(seq $(echo $((${VF_NUM// /} - 1 ))) -1  0)
    do
        if [ `expr ${vf} % 5` == "0" ]; then
            printf "\n"
        fi
        printf "   ${all_vf[${vf}]}   "
    done
    echo "   ${all_vf[0]}   "
    # 设置物理口的 mtu 为 9000
    optim_net_card ${int_name}
    # 设置 所有 VF 口 的 mtu 为 9000
    for vf_dev in `cat /proc/net/dev | egrep -iv 'lo:|virbr|vnet|face|inter' | cut -d: -f1 | egrep -i "${int_name}[a-z]{1,}" | sort --field-separator=" " --key=3 | awk '{print $1}'`
    do
#        ip link set ${vf_dev// /} mtu 9000
        optim_net_card ${vf_dev}
    done
fi
echo
echo

# 优化 物理网口
    # 设置最大队列
#combined=`ethtool  -l  ${int_name} | grep "Combined" | head -1 | awk -F ":" '{print $2}'`
#ethtool -L ${int_name} combined  ${combined}
#    # 设置网卡最大缓存
#rx_num=`ethtool -g ${int_name} | grep -i rx  | sed -n  '1p' | cut -d: -f2`
#tx_num=`ethtool -g ${int_name} | grep -i tx  | sed -n  '1p' | cut -d: -f2`
#ethtool -G ${int_name} rx  ${rx_num}  tx  ${tx_num}

# DHCP  获取 IP
dhclient -r
dhclient &> /dev/zero

# 善意的提醒
# 1. 测试 SRIOV bond 时 , 别忘记安装  python3 了






posted @ 2021-06-22 20:17  梭梭666  阅读(443)  评论(0编辑  收藏  举报
返回顶部