From 426c1043b1464386291df8fe4557ceae81e54166 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 29 May 2017 08:45:38 +0200 Subject: [PATCH] luci-mod-admin-full: auto-migrate ifnames when changing VLAN configuration This change extends the switch VLAN configuration page to automatically adjust interface ifname options when altering VLAN settings. For example "eth0" is changed to "eth0.1" when a previously untagged LAN VLAN is switched to tagged on the CPU port and vice versa. Notifications are displayed in the page header if an auto migration was performed. This change should make the switch configuration more user friendly and less prone to soft bricking. Signed-off-by: Jo-Philipp Wich --- .../luasrc/model/cbi/admin_network/vlan.lua | 59 ++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua index 902767c90..89a73a5ca 100644 --- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua +++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua @@ -12,6 +12,35 @@ nw.init(m.uci) local topologies = nw:get_switch_topologies() or {} +local update_interfaces = function(old_ifname, new_ifname) + local info = { } + + m.uci:foreach("network", "interface", function(section) + local old_ifnames = m.uci:get("network", section[".name"], "ifname") + local new_ifnames = { } + local cur_ifname + local changed = false + for cur_ifname in luci.util.imatch(old_ifnames) do + if cur_ifname == old_ifname then + new_ifnames[#new_ifnames+1] = new_ifname + changed = true + else + new_ifnames[#new_ifnames+1] = cur_ifname + end + end + if changed then + m.uci:set("network", section[".name"], "ifname", table.concat(new_ifnames, " ")) + + info[#info+1] = translatef("Interface %q device auto-migrated from %q to %q.", + section[".name"], old_ifname, new_ifname) + end + end) + + if #info > 0 then + m.message = (m.message and m.message .. "\n" or "") .. table.concat(info, "\n") + end +end + m.uci:foreach("network", "switch", function(x) local sid = x['.name'] @@ -259,17 +288,32 @@ m.uci:foreach("network", "switch", -- When writing the "vid" or "vlan" option, serialize the port states -- as well and write them as "ports" option to uci. - vid.write = function(self, section, value) + vid.write = function(self, section, new_vid) local o local p = { } - for _, o in ipairs(port_opts) do - local v = o:formvalue(section) - if v == "t" then - p[#p+1] = o.option .. v - elseif v == "u" then + local new_tag = o:formvalue(section) + if new_tag == "t" then + p[#p+1] = o.option .. new_tag + elseif new_tag == "u" then p[#p+1] = o.option end + + if o.info and o.info.device then + local old_tag = o:cfgvalue(section) + local old_vid = self:cfgvalue(section) + if old_tag ~= new_tag or old_vid ~= new_vid then + local old_ifname = (old_tag == "u") and o.info.device + or "%s.%s" %{ o.info.device, old_vid } + + local new_ifname = (new_tag == "u") and o.info.device + or "%s.%s" %{ o.info.device, new_vid } + + if old_ifname ~= new_ifname then + update_interfaces(old_ifname, new_ifname) + end + end + end end if enable_vlan4k then @@ -277,7 +321,7 @@ m.uci:foreach("network", "switch", end m:set(section, "ports", table.concat(p, " ")) - return Value.write(self, section, value) + return Value.write(self, section, new_vid) end -- Fallback to "vlan" option if "vid" option is supported but unset. @@ -301,6 +345,7 @@ m.uci:foreach("network", "switch", po.cfgvalue = portvalue po.validate = portvalidate po.write = function() end + po.info = pt port_opts[#port_opts+1] = po end -- 2.25.1