Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements and bug fixes #7

Merged
merged 7 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*log
Vagrantfile
trunk
trunks
trunks_amd64

# Dependency directories (remove the comment below to include it)
Expand Down
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ COMMANDS:
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--config FILE Load configuration from FILE (default: not set)
--flush Flush IPTABLES table mangle and clear all TC rules (default: false)
--acm Activate the ACM simulation (default: not activated)
--qos Process traffic using QoS (default: not activated)
--help, -h show help (default: false)
--config FILE Load configuration from FILE (default: not set)
--logs value Log path for the log file (default: not set)
--flush Flush IPTABLES table mangle and clear all TC rules (default: false)
--acm Activate the ACM simulation (default: not activated)
--qos Process traffic using QoS (default: not activated)
--disable-kernel-version-check Disable check for bugged kernel versions (default: kernel version check enabled)
--help, -h show help (default: false)

```

Expand Down Expand Up @@ -149,4 +151,7 @@ cd container
docker-compose up -d
```

You still must configure the routes inside the client and server containers.
You still must configure the routes inside the client and server containers.

## Known issues
Some versions of the kernel are known to crash when offset delay is enabled. As a protection, offset delay is by default disabled if you are running on affected versions. You can bypass protection by using the flag `--disable-kernel-version-check`, but this is NOT recommended. See [this issue](https://github.com/shynuu/trunks/issues/6) for details.
21 changes: 21 additions & 0 deletions bash-completion/completions/trunks
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#! /bin/bash

: ${PROG:=$(basename ${BASH_SOURCE})}

_cli_bash_autocomplete() {
if [[ "${COMP_WORDS[0]}" != "source" ]]; then
local cur opts base
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ "$cur" == "-"* ]]; then
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
else
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}

complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG
unset PROG
31 changes: 24 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,33 @@ import (
"fmt"
"log"
"os"
"os/signal"
"syscall"

trunks "github.com/shynuu/trunks/runtime"

"github.com/urfave/cli/v2"
)

// Initialize signals handling
func initSignals() {
cancelChan := make(chan os.Signal, 1)
signal.Notify(cancelChan, syscall.SIGTERM, syscall.SIGINT)
func(_ os.Signal) {}(<-cancelChan)
os.Exit(0)
}

func main() {
var config string
var flush bool = false
var acm bool = false
var qos bool = false
var disable_kernel_version_check = false
var logs string

app := &cli.App{
Name: "trunks",
Usage: "a simple DVB-S2/DVB-RCS2 simulator",
Name: "trunks",
Usage: "a simple DVB-S2/DVB-RCS2 simulator",
EnableBashCompletion: true,
Authors: []*cli.Author{
{Name: "Youssouf Drif"},
},
Expand Down Expand Up @@ -55,27 +66,33 @@ func main() {
Destination: &qos,
DefaultText: "not activated",
},
&cli.BoolFlag{
Name: "disable-kernel-version-check",
Usage: "Disable check for bugged kernel versions",
Destination: &disable_kernel_version_check,
DefaultText: "kernel version check enabled",
},
},
Action: func(c *cli.Context) error {
err := trunks.InitTrunks(config, qos, logs)
trunksConfig, err := trunks.InitTrunks(config, qos, logs, acm, disable_kernel_version_check)
if err != nil {
fmt.Println("Init error, exiting...")
os.Exit(1)
}

if flush {
err = trunks.FlushTables()
err = trunksConfig.FlushTables()
if err != nil {
fmt.Println("Impossible to flush tables, exiting...")
os.Exit(1)
}
}

trunks.Run(acm)
trunksConfig.Run()
return nil
},
}

go initSignals()
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
Expand Down
28 changes: 14 additions & 14 deletions runtime/acm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,33 @@ import (
)

// RunACM simulate the used by the DVB-S2/RCS2 system
func RunACM(qos bool) {
if Trunks.CurrentACM == nil || Trunks.ACMCounter >= Trunks.CurrentACM.Duration {
func (t *TrunksConfig) RunACM(qos bool) {
if t.CurrentACM == nil || t.ACMCounter >= t.CurrentACM.Duration {
log.Println("Changing link capacity")
var l = len(Trunks.ACMList)
var l = len(t.ACMList)
rand.Seed(time.Now().UnixNano())
var index int = rand.Intn(l)
Trunks.CurrentACM = Trunks.ACMList[index]
t.CurrentACM = t.ACMList[index]

var forward string
var retun string

if qos {
forward = fmt.Sprintf("%dmbit", int64(math.Round(Trunks.Bandwidth.Forward*Trunks.CurrentACM.Weight))-1)
retun = fmt.Sprintf("%dmbit", int64(math.Round(Trunks.Bandwidth.Return*Trunks.CurrentACM.Weight))-1)
runTC("class", "change", "dev", Trunks.NIC.GW, "parent", "1:0", "classid", "1:20", "htb", "rate", retun, "prio", "1")
runTC("class", "change", "dev", Trunks.NIC.ST, "parent", "1:0", "classid", "1:20", "htb", "rate", forward, "prio", "1")
forward = fmt.Sprintf("%dmbit", int64(math.Round(t.Bandwidth.Forward*t.CurrentACM.Weight))-1)
retun = fmt.Sprintf("%dmbit", int64(math.Round(t.Bandwidth.Return*t.CurrentACM.Weight))-1)
runTC("class", "change", "dev", t.NIC.GW, "parent", "1:0", "classid", "1:20", "htb", "rate", retun, "prio", "1")
runTC("class", "change", "dev", t.NIC.ST, "parent", "1:0", "classid", "1:20", "htb", "rate", forward, "prio", "1")

} else {
forward = fmt.Sprintf("%dmbit", int64(math.Round(Trunks.Bandwidth.Forward*Trunks.CurrentACM.Weight)))
retun = fmt.Sprintf("%dmbit", int64(math.Round(Trunks.Bandwidth.Return*Trunks.CurrentACM.Weight)))
runTC("class", "change", "dev", Trunks.NIC.GW, "parent", "1:0", "classid", "1:1", "htb", "rate", retun)
runTC("class", "change", "dev", Trunks.NIC.ST, "parent", "1:0", "classid", "1:1", "htb", "rate", forward)
forward = fmt.Sprintf("%dmbit", int64(math.Round(t.Bandwidth.Forward*t.CurrentACM.Weight)))
retun = fmt.Sprintf("%dmbit", int64(math.Round(t.Bandwidth.Return*t.CurrentACM.Weight)))
runTC("class", "change", "dev", t.NIC.GW, "parent", "1:0", "classid", "1:1", "htb", "rate", retun)
runTC("class", "change", "dev", t.NIC.ST, "parent", "1:0", "classid", "1:1", "htb", "rate", forward)
}
log.Println("Setting the forward link bandwidth at", forward)
log.Println("Setting the return link bandwidth at", retun)

Trunks.ACMCounter = 0
t.ACMCounter = 0
}
Trunks.ACMCounter++
t.ACMCounter++
}
32 changes: 17 additions & 15 deletions runtime/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import (
)

// ParseConf read the yaml file and populate the Config instancce
func ParseConf(file string) error {
func ParseConf(file string) (*TrunksConfig, error) {
var trunksConfig *TrunksConfig
path, err := filepath.Abs(file)
yamlFile, err := ioutil.ReadFile(path)
if err != nil {
return err
return nil, err
}
err = yaml.Unmarshal(yamlFile, &Trunks)
if err != nil {
return err
if err := yaml.Unmarshal(yamlFile, &trunksConfig); err != nil {
return nil, err
}
return nil
return trunksConfig, nil
}

// Interfaces struct
Expand Down Expand Up @@ -47,13 +47,15 @@ type ACM struct {

// TrunksConfig struct
type TrunksConfig struct {
NIC NIC `yaml:"nic"`
Bandwidth Bandwidth `yaml:"bandwidth"`
Delay Delay `yaml:"delay"`
ACMList []*ACM `yaml:"acm"`
QoS bool
Logs string
ACMCounter int
ACMIndex int
CurrentACM *ACM
NIC NIC `yaml:"nic"`
Bandwidth Bandwidth `yaml:"bandwidth"`
Delay Delay `yaml:"delay"`
ACMList []*ACM `yaml:"acm"`
QoS bool
Logs string
KernelVersionCheck bool
ACMEnabled bool
ACMCounter int
ACMIndex int
CurrentACM *ACM
}
46 changes: 25 additions & 21 deletions runtime/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ func Exists(path string) (bool, error) {
}

// CheckInterfaces checks if the interfaces exist
func CheckInterfaces(st string, gw string) error {
func (t *TrunksConfig) CheckInterfaces() error {
path := "/sys/class/net/%s/operstate"
ifST := fmt.Sprintf(path, st)
ifGW := fmt.Sprintf(path, gw)
ifST := fmt.Sprintf(path, t.NIC.ST)
ifGW := fmt.Sprintf(path, t.NIC.GW)
var err1, err2 error
existST, _ := Exists(ifST)
if !existST {
Expand All @@ -44,9 +44,9 @@ func CheckInterfaces(st string, gw string) error {
return nil
}

func FindInterfaces() error {
ip_st := Trunks.NIC.ST
ip_gw := Trunks.NIC.GW
func (t *TrunksConfig) FindInterfaces() error {
ip_st := t.NIC.ST
ip_gw := t.NIC.GW
ifaces, err := net.Interfaces()
if err != nil {
log.Printf("Error reading interfaces: %+v\n", err.Error())
Expand All @@ -61,24 +61,24 @@ func FindInterfaces() error {
for _, a := range addrs {
switch v := a.(type) {
case *net.IPNet:
if v.IP.To4().String() == Trunks.NIC.GW {
Trunks.NIC.GW = i.Name
if v.IP.To4().String() == t.NIC.GW {
t.NIC.GW = i.Name
}
if v.IP.To4().String() == Trunks.NIC.ST {
Trunks.NIC.ST = i.Name
if v.IP.To4().String() == t.NIC.ST {
t.NIC.ST = i.Name
}
}

}
}

var err1, err2 error
if ip_st == Trunks.NIC.ST {
if ip_st == t.NIC.ST {
err1 = errors.New("[L3] Interface for ST not found")
log.Println(err1.Error())
}

if ip_gw == Trunks.NIC.GW {
if ip_gw == t.NIC.GW {
err2 = errors.New("[L3] Interface for GW not found")
log.Println(err2.Error())
}
Expand All @@ -91,17 +91,21 @@ func FindInterfaces() error {
}

// InitTrunks initialize the trunks module
func InitTrunks(file string, qos bool, logs string) error {
err := ParseConf(file)
func InitTrunks(file string, qos bool, logs string, acm bool, disable_kernel_version_check bool) (*TrunksConfig, error) {
t, err := ParseConf(file)
if err != nil {
return err
return nil, err
}
err = CheckInterfaces(Trunks.NIC.ST, Trunks.NIC.GW)
if err != nil {
if err := t.CheckInterfaces(); err != nil {
log.Println("Interfaces configuration by IP")
err = FindInterfaces()
if err := t.FindInterfaces(); err != nil {
return nil, err
}
}
Trunks.QoS = qos
Trunks.Logs = logs
return err

t.QoS = qos
t.Logs = logs
t.ACMEnabled = acm
t.KernelVersionCheck = !disable_kernel_version_check
return t, nil
}
Loading