4 .
/lib
/functions
/network.sh
15 local vlans
=$
(bridge vlan show dev
"$port" |
sed -ne 's#^[^ ]* \+\([0-9]\+\).*$#\1#p')
18 for vlan
in $vlans; do
19 bridge vlan del vid
"$vlan" dev
"$port" $self
27 config_get swname
"$cfg" switch
29 # Auto-determine switch if not specified ...
30 if [ -z "$swname" ]; then
31 case "$switch_names" in
33 warn
"VLAN section '$cfg' does not specify a switch but multiple switches present, using first one"
34 swname
=${switch_names%% *}
37 swname
=${switch_names}
41 # ... otherwise check if the referenced switch is declared
43 case " $switch_names " in
46 warn
"Switch '$swname' specified by VLAN section '$cfg' does not exist"
52 export -n "switch=$swname"
59 [1-9]|
[1-9][0-9]|
[1-9][0-9][0-9]|
[1-4][0-9][0-9][0-9])
60 if [ $vid -gt 4096 ]; then
76 # Read configured CPU port from uci ...
77 config_get cpu
"$cfg" cpu_port
79 # ... if unspecified, find first CPU port
80 if [ -z "$cpu" ]; then
82 for e
in /sys
/class
/net
/*/dsa
; do
91 # Bail out if we cannot determine the CPU port
92 if [ -z "$cpu" ]; then
93 warn
"Unable to determine CPU port for switch '$cfg'"
97 append switch_names
"$cfg"
99 # Prevent netifd from picking up our switch bridge just yet
100 network_defer_device
"$cfg"
102 # Increase MTU of CPU port to 1508 to accomodate for VID + DSA tag
103 ip link
set "$cpu" mtu
1508
104 ip link
set "$cpu" up
106 # (Re)create switch bridge device in case it is not yet set up
107 local filtering
=$
(cat "/sys/class/net/$cfg/bridge/vlan_filtering" 2>/dev
/null
)
108 if [ ${filtering:-0} != 1 ]; then
109 ip link
set "$cfg" down
2>/dev
/null
110 ip link delete dev
"$cfg" 2>/dev
/null
111 ip link add name
"$cfg" type bridge
112 echo 1 > "/sys/class/net/$cfg/bridge/vlan_filtering"
115 ip link
set "$cfg" up
117 # Unbridge DSA ports and flush any VLAN filters on them, they're added back later
119 for port
in /sys
/class
/net
/*"/upper_${cfg}"; do
120 if [ -e "$port" ]; then
121 port
=${port%/upper_*}
124 ip link
set "$port" nomaster
126 # Unbridging the port should already clear VLANs, but be safe
127 clear_port_vlans
"$port"
131 # Clear any VLANs on the switch bridge, they're added back later
132 clear_port_vlans
"$cfg" self
135 setup_switch_vlan
() {
137 local switch vlan ports
139 config_get switch
"$cfg" switch
140 config_get vlan
"$cfg" vlan
141 config_get ports
"$cfg" ports
143 lookup_switch
"$cfg" ||
return 1
144 validate_vid
"$vlan" ||
{
145 warn
"VLAN section '$cfg' specifies an invalid VLAN ID '$vlan'"
151 for port
in $ports; do
156 if [ "$tag" != "$port" ] && [ "$tag" = t
]; then
162 # Add the port to the switch bridge and delete the default
163 # VLAN 1 if it is not yet joined to the switch.
164 if [ ! -e "/sys/class/net/$port/upper_$switch" ]; then
165 ip link
set dev
"$port" up
166 ip link
set dev
"$port" master
"$switch"
168 # Get rid of default VLAN 1
169 bridge vlan del vid
1 dev
"$port"
172 # Promote the first untagged VLAN of this port to the PVID
173 if [ "$tag" = untagged
] && ! bridge vlan show dev
"$port" |
grep -qi pvid
; then
177 # Add VLAN filter entry for port
178 bridge vlan add dev
"$port" vid
$vlan $pvid $tag
181 # Make the switch bridge itself handle the VLAN as well
182 bridge vlan add dev
"$switch" self vid
$vlan tagged
185 setup_switch_port
() {
187 local switch port pvid tag
189 config_get port
"$cfg" port
190 config_get pvid
"$cfg" pvid
192 lookup_switch
"$cfg" ||
return 1
193 validate_vid
"$pvid" ||
{
194 warn
"Port section '$cfg' specifies an invalid PVID '$pvid'"
198 # Disallow setting the PVID of the switch bridge itself
199 [ "$port" != "$switch" ] ||
{
200 warn
"Port section '$cfg' must not change PVID of the switch bridge"
204 # Determine existing VLAN config
205 local vlanspec
=$
(bridge vlan show dev
"$port" vid
"$pvid" 2>/dev
/null |
sed -ne2p)
206 echo "$vlanspec" |
grep -qi untagged
&& tag
=untagged || tag
=tagged
208 bridge vlan add vid
"$pvid" dev
"$port" pvid
$tag
213 config_foreach setup_switch dsa
215 # If no switch is explicitely declared, synthesize switch0
216 if [ -z "$switch_names" ] && ! setup_switch switch0
; then
217 warn
"No DSA switches found"
221 config_foreach setup_switch_vlan dsa_vlan
222 config_foreach setup_switch_port dsa_port
224 # Ready switch bridge devices
226 for switch
in $switch_names; do
227 network_ready_device
"$switch"
234 printf "Switch: %s\n" "$switch"
238 for port
in "/sys/class/net/$switch/lower_"*; do
239 port
=${port##*/lower_}
242 printf " | %-5s" "$port"
248 for port
in $ports; do
249 local carrier
=$
(cat "/sys/class/net/$port/carrier")
250 local duplex
=$
(cat "/sys/class/net/$port/duplex")
251 local speed
=$
(cat "/sys/class/net/$port/speed")
253 if [ ${carrier:-0} -eq 0 ]; then
254 printf " | %-5s" "down"
256 [ "$duplex" = "full" ] && duplex
=F || duplex
=H
257 printf " | %4d%s" "$speed" "$duplex"
261 local vlans
=$
(bridge vlan show dev
"$switch" |
sed -ne 's#^[^ ]* \+\([0-9]\+\).*$#\1#p')
263 for vlan
in $vlans; do
264 printf " |\n%4d " "$vlan"
266 for port
in $ports; do
267 local pvid
="" utag
="" word
268 for word
in $
(bridge vlan show dev
"$port" vid
"$vlan"); do
272 Untagged
) utag
="u" ;;
276 printf " | %-2s " "$utag$pvid"
284 append switch_names
"$1"
289 config_foreach add_switch dsa
292 for switch
in ${switch_names:-switch0}; do
293 show_switch
"$switch"
300 apply
) apply_config
;;
302 echo "Usage: ${0##*/} show"
303 echo " ${0##*/} apply"