summaryrefslogtreecommitdiffstats
path: root/extras/hs-test/netconfig.go
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2022-08-09 14:44:47 +0000
committerFlorin Coras <florin.coras@gmail.com>2022-09-19 21:00:18 +0000
commit229f5fcf188cf710f4a8fb269d92f1a1d04a99da (patch)
treebc2c85a49bac6aea4e5ef3304c356acb75ad9493 /extras/hs-test/netconfig.go
parent6cacc94de3984d9f0cf6d562a27d89a4ab0a89f9 (diff)
misc: add test framework for host stack
Type: feature Signed-off-by: Filip Tehlar <ftehlar@cisco.com> Change-Id: I5a64a2c095cae3a4d5f8fdc73e624b010339ec8e
Diffstat (limited to 'extras/hs-test/netconfig.go')
-rwxr-xr-xextras/hs-test/netconfig.go283
1 files changed, 283 insertions, 0 deletions
diff --git a/extras/hs-test/netconfig.go b/extras/hs-test/netconfig.go
new file mode 100755
index 00000000000..f3f3c1b2fcb
--- /dev/null
+++ b/extras/hs-test/netconfig.go
@@ -0,0 +1,283 @@
+package main
+
+import (
+ "errors"
+ "fmt"
+ "os/exec"
+)
+
+type NetType string
+
+const (
+ NetNs NetType = "netns"
+ Veth = "veth"
+ Tap = "tap"
+)
+
+type NetConfig struct {
+ Configure func() error
+ Unconfigure func()
+}
+
+type NetTopology []NetConfig
+
+func (t *NetTopology) Configure() error {
+ for _, c := range *t {
+ err := c.Configure()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (t *NetTopology) Unconfigure() {
+ for _, c := range *t {
+ c.Unconfigure()
+ }
+}
+
+func newConfigFn(cfg NetDevConfig) func() error {
+ t := cfg["type"]
+ if t == "netns" {
+ return func() error { return AddNetns(cfg["name"].(string)) }
+ } else if t == "veth" {
+ return func() error {
+ var peerNs string
+ peer := cfg["peer"].(NetDevConfig)
+ peerName := peer["name"].(string)
+ err := AddVethPair(cfg["name"].(string), peerName)
+ if err != nil {
+ return err
+ }
+
+ if peer["netns"] != nil {
+ peerNs = peer["netns"].(string)
+ if peerNs != "" {
+ err := LinkSetNetns(peerName, peerNs)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ if peer["ip4"] != nil {
+ err = AddAddress(peerName, peer["ip4"].(string), peerNs)
+ if err != nil {
+ return fmt.Errorf("failed to add configure address for %s: %v", peerName, err)
+ }
+ }
+ return nil
+ }
+ } else if t == "bridge" {
+ return func() error { return configureBridge(cfg) }
+ } else if t == "tap" {
+ return func() error { return configureTap(cfg) }
+ }
+ return nil
+}
+
+func newUnconfigFn(cfg NetDevConfig) func() {
+ t := cfg["type"]
+ name := cfg["name"].(string)
+
+ if t == "tap" {
+ return func() { DelLink(name) }
+ } else if t == "netns" {
+ return func() { DelNetns(name) }
+ } else if t == "veth" {
+ return func() { DelLink(name) }
+ } else if t == "bridge" {
+ return func() { DelBridge(name, cfg["netns"].(string)) }
+ }
+ return nil
+}
+
+func NewNetConfig(cfg NetDevConfig) NetConfig {
+ var nc NetConfig
+
+ nc.Configure = newConfigFn(cfg)
+ nc.Unconfigure = newUnconfigFn(cfg)
+
+ return nc
+}
+
+func DelBridge(brName, ns string) error {
+ err := SetDevDown(brName, ns)
+ if err != err {
+ return err
+ }
+
+ err = addDelBridge(brName, ns, false)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func configureBridge(dev NetDevConfig) error {
+ var ifs []string
+ for _, v := range dev["interfaces"].([]interface{}) {
+ ifs = append(ifs, v.(string))
+ }
+ return AddBridge(dev["name"].(string), ifs, dev["netns"].(string))
+}
+
+func configureTap(dev NetDevConfig) error {
+ return AddTap(dev["name"].(string), dev["ip4"].(string))
+}
+
+func SetDevUp(dev, ns string) error {
+ return setDevUpDown(dev, ns, true)
+}
+
+func SetDevDown(dev, ns string) error {
+ return setDevUpDown(dev, ns, false)
+}
+
+func AddTap(ifName, ifAddress string) error {
+ cmd := exec.Command("ip", "tuntap", "add", ifName, "mode", "tap")
+ o, err := cmd.CombinedOutput()
+ if err != nil {
+ s := fmt.Sprintf("error creating tap %s: %v: %s", ifName, err, string(o))
+ return errors.New(s)
+ }
+
+ cmd = exec.Command("ip", "addr", "add", ifAddress, "dev", ifName)
+ err = cmd.Run()
+ if err != nil {
+ DelLink(ifName)
+ s := fmt.Sprintf("error setting addr for tap %s: %v", ifName, err)
+ return errors.New(s)
+ }
+
+ err = SetDevUp(ifName, "")
+ if err != nil {
+ DelLink(ifName)
+ return err
+ }
+ return nil
+}
+
+func DelLink(ifName string) {
+ cmd := exec.Command("ip", "link", "del", ifName)
+ cmd.Run()
+}
+
+func setDevUpDown(dev, ns string, isUp bool) error {
+ var op string
+ if isUp {
+ op = "up"
+ } else {
+ op = "down"
+ }
+ c := []string{"ip", "link", "set", "dev", dev, op}
+ cmd := appendNetns(c, ns)
+ err := cmd.Run()
+ if err != nil {
+ s := fmt.Sprintf("error bringing %s device %s!", dev, op)
+ return errors.New(s)
+ }
+ return nil
+}
+
+func AddVethPair(ifName, peerName string) error {
+ cmd := exec.Command("ip", "link", "add", ifName, "type", "veth", "peer", "name", peerName)
+ err := cmd.Run()
+ if err != nil {
+ return fmt.Errorf("creating veth pair failed: %v", err)
+ }
+ err = SetDevUp(ifName, "")
+ if err != nil {
+ return fmt.Errorf("set link up failed: %v", err)
+ }
+ return nil
+}
+
+func addDelNetns(name string, isAdd bool) error {
+ var op string
+ if isAdd {
+ op = "add"
+ } else {
+ op = "del"
+ }
+ cmd := exec.Command("ip", "netns", op, name)
+ _, err := cmd.CombinedOutput()
+ if err != nil {
+ return errors.New("add/del netns failed")
+ }
+ return nil
+}
+
+func AddNetns(nsName string) error {
+ return addDelNetns(nsName, true)
+}
+
+func DelNetns(nsName string) error {
+ return addDelNetns(nsName, false)
+}
+
+func LinkSetNetns(ifName, ns string) error {
+ cmd := exec.Command("ip", "link", "set", "dev", ifName, "up", "netns", ns)
+ err := cmd.Run()
+ if err != nil {
+ return fmt.Errorf("error setting device '%s' to netns '%s: %v", ifName, ns, err)
+ }
+ return nil
+}
+
+func NewCommand(s []string, ns string) *exec.Cmd {
+ return appendNetns(s, ns)
+}
+
+func appendNetns(s []string, ns string) *exec.Cmd {
+ var cmd *exec.Cmd
+ if ns == "" {
+ // use default namespace
+ cmd = exec.Command(s[0], s[1:]...)
+ } else {
+ var args = []string{"netns", "exec", ns}
+ args = append(args, s[:]...)
+ cmd = exec.Command("ip", args...)
+ }
+ return cmd
+}
+
+func addDelBridge(brName, ns string, isAdd bool) error {
+ var op string
+ if isAdd {
+ op = "addbr"
+ } else {
+ op = "delbr"
+ }
+ var c = []string{"brctl", op, brName}
+ cmd := appendNetns(c, ns)
+ err := cmd.Run()
+ if err != nil {
+ s := fmt.Sprintf("%s %s failed!", op, brName)
+ return errors.New(s)
+ }
+ return nil
+}
+
+func AddBridge(brName string, ifs []string, ns string) error {
+ err := addDelBridge(brName, ns, true)
+ if err != nil {
+ return err
+ }
+
+ for _, v := range ifs {
+ c := []string{"brctl", "addif", brName, v}
+ cmd := appendNetns(c, ns)
+ err = cmd.Run()
+ if err != nil {
+ s := fmt.Sprintf("error adding %s to bridge %s: %v", v, brName, err)
+ return errors.New(s)
+ }
+ }
+ err = SetDevUp(brName, ns)
+ if err != nil {
+ return err
+ }
+ return nil
+}