fea: remove qos download limit (#45)

* fea: remove qos download limit
* fix: crash when qos config missing
* fea: update inSpeed unit to Mbit
This commit is contained in:
Teddy_Zhu
2024-03-28 16:56:14 +08:00
committed by GitHub
parent ffce18224b
commit 2fa0ed3e19
9 changed files with 72 additions and 150 deletions

View File

@@ -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,
},

View File

@@ -2,8 +2,7 @@
"name": "example",
"qos":{
"hi@example": {
"inSpeed": 125000,
"outSpeed":125000
"inSpeed": 125000
}
}
}

View File

@@ -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()

View File

@@ -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
}

View File

@@ -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() {

View File

@@ -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
}
}
}

View File

@@ -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"`
}

View File

@@ -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",
})
}
}

View File

@@ -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)
}