#!/usr/bin/lua -- miqos 主框架 local socket=require("socket") local io= require 'io' local libunix= require 'socket.unix' local json= require 'json' local unsock=assert(libunix()) -- 单一流的设备,比如电视/盒子,用来做设备最低带宽预留 band_reserve_hosts={ changed=true, ['video']={}, ['other']={}, } -- 特殊设备优先级 special_host_list={ host={ }, changed=false, } require "miqos.common" require "miqos.command" --require "miqos.rule_by_flow" require "miqos.rule_by_host" require "miqos.rule_by_prio" require "miqos.rule_by_service" local QOS_CMD --read args QOS_VER='CTF' if #arg >= 1 then if arg[1] == 'std' then QOS_VER='STD' elseif arg[1] == 'ctf' then QOS_VER='CTF' elseif arg[1] == 'fix' then QOS_VER='FIX' elseif arg[1] == 'hwqos' then QOS_VER='HWQOS' else QOS_VER='FIX' QOS_CMD=arg end else clean_sock() logger(3,'======== Process Exit. =====') os.exit(0) end -----全局定义----------------- g_group_def=nil g_class_def={} -- TODO: 暂时关闭,需要看测试结果 g_enable_stab=false --- g_leaf_type='fq_codel' --,sfq,fq_codel --g_leaf_type='sfq' --,sfq,fq_codel function clean_sock() unsock:close() util.exec('rm -rf ' .. cfg.server.path) end -- 清除规则,并退出服务 function system_exit() cleanup_system() clean_sock() logger(3,'======== Process Exit. =====') os.exit(0) end -- 系统初始化 local function system_init() -- 将配置文件copy到tmp内存中,并初始化cursor if not cfg2tmp() then return false end -- 读取网络配置 if not read_network_conf() then logger(3, 'failed to read network config!') return false end -- read_qos_config() -- SIGTERM to clear and exit px.signal(px.SIGTERM, function () logger(3,'signal TERM to stop miqos.') system_exit() end) px.signal(px.SIGINT, function () logger(3,'signal INT to stop miqos.') system_exit() end) return true end g_ifb_status='' local function check_ifb_up() if QOS_VER == 'HWQOS' then return true end -- 如果ifb状态未UP,则尝试UP if g_ifb_status ~= UP then --check if dev ifb0 is up local ifb_up = '/usr/sbin/ip link set ifb0 up ' local ifb_check = '/usr/sbin/ip link show ifb0 |grep "state DOWN"' local ret = util.exec(ifb_up) ret = util.exec(ifb_check) if ret == '' then g_ifb_status = UP else logger(3, 'ifb0 is not up, wait for next link up.') return false -- 继续下一次set link up end end return true end -- 更新调用QoS local function update_qos_rules() local ret=false if not check_ifb_up() then return false end -- 读取配置文件(TODO: 这里需要添加一个触发开关,只有通过命令行触发的配置改变才能激发重读qos config) if not read_qos_config() then -- logger(3,'config no changed.') return false end if qdisc[cur_qdisc].changed() or old_qdisc ~= cur_qdisc then ret = qdisc[cur_qdisc].apply(old_qdisc,cfg.bands,cfg.DEVS,false) cfg.qdisc.old = cfg.qdisc.cur end return ret end -- 为FIX-版本更新简化QoS local function update_fix_qos_rules() -- 读取配置文件 if not read_qos_config() then return false end if cfg.enabled.flag == '0' then -- clean rule & exit if qos off system_exit() end if qdisc[cur_qdisc] then if qdisc[cur_qdisc].apply then logger(3,'-------------apply '..cur_qdisc) return qdisc[cur_qdisc].apply(nil,cfg.bands,cfg.DEVS,true,true) end else logger(3, 'service-mode-qdisc not exist.') end return false end -- 读取uptime计数 local function get_uptime() local pp=io.open('/proc/uptime') local n=pp:read('*n') pp:close() return math.ceil(n) end -- 主循环 local function main_loop() util.exec('rm -rf ' .. cfg.server.path) assert(unsock:bind(cfg.server.path)) assert(unsock:listen()) unsock:settimeout(1) local now_time = get_uptime() local next_qos_time = now_time local delta local gc_timer=0 -- tables for select event local set=newset() set:insert(unsock) -- add 'server' into select events while true do now_time = get_uptime() -- 读取当前的uptime ticks if now_time >= next_qos_time then if update_qos_rules() then gc_timer = gc_timer + 1 if gc_timer >= 180 then gc_timer = 0 local tmp_cnt = collectgarbage('count') logger(3,p_sysinfo()) end -- 更新tc的counters,便于直接调用返回 update_counters(cfg.DEVS) end next_qos_time = now_time + cfg.check_interval -- 更新下一次update QOS检测时间 end delta = next_qos_time - now_time if delta > cfg.check_interval then logger(3, "Warning!!! plz check Update QoS delta = " .. delta .. ", it's too long!!!!") delta = cfg.check_interval end local readable, _, error = socket.select(set, nil , delta) for _,v in ipairs(readable) do if v == unsock then -- logger(3, 'new client come in ...') local clt=v:accept() if clt then clt:settimeout(1) set:insert(clt) else logger(3, 'accept client error.') end else local data,error = v:receive() if error then v:close() -- logger(3, 'client is disconnected.') set:remove(v) else local args=string.split(data,' ') local res,execflag='','' if not args[1] then res={status=3,data='cmd is NULL.'} elseif args[1] == 'die' then v:send(json.encode({status=0}) .. "\n") v:close() logger(3,"======== COMMAND `qos die` ============") system_exit() ---===OVER NOW===--- else -- 命令行的处理 res,execflag = process_cmd(unpack(args)) if execflag then -- 触发立即执行更新qos操作 next_qos_time = 0 end end v:send(json.encode(res) .. '\n') v:close() set:remove(v) end end end end end function main_once() -- FIX 模式强制service模式 cur_qdisc='service' local res={result=0,data='ok'} cfg.DEVS={ UP={dev=read_interfaces("wan"),id='2',}, DOWN={dev="ifb0",id='1',}, } if not QOS_CMD or not QOS_CMD[1] then update_fix_qos_rules() else -- 命令行的处理 read_qos_config() res,execflag = process_cmd(unpack(QOS_CMD)) if execflag then -- 触发立即执行更新qos操作 update_fix_qos_rules() end end if g_debug then pr(res) end end --[[main]]------------------- local function main() if system_init() then local s,e if QOS_VER == 'FIX' then -- logger(3, 'apply rule as FIX mode.') s, e = pcall(function() main_once() end) else -- logger(3, 'apply rule as non-FIX mode.') s, e = pcall(function() main_loop() end) end if not s then logger(3,e) cleanup_system() end else logger(3, 'system initial failed. exit.') end end main() --[[main end]]-------------------