Skip to content

Commit

Permalink
fea: support rate limit.
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldin95 committed Sep 6, 2024
1 parent 8377782 commit a0f3e13
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 23 deletions.
1 change: 1 addition & 0 deletions cmd/api/v5/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ func Commands(app *api.App) {
Version{}.Commands(app)
Log{}.Commands(app)
ZTrust{}.Commands(app)
Rate{}.Commands(app)
}
92 changes: 92 additions & 0 deletions cmd/api/v5/rate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package v5

import (
"github.com/luscis/openlan/cmd/api"
"github.com/luscis/openlan/pkg/schema"
"github.com/urfave/cli/v2"
)

type Rate struct {
Cmd
}

func (u Rate) Url(prefix, name string) string {
return prefix + "/api/interface/" + name + "/rate"
}

func (u Rate) Tmpl() string {
return `# total {{ len . }}
{{ps -16 "device"}} {{ps -8 "speed"}}
{{- range . }}
{{ps -16 .Device}} {{pi .Speed}}
{{- end }}
`
}

func (u Rate) List(c *cli.Context) error {
url := u.Url(c.String("url"), "")
clt := u.NewHttp(c.String("token"))
var items []schema.Rate
if err := clt.GetJSON(url, &items); err != nil {
return err
}
return u.Out(items, c.String("format"), u.Tmpl())
}

func (u Rate) Add(c *cli.Context) error {
name := c.String("device")
rate := &schema.Rate{
Device: name,
Speed: c.Int("speed"),
}
url := u.Url(c.String("url"), name)
clt := u.NewHttp(c.String("token"))
if err := clt.PostJSON(url, rate, nil); err != nil {
return err
}
return nil
}

func (u Rate) Remove(c *cli.Context) error {
name := c.String("device")

url := u.Url(c.String("url"), name)
clt := u.NewHttp(c.String("token"))
if err := clt.DeleteJSON(url, nil, nil); err != nil {
return err
}
return nil
}

func (u Rate) Commands(app *api.App) {
app.Command(&cli.Command{
Name: "rate",
Usage: "Rate Limit",
Subcommands: []*cli.Command{
{
Name: "list",
Usage: "Display all rate limits",
Aliases: []string{"ls"},
Action: u.List,
},
{
Name: "add",
Usage: "Add a rate limit",
Flags: []cli.Flag{
&cli.StringFlag{Name: "device", Required: true},
&cli.StringFlag{Name: "speed", Required: true},
},
Action: u.Add,
},
{
Name: "remove",
Usage: "Remove a rate limit",
Aliases: []string{"rm"},
Flags: []cli.Flag{
&cli.StringFlag{Name: "device", Required: true},
},
Action: u.Remove,
},
},
})
}
10 changes: 8 additions & 2 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
"github.com/luscis/openlan/pkg/schema"
)

type Rater interface {
AddRate(device string, mbit int)
DelRate(device string)
}

type Switcher interface {
UUID() string
UpTime() int64
Expand All @@ -20,6 +25,7 @@ type Switcher interface {
AddNetwork(network string)
DelNetwork(network string)
SaveNetwork(network string)
Rater
}

func NewWorkerSchema(s Switcher) schema.Worker {
Expand Down Expand Up @@ -89,8 +95,6 @@ type Super interface {
Start(v Switcher)
Stop()
Reload(v Switcher)
DoZTrust()
UndoZTrust()
}

type Networker interface {
Expand All @@ -108,6 +112,8 @@ type Networker interface {
Qoser() Qoser
ACLer() ACLer
FindHoper() FindHoper
DoZTrust()
UndoZTrust()
}

type IPSecer interface {
Expand Down
35 changes: 35 additions & 0 deletions pkg/api/rate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package api

import (
"net/http"

"github.com/gorilla/mux"
"github.com/luscis/openlan/pkg/schema"
)

type Rate struct {
Switcher Switcher
}

func (h Rate) Router(router *mux.Router) {
router.HandleFunc("/api/interface/{id}/rate", h.Post).Methods("POST")
router.HandleFunc("/api/interface/{id}/rate", h.Delete).Methods("DELETE")
}

func (h Rate) Post(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
device := vars["id"]

rate := &schema.Rate{}
if err := GetData(r, rate); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
h.Switcher.AddRate(device, rate.Speed)
}

func (h Rate) Delete(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
device := vars["id"]
h.Switcher.DelRate(device)
}
2 changes: 1 addition & 1 deletion pkg/api/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ func Add(router *mux.Router, switcher Switcher) {
Device{}.Router(router)
VPNClient{}.Router(router)
PProf{}.Router(router)
VxLAN{}.Router(router)
Config{Switcher: switcher}.Router(router)
Version{}.Router(router)
Log{}.Router(router)
Expand All @@ -26,4 +25,5 @@ func Add(router *mux.Router, switcher Switcher) {
Route{Switcher: switcher}.Router(router)
IPSec{}.Router(router)
FindHop{}.Router(router)
Rate{Switcher: switcher}.Router(router)
}
20 changes: 0 additions & 20 deletions pkg/api/vxlan.go

This file was deleted.

6 changes: 6 additions & 0 deletions pkg/schema/rate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package schema

type Rate struct {
Device string `json:"device"`
Speed int `json:"speed"` // Mbit
}
19 changes: 19 additions & 0 deletions pkg/switch/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cswitch

import (
"encoding/json"
"fmt"
"os"
"strings"
"sync"
Expand Down Expand Up @@ -599,3 +600,21 @@ func (v *Switch) Reload() {
func (v *Switch) Save() {
v.cfg.Save()
}

func (v *Switch) AddRate(device string, mbit int) {
kbits := fmt.Sprintf("%dMbit", mbit)
burst := "64Kb"
latency := "400ms"

out, err := libol.Exec("tc", "qdisc", "add", "dev", device, "root", "tbf", "rate", kbits, "burst", burst, "latency", latency)
if err != nil {
v.out.Warn("Switch.AddRate: %s %d %s", device, mbit, out)
}
}

func (v *Switch) DelRate(device string) {
out, err := libol.Exec("tc", "qdisc", "del", "dev", device, "root")
if err != nil {
v.out.Warn("Switch.AddRate: %s %s", device, out)
}
}

0 comments on commit a0f3e13

Please sign in to comment.