#!/bin/bash

# Support for Fliwi style VLANs

function fliwi_vlan_wait_for_device
{
  local mode="$1"
  local device="$2"
  local device_path="/sys/class/net/$device"
  local counter=0
  local max_loops=60
  local loop_delay="0.5"

  while [ $counter -le $max_loops ]
  do
    sleep $loop_delay
    counter=$(expr $counter + 1)
    if [ -r "$device_path/operstate" ]; then
      if [ "$mode" == "down" ] && \
         [ "$(cat $device_path/operstate)" != "down" ] ; then
        continue
      fi
      return 0
    fi
  done
  return 1
}


if [ -n "$IFACE" ] && \
   [ -n "$IF_FLIWI_VLAN_ID" ] && \
   [ -n "$IF_FLIWI_VLAN_RAW_DEVICE" ]; then
    if [ ! -x "/sbin/vconfig" ]; then
        exit 0
    fi

    if [ $(lsmod | grep -c 8021q) -le 0 ]; then
      modprobe 8021q || true
      sleep 5
    fi

    if ! ip link show dev "$IF_FLIWI_VLAN_RAW_DEVICE" 2>/dev/null 1>&2; then
      echo "E: Raw device '$IF_FLIWI_VLAN_RAW_DEVICE' does not exist, unable to create vlan device '$IFACE' using '$0'" 1>&2
      exit 1
    fi

    # Only do something if the vlan device is not present, yet
    if [ ! -e "/sys/class/net/$IFACE" ]; then
      current_vlan_naming_convention="$(grep Name-Type: /proc/net/vlan/config | cut -d ' ' -f 2)"
      case "$current_vlan_naming_convention" in
        VLAN_NAME_TYPE_PLUS_VID)
          # Format: VLAN_PLUS_VID (vlan0005)
          created_vlan_dev_name="vlan$(printf "%04d" ${IF_FLIWI_VLAN_ID})"
        ;;

        VLAN_NAME_TYPE_PLUS_VID_NO_PAD)
          # Format: VLAN_PLUS_VID_NO_PAD (vlan5)
          created_vlan_dev_name="vlan${IF_FLIWI_VLAN_ID}"
        ;;

        VLAN_NAME_TYPE_RAW_PLUS_VID)
          # Format: DEV_PLUS_VID (eth0.0005)
          created_vlan_dev_name="${IF_FLIWI_VLAN_RAW_DEVICE}.$(printf "%04d" ${IF_FLIWI_VLAN_ID})"
        ;;

        VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD)
          # Format: DEV_PLUS_VID_NO_PAD (eth0.5)
          created_vlan_dev_name="${IF_FLIWI_VLAN_RAW_DEVICE}.${IF_FLIWI_VLAN_ID}"
        ;;

        *)
          echo "E: VLAN naming convention '$current_vlan_naming_convention' is unsupported by '$0'" 1>&2
          exit 1
        ;;
      esac

      # Take raw device online (just in case, it should be online already)
      ip link set up dev $IF_FLIWI_VLAN_RAW_DEVICE

      # Add vlan device
      vconfig add $IF_FLIWI_VLAN_RAW_DEVICE $IF_FLIWI_VLAN_ID

      # Wait for the vlan device to appear
      fliwi_vlan_wait_for_device appear $created_vlan_dev_name

      # Take the created vlan device offline (in order to rename it)
      ip link set down dev $created_vlan_dev_name

      # Wait for the vlan device to go down
      fliwi_vlan_wait_for_device down $created_vlan_dev_name

      # Rename the created vlan device to whatever the $IFACE name is
      ifrename -i $created_vlan_dev_name -n $IFACE

      # Wait for the vlan device to appear
      fliwi_vlan_wait_for_device appear $IFACE

      # Take the created vlan device back online
      ip link set up dev $IFACE
    fi
fi

