local n=require
local s=type
local m=tostring
local o=error
local e=ipairs
local c=pairs
local x=unpack
local g=table.concat
local k=table.insert
local f=setmetatable
local w=rawget
local l=n("transformer.shared.models.uciconfig").Loader()local _=n"transformer.shared.models.dmordering"local u=n("transformer.shared.models.xdsl")local n=n("transformer.mapper.ucihelper")local I=n.get_from_uci
local h=n.set_on_uci
local A=n.delete_on_uci
local t={config="ethernet",sectionname="",option="",default=""}local r={}local function i(e,...)o(e:format(...),2)end
local a={}local p={"IPInterface","PPPInterface","VLAN","EthLink","Bridge","BridgePort","PTMLink","ATMLink","DSLChannel","DSLLine","GFASTLine","EthInterface","WifiRadio","WiFiSSID","WiFiAP","GRE",}function r.register(e,n)if not a[e]then
a[e]=n
return e
else
i("duplicate path mapping for %s->%s have %s",e,n,a[e])end
end
local y
function r.load()return y()end
local n={}n.__index=n
local function v()local t={all={},typed={loopback={},},networks={},key_aliases={},key_ignore={},_explicit_links={},}for n,e in e(p)do
t.typed[e]={}end
return f(t,n)end
local function d(n,e,l)local t=n.typed[e]local n=n.all
if not t then
i("Programming Error: Adding unknown type %s is not possible",e)end
if n[l]then
i("Programming Error: Adding duplicate name %s (%s) is not possible",l,e)end
return t,n
end
local function b(n,e)return{type=n,name=e,lower={},}end
function n:add(e,t,o)local n,l=d(self,e,t)local e=b(e,t)if o then
k(n,o,e)else
n[#n+1]=e
end
n[t]=e
l[#l+1]=e
l[t]=e
return e
end
local function o(l,n,t,a)local o=false
local e=l:get(n,t)if a then
if not e then
e=l:add(n,t)e.placeholder=true
else
o=true
end
else
if e then
if e.placeholder then
e.placeholder=nil
e.ucikey=nil
else
i("Adding duplicate %s object %s is not possible",n,t)end
else
e=l:add(n,t)end
end
return e,o
end
local function d(t,n,l)local e
if n then
e=t.typed[n]else
e=t.all
end
if e then
return e[l]end
end
function n:get(n,e)if not e then
e=n
n=nil
end
local t=self.key_aliases[e]if t and(t.master==e)then
return d(self,n,t.slave)or d(self,n,e)else
return d(self,n,e)end
end
local i={__index=function(e)return w(e,"__default")end}f(i,i)function i.__default(t,l)local n={}for l,e in e(t.typed[l]or{})do
if not e.hide_in_datamodel and(not t.key_ignore[e.name])then
n[#n+1]=e.name
end
end
return n
end
function i.BridgePort(t,n,l)local n={}local t=t:get("Bridge",l)if t then
for t,e in e(t.members)do
n[#n+1]=e
end
end
return n
end
function n:getKeys(e,n)local n=i[e](self,e,n)return _.sort(n,e)end
function n:getStackEntries()local t={}for l,n in e(p)do
for n,l in e(self.typed[n])do
if a[l.type]then
local n=l.lower
if n and(#n>0)then
local l=l.name
for e,n in e(n)do
local e=self:get(n)if e and a[e.type]then
t[#t+1]=l..'('..n..')'end
end
end
end
end
end
return t
end
function n:getUciKey(e)local e=self.all[e]if e then
local n=e.ucikey
if not n then
n=e.name:match(":(.+)")or e.name
e.ucikey=n
end
return n
end
end
function n:getBaseKey(n)local e=self.all[n]if e and e.refers_to then
e=self.all[e.refers_to]if e and not e.hide_in_datamodel then
return e.name
end
end
return n
end
local function i(n)local e=n._Name
if not e then
e=n.name:match("[^:]*:(.*)")or n.name
n._Name=e
end
return e
end
local function f(e)return e.device or i(e)end
function n:getDevice(e)local e=self:get(e)if e then
return f(e)end
end
function n:getInterface(e)local n=self.all[e]if n then
return n.interface or self:getUciKey(e)end
end
function n:getName(e)local e=self.all[e]if e then
return i(e)end
end
function n:getPresent(e)local e=self:get(e)if e then
local n=e.present
if n==nil then
if e._present then
n=e:_present()end
end
return(n==nil)and true or n,e
end
end
function n:checkLower()for n,t in e(self.all)do
if t.lower then
local n={}for e,l in e(t.lower)do
local e=self.all[l]if e then
if e.hide_in_datamodel and e.linkto then
l=self.all[e.linkto]and e.linkto
end
n[#n+1]=l
end
end
t.lower=n
end
end
end
function n.setLower(t,l,...)local n={}for l,e in e{l,...}do
n[#n+1]=e
end
t.lower=n
end
function n:getLowerLayers(t)local n={}local l,t=self:getPresent(t)if l and t then
for t,e in e(t.lower)do
local t=self:get(e)if t then
local t=a[t.type]if t then
n[#n+1]={t,e}end
end
end
end
return n
end
function n:getLowerLayersResolved(t,l,a)if l then
local n={}for e,o in e(self:getLowerLayers(t))do
local e=o[2]local t=self.key_aliases[e]if t and(t.slave==e)then
e=t.master
end
n[#n+1]=l(o[1],e)end
return g(n,a or",")end
return""end
local function i(t,e,o,l)local e,n=e:match("^(.*)%((.*)%)$")if not e then
return""end
local n=o and e or n
local e=t:get(n)if not e then
return""end
local e=a[e.type]if e then
return l(e,n)or""else
return""end
end
function n:getStackHigherResolved(e,n)return i(self,e,true,n)end
function n:getStackLowerResolved(e,n)return i(self,e,false,n)end
local function P(n)local t=l:load("ethernet")local l=t.port or{}for t,e in e(l)do
n:add("EthInterface",e['.name'])end
local t=t.mapping or{}for e,t in e(t)do
local e=t.port
local e=e and n:get("EthInterface",e)if e and(t.wlan_remote=="1")then
e.hide_in_datamodel=true
e.wlan_remote=true
end
end
end
local function S(n)local t=l:load("xdsl")for t,e in e(t.xdsl or{})do
local e=e[".name"]local l=n:add("DSLLine","dsl:"..e)l.device=e
local t=n:add("DSLChannel",e)t.device=e
n.setLower(t,l.name)end
end
local function R(n)local e="fast0"local n=n:add("GFASTLine","fast:"..e)n.device=e
end
local function a(e)if e.type=='ATMLink'then
return u.isADSL()elseif e.type=='PTMLink'then
return u.isVDSL()end
end
local function T(n)local t=l:load("xtm")for t,e in e(t.atmdevice or{})do
local e=n:add("ATMLink",e[".name"])n.setLower(e,"dsl0")e._present=a
end
for e,t in e(t.ptmdevice or{})do
local e=t['.name']local l=t['.placeholder']if l then
e=t.uciname or e
end
local e,o=o(n,"PTMLink",e,l)n.setLower(e,"dsl0")if l and not o then
e.ucikey=t['.name']e.present=false
else
e.present=nil
e._present=a
end
end
end
local function p(n,t,e)return n:get(e)or n:get("vlan:"..e)or n:get("vlan:"..t..':'..e)or n:get("link:"..e)end
local function b(n)local t=s(n)if t=='string'then
local e={}for n in n:gmatch("%S+")do
e[#e+1]=n
end
return e
elseif t=='table'then
return n
end
return{}end
local function a(t,n,l,e)if not e then
e=n
local t=t.key_aliases[n]if t and t.slave==n then
e=t.master or n
end
end
return e..':'..l,e
end
local function L(n,l,f,d)local i,t=o(n,"Bridge",l,d)if t then
local e=n:get("BridgePort",l..':mgmt')return e,i
end
local r={}i.members=r
f=f or{}local c,h=a(n,l,"mgmt")local t=o(n,"BridgePort",c,d)t.management=true
t.device=l
r[#r+1]=t.name
local u={}for t,e in e(b(f))do
local t=p(n,i.name,e)if t and t.wlan_remote then
t=nil
n.ext_wlan_bridge=i.name
end
if t then
c=a(n,l,e,h)local e=o(n,"BridgePort",c,d)if d then
e.present=false
else
e.present=nil
end
n.setLower(e,t.name)e.device=e.lower[1]r[#r+1]=e.name
u[#u+1]=e.name
end
end
n.setLower(t,x(u))return t.name,i
end
local function w(t,n,e)t._explicit_links[n]=e
end
local function x(n,t)for t,e in e(t)do
local l="link:"..e['.name']local t=n:add("EthLink",l)if e.linkedto then
w(n,e.linkedto,l)end
if e.ifname then
n.setLower(t,e.ifname)t.device=e.ifname
end
end
end
local function i(e,n)return e._explicit_links[n]end
function n:explicit_link_for(e)return i(self,e)end
local function D(n,e)local t
if not e['.placeholder']then
t=i(n,e['.name'])if not t and(e.dev2_dynamic~="1")then
t="link:"..e['.name']local t=n:add("EthLink","link:"..e['.name'])if e.ifname then
n.setLower(t,e.ifname)end
t.device=e.name
end
else
t="link:"..e['.name']end
local o=e.type or"8021q"if(o=="8021q")or(o=="8021ad")then
local l=n:add("VLAN","vlan:"..e['.name'])l._Name=e['.name']if e.type then
l.device=e.name
end
if e.ifname then
n.setLower(l,t)elseif e.type then
local e=n:get(t)if e then
n.setLower(l,e.name)end
end
elseif o=='bridge'then
L(n,e.name,e.ifname,e['.placeholder'])end
end
local function p(n,t)if n then
for n,e in e(n)do
if e==t then
return n
end
end
end
return 0
end
local function u(t,n,l)for n,e in e(t.typed[n])do
if f(e)==l then
return e.name,e
end
end
end
local function E(l,t)if not t then
return
end
local n=u(l,"VLAN",t)if not l:get("VLAN",n)then
n=u(l,"EthLink",t)if not n then
for l,e in e(l.typed.EthLink or{})do
if p(e.lower,t)>0 then
n=e.name
break
end
end
end
n=n or t
end
return n
end
local function p(n,t)for l,e in e(n)do
if e==t then
return
end
end
n[#n+1]=t
end
local function u(l,n,t)if not n then return end
if f(n)==t then
return true
else
for n,e in e(n.lower)do
local e=l:get(e)if e and u(l,e,t)then
return true
end
end
end
end
local function W(n,l,o)local t=f(o)for l,e in e(l.members)do
if u(n,n:get(e),t)then
return
end
end
local e=a(n,l.name,t)local t=n:get(e)if not t then
t=n:add("BridgePort",e)p(l.members,e)end
if o.device then
t.device=o.device
end
n.setLower(t,o.name)local n=n:get("BridgePort",l.name..':mgmt')if n and n.management then
p(n.lower,e)end
end
local function u(e,n,t)return o(e,"PPPInterface",n,t)end
local function N(l,n,t)local o=n.proto
local a=n['.name']local e=u(l,o.."-"..a)e.proto=o
e.ucikey=a
n.device=e.name
if t then
l.setLower(e,t)end
return e.name
end
local function f(n,t)for t,e in e(t.device or{})do
if e.name==n then
if e.type then
return e
else
return
end
end
end
end
local function k(e)if not e.proto then
return false
end
if e.proto=='none'then
return false
end
if(e.proto=='static')and not e.ipaddr then
return false
end
if e.proto:match('^gre')then
return false
end
return true
end
local function g(n,e,l,t)local e=n:add("EthLink","link:"..e,1)e.device=l
n.setLower(e,t)return e.name
end
local function p(t,n,o,a,l)local e=t:add("VLAN","vlan:"..n)e._Name=n
e.device=o
e.vid=a
t.setLower(e,l)return e.name
end
local function B(l,o,a,e)local n
e=e or o.ifname
local t=i(l,o['.name'])if f(e,a)then
n=E(l,e)elseif t then
n=t
elseif e then
local t,a=e:match("^([^.]+)%.(%d+)$")if not t then
t=e
a=nil
end
if t=="lo"then
return
end
local r=o['.name']local e=o.device or e
n=g(l,r,e,t)if a then
n=p(l,r,e,a,n)end
end
return n
end
local function f(n,e)if e and n and(n.proto or""):match("^gre")then
return"gre-"..e
end
end
local function E(e,l)local n=e:match("^@(.*)")if n then
local t=l.interface[n]if t then
e=f(t,n)or e
else
e=""end
else
e=f(l.interface[e],e)or e
end
return e
end
local function f(e,t)if not e then
return
end
local n=t.device or{}if n[e]then
return e
end
if e:match("^@")then
local n=e:match("^@([^.]+)")local n=t.interface[n]if n then
if n.proto=="gretap"then
return e:gsub("^@","gre4t-")elseif n.proto=="grev6tap"then
return e:gsub("^@","gre6t-")elseif n.proto:match("^gre")then
return e:gsub("^@","")else
return f(n.ifname,t)end
end
return
end
return e:match("^([^.]+)")end
local function F(r,n,a)local l=b(n.ifname or"")for o,t in e(l)do
local e,i=t:match("^([^.]+)%.(%d+)$")if e then
e=E(e,a)local n='br-'..n['.name']..':@'..m(o)local t=f(t,a)or t
local e=g(r,n,t,e)p(r,n,t,i,e)l[o]=n
end
end
return l
end
local function g(n,e,t)if e.auto=='0'then
return
end
local o=F(n,e,t)local t=e['.name']local l='br-'..t
local a,o=L(n,l,o)e.device=l
o.ucikey=t
if k(e)then
local l=n:add("EthLink","link:"..t,1)l.ucikey=t
l.device=o.name
e.device=o.name
n.setLower(l,a)return l.name
else
local e=n:get(a)e.management=false
e.lower={}end
end
local f
local function p(a,n,r)local e=n.ifname
if s(e)=='string'then
local t
local l=e:match("^@([^.]*)")if l then
local e=r.interface[l]if e then
local o=d(a,"IPInterface",e['.name'])if not o then
o=f(a,e,r)end
if e.type=='bridge'then
t='link:'..e['.name']n.device=t
else
t=o.lower[1]n.device=l
end
else
n.ifname=nil
end
end
return t,l
end
end
function f(t,n,a)local o=n['.name']local e=d(t,"IPInterface",o)if e then
return e
end
local l,r=p(t,n,a)if not l then
if n.type=='bridge'then
l=g(t,n,a)else
l=B(t,n,a)end
end
if n.proto and n.proto:match('^ppp')then
if not i(t,o)then
l=N(t,n,l)end
end
e=t:add("IPInterface",o)e.device=n.device or n.ifname
e.refers_to=r
e.has_ip_layer=k(n)if not e.has_ip_layer then
e.hide_in_datamodel=n.dev2_dynamic~="1"end
local n=_.linked("network.interface",o)if n then
e.hide_in_datamodel=true
e.linkto=n
end
t.setLower(e,l)return e
end
local function g(l,e)local n=e.proto or""if n:match("^gre")then
local n=e['.name']local t=l:add("GRE","gre-"..n)t.ucikey=n
l.setLower(t,e.tunlink)end
end
local function p(n,e)local e=n:get("IPInterface",e)while e and(e.type~="Bridge")do
e=n:get(e.device)end
return e
end
local function d(n,t)for t,e in e(t)do
if not e['.placeholder']then
local t=u(n,e['.name'])local l=i(n,e['.name'])if l then
n.setLower(t,l)end
if e.linkedto then
w(n,e.linkedto,t.name)end
end
end
end
local function s(t)local n=l:load("network")x(t,n.dev2_link or{})d(t,n.ppp or{})for n,e in e(n.device or{})do
D(t,e)end
for n,e in e(n.interface or{})do
g(t,e)end
for l,e in e(n.interface or{})do
f(t,e,n)end
for n,e in e(n.ppp or{})do
local o=e.uciname or e['.name']local l=e['.placeholder']if l then
local n,t=u(t,o,l)if l and not t then
n.ucikey=e['.name']if e.interface then
n.interface=e.interface
else
n.interface=o:match("^[^-]+%-(.*)")or e['.name']end
n.present=false
end
end
end
end
local function d(n)for n,e in e(n.typed.EthInterface)do
if e.wlan_remote then
return e.name
end
end
end
local function i(t,n,e)local e=t:add('WiFiSSID',e)if n.remote then
e.device=n.device
else
e.device=e.name
end
t.setLower(e,n.name)return e
end
local function f(n,t)for t,e in e(t['wifi-device']or{})do
local t=n:add("WifiRadio",e['.name'])if e.type=='quantenna'then
t.remote=true
t.device=d(n)end
end
end
local function d(n,t)for t,e in e(t['wifi-iface']or{})do
local t=n:get('WifiRadio',e.device)local l
if t.remote then
if n.ext_wlan_bridge then
l=n:get('Bridge',n.ext_wlan_bridge)end
end
if not l then
l=p(n,e.network or'lan')end
local o=e.network and n:get("IPInterface",e.network)if t and l then
local e=i(n,t,e['.name'])W(n,l,e)elseif t and o then
i(n,t,e['.name'])elseif e['.placeholder']then
local e=n:add("WiFiSSID",e['.name'])e.present=false
end
end
end
local function i(t,n)for n,e in e(n['wifi-ap']or{})do
local n=e['.name']local l=e['.placeholder']if l then
n=e.uciname or n
end
local n=o(t,"WiFiAP",n,l)n.ucikey=e['.name']local e=e.iface
if e then
t.setLower(n,e)end
end
end
local function u(e)local n=l:load("wireless")f(e,n)d(e,n)i(e,n)end
local function f(a)local r=l:load("dmordering")local n={}local l={}for t,e in e(r.alias or{})do
local o=e.master
local t=e.slave
if o and t then
n[o]=e
n[t]=e
l[t]=true
end
end
a.key_aliases=n
a.key_ignore=l
local n={}for t,e in e(r.bridgeports or{})do
local t=e.name or e['.name']n[t]=e.port
end
return n
end
local function p(t,e,n)local n=n and t:get(n)if not n or(e.type~=n.type)then
return
end
for n in c(e)do
if n~='name'then
e[n]=nil
end
end
for n,t in c(n)do
if n~='name'then
e[n]=t
end
end
end
local function g(t,n)for n,d in c(n)do
local l=t:get('Bridge',n)if l then
local f=a(t,l.name,'mgmt')local r={}local i
for e,n in e(d)do
if e==1 then
r[1]=f
i=a(t,l.name,n)else
r[e]=a(t,l.name,n)end
end
local n={}for t,e in c(l.members)do
if e~=i then
n[#n+1]=e
n[e]=true
end
end
local a={}for r,l in e(r)do
local e=t:get('BridgePort',l)if not e then
e=o(t,"BridgePort",l,true)elseif r==1 then
if not e.management and d[1]~='-'then
p(t,e,i)end
end
a[#a+1]=l
n[l]=nil
end
for t,e in e(n)do
if n[e]then
a[#a+1]=e
n[e]=nil
end
end
l.members=a
end
end
end
local n
y=function()if not n or l:config_changed()then
local e=v()local t=f(e)e:add("loopback","lo")P(e)S(e)R(e)T(e)s(e)u(e)g(e,t)e:checkLower()n=e
end
return n
end
function r.invalidate()n=nil
end
local function d(n,e,l)t.sectionname=n
t.option=e
t.default=l
return I(t)or""end
local function o(e,n,l)t.sectionname=n
t.option=l
h(t,e,commitapply)end
function r.getShapingRate(e,n)local e=d(e,"td","")if e~=""then
local e=d(e,"max_bit_rate","")return e~=""and m(tonumber(e)*1000)or"-1"end
return"-1"end
local function c(n,e)t.sectionname=e
t.option=nil
A(t,commitapply)o("",n,"td")return true
end
local function i(e,n)o(n.max_bit_rate,e,"max_bit_rate")o(n.max_burst_size,e,"max_burst_size")o(n.rate,e,"rate")o(n.ratio,e,"ratio")return true
end
function r.setShapingRate(e,n,r)e=tonumber(e)local a="2000"if e then
local n=d(r,"td","")local l="td"..r
if n~=""then
a=d(n,"max_burst_size","2000")end
if n==""and e==-1 then
return true
elseif e==0 then
return nil,"Not supported"elseif n==""and(e>-1)and(e<=100)then
h(t,l,commitapply)o("trafficdesc",l)return i(l,{max_bit_rate=e,max_burst_size=a,rate="",ratio="enabled",})elseif n==""and(e>100)then
if e<1000 then
return nil,"Absolute value should be at least 1000 bps"end
h(t,l,commitapply)o("trafficdesc",l)return i(l,{max_bit_rate=e/1000,max_burst_size=a,rate="enabled",ratio=""})elseif n~=""and e==-1 then
return c(r,n)elseif n~=""and(e>-1)and(e<=100)then
return i(l,{max_bit_rate=e,max_burst_size=a,rate="",ratio=""})elseif n~=""and(e>100)then
if e<1000 then
return nil,"Absolute value should be at least 1000 bps"end
return i(l,{max_bit_rate=e/1000,max_burst_size=a,rate="enabled",ratio=""})end
end
return nil,"Not supported"end
return r