Skip to content

Commit 4952d29

Browse files
committed
ucentral-event: add VLAN reference counting to prevent race condition
When a station roams between bands on the same VLAN, the vlan_remove event from the old band can arrive after the vlan_add event from the new band, causing the VLAN to be incorrectly deleted whilst still in use. Add reference counting that tracks how many interfaces are using each VLAN ID. Only create VLAN devices on the first reference and only remove them when the last reference is dropped. On startup, initialise refcounts from current station state to handle daemon restarts correctly. Signed-off-by: John Crispin <[email protected]>
1 parent e27424e commit 4952d29

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

feeds/ucentral/ucentral-event/files/ucentral-event

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
'use strict';
44

5+
push(REQUIRE_SEARCH_PATH, '/usr/share/ucentral/*.uc');
6+
57
import * as libubus from 'ubus';
68
import * as libuci from 'uci';
79
import * as uloop from 'uloop';
@@ -36,6 +38,7 @@ let ucentral_running = false;
3638
let pending_events = [];
3739
let relay = {};
3840
let net_config = {};
41+
let vlan_refcount = {};
3942

4043

4144
function config_load() {
@@ -52,6 +55,20 @@ function config_load() {
5255
net_config = {};
5356
}
5457

58+
function vlan_refcount_init() {
59+
let stations = require('wifi.station');
60+
61+
vlan_refcount = {};
62+
63+
for (let k, v in stations) {
64+
let vlan = split(k, '-v')[1];
65+
let count = length(v);
66+
if (vlan && count > 0) {
67+
vlan_refcount[vlan] = count;
68+
}
69+
}
70+
}
71+
5572
function match(object, type, list) {
5673
if (object in list || type in list)
5774
return true;
@@ -258,6 +275,13 @@ handlers = {
258275
},
259276

260277
vlan_add: function(notify) {
278+
let vlan_id = `${notify.data.vlan_id}`;
279+
vlan_refcount[vlan_id] = (vlan_refcount[vlan_id] || 0) + 1;
280+
281+
if (vlan_refcount[vlan_id] > 1) {
282+
return;
283+
}
284+
261285
if (config.config.swconfig)
262286
return handlers.vlan_add_swconfig(notify);
263287

@@ -280,6 +304,14 @@ handlers = {
280304
},
281305

282306
vlan_remove: function(notify) {
307+
let vlan_id = `${notify.data.vlan_id}`;
308+
vlan_refcount[vlan_id] = (vlan_refcount[vlan_id] || 1) - 1;
309+
310+
if (vlan_refcount[vlan_id] > 0) {
311+
return;
312+
}
313+
delete vlan_refcount[vlan_id];
314+
283315
if (config.config.swconfig)
284316
return;
285317
for (let wan in wan_ports) {
@@ -624,6 +656,7 @@ let ubus_methods = {
624656
};
625657

626658
config_load();
659+
vlan_refcount_init();
627660

628661
hapd_subscriber = ubus.subscriber(hapd_subscriber_notify_cb, hapd_subscriber_remove_cb);
629662
dhcp_subscriber = ubus.subscriber(dhcp_subscriber_notify_cb, dhcp_subscriber_remove_cb);

0 commit comments

Comments
 (0)