aboutsummaryrefslogtreecommitdiff
path: root/net/vlan.sh
blob: ff63dfd096988d2aecb94270e03c0d9418f1ec88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.

vlan_depend()
{
	program ip
	after interface
	before dhcp
}

_config_vars="$_config_vars vlans"

_is_vlan()
{
	[ ! -d /proc/net/vlan ] && return 1
	[ -e /proc/net/vlan/"${IFACE}" ] && return 0
	grep -Eq "^${IFACE}[[:space:]]+" /proc/net/vlan/config
}

_get_vlans()
{
	[ -e /proc/net/vlan/config ] || return 1
	sed -n -e 's/^\W*\([^ ]*\) \(.* \) .*'"${IFACE}"'$/\1/p' /proc/net/vlan/config
}

_check_vlan()
{
	if [ ! -d /proc/net/vlan ]; then
		modprobe 8021q
		if [ ! -d /proc/net/vlan ]; then
			eerror "VLAN (802.1q) support is not present in this kernel"
			return 1
		fi
	fi
}

vlan_pre_start()
{
	local vconfig
	eval vconfig=\$vconfig_${IFVAR}
	if [ -n "${vconfig}" ]; then
		eerror "You must convert your vconfig_ VLAN entries to vlan${N} entries."
		return 1
	fi
	local vlans=
	eval vlans=\$vlans_${IFVAR}
	[ -z "$vlans" ] && return 0
	case " ${MODULES} " in
		*" ifconfig "*)
				eerror "sys-apps/iproute2 is required to configure VLANs"
				return 1 ;;
	esac
}

vlan_post_start()
{
	local vlans=
	eval vlans=\$vlans_${IFVAR}
	[ -z "${vlans}" ] && return 0

	_check_vlan || return 1
	_exists || return 1

	local vlan= e= s= vname= vflags= vingress= vegress=
	for vlan in ${vlans}; do
		einfo "Adding VLAN ${vlan} to ${IFACE}"
		# We need to gather all interface configuration options
		# 1) naming. Default to the standard "${IFACE}.${vlan}" but it can be anything
		eval vname=\$vlan${vlan}_name
		[ -z "${vname}" ] && vname="${IFACE}.${vlan}"
		# 2) flags
		eval vflags=\$vlan${vlan}_flags
		# 3) ingress/egress map
		eval vingress=\$vlan${vlan}_ingress
		[ -z "${vingress}" ] || vingress="ingress-qos-map ${vingress}"
		eval vegress=\$vlan${vlan}_egress
		[ -z "${vegress}" ] || vegress="egress-qos-map ${vegress}"

		local txqueuelen=
		eval txqueuelen=\$txqueuelen_vlan${vlan}
		local mac=
		eval mac=\$mac_vlan${vlan}
		local broadcast=
		eval broadcast=\$broadcast_vlan${vlan}
		local mtu=
		eval mtu=\$mtu_vlan${vlan}
		local opts="${txqueuelen:+txqueuelen} ${txqueuelen} ${mac:+address} ${mac} ${broadcast:+broadcast} ${broadcast} ${mtu:+mtu} ${mtu}"

		e="$(ip link add link "${IFACE}" name "${vname}" ${opts} type vlan id "${vlan}" ${vflags} ${vingress} ${vegress} 2>&1 1>/dev/null)"
		if [ -n "${e}" ]; then
			eend 1 "${e}"
			continue
		fi

		# We may not want to start the vlan ourselves
		eval s=\$vlan_start_${IFVAR}
		yesno ${s:-yes} || continue

		# We need to work out the interface name of our new vlan id
		local ifname="$(sed -n -e \
			's/^\([^[:space:]]*\) *| '"${vlan}"' *| .*'"${IFACE}"'$/\1/p' \
			/proc/net/vlan/config )"
		mark_service_started "net.${ifname}"
		(
			export RC_SVCNAME="net.${ifname}"
			start
		) || mark_service_stopped "net.${ifname}"
	done

	return 0
}

vlan_pre_stop()
{
	local vlan=

	_exists || return 0

	for vlan in $(_get_vlans); do
		einfo "Removing VLAN ${vlan##*.} from ${IFACE}"
		(
			export RC_SVCNAME="net.${vlan}"
			stop
		) && {
			mark_service_stopped "net.${vlan}"
			ip link delete "${vlan}" type vlan >/dev/null
		}
	done

	return 0
}