Linux Vlan

From Leo's Notes
Last edited on 1 September 2019, at 06:21.

If an interface is trunked, you can 'untag' the traffic like so:

# ip link add link enp3s0f1 name enp3s0f1.1012 type vlan id 1012

You can then assign an IP address to the interface enp3s0f1.1012.


Linux Switch[edit | edit source]

You can make your linux box act like a smart switch by using this script:

#!/bin/bash

declare -a Ports # List of ports
declare -A Config # Vlan ID for each port
declare -A Vlans # key=>value | vlanid=>vlan name
Uplink="p4p2"

DryRun=0

function Main() {
	setup_requirements

	add_vlan 911 "BuildNet"
	add_vlan 912 "BuildNet2"
	add_vlan 1010 "DeptNFS"
	add_vlan 7 "WildWest"
	add_vlan 1012 "AdminNet"
	add_vlan 915 "OS-Int"
	# add_vlan 916 "OS-VM"

	# Interfaces are sorted. Run `get_network_interfaces` to see the mapping.
	# eth2 p1p1 p1p2 p4p2
	config_port 0 911
	config_port 1 911
	config_port 2 7
	# config_port 3 trunked

	setup_network
	show_ports

	configure_port_vlan
	show_config

	# Give this machine an IP address through a bridge.
	# ifconfig br1010 172.17.10.9 netmask 255.255.255.0
	# route add default gw 172.17.10.1

	# Statically configure the network for this machine on the trunked bridge
	# p4p2 (the uplink) at 1010 is our interface.
	ifconfig br1010 172.17.10.9 netmask 255.255.255.0
	route add default gw 172.17.10.1

	# dhclient br1010
}

function setup_requirements() {
	echo 1 >  /proc/sys/net/ipv4/ip_forward
	modprobe 8021q
}

function get_network_interfaces() {
	# Get all interfaces except bridges and vlan interfaces and loopback
	/sbin/ip a \
	| /bin/grep -E '^[0-9]+' \
	| cut -f2 -d' ' \
	| grep -vE '(br|@)' \
	| tr : ' ' \
	| grep -v lo \
	| sort
}

function config_port() {
	Config[$1]="$2"
}

function add_vlan() {
	Vlans[$1]="$2"
}

function die() {
	echo $@
	exit
}

function show_ports() {
	echo "Network Interfaces Found:"
	for i in "${!Ports[@]}" ; do
		echo "$i: ${Ports[$i]}"
	done
}

function show_config() {
	echo "Vlan Configuration:"
	for i in "${!Ports[@]}" ; do
		Vlan=${Config[$i]}
		echo "$i: ${Ports[$i]} --> VLAN $Vlan (${Vlans[$Vlan]})"
	done
}

function teardown_network() {
	ifconfig $Uplink down
	for Port in "${Ports[@]}" ; do
		ifconfig $Port down
	done
	
	cat /proc/net/vlan/config | tail -n+3 | cut -f1 -d' '|tr . ' ' | while read line ; do
		Port=`echo $line | cut -f1 -d' '`
		Vlan=`echo $line | cut -f2 -d' '`

		brctl delif br$Vlan $Uplink.Vlan
		brctl delbr br$Vlan

		vconfig rem $Uplink.$Vlan
	done
}

function setup_network() {
	Interfaces=$(get_network_interfaces)
	echo $Interfaces | grep $Uplink > /dev/null || die "Could not find $Uplink interface."
	# Add each port to the ports list excluding the uplink
	for Port in $Interfaces ; do
		if [[ "$Port" != "$Uplink" ]] ; then
			Ports+=($Port)
		fi
	done

	# Set up vlans on the uplink port
	for i in "${!Vlans[@]}" ; do
		Vlan=$i
		VlanName=${Vlans[$i]}

		# Check to see if it's already configured. Skip if it is.
		grep "\b$Vlan\b" /proc/net/vlan/config > /dev/null && continue

		# Add vlan to port. This creates $Uplink.$Vlan
		vconfig add $Uplink $Vlan

		# Create bridge for each vlan
		brctl addbr br$Vlan
		brctl addif br$Vlan $Uplink.$Vlan
		
		# Start the bridge and vlan uplink
		ifconfig br$Vlan up
		ifconfig $Uplink.$Vlan up
	done
}

function configure_port_vlan() {
	# Ensure everything is down.
	for i in "${!Ports[@]}" ; do
		Vlan=${Config[$i]}
		Port=${Ports[$i]}

		# Add the port to the vlan bridge
		brctl addif br$Vlan $Port
		ifconfig $Port up
	done

	# Start things up
	for Port in "${Ports[@]}" ; do
		ifconfig $Port up
	done
}

function ifconfig() {
	echo ifconfig $@
	if [ $DryRun -eq 0 ] ; then
		/sbin/ifconfig $@
	fi
}
function brctl() {
	echo brctl $@
	if [ $DryRun -eq 0 ] ; then
		/sbin/brctl $@
	fi
}
function vconfig() {
	echo vconfig $@
	if [ $DryRun -eq 0 ] ; then
		/sbin/vconfig $@
	fi
}
function dhclient() {
	echo dhclient $@
	if [ $DryRun -eq 0 ] ; then
		/sbin/dhclient $@
	fi
}

Main $@