#!/usr/bin/env bash

CONFIG_PATH="/etc/network/interfaces.d"
NETPLAN_PATH="/etc/netplan"
RT_TABLE_DIR="/etc/networkd-dispatcher/routable.d"
MAC_URL="169.254.169.254/2009-04-04/meta-data/network/interfaces/macs"
NET_CLOUD_CFG="/etc/network/interfaces.d/50-cloud-init.cfg"
CLOUDINIT_CFG="/etc/cloud/cloud.cfg"
RT_TABLES="/etc/iproute2/rt_tables"
PRIMARY_NIC=
DEFAULT_EIP_NIC=
DEFAULT_EIP=
DEFAULT_EIP_GATEWAY=
SCRIPT_VERSION="3.0.20260323"
NOTCFG_AUXIPEIP=0
nic_type_cache=
primary_ip_cahce=
declare -A nametotype
declare -A nametoprimaryip
ipv4_sed_index=6
ONLY_CONFIG_IPv4=0
ONLY_CONFIG_IPv6=0
declare -A nametomac
mac_address_cache=

function calculate_network {
    IP=$1
    MASK=$2
    if ! [ -x "$(command -v sipcalc)" ]; then
        sudo apt-get -y install sipcalc >/dev/null 2>&1
    fi
    NETWORK=$(sipcalc $IP/$MASK | grep 'Network range' | awk -F "- " '{gsub(" -", ""); print $2}')
    NETWORK="${NETWORK}/${MASK}"
    echo $NETWORK
}

function ip_version() {
    local ip=$1
    local IFS=.
    local -a octets=($ip)
    if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        return 4
    else
        return 6
    fi
}
function get_primary_ip(){
    name=$1
    if [[ -z ${nametoprimaryip[$name]} ]]; then
        get_mac_address $name
        mac=$mac_address_cache
        primary_ip=$(curl -s "$MAC_URL/$mac/primary_ipv4_addr")
        nametoprimaryip[$name]=$primary_ip
        primary_ip_cahce=$primary_ip
    else
        primary_ip_cahce=${nametoprimaryip[$name]}
    fi
}

function get_mac_address(){
    name=$1
    #if [[ -z ${nametomac[$name]} ]]; then
        mac_address_tmp=$(cat /sys/class/net/$name/address)
        mac_address=$(curl -f -s "$MAC_URL" | grep -iE "$mac_address_tmp" | sed 's/\///g')
        if [[ $? -ne 0 ]]; then
            echo "[get_mac_address] failed to get mac address for $name from metadata server" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            mac_address_cache=""
            return 1
        fi
    #    nametomac[$name]=$mac_address
        mac_address_cache=$mac_address
    #else
    #    mac_address_cache=${nametomac[$name]}
    #fi
}

function get_nic_type() {
    name=$1
    if [[ -z ${nametotype[$name]} ]]; then
      get_mac_address $name
      mac=$mac_address_cache
      if [[ -z "$mac" ]]; then
        echo "[get_nic_type] mac address is empty for $name" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        nic_type_cache=""
        return 1
      fi
      nic_type=$(curl -f -s "$MAC_URL/$mac/vif_features")
      if [[ $? -ne 0 ]]; then
        echo "[get_nic_type] failed to get vif_features for $name from metadata server" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        nic_type_cache=""
        return 1
      fi
      nametotype[$name]=$nic_type
      nic_type_cache=$nic_type
    else
      nic_type_cache=${nametotype[$name]}
    fi
}

function get_MTU(){  
    name=$1
    get_mac_address $name
    mac=$mac_address_cache
    mtu=$(curl -s "$MAC_URL/$mac/mtu")
    echo $mtu
} 

function netmask2cidr() { 
    local mask=$1
    if [[ $mask =~ ":" ]]; then
        # If the mask is IPv6
        local bin_mask=$(echo $mask | tr -d ':' | xxd -r -p | xxd -b -c 16 | tr -d ' \n')
        local count_segment=0
        for ((i=0; i<${#bin_mask}; i++)); do
            if [[ "${bin_mask:$i:1}" == "1" ]]; then
                ((count_segment++))
            fi
        done
        echo $count_segment
    else
        # If the mask is IPv4
        awk -F. '{
        split($0, arrSep)
        for (i in arrSep) {
            mask += int(8 - log(2^8 - arrSep[i])/log(2));
        }
        print mask
        }' <<< $mask
    fi
}

# disable cloud-init's network configuration capabilities
function disable_cloud_network(){
    grep -i -q "network: {config: disabled}" $CLOUDINIT_CFG
    if [[ "$?" -ne 0 ]]; then
        echo "" >> $CLOUDINIT_CFG
        echo "network: {config: disabled}" >> $CLOUDINIT_CFG
    fi
}

function disable_networkmanager(){
    version=$1
    if [[ "$version" == "14" ]]; then
        service network-manager stop >/dev/null 2>&1
        dpkg -l | grep -i -q "network-manager"
        if [[ "$?" -eq 0 ]]; then
            echo "  Remove package: network-manager." | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            apt-get --purge remove -y network-manager >/dev/null 2>&1
        fi
    else
        #echo "  Disable NetworkManager."
        systemctl stop NetworkManager >/dev/null 2>&1
        systemctl disable NetworkManager >/dev/null 2>&1
    fi
}
# reset interfaces config file
function modify_interfaces_file(){
    cat > /etc/network/interfaces  << EOF
auto lo
iface lo inet loopback

source /etc/network/interfaces.d/*
EOF
    if [[ ! -d "$CONFIG_PATH" ]]; then
        mkdir $CONFIG_PATH
    fi
}


function get_primary_nic(){
    nics=$(ls /sys/class/net/ | grep "^eth")
    for name in ${nics[*]}
    do
        get_mac_address $name
        mac=$mac_address_cache
        eni_type=$(curl -f -s "$MAC_URL/$mac/eni_type")
        if [[ "$eni_type" == "primary" ]]; then
            echo $name
            break
        fi
    sleep 1 
    done
}


function get_meta_value(){
    name=$1
    ip=$2
    item=$3
    get_mac_address $name
    mac=$mac_address_cache
    ret=0
    for ((i=1; i<=3; i++)); do
        value=$(curl -f -s $MAC_URL/$mac/fixed_ips/$ip/$item)
        ret="$?"
        if [[ "$ret" -eq 0 ]]; then
            break
        fi
        sleep 1
    done
    echo $value
}

function create_net_config(){
    name=$1
    mac=$2
    local primary_ip
    local netmask
    if [[ "${name}" != "${PRIMARY_NIC}" ]]; then
        get_primary_ip "${name}"
        primary_ip=$primary_ip_cahce
        netmask=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${primary_ip}/mask")
        cat  > "$CONFIG_PATH/${name}.cfg" << EOF
auto ${name}
iface ${name} inet static
hwaddress ether ${mac}
address ${primary_ip}
netmask ${netmask}
mtu $(get_MTU $name)
EOF
    else
        cat  > "$CONFIG_PATH/${name}.cfg" << EOF
auto $name
iface $name inet dhcp
hwaddress ether $mac
EOF
    fi
}

function create_net_config_netplan(){
    name=$1
    mac=$2
    local primary_ip
    local netmask
    if [[ "${name}" != "${PRIMARY_NIC}" ]]; then
        get_primary_ip "${name}"
        primary_ip=$primary_ip_cahce
        netmask=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${primary_ip}/mask")
        cat  > "$NETPLAN_PATH/${name}.yaml" << EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    ${name}:
      addresses:
        - ${primary_ip}/$(netmask2cidr $netmask)
      mtu: $(get_MTU $name)
EOF
    else
        echo eth-$name write 
        cat  > "$NETPLAN_PATH/${name}.yaml" << EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    ${name}:
      dhcp4: yes
EOF
        if [[ "18 20 22 24" =~ $version ]]; then
            ip link set $name up
        fi
    fi
}

function restrict_default_route(){
    name=$(get_primary_nic)
    cat > /etc/dhcp/dhclient-enter-hooks.d/restrict-default-route << EOF
case \${interface} in
  $name)
    ;;
  *)
    unset new_routers
    ;;
esac
EOF
}

function is_eip_direct_enabled() {
    local mac=$1
    local ip=$2
    eip_direct=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${ip}/eip_direct")
    if [ "$eip_direct"x = "true"x ]; then
        return 0
    fi
    return 1
}

function config_eip_direct() {
    local name=$1
    local mac=$2
    local ip=$3
    local ipversion=$4
    local ub16index2=$5
    if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        cfg_append=
        iplen="32"
        mask="255.255.255.255"
        #echo IPv4
    else
        #echo IPv6
        cfg_append="6"
        iplen="128"
        mask="ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
    fi
    local eip=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${ip}/eip")
    local eip_gateway=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${ip}/gateway")

    #echo "ip: $ip"
    #echo "eip: $eip"
    #echo "ub16index2: $ub16index2"
    
    echo "[config_eip_direct]nic:$name,ip=$ip,eip=$eip" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    if  [[ "14 16" =~ $version ]]; then
        netmask=$(curl -s "$MAC_URL/$mac/fixed_ips/$ip/mask")
        if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            cat >> $CONFIG_PATH/${name}.cfg << EOF

auto $name:$ub16index2
iface $name:$ub16index2 inet static
address $eip
netmask $netmask
EOF
        else
            cat >> $CONFIG_PATH/${name}.cfg << EOF

auto $name:$ub16index2
iface $name:$ub16index2 inet6 static
address $eip
netmask $(netmask2cidr $netmask)
EOF
        fi
    else
        local config_file=$name.yaml
        if [ $name = 'eth0' ]; then
            config_file='01-netcfg.yaml'
        fi
        cat >> $NETPLAN_PATH/${config_file} << EOF
      addresses:
        - $eip/$iplen
EOF
    fi

    if [[ "${EIP_OPT}" = "install" ]]; then
        echo "${DEFAULT_EIP:=${eip}}" > /dev/null
        if [[ "${DEFAULT_EIP}" = "${eip}" ]]; then
            DEFAULT_EIP_NIC="${name}"
            DEFAULT_EIP_GATEWAY="${eip_gateway}"
        fi
    elif [[ "${EIP_OPT}" = "uninstall" ]]; then
        DEFAULT_EIP=""
        DEFAULT_EIP_NIC=""
        DEFAULT_EIP_GATEWAY=""
    fi

    echo "EIP_OPT=$EIP_OPT,DEFAULT_EIP=$DEFAULT_EIP,DEFAULT_EIP_NIC=$DEFAULT_EIP_NIC,DEFAULT_EIP_GATEWAY=$DEFAULT_EIP_GATEWAY" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
}

function config_secondary_ips(){
    name=$1
    mac=$2
    ips=($(curl -s $MAC_URL/$mac/fixed_ips| sed 's/\///g'))
    get_primary_ip "${name}"
    primary_ip=$primary_ip_cahce

    ub16index=0
    first=true

    for ip in ${ips[*]}
    do
        ip_version $ip
        ipversion=$?
        echo "[config_secondary_ips]nic:$name,ip:$ip,primary ip:$primary_ip" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        if is_eip_direct_enabled "${mac}" "${ip}"; then
            if ([ "$ipversion" = "4" ] && [ $ONLY_CONFIG_IPv6 -eq 0 ]) || ([ "$ipversion" = "6" ] && [ $ONLY_CONFIG_IPv4 -eq 0 ]); then
                config_eip_direct "${name}" "${mac}" "${ip}" "${ipversion}" "${ub16index}"
                let ub16index++
            fi
        fi

        if [ "$ip" != "$primary_ip" ]; then
            netmask=$(curl -s "$MAC_URL/$mac/fixed_ips/$ip/mask")
            if  [[ "14 16" =~ $version ]]; then
                if [ "$ipversion" = "4" ] && [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                    let ub16index++
                    cat >> $CONFIG_PATH/${name}.cfg << EOF

auto $name:$ub16index
iface $name:$ub16index inet static
address $ip
netmask $netmask
EOF
                fi
                if [ $ipversion = 6 ]; then
                    if [ "$first" = true ]; then
                        first=false
                        #ipv4_sed_index=$(wc -l /etc/network/interfaces.d/$name.cfg | awk '{print $1}')
                    fi
                    if [ $ONLY_CONFIG_IPv4 -eq 0 ];then
                    cat >> $CONFIG_PATH/${name}.cfg << EOF

auto $name:$ub16index
iface $name:$ub16index inet6 static
address $ip
netmask $(netmask2cidr $netmask)
EOF
                    let ub16index++
                    fi
                fi
            else
                if [ $PRIMARY_NIC = $name ]; then
                    if ([ "$ipversion" = "4" ] && [ $ONLY_CONFIG_IPv6 -eq 0 ]) || ([ "$ipversion" = "6" ] && [ $ONLY_CONFIG_IPv4 -eq 0 ]); then
                    cat >> $NETPLAN_PATH/01-netcfg.yaml << EOF
      addresses:
        - $ip/$(netmask2cidr $netmask)
EOF
                    fi
                else
                    if ([ "$ipversion" = "4" ] && [ $ONLY_CONFIG_IPv6 -eq 0 ]) || ([ "$ipversion" = "6" ] && [ $ONLY_CONFIG_IPv4 -eq 0 ]); then
                        cat >> $NETPLAN_PATH/${name}.yaml << EOF
      addresses:
        - $ip/$(netmask2cidr $netmask)
EOF
                    fi
                fi
            fi
        fi
    done
    if [[ "18 20 22 24" =~ $version ]] && [ $ONLY_CONFIG_IPv4 -eq 1 ] && [ "$name" != "$PRIMARY_NIC" ]; then
        echo "      accept-ra: false" >> $NETPLAN_PATH/${name}.yaml
    fi
    if [[ "18 20 22 24" =~ $version ]] && [ $ONLY_CONFIG_IPv4 -eq 1 ] && [ "$name" = "$PRIMARY_NIC" ]; then
        echo "      accept-ra: false" >> $NETPLAN_PATH/01-netcfg.yaml
    fi
          
}

# create/recreate nic's config file
function create_nics_config(){
    nics=$(ls /sys/class/net/ | grep "^eth"  | grep -v "$PRIMARY_NIC")
    for name in ${nics[*]}
    do
        get_nic_type $name
        nictype=$nic_type_cache
        if [[ -z "$nictype" ]]; then
            echo "nic:$name failed to get nic type, skip this nic" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            continue
        fi
        if [ "$nictype"x = "rdma_roce"x ]; then
            echo "nic:$name is roce nic,not create ifcfg,continue" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            continue
        fi
        get_mac_address $name
        mac=$mac_address_cache
        echo "create cfg for nic:$name,mac:$mac" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        if  [[ "14 16" =~ $version ]]; then
            rm -f "${CONFIG_PATH}"/${name}.cfg
            create_net_config $name $mac
        else
            echo "rm old ${name}.yaml and create it again" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            rm -f "${NETPLAN_PATH}"/${name}.yaml
            create_net_config_netplan $name $mac
        fi
        if [ $NOTCFG_AUXIPEIP -eq 0 ]; then
            config_secondary_ips $name $mac
        fi
    done
    # primary nic secondary ip config
    get_mac_address $PRIMARY_NIC
    mac=$mac_address_cache
    if  [[ "14 16" =~ $version ]]; then
        rm -f "${CONFIG_PATH}"/${PRIMARY_NIC}.cfg
        create_net_config $PRIMARY_NIC $mac
    else
        sed -i '/addresses:/{N;d;}' "${NETPLAN_PATH}"/01-netcfg.yaml
    fi
    if [ $NOTCFG_AUXIPEIP -eq 0 ]; then
        config_secondary_ips $PRIMARY_NIC $mac
    fi
    echo -e "    create/recreate network config file \033[32m[OK]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
}

function add_route_table(){
    if [[ "18 20 22 24" =~ $version ]]; then
        #  install package networkd-dispatcher
	    dpkg -l | grep -q networkd-dispatcher
	    if ([ $? != 0 ] || [ 18 = $version ]); then
            echo " Install package: networkd-dispatcher" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            apt-get update >/dev/null 2>&1
	        apt-get install -y networkd-dispatcher >/dev/null 2>&1
        fi
    fi
    dpkg -l |grep -w ipcalc
    if [ $? != 0 ]; then
            echo " Install package: ipcalc" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
	        apt-get update >/dev/null 2>&1
            apt-get install -y ipcalc >/dev/null 2>&1
    fi
    nics=$(ls /sys/class/net/ | grep "^eth" | grep -v "$PRIMARY_NIC")
    if command -v wc >/dev/null 2>&1 && command -v tail >/dev/null 2>&1 ; then
        if [ $(tail -c 1 /etc/iproute2/rt_tables | wc -l) -eq 0 ]; then
            echo "Unexpected end of rt_tables" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            echo >> /etc/iproute2/rt_tables
        fi
    fi
    for name in ${nics[*]}
    do
        let index=10+${name:3}*10
        get_nic_type $name
        nictype=$nic_type_cache
        if [[ -z "$nictype" ]]; then
            echo "nic:$name failed to get nic type, skip this nic" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            continue
        fi
        if [ "$nictype"x = "rdma_roce"x ]; then
            echo "nic:$name is roce nic,not config route,continue" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
	    continue
        fi
	    if [[ $name == "$PRIMARY_NIC" ]]; then
            continue
        fi
        if [[ "18 20 22 24" =~ $version ]]; then
            if [ ! -d /etc/networkd-dispatcher/routable.d ]; then
                mkdir -p /etc/networkd-dispatcher/routable.d
            fi
           
            if [ -f "$RT_TABLE_DIR/config_rt_$name.sh" ]; then
                echo "rm old $RT_TABLE_DIR/config_rt_$name.sh" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
                rm -f $RT_TABLE_DIR/config_rt_$name.sh
            fi
        fi

        get_mac_address $name
        mac=$mac_address_cache
        get_primary_ip "${name}"
        primary_ip=$primary_ip_cahce
        netmask=$(get_meta_value $name $primary_ip "mask")
        if [[ -z $netmask ]]; then
            echo -e "\033[31m  can't get the netmask for $primary_ip from the metadata server.\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            exit 
        fi
        gateway=$(get_meta_value $name $primary_ip "gateway")
        if [[ -z $gateway ]]; then
            echo -e "\033[31m  can't get the gateway for $primary_ip from the metadata server.\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            exit
        fi

        table_name="rt_$name"

        grep -q "^$index $table_name" $RT_TABLES >/dev/null 2>&1
        if [ "$?" -ne 0 ]; then
            echo "[add_route_table]nic=${name},update iproute2 rt_tables,index=$index,table_name=$table_name" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            echo "$index $table_name" >> $RT_TABLES
        fi

        ip route flush table $table_name >/dev/null 2>&1
        ip -6 route flush table $table_name >/dev/null 2>&1
        ip rule show | grep "${table_name}" | awk '{print $NF}' | xargs -r -L1 ip rule del table
        ip -6 rule show | grep "${table_name}" | awk '{print $NF}' | xargs -r -L1 ip -6 rule del table

        #ip route add default via $gateway dev $name table $table_name >/dev/null 2>&1
        if [[ "18 20 22 24" =~ $version ]]; then
            config_script=$RT_TABLE_DIR/"config_$table_name.sh"
            prefix=""
            echo "#!/bin/bash" > $config_script
            echo "" >> $config_script
            echo "ip route add default via $gateway dev $name table $table_name" >> $config_script
            # add executable permissions to the script
            chmod +x $config_script
        else
            config_script=$CONFIG_PATH/${name}.cfg
            prefix="up "
            echo "" >> $config_script
            #echo $prefix"ip route add default via $gateway dev $name table $table_name" >> $config_script
            sed -i "${ipv4_sed_index}a\\up ip route add default via $gateway dev $name table $table_name" $config_script
            let ipv4_sed_index++
        fi

        for ((i=1; i<=3; i++)); do
            all_ips=$(curl -f -s $MAC_URL/$mac/fixed_ips | sed 's/\///g')
            if [[ "$?" -eq 0 ]]; then
                break
            fi
            sleep 1
        done
        if [[ -z "$all_ips" ]]; then
            echo -e "\033[31m  can't get the fixed_ip list of $name from metadata server.\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            exit
        fi
        if [ $NOTCFG_AUXIPEIP -eq 1 ]; then
            echo "not config auxip and eip,set all_ips to primary ip:$primary_ip" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            all_ips=$primary_ip
        fi
        
        echo "" >> $config_script
        echo "# route for every ip" >> $config_script
        first_ipv6=true
        for one_ip in ${all_ips[*]}
        do
            netmask_one=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${one_ip}/mask")
            netmask_one_cidr=$(netmask2cidr $netmask_one)
            ip_version "$one_ip"
            if [ $? -eq 4 ]; then
                one_ip_network=$(ipcalc -n -b $one_ip $netmask_one | grep Network | awk -F " " '{print $2}')
                if [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                    if [ "16" = $version ]; then
                        sed -i "${ipv4_sed_index}a\\up ip route add $one_ip_network dev $name table $table_name" $config_script
                        let ipv4_sed_index++
                    else
                        echo $prefix"ip route add $one_ip_network dev $name table $table_name" >> $config_script
                    fi
                fi    
            else
                #echo "IPv6"
                if [ $first_ipv6 == true ]; then
                    gateway_v6=$(get_meta_value $name $one_ip "gateway")
                    if [  $ONLY_CONFIG_IPv4 -eq 0 ]; then
                        echo $prefix"ip -6 route add default via $gateway_v6 dev $name table $table_name" >> $config_script
                    fi
                    first_ipv6=false
                fi
                one_ip_network=$(calculate_network "$one_ip" $netmask_one_cidr)
                if [  $ONLY_CONFIG_IPv4 -eq 0 ]; then
                    echo $prefix"ip -6 route add $one_ip_network dev $name table $table_name" >> $config_script
                fi
            fi

            if is_eip_direct_enabled  "${mac}" "${one_ip}"; then
                local eip=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${one_ip}/eip")
                if [ "16" = $version ]; then
                    if [[ $eip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                        if [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                            sed -i "${ipv4_sed_index}a\\up ip route add $eip/32 dev $name table $table_name" $config_script
                            let ipv4_sed_index++
                        fi
                    else
                        if [ $ONLY_CONFIG_IPv4 -eq 0 ]; then
                            echo $prefix"ip -6 route add $eip/128 dev $name table $table_name" >> $config_script
                        fi
                    fi
                else
                    if [[ $eip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                        if [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                            echo $prefix"ip route add $eip dev $name table $table_name" >> $config_script
                        fi
                    else
                        if [ $ONLY_CONFIG_IPv4 -eq 0 ]; then
                            echo $prefix"ip -6 route add $eip dev $name table $table_name" >> $config_script
                        fi
                    fi
                fi
            fi
            #ip route add $one_ip dev $name table $table_name >/dev/null 2>&1
            echo "add route for dev:$name,ip:$one_ip,network:$one_ip_network,table:$table_name" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        done

        echo "" >> $config_script
        echo "# rule for every ip" >> $config_script
        
        grep -q "ip rule del table" $config_script
        if [ $? -ne 0 ]; then
            if [ "16" = $version ]; then
                sed -i "6a\\up ip rule show | grep "$table_name" | awk '{print \$NF}' | xargs -r -L1 ip rule del table" $config_script
                let ipv4_sed_index++
            else
                echo $prefix"ip rule show | grep "$table_name" | awk '{print \$NF}' | xargs -r -L1 ip rule del table" >> $config_script
            fi
            echo $prefix"ip -6 rule show | grep "$table_name" | awk '{print \$NF}' | xargs -r -L1 ip -6 rule del table" >> $config_script
        fi
        if [ "16" = $version ]; then
            sed -i "${ipv4_sed_index}a\\up ip rule add from all oif $name lookup $table_name" $config_script
            let ipv4_sed_index++
        else
            echo $prefix"ip  rule add from all oif $name lookup $table_name" >> $config_script
        fi
        echo $prefix"ip  -6 rule add from all oif $name lookup $table_name" >> $config_script
        

        for one_ip in ${all_ips[*]}
        do
            ip_version "$one_ip"
            if [ $? -eq 4 ]; then
                if [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                    if [ "16" = $version ]; then
                        sed -i "${ipv4_sed_index}a\\up ip rule add from $one_ip lookup $table_name" $config_script
                        let ipv4_sed_index++
                    else
                        echo $prefix"ip rule add from $one_ip lookup $table_name" >> $config_script
                    fi
                fi
            else
                if [ $ONLY_CONFIG_IPv4 -eq 0 ]; then
                    echo $prefix"ip -6 rule add from $one_ip lookup $table_name" >> $config_script
                fi
            fi
            if is_eip_direct_enabled  "${mac}" "${one_ip}"; then
                local eip=$(curl -s "${MAC_URL}/${mac}/fixed_ips/${one_ip}/eip")
                
                if [ "16" = $version ]; then
                    if [[ $eip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                        if [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                            sed -i "${ipv4_sed_index}a\\up ip rule add from $eip lookup $table_name" $config_script
                            let ipv4_sed_index++
                        fi
                    else
                        if [ $ONLY_CONFIG_IPv4 -eq 0 ]; then
                            echo $prefix"ip -6 rule add from $eip lookup $table_name" >> $config_script
                        fi
                    fi
                else
                    if [[ $eip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                        if [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                            echo $prefix"ip rule add from $eip lookup $table_name" >> $config_script
                        fi
                    else
                        if [ $ONLY_CONFIG_IPv6 -eq 0 ]; then
                            echo $prefix"ip -6 rule add from $eip lookup $table_name" >> $config_script
                        fi
                    fi
                fi
            fi
            #ip rule add from $one_ip lookup $table_name >/dev/null 2>&1
            echo -e "    add $one_ip to route table: $table_name \033[32m[OK]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        done
    done

}

function config_eip_default_route() {
    local default_gateway
    local primary_nic="${PRIMARY_NIC}"
    primary_default_gateway=$(route  -n |awk '{if($1=="0.0.0.0")print $2}')
    default_gateway="${DEFAULT_EIP_GATEWAY}"

    echo "EIP_OPT=$EIP_OPT,DEFAULT_EIP=$DEFAULT_EIP,DEFAULT_EIP_NIC=$DEFAULT_EIP_NIC,DEFAULT_EIP_GATEWAY=$DEFAULT_EIP_GATEWAY" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'


    if [[ -n "${DEFAULT_EIP_NIC}" && -n "${DEFAULT_EIP}" && -n "${default_gateway}" ]]; then
        echo -e "\033[31m  Default Route is setting to ${DEFAULT_EIP_NIC}....\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        echo -e "\033[31m  You can run $0 uninstall to uninstall eip direction.\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        if  [[ "14 16" =~ $version ]]; then
            prefix="up "
            eip_conf_script=$CONFIG_PATH/${DEFAULT_EIP_NIC}.cfg
            echo "" >> $eip_conf_script
            echo "# default route for eip direct " >> $eip_conf_script
        else
            prefix=""
            eip_conf_script=$RT_TABLE_DIR/"config_eip_route.sh"
            echo "#!/bin/bash" > $eip_conf_script
            echo "" >> $eip_conf_script
            echo "# default route for eip direct " >> $eip_conf_script
            chmod +x $eip_conf_script
        fi
        if [[ $DEFAULT_EIP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            echo "$prefix"ip route add 10.0.0.0/8 dev "${DEFAULT_EIP_NIC}" via "${default_gateway}" >> $eip_conf_script
            echo "$prefix"ip route add 100.64.0.0/10 dev "${DEFAULT_EIP_NIC}" via "${default_gateway}" >> $eip_conf_script
            echo "$prefix"ip route add 172.16.0.0/12 dev "${DEFAULT_EIP_NIC}" via "${default_gateway}" >> $eip_conf_script
            echo "$prefix"ip route add 192.168.0.0/16 dev "${DEFAULT_EIP_NIC}" via "${default_gateway}" >> $eip_conf_script
            echo "$prefix"ip route add 169.254.0.0/16 dev "${DEFAULT_EIP_NIC}" via "${default_gateway}" >> $eip_conf_script
            echo "$prefix"ip route add 255.255.255.255 dev "${DEFAULT_EIP_NIC}" via "${default_gateway}" >> $eip_conf_script
            echo "$prefix"ip route del default >> $eip_conf_script
            echo "$prefix"ip route add default via "${default_gateway}" dev "${DEFAULT_EIP_NIC}" src "${DEFAULT_EIP}" >> $eip_conf_script
        else
            echo "$prefix"ip -6 route del default >> $eip_conf_script
            echo "$prefix"ip -6 route add default via "${default_gateway}" dev "${DEFAULT_EIP_NIC}" src "${DEFAULT_EIP}" >> $eip_conf_script
        fi
    elif [[ -z "${DEFAULT_EIP_NIC}" && -n "${DEFAULT_EIP}" ]]; then
        echo -e "\033[31m  Default Route set failed!!, No NIC for ${DEFAULT_EIP}\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    elif [[ "${EIP_OPT}" = "uninstall" ]]; then
        ip route del 10.0.0.0/8
        ip route del 100.64.0.0/10
        ip route del 172.16.0.0/12
        ip route del 192.168.0.0/16
        ip route del 169.254.0.0/16
        ip route del 255.255.255.255 
        ip route del default
        ip route add default via "${primary_default_gateway}" dev "${primary_nic}"
    fi
}

function parse_args() {
    if [[ "$#" = 0 ]]; then
        return 0
    elif [[ "$#" -gt 2 ]]; then
        echo "Error Parameter!!" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        return 1
    fi

    case "$1" in
        install)
            EIP_OPT="install"
            if [[ "$#" = 2 ]]; then
                DEFAULT_EIP=$2
            fi
            ;;
        uninstall)
            EIP_OPT="uninstall"
            ;;
        noauxipeip)
            echo "not config auxiliary ip and EIP" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            NOTCFG_AUXIPEIP=1
            ;;
        onlyipv4)
            echo "only config IPv4"  | logger -i -t 'bcc_elastic_net_centos_manual.sh'
            ONLY_CONFIG_IPv4=1
            ;;
        onlyipv6)
            echo "only config IPv6"  | logger -i -t 'bcc_elastic_net_centos_manual.sh'
            ONLY_CONFIG_IPv6=1
            ;;
        help|*)
            echo "usage:" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            echo "  $0 [install/uninstall/help] [eip]" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            return 1
            ;;
    esac
    return 0
}

function restart_network(){
    if [[ "$version" == "14" ]]; then
        nics=$(ls /sys/class/net/ | grep -v "lo")
        for name in ${nics[*]}
        do
            ifdown $name >/dev/null 2>&1 && ifup $name >/dev/null 2>&1
            if [ "$?" -eq 0 ]; then
                echo -e "  Restart network $name  \033[32m[OK]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            else
                echo -e "  Restart network $name  \033[31m[FAILED]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            fi
        done
    else 
        if [[ "$version" == "16" ]]; then
            echo -n "  Restart network..." | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            systemctl restart networking >/dev/null 2>&1
            if [ "$?" -eq 0 ]; then
                echo -e "  \033[32m[OK]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            else
                echo -e "  \033[31m[FAILED]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
            fi
        else 
            if [[ "$version" == "18" || "$version" == "20" || "$version" == "22" || "$version" == "24" ]]; then
                echo -n "  Restart network..." | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
                netplan apply
                if [ "$?" -eq 0 ]; then
                    echo -e "  \033[32m[OK]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
                else
                    echo -e "  \033[31m[FAILED]\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
                fi
            fi
        fi
    fi
}

function change_direct_route_metric() {
    cat > /etc/networkd-dispatcher/routable.d/change_direct_route.sh << 'EOF'
#!/bin/bash

nics=$(ls /sys/class/net/ | grep "^eth")

for nic in ${nics[@]}
do
    ifnu=${nic:3}
    ifnu=$(($ifnu+1))
    ans=$(ip route s | grep "$nic proto kernel")
    ip route del $ans
    ip route add $ans metric $ifnu
done
EOF
    chmod +x /etc/networkd-dispatcher/routable.d/change_direct_route.sh
}


##################################################
# get distro
for file in issue issue.net lsb-release
do
    [[ ! -f /etc/$file ]] && continue
    grep -i -q "ubuntu" /etc/$file
    if [ "$?" -eq 0 ]; then
        distro="ubuntu"
    fi
done

if ! parse_args "$@"; then
    exit 1
fi

if [[ "$distro" == "ubuntu" ]]; then
    version=$(cat /etc/lsb-release | grep DISTRIB_RELEASE | awk -F '=' '{print $2}' | awk -F '.' '{print $1}')
    # if the system has not been tested, exit
    spt_versions="14 16 18 20 22 24"
    if ! [[ $spt_versions =~ $version ]]; then
        echo -e "\033[31mThis tool doesn't support ubuntu $version .\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        echo "This tool doesn't support ubuntu $version."
        exit 1
    fi
    if [[ $EUID -ne 0 ]]; then
        echo -e "\033[31m please run this tool as root. \033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        echo "please run this tool as root."
        exit 2
    fi
    for((i=0;i<30;i++))
    do
        curl -f -s http://169.254.169.254/2009-04-04/meta-data/create-time >/dev/null 2>&1
        if [[ $? -ne 0 ]]; then
            sleep 1
        else
            break
        fi
    done
    if [ $i -ge 30 ]; then
        echo -e "\033[31m error occured when curl meta server. Please check network conncection.  \033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        echo "error occured when curl meta server. Please check network conncection."
        exit 3
    else
        echo "curl meta server successfully,network conncection is OK,retry times=$i" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    fi

    echo -e "\033[32m  tool version: $SCRIPT_VERSION \033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    if [[ -f "$NET_CLOUD_CFG" ]]; then
        rm -f $NET_CLOUD_CFG
    fi

    echo "----------------------------------" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    
    disable_cloud_network
    if  [[ "14 16" =~ $version ]]; then
        disable_networkmanager $version
        modify_interfaces_file
    fi
    restrict_default_route
    
    PRIMARY_NIC=$(get_primary_nic)
    echo "  Begin to config network...primary nic=$PRIMARY_NIC" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    create_nics_config
    echo "  Begin to create route table..." | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    tlcont=$(tail -c 1 $RT_TABLES | xxd -p)
    if [ "$tlcont" != "0a" ]; then
        echo "  add newline to $RT_TABLES " | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        echo "" >> $RT_TABLES
    fi
    add_route_table

    echo "----------------------------------"
    #set eip default route
    if [ $NOTCFG_AUXIPEIP -eq 0 ]; then
        echo "  Begin to set eip default route..." | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
        config_eip_default_route
        echo "----------------------------------" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
    fi

    cur_nics=$(ls /sys/class/net/ | grep "^eth" | grep -v "$PRIMARY_NIC")

    if [ -d "/etc/netplan/" ]; then
        cur_ifcfgs=$(ls /etc/netplan/ | grep -E "^eth")
        for ifcfg in ${cur_ifcfgs}
        do
            netdev=$(echo $ifcfg | awk -F. '{print $1}')
            [ "$netdev" == "$PRIMARY_NIC" ] && continue
            echo $cur_nics | grep -w $netdev >/dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "nic:$netdev not exist, delete its ifcfg:$ifcfg" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
                rm -f /etc/netplan/$ifcfg
            fi
        done
    fi

    if [ -d "/etc/networkd-dispatcher/routable.d/" ]; then
        cur_rtcfgs=$(ls /etc/networkd-dispatcher/routable.d/ | grep "config_rt_eth")
        for rtcfg in ${cur_rtcfgs}
        do
            netdev=$(echo $rtcfg | awk -F. '{print $1}' | cut -d'_' -f 3)
            [ "$netdev" == "$PRIMARY_NIC" ] && continue
            echo $cur_nics | grep -w $netdev >/dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "nic:$netdev not exist, delete its rtcfg:$rtcfg" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
                rm -f /etc/networkd-dispatcher/routable.d/$rtcfg
                ip rule show | grep rt_${netdev} | awk '{print $NF}' | xargs -r -L1 ip rule del table
                sed -i "/rt_${netdev}/d" /etc/iproute2/rt_tables
            fi
        done
    fi
    if [[ "18 20 22 24" =~ $version ]]; then
        change_direct_route_metric
    fi

    restart_network
else
    echo -e "\033[31mPlease run the script on Ubuntu system.\033[0m" | logger -i -t 'bcc_elastic_net_ubuntu_manual.sh'
fi
