import (
"fmt"
"github.com/edwarnicke/exechelper"
+ "os"
+ "os/exec"
+ "os/signal"
"strings"
+ "syscall"
"time"
"go.fd.io/govpp"
const vppConfigTemplate = `unix {
nodaemon
- log %[1]s/var/log/vpp/vpp.log
+ log %[1]s%[4]s
full-coredump
cli-listen %[1]s%[2]s
runtime-dir %[1]s/var/run
plugin http_plugin.so { enable }
}
+logging {
+ default-log-level debug
+ default-syslog-log-level debug
+}
+
`
const (
defaultCliSocketFilePath = "/var/run/vpp/cli.sock"
defaultApiSocketFilePath = "/var/run/vpp/api.sock"
+ defaultLogFilePath = "/var/log/vpp/vpp.log"
)
type VppInstance struct {
containerWorkDir,
defaultCliSocketFilePath,
defaultApiSocketFilePath,
+ defaultLogFilePath,
)
configContent += vpp.additionalConfig.ToString()
startupFileName := vpp.getEtcDir() + "/startup.conf"
vpp.container.createFile(startupFileName, configContent)
- // Start VPP
- vpp.container.execServer("vpp -c " + startupFileName)
+ if *IsVppDebug {
+ sig := make(chan os.Signal, 1)
+ signal.Notify(sig, syscall.SIGINT)
+ cont := make(chan bool, 1)
+ go func() {
+ sig := <-sig
+ fmt.Println(sig)
+ cont <- true
+ }()
+
+ // Start VPP in GDB and wait for user to attach it
+ vpp.container.execServer("su -c \"gdb -ex run --args vpp -c " + startupFileName + " &> /proc/1/fd/1\"")
+ fmt.Println("run following command in different terminal:")
+ fmt.Println("docker exec -it " + vpp.container.name + " gdb -ex \"attach $(docker exec " + vpp.container.name + " pidof gdb)\"")
+ fmt.Println("Afterwards press CTRL+C to continue")
+ <-cont
+ fmt.Println("continuing...")
+ } else {
+ // Start VPP
+ vpp.container.execServer("su -c \"vpp -c " + startupFileName + " &> /proc/1/fd/1\"")
+ }
// Connect to VPP and store the connection
sockAddress := vpp.container.GetHostWorkDir() + defaultApiSocketFilePath
return string(output)
}
-func (vpp *VppInstance) waitForApp(appName string, timeout int) error {
+func (vpp *VppInstance) waitForApp(appName string, timeout int) {
for i := 0; i < timeout; i++ {
o := vpp.vppctl("show app")
if strings.Contains(o, appName) {
- return nil
+ return
}
time.Sleep(1 * time.Second)
}
- return fmt.Errorf("timeout while waiting for app '%s'", appName)
+ vpp.Suite().assertNil(1, "Timeout while waiting for app '%s'", appName)
+ return
}
func (vpp *VppInstance) createAfPacket(
- netInterface NetInterface,
+ veth *NetInterface,
) (interface_types.InterfaceIndex, error) {
- veth := netInterface.(*NetworkInterfaceVeth)
-
createReq := &af_packet.AfPacketCreateV2{
UseRandomHwAddr: true,
HostIfName: veth.Name(),
if veth.AddressWithPrefix() == (AddressWithPrefix{}) {
var err error
var ip4Address string
- if ip4Address, err = veth.addresser.NewIp4Address(veth.peerNetworkNumber); err == nil {
+ if ip4Address, err = veth.addresser.NewIp4Address(veth.Peer().networkNumber); err == nil {
veth.SetAddress(ip4Address)
} else {
return 0, err
}
func (vpp *VppInstance) createTap(
- hostInterfaceName string,
- hostIp4Address IP4AddressWithPrefix,
- vppIp4Address AddressWithPrefix,
+ tap *NetInterface,
+ tapId ...uint32,
) error {
+ var id uint32 = 1
+ if len(tapId) > 0 {
+ id = tapId[0]
+ }
createTapReq := &tapv2.TapCreateV2{
+ ID: id,
HostIfNameSet: true,
- HostIfName: hostInterfaceName,
+ HostIfName: tap.Name(),
HostIP4PrefixSet: true,
- HostIP4Prefix: hostIp4Address,
+ HostIP4Prefix: tap.IP4AddressWithPrefix(),
}
createTapReply := &tapv2.TapCreateV2Reply{}
addAddressReq := &interfaces.SwInterfaceAddDelAddress{
IsAdd: true,
SwIfIndex: createTapReply.SwIfIndex,
- Prefix: vppIp4Address,
+ Prefix: tap.Peer().AddressWithPrefix(),
}
addAddressReply := &interfaces.SwInterfaceAddDelAddressReply{}
return nil
}
+func (vpp *VppInstance) saveLogs() {
+ logTarget := vpp.container.getLogDirPath() + "vppinstance-" + vpp.container.name + ".log"
+ logSource := vpp.container.GetHostWorkDir() + defaultLogFilePath
+ cmd := exec.Command("cp", logSource, logTarget)
+ vpp.Suite().T().Helper()
+ vpp.Suite().log(cmd.String())
+ cmd.Run()
+}
+
func (vpp *VppInstance) disconnect() {
vpp.connection.Disconnect()
vpp.apiChannel.Close()