summaryrefslogtreecommitdiff
path: root/net/bonding.sh
blob: 7097a4ddc918261a7db7b8513ecb2bd3525db790 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.

bonding_depend()
{
	before interface macchanger
}

_config_vars="$_config_vars slaves"

_is_bond()
{
	[ -f "/proc/net/bonding/${IFACE}" ]
}

bonding_pre_start()
{
	local x= s= n= slaves= primary=

	slaves="$(_get_array "slaves_${IFVAR}")"
	unset slaves_${IFVAR}

	eval primary="\$primary_${IFVAR}"
	unset primary_${IFVAR}


	[ -z "${slaves}" ] && return 0

	# Load the kernel module if required
	if [ ! -d /proc/net/bonding ]; then
		if ! modprobe bonding; then
			eerror "Cannot load the bonding module"
			return 1
		fi
	fi

	# We can create the interface name we like now, but this
	# requires sysfs
	if ! _exists && [ -d /sys/class/net ]; then
		echo "+${IFACE}" > /sys/class/net/bonding_masters
	fi
	_exists true || return 1

	if ! _is_bond; then
		eerror "${IFACE} is not capable of bonding"
		return 1
	fi

	# Interface must be down in order to configure
	_down

	# Configure the bond mode, then we can reloop to ensure we configure
	# All other options
	for x in /sys/class/net/"${IFACE}"/bonding/mode; do
		[ -f "${x}" ] || continue
		n=${x##*/}
		eval s=\$${n}_${IFVAR}
		if [ -n "${s}" ]; then
			einfo "Setting ${n}: ${s}"
			echo "${s}" >"${x}" || \
			eerror "Failed to configure $n (${n}_${IFVAR})"
		fi
	done
	# Nice and dynamic for remaining options:)
	for x in /sys/class/net/"${IFACE}"/bonding/*; do
		[ -f "${x}" ] || continue
		n=${x##*/}
		eval s=\$${n}_${IFVAR}
		[ "${n}" != "mode" ] || continue
		if [ -n "${s}" ]; then
			einfo "Setting ${n}: ${s}"
			echo "${s}" >"${x}" || \
			eerror "Failed to configure $n (${n}_${IFVAR})"
		fi
	done

	ebegin "Adding slaves to ${IFACE}"
	eindent
	einfo "${slaves}"

	# Check that our slaves exist
	(
	for IFACE in ${slaves}; do
		_exists true || return 1
	done

	# Must force the slaves to a particular state before adding them
	for IFACE in ${slaves}; do
		_delete_addresses
		_down
	done
	)

	# now force the master to up
	_up

	# finally add in slaves
	# things needed in the process, and if they are done by ifenslave, openrc, and/or the kernel.
	# down new slave interface: ifenslave, openrc
	# set mtu: ifenslave, kernel
	# set slave MAC: ifenslave, kernel
	eoutdent
	if [ -d /sys/class/net ]; then
		sys_bonding_path=/sys/class/net/"${IFACE}"/bonding
		local oiface
		oiface=$IFACE
		if [ -n "${primary}" ]; then
			IFACE=$primary
			_down
			IFACE=$oiface
			echo "+${primary}" >$sys_bonding_path/slaves
			echo "${primary}" >$sys_bonding_path/primary
		fi
		for s in ${slaves}; do
			[ "${s}" = "${primary}" ] && continue
			if ! grep -q ${s} $sys_bonding_path/slaves; then
				IFACE=$s
				_down
				IFACE=$oiface
				echo "+${s}" >$sys_bonding_path/slaves
			fi
		done
	else
		/sbin/ifenslave "${IFACE}" ${slaves} >/dev/null
	fi
	eend $?

	return 0 #important
}

bonding_stop()
{
	_is_bond || return 0

	local slaves= s=
	slaves=$( \
		sed -n -e 's/^Slave Interface: //p' "/proc/net/bonding/${IFACE}" \
		| tr '\n' ' ' \
	)
	[ -z "${slaves}" ] && return 0

	# remove all slaves
	ebegin "Removing slaves from ${IFACE}"
	eindent
	einfo "${slaves}"
	eoutdent
	if [ -d /sys/class/net ]; then
		for s in ${slaves}; do
			echo -"${s}" > /sys/class/net/"${IFACE}"/bonding/slaves
		done
	else
		/sbin/ifenslave -d "${IFACE}" ${slaves}
	fi

	# reset all slaves
	(
	for IFACE in ${slaves}; do
		if _exists; then
			_delete_addresses
			_down
		fi
	done
	)

	_down

	if [ -d /sys/class/net ]; then
		echo "-${IFACE}" > /sys/class/net/bonding_masters
	fi

	eend 0
	return 0
}