diff --git a/cmd/api/v5/qos.go b/cmd/api/v5/qos.go index c4d3cb5..6af2fa2 100644 --- a/cmd/api/v5/qos.go +++ b/cmd/api/v5/qos.go @@ -37,9 +37,8 @@ func (qr QosRule) Add(c *cli.Context) error { url := qr.Url(c.String("url"), name) rule := &schema.Qos{ - Name: c.String("clientname"), - InSpeed: c.Int64("inspeed"), - OutSpeed: c.Int64("outspeed"), + Name: c.String("client"), + InSpeed: c.Float64("inspeed"), } clt := qr.NewHttp(c.String("token")) @@ -55,7 +54,7 @@ func (qr QosRule) Remove(c *cli.Context) error { url := qr.Url(c.String("url"), name) rule := &schema.Qos{ - Name: c.String("clientname"), + Name: c.String("client"), } clt := qr.NewHttp(c.String("token")) @@ -68,9 +67,9 @@ func (qr QosRule) Remove(c *cli.Context) error { func (qr QosRule) Tmpl() string { return `# total {{ len . }} -{{ps -15 "Name"}} {{ps -15 "Device"}} {{ps -15 "ip"}} {{ps -8 "InSpeed"}} {{ps -8 "OutSpeed"}} +{{ps -15 "Name"}} {{ps -15 "Device"}} {{ps -15 "ip"}} {{ps -8 "InSpeed"}} {{- range . }} -{{ps -15 .Name}} {{ps -15 .Device}} {{ps -15 .Ip}} {{pi -8 .InSpeed}} {{pi -8 .OutSpeed}} +{{ps -15 .Name}} {{ps -15 .Device}} {{ps -15 .Ip}} {{pi -8 .InSpeed}} {{- end }} ` } @@ -110,9 +109,8 @@ func (qr QosRule) Commands() *cli.Command { Name: "add", Usage: "Add a new qos rule for client", Flags: []cli.Flag{ - &cli.StringFlag{Name: "clientname", Aliases: []string{"cn"}}, - &cli.StringFlag{Name: "inspeed", Aliases: []string{"is"}}, - &cli.StringFlag{Name: "outspeed", Aliases: []string{"os"}}, + &cli.StringFlag{Name: "client", Aliases: []string{"c"}}, + &cli.Float64Flag{Name: "inspeed", Aliases: []string{"is"}}, }, Action: qr.Add, }, @@ -121,7 +119,7 @@ func (qr QosRule) Commands() *cli.Command { Usage: "remove a qos rule", Aliases: []string{"rm"}, Flags: []cli.Flag{ - &cli.StringFlag{Name: "clientname", Aliases: []string{"cn"}}, + &cli.StringFlag{Name: "client", Aliases: []string{"c"}}, }, Action: qr.Remove, }, diff --git a/dist/rootfs/etc/openlan/switch/qos/example.json.example b/dist/rootfs/etc/openlan/switch/qos/example.json.example index 3bbb95d..6721291 100644 --- a/dist/rootfs/etc/openlan/switch/qos/example.json.example +++ b/dist/rootfs/etc/openlan/switch/qos/example.json.example @@ -2,8 +2,7 @@ "name": "example", "qos":{ "hi@example": { - "inSpeed": 125000, - "outSpeed":125000 + "inSpeed": 125000 } } } \ No newline at end of file diff --git a/pkg/api/api.go b/pkg/api/api.go index 451b996..28915d2 100755 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -48,8 +48,8 @@ type ZTruster interface { } type Qoser interface { - AddQosUser(name string, inSpeed int64, outSpeed int64) error - UpdateQosUser(name string, inSpeed int64, outSpeed int64) error + AddQosUser(name string, inSpeed float64) error + UpdateQosUser(name string, inSpeed float64) error DelQosUser(name string) error ListQosUsers(call func(obj schema.Qos)) Save() diff --git a/pkg/api/qos.go b/pkg/api/qos.go index f780ffd..cfeefb0 100644 --- a/pkg/api/qos.go +++ b/pkg/api/qos.go @@ -54,7 +54,7 @@ func (h QosApi) Add(w http.ResponseWriter, r *http.Request) { } if qos != nil { - if err := worker.Qoser().AddQosUser(qos.Name, qos.InSpeed, qos.OutSpeed); err != nil { + if err := worker.Qoser().AddQosUser(qos.Name, qos.InSpeed); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } diff --git a/pkg/config/qos.go b/pkg/config/qos.go index aabcd72..6e2ebad 100644 --- a/pkg/config/qos.go +++ b/pkg/config/qos.go @@ -8,6 +8,15 @@ type Qos struct { Config map[string]*QosLimit `json:"qos,omitempty"` } +func (q *Qos) Correct(sw *Switch) { + for _, rule := range q.Config { + rule.Correct() + } + if q.File == "" { + q.File = sw.Dir("qos", q.Name+".json") + } +} + func (q *Qos) Save() { if err := libol.MarshalSave(q, q.File, true); err != nil { libol.Error("Switch.Save.Qos %s %s", q.Name, err) @@ -15,8 +24,7 @@ func (q *Qos) Save() { } type QosLimit struct { - InSpeed int64 `json:"inSpeed,omitempty"` - OutSpeed int64 `json:"outSpeed,omitempty"` + InSpeed float64 `json:"inSpeed,omitempty"` } func (ql *QosLimit) Correct() { diff --git a/pkg/config/switch.go b/pkg/config/switch.go index fa30deb..f5413ea 100755 --- a/pkg/config/switch.go +++ b/pkg/config/switch.go @@ -206,6 +206,13 @@ func (s *Switch) LoadNetwork() { obj.Correct(s) s.Acl[obj.Name] = obj } + if _, ok := s.Qos[obj.Name]; !ok { + obj := &Qos{ + Name: obj.Name, + } + obj.Correct(s) + s.Qos[obj.Name] = obj + } } } diff --git a/pkg/schema/qos.go b/pkg/schema/qos.go index 7f1c9df..cb5496f 100644 --- a/pkg/schema/qos.go +++ b/pkg/schema/qos.go @@ -1,9 +1,8 @@ package schema type Qos struct { - Name string `json:"name"` - Device string `json:"device"` - Ip string `json:"ip"` - InSpeed int64 `json:"inSpeed"` - OutSpeed int64 `json:"outSpeed"` + Name string `json:"name"` + Device string `json:"device"` + Ip string `json:"ip"` + InSpeed float64 `json:"inSpeed"` } diff --git a/pkg/switch/network.go b/pkg/switch/network.go index 5f0f1c9..dc788cb 100755 --- a/pkg/switch/network.go +++ b/pkg/switch/network.go @@ -412,11 +412,6 @@ func (w *WorkerImpl) Start(v api.Switcher) { Jump: w.qos.ChainIn(), Comment: "Goto Qos ChainIn", }) - fire.Mangle.Out.AddRule(cn.IPRule{ - Output: vpn.Device, - Jump: w.qos.ChainOut(), - Comment: "Goto Qos ChainOut", - }) } } diff --git a/pkg/switch/qos.go b/pkg/switch/qos.go index 93ccbda..0acabbf 100644 --- a/pkg/switch/qos.go +++ b/pkg/switch/qos.go @@ -16,13 +16,11 @@ import ( type QosUser struct { QosChainName string - InSpeed int64 // bits - OutSpeed int64 // bits + InSpeed float64 // Mbit Name string Ip string Device string qosChainIn *cn.FireWallChain - qosChainOut *cn.FireWallChain out *libol.SubLogger } @@ -32,74 +30,20 @@ func (qr *QosUser) RuleName(dir string) string { } func (qr *QosUser) InLimitPacket() string { - //bytes / mtu - return strconv.Itoa(int(qr.InSpeed / 1500)) -} - -func (qr *QosUser) OutLimitPacket() string { - //bytes / mtu - return strconv.Itoa(int(qr.OutSpeed / 1500)) + //Mbit * 125000 / mtu + return strconv.Itoa(int((qr.InSpeed * 125000) / 1300)) } func (qr *QosUser) InLimitStr() string { - //bytes / mtu return qr.InLimitPacket() + "/s" } -func (qr *QosUser) OutLimitStr() string { - //bytes / mtu - return qr.OutLimitPacket() + "/s" -} func (qr *QosUser) InLimitRule() cn.IPRule { return cn.IPRule{ - Limit: qr.InLimitStr(), - //LimitBurst: qr.InLimitPacket(), - Comment: "Qos Limit In " + qr.Name, - Jump: "ACCEPT", - } -} - -func (qr *QosUser) OutLimitRule() cn.IPRule { - return cn.IPRule{ - Limit: qr.OutLimitStr(), - Comment: "Qos Limit Out " + qr.Name, - Jump: "ACCEPT", - } -} - -func (qr *QosUser) BuildChainOut(chain *cn.FireWallChain) { - if qr.OutSpeed > 0 { - qr.qosChainOut = cn.NewFireWallChain(qr.RuleName("out"), cn.TMangle, "") - qr.qosChainOut.AddRule(qr.OutLimitRule()) - qr.qosChainOut.AddRule(cn.IPRule{ - Comment: "Qos Default Drop", - Jump: "DROP", - }) - qr.qosChainOut.Install() - - qr.BuildChainOutJump(chain) - } -} - -func (qr *QosUser) BuildChainOutJump(chain *cn.FireWallChain) { - if qr.Ip != "" { - if err := chain.AddRuleX(cn.IPRule{ - Comment: "Qos Jump", - Jump: qr.RuleName("out"), - Dest: qr.Ip, - }); err != nil { - qr.out.Warn("Qos.Add Out Rule: %s", err) - } - } -} - -func (qr *QosUser) ClearChainOutJump(chain *cn.FireWallChain) { - if err := chain.DelRuleX(cn.IPRule{ - Comment: "Qos Jump", - Jump: qr.RuleName("out"), - Dest: qr.Ip, - }); err != nil { - qr.out.Warn("Qos.Del Out Rule: %s", err) + Limit: qr.InLimitStr(), + LimitBurst: "100", + Comment: "Qos Limit In " + qr.Name, + Jump: "ACCEPT", } } @@ -139,14 +83,13 @@ func (qr *QosUser) ClearChainInJump(chain *cn.FireWallChain) { } } -func (qr *QosUser) Start(chainIn *cn.FireWallChain, chainOut *cn.FireWallChain) { +func (qr *QosUser) Start(chainIn *cn.FireWallChain) { qr.BuildChainIn(chainIn) - qr.BuildChainOut(chainOut) } -func (qr *QosUser) ReBuild(chainIn *cn.FireWallChain, chainOut *cn.FireWallChain) { - qr.Clear(chainIn, chainOut) - qr.Start(chainIn, chainOut) +func (qr *QosUser) ReBuild(chainIn *cn.FireWallChain) { + qr.Clear(chainIn) + qr.Start(chainIn) } func (qr *QosUser) ClearChainIn(chain *cn.FireWallChain) { @@ -156,30 +99,22 @@ func (qr *QosUser) ClearChainIn(chain *cn.FireWallChain) { qr.qosChainIn = nil } } -func (qr *QosUser) ClearChainOut(chain *cn.FireWallChain) { - if qr.qosChainOut != nil { - qr.ClearChainOutJump(chain) - qr.qosChainOut.Cancel() - qr.qosChainOut = nil - } -} -func (qr *QosUser) Clear(chainIn *cn.FireWallChain, chainOut *cn.FireWallChain) { + +func (qr *QosUser) Clear(chainIn *cn.FireWallChain) { qr.ClearChainIn(chainIn) - qr.ClearChainOut(chainOut) } -func (qr *QosUser) Update(chainIn *cn.FireWallChain, chainOut *cn.FireWallChain, inSpeed int64, outSpeed int64, device string, ip string) { +func (qr *QosUser) Update(chainIn *cn.FireWallChain, inSpeed float64, device string, ip string) { - ipChange := false + changed := false + qr.Device = device if qr.Ip != ip { - ipChange = true + changed = true qr.Ip = ip } - if ipChange { + if changed { qr.ClearChainInJump(chainIn) - qr.ClearChainOutJump(chainOut) - qr.BuildChainOutJump(chainOut) qr.BuildChainInJump(chainIn) } @@ -189,21 +124,14 @@ func (qr *QosUser) Update(chainIn *cn.FireWallChain, chainOut *cn.FireWallChain, qr.BuildChainIn(chainIn) } - if qr.OutSpeed != outSpeed { - qr.OutSpeed = outSpeed - qr.ClearChainOut(chainOut) - qr.BuildChainOut(chainOut) - } - } type QosCtrl struct { - Name string - Rules map[string]*QosUser - chainIn *cn.FireWallChain - chainOut *cn.FireWallChain - out *libol.SubLogger - lock sync.Mutex + Name string + Rules map[string]*QosUser + chainIn *cn.FireWallChain + out *libol.SubLogger + lock sync.Mutex } func NewQosCtrl(name string) *QosCtrl { @@ -218,14 +146,9 @@ func (q *QosCtrl) ChainIn() string { return "Qos_" + q.Name + "-in" } -func (q *QosCtrl) ChainOut() string { - return "Qos_" + q.Name + "-out" -} - func (q *QosCtrl) Initialize() { //q.Start() q.chainIn = cn.NewFireWallChain(q.ChainIn(), cn.TMangle, "") - q.chainOut = cn.NewFireWallChain(q.ChainOut(), cn.TMangle, "") qosCfg := config.GetQos(q.Name) @@ -235,7 +158,6 @@ func (q *QosCtrl) Initialize() { QosChainName: q.Name, Name: name, InSpeed: limit.InSpeed, - OutSpeed: limit.OutSpeed, Ip: "", out: libol.NewSubLogger("Qos_" + name), } @@ -248,11 +170,10 @@ func (q *QosCtrl) Initialize() { func (q *QosCtrl) Start() { q.out.Info("Qos.Start") q.chainIn.Install() - q.chainOut.Install() if len(q.Rules) > 0 { for _, rule := range q.Rules { - rule.Start(q.chainIn, q.chainOut) + rule.Start(q.chainIn) } } @@ -263,19 +184,18 @@ func (q *QosCtrl) Stop() { q.out.Info("Qos.Stop") if len(q.Rules) != 0 { for _, rule := range q.Rules { - rule.Clear(q.chainIn, q.chainOut) + rule.Clear(q.chainIn) } } q.chainIn.Cancel() - q.chainOut.Cancel() } func (q *QosCtrl) DelUserRule(name string) { q.lock.Lock() defer q.lock.Unlock() if rule, ok := q.Rules[name]; ok { - rule.Clear(q.chainIn, q.chainOut) + rule.Clear(q.chainIn) delete(q.Rules, name) } } @@ -298,7 +218,7 @@ func (q *QosCtrl) FindClient(name string) *schema.VPNClient { return nil } -func (q *QosCtrl) AddOrUpdateQosUser(name string, inSpeed int64, outSpeed int64) { +func (q *QosCtrl) AddOrUpdateQosUser(name string, inSpeed float64) { q.lock.Lock() defer q.lock.Unlock() client := q.FindClient(name) @@ -311,18 +231,17 @@ func (q *QosCtrl) AddOrUpdateQosUser(name string, inSpeed int64, outSpeed int64) if rule, ok := q.Rules[name]; ok { - rule.Update(q.chainIn, q.chainOut, inSpeed, outSpeed, device, ip) + rule.Update(q.chainIn, inSpeed, device, ip) } else { rule = &QosUser{ QosChainName: q.Name, Name: name, InSpeed: inSpeed, - OutSpeed: outSpeed, Ip: ip, out: libol.NewSubLogger("Qos_" + name), } - rule.Start(q.chainIn, q.chainOut) + rule.Start(q.chainIn) q.Rules[name] = rule } @@ -350,11 +269,10 @@ func (q *QosCtrl) ClientUpdate() { } } if existClient != nil { - rule.Update(q.chainIn, q.chainOut, rule.InSpeed, rule.OutSpeed, existClient.Device, existClient.Address) + rule.Update(q.chainIn, rule.InSpeed, existClient.Device, existClient.Address) } else { if rule.Ip != "" { rule.ClearChainInJump(q.chainIn) - rule.ClearChainOutJump(q.chainOut) rule.Ip = "" } } @@ -377,23 +295,22 @@ func (q *QosCtrl) Save() { cfg.Config = make(map[string]*config.QosLimit, 1024) for _, rule := range q.Rules { ql := &config.QosLimit{ - InSpeed: rule.InSpeed, - OutSpeed: rule.OutSpeed, + InSpeed: rule.InSpeed, } cfg.Config[rule.Name] = ql } cfg.Save() } -func (q *QosCtrl) AddQosUser(name string, inSpeed int64, outSpeed int64) error { +func (q *QosCtrl) AddQosUser(name string, inSpeed float64) error { - q.AddOrUpdateQosUser(name, inSpeed, outSpeed) + q.AddOrUpdateQosUser(name, inSpeed) return nil } -func (q *QosCtrl) UpdateQosUser(name string, inSpeed int64, outSpeed int64) error { +func (q *QosCtrl) UpdateQosUser(name string, inSpeed float64) error { - q.AddOrUpdateQosUser(name, inSpeed, outSpeed) + q.AddOrUpdateQosUser(name, inSpeed) return nil } @@ -407,11 +324,10 @@ func (q *QosCtrl) ListQosUsers(call func(obj schema.Qos)) { for _, rule := range q.Rules { obj := schema.Qos{ - Name: rule.Name, - Device: rule.Device, - InSpeed: rule.InSpeed, - OutSpeed: rule.OutSpeed, - Ip: rule.Ip, + Name: rule.Name, + Device: rule.Device, + InSpeed: rule.InSpeed, + Ip: rule.Ip, } call(obj) }