diff --git a/examples/rpc-service/rpc_service.go b/examples/rpc-service/rpc_service.go index 71dadbfb..101fe367 100644 --- a/examples/rpc-service/rpc_service.go +++ b/examples/rpc-service/rpc_service.go @@ -22,12 +22,16 @@ import ( "fmt" "io" "log" - "strings" + "net" + "os" + "sync" "go.fd.io/govpp" "go.fd.io/govpp/adapter/socketclient" "go.fd.io/govpp/api" interfaces "go.fd.io/govpp/binapi/interface" + "go.fd.io/govpp/binapi/interface_types" + "go.fd.io/govpp/binapi/ip_types" "go.fd.io/govpp/binapi/vpe" ) @@ -47,40 +51,153 @@ func main() { } defer conn.Disconnect() - showVersion(conn) - interfaceDump(conn) + getVppInfo(conn) + idx := createLoopback(conn) + listInterfaces(conn) + addIPAddress(conn, idx) + watchInterfaceEvents(conn, idx) } -// showVersion shows an example of simple request with services. -func showVersion(conn api.Connection) { +func getVppInfo(conn api.Connection) { c := vpe.NewServiceClient(conn) version, err := c.ShowVersion(context.Background(), &vpe.ShowVersion{}) if err != nil { - log.Fatalln("ERROR: ShowVersion failed:", err) + log.Fatalln("ERROR: getting VPP version failed:", err) } + fmt.Printf("VPP Version: %v\n", version.Version) - fmt.Printf("Version: %v\n", version.Version) + systime, err := c.ShowVpeSystemTime(context.Background(), &vpe.ShowVpeSystemTime{}) + if err != nil { + log.Fatalln("ERROR: getting system time failed:", err) + } + fmt.Printf("System Time: %v\n", systime.VpeSystemTime) } -// interfaceDump shows an example of multi request with services. -func interfaceDump(conn api.Connection) { +func createLoopback(conn api.Connection) interface_types.InterfaceIndex { c := interfaces.NewServiceClient(conn) - stream, err := c.SwInterfaceDump(context.Background(), &interfaces.SwInterfaceDump{}) + reply, err := c.CreateLoopback(context.Background(), &interfaces.CreateLoopback{}) if err != nil { - log.Fatalln("ERROR: DumpSwInterface failed:", err) + log.Fatalln("ERROR: creating loopback failed:", err) } + fmt.Printf("Loopback interface created: %v\n", reply.SwIfIndex) + + return reply.SwIfIndex +} + +func listInterfaces(conn api.Connection) { + c := interfaces.NewServiceClient(conn) - fmt.Println("Dumping interfaces") + stream, err := c.SwInterfaceDump(context.Background(), &interfaces.SwInterfaceDump{ + SwIfIndex: ^interface_types.InterfaceIndex(0), + }) + if err != nil { + log.Fatalln("ERROR: listing interfaces failed:", err) + } for { iface, err := stream.Recv() if err == io.EOF { break } if err != nil { - log.Fatalln("ERROR: DumpSwInterface failed:", err) + log.Fatalln("ERROR: receiving interface list failed:", err) + } + fmt.Printf("- interface: %s (index: %v)\n", iface.InterfaceName, iface.SwIfIndex) + } +} + +func addIPAddress(conn api.Connection, ifIdx interface_types.InterfaceIndex) { + c := interfaces.NewServiceClient(conn) + + addr := ip_types.NewAddress(net.IPv4(10, 10, 0, byte(ifIdx))) + + _, err := c.SwInterfaceAddDelAddress(context.Background(), &interfaces.SwInterfaceAddDelAddress{ + SwIfIndex: ifIdx, + IsAdd: true, + Prefix: ip_types.AddressWithPrefix{Address: addr, Len: 32}, + }) + if err != nil { + log.Fatalln("ERROR: adding IP address failed:", err) + } + + fmt.Printf("IP address %v added\n", addr) +} + +func watchInterfaceEvents(conn api.Connection, index interface_types.InterfaceIndex) { + c := interfaces.NewServiceClient(conn) + + // start watcher for specific event message + watcher, err := conn.WatchEvent(context.Background(), (*interfaces.SwInterfaceEvent)(nil)) + if err != nil { + log.Fatalln("ERROR: watching interface events failed:", err) + } + + // enable interface events in VPP + _, err = c.WantInterfaceEvents(context.Background(), &interfaces.WantInterfaceEvents{ + PID: uint32(os.Getpid()), + EnableDisable: 1, + }) + if err != nil { + log.Fatalln("ERROR: enabling interface events failed:", err) + } + + fmt.Printf("watching interface events for index %d\n", index) + + var wg sync.WaitGroup + + // receive notifications + wg.Add(1) + go func() { + defer wg.Done() + for notif := range watcher.Events() { + e := notif.(*interfaces.SwInterfaceEvent) + fmt.Printf("incoming interface event: %+v\n", e) } - fmt.Printf("- interface: %s\n", strings.Trim(iface.InterfaceName, "\x00")) + fmt.Println("watcher done") + }() + + // generate some events in VPP + setInterfaceStatus(conn, index, true) + setInterfaceStatus(conn, index, false) + + // disable interface events in VPP + _, err = c.WantInterfaceEvents(context.Background(), &interfaces.WantInterfaceEvents{ + PID: uint32(os.Getpid()), + EnableDisable: 0, + }) + if err != nil { + log.Fatalln("ERROR: disabling interface events failed:", err) + } + + // close watcher to stop receiving notifications + watcher.Close() + + // generate ignored events in VPP + setInterfaceStatus(conn, index, true) + + wg.Wait() +} + +func setInterfaceStatus(conn api.Connection, ifIdx interface_types.InterfaceIndex, up bool) { + c := interfaces.NewServiceClient(conn) + + var flags interface_types.IfStatusFlags + if up { + flags = interface_types.IF_STATUS_API_FLAG_ADMIN_UP + } else { + flags = 0 + } + _, err := c.SwInterfaceSetFlags(context.Background(), &interfaces.SwInterfaceSetFlags{ + SwIfIndex: ifIdx, + Flags: flags, + }) + if err != nil { + log.Fatalln("ERROR: setting interface flags failed:", err) + } + if up { + fmt.Printf("interface status set to UP") + } else { + fmt.Printf("interface status set to DOWN") } } diff --git a/examples/simple-client/simple_client.go b/examples/simple-client/simple_client.go index 515219d4..85b39572 100644 --- a/examples/simple-client/simple_client.go +++ b/examples/simple-client/simple_client.go @@ -21,7 +21,9 @@ import ( "flag" "fmt" "log" + "net" "os" + "sync" "go.fd.io/govpp" "go.fd.io/govpp/adapter/socketclient" @@ -42,27 +44,26 @@ func main() { flag.Parse() fmt.Println("Starting simple client example") - fmt.Println() - // connect to VPP asynchronously + // connect to VPP conn, connEv, err := govpp.AsyncConnect(*sockAddr, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval) if err != nil { log.Fatalln("ERROR:", err) } defer conn.Disconnect() - // wait for Connected event e := <-connEv if e.State != core.Connected { log.Fatalln("ERROR: connecting to VPP failed:", e.Error) } - // check compatibility of used messages + // check message compatibility ch, err := conn.NewAPIChannel() if err != nil { log.Fatalln("ERROR: creating channel failed:", err) } defer ch.Close() + if err := ch.CheckCompatiblity(vpe.AllMessages()...); err != nil { log.Fatalf("compatibility check failed: %v", err) } @@ -73,26 +74,21 @@ func main() { // process errors encountered during the example defer func() { if len(errors) > 0 { - fmt.Printf("finished with %d errors\n", len(errors)) - os.Exit(1) - } else { - fmt.Println("finished successfully") + log.Fatalf("finished with %d errors", len(errors)) } }() - // use request/reply (channel API) + // use Channel request/reply (channel API) getVppVersion(ch) getSystemTime(ch) idx := createLoopback(ch) - interfaceDump(ch) + listInterfaces(ch) addIPAddress(ch, idx) - ipAddressDump(ch, idx) - interfaceNotifications(ch, idx) + listIPaddresses(ch, idx) + watchInterfaceEvents(ch, idx) } func getVppVersion(ch api.Channel) { - fmt.Println("Retrieving version..") - req := &vpe.ShowVersion{} reply := &vpe.ShowVersionReply{} @@ -102,13 +98,9 @@ func getVppVersion(ch api.Channel) { } fmt.Printf("VPP version: %q\n", reply.Version) - fmt.Println("OK") - fmt.Println() } func getSystemTime(ch api.Channel) { - fmt.Println("Retrieving system time..") - req := &vpe.ShowVpeSystemTime{} reply := &vpe.ShowVpeSystemTimeReply{} @@ -118,115 +110,87 @@ func getSystemTime(ch api.Channel) { } fmt.Printf("system time: %v\n", reply.VpeSystemTime) - fmt.Println("OK") - fmt.Println() } func createLoopback(ch api.Channel) interface_types.InterfaceIndex { - fmt.Println("Creating loopback interface..") - req := &interfaces.CreateLoopback{} reply := &interfaces.CreateLoopbackReply{} if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { - logError(err, "creating loopback interface") + logError(err, "creating loopback") return 0 } - fmt.Printf("interface index: %v\n", reply.SwIfIndex) - fmt.Println("OK") - fmt.Println() + fmt.Printf("loopback created: %v\n", reply.SwIfIndex) return reply.SwIfIndex } -func interfaceDump(ch api.Channel) { - fmt.Println("Dumping interfaces..") - - n := 0 +func listInterfaces(ch api.Channel) { reqCtx := ch.SendMultiRequest(&interfaces.SwInterfaceDump{ SwIfIndex: ^interface_types.InterfaceIndex(0), }) for { - msg := &interfaces.SwInterfaceDetails{} - stop, err := reqCtx.ReceiveReply(msg) + iface := &interfaces.SwInterfaceDetails{} + stop, err := reqCtx.ReceiveReply(iface) if stop { break } if err != nil { - logError(err, "dumping interfaces") + logError(err, "listing interfaces") return } - n++ - fmt.Printf(" - interface #%d: %+v\n", n, msg) - marshal(msg) + fmt.Printf(" - interface: %+v (ifIndex: %v)\n", iface.InterfaceName, iface.SwIfIndex) + marshal(iface) } fmt.Println("OK") fmt.Println() } -func addIPAddress(ch api.Channel, index interface_types.InterfaceIndex) { - fmt.Printf("Adding IP address to interface index %d\n", index) +func addIPAddress(ch api.Channel, ifIdx interface_types.InterfaceIndex) { + addr := ip_types.NewAddress(net.IPv4(10, 10, 0, byte(ifIdx))) req := &interfaces.SwInterfaceAddDelAddress{ - SwIfIndex: index, + SwIfIndex: ifIdx, IsAdd: true, - Prefix: ip_types.AddressWithPrefix{ - Address: ip_types.Address{ - Af: ip_types.ADDRESS_IP4, - Un: ip_types.AddressUnionIP4(ip_types.IP4Address{10, 10, 0, uint8(index)}), - }, - Len: 32, - }, + Prefix: ip_types.AddressWithPrefix{Address: addr, Len: 32}, } marshal(req) reply := &interfaces.SwInterfaceAddDelAddressReply{} if err := ch.SendRequest(req).ReceiveReply(reply); err != nil { - logError(err, "adding IP address to interface") + logError(err, "adding IP address") return } - - fmt.Println("OK") - fmt.Println() } -func ipAddressDump(ch api.Channel, index interface_types.InterfaceIndex) { - fmt.Printf("Dumping IP addresses for interface index %d..\n", index) - - req := &ip.IPAddressDump{ +func listIPaddresses(ch api.Channel, index interface_types.InterfaceIndex) { + reqCtx := ch.SendMultiRequest(&ip.IPAddressDump{ SwIfIndex: index, - } - reqCtx := ch.SendMultiRequest(req) - + }) for { - msg := &ip.IPAddressDetails{} - stop, err := reqCtx.ReceiveReply(msg) + ipAddr := &ip.IPAddressDetails{} + stop, err := reqCtx.ReceiveReply(ipAddr) if err != nil { - logError(err, "dumping IP addresses") + logError(err, "listing IP addresses") return } if stop { break } - fmt.Printf(" - ip address: %+v\n", msg) - marshal(msg) + fmt.Printf(" - IP address: %+v\n", ipAddr) + marshal(ipAddr) } - - fmt.Println("OK") - fmt.Println() } -// interfaceNotifications shows the usage of notification API. Note that for notifications, +// watchInterfaceEvents shows the usage of notification API. Note that for notifications, // you are supposed to create your own Go channel with your preferred buffer size. If the channel's // buffer is full, the notifications will not be delivered into it. -func interfaceNotifications(ch api.Channel, index interface_types.InterfaceIndex) { - fmt.Printf("Subscribing to notificaiton events for interface index %d\n", index) - +func watchInterfaceEvents(ch api.Channel, index interface_types.InterfaceIndex) { notifChan := make(chan api.Message, 100) - // subscribe for specific notification message + // subscribe for specific event message sub, err := ch.SubscribeNotification(notifChan, &interfaces.SwInterfaceEvent{}) if err != nil { logError(err, "subscribing to interface events") @@ -243,32 +207,25 @@ func interfaceNotifications(ch api.Channel, index interface_types.InterfaceIndex return } + fmt.Printf("subscribed to interface events for index %d\n", index) + + var wg sync.WaitGroup + // receive notifications + wg.Add(1) go func() { + defer wg.Done() for notif := range notifChan { e := notif.(*interfaces.SwInterfaceEvent) - fmt.Printf("incoming event: %+v\n", e) + fmt.Printf("incoming interface event: %+v\n", e) marshal(e) } + fmt.Println("watcher done") }() // generate some events in VPP - err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP, - }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}) - if err != nil { - logError(err, "setting interface flags") - return - } - err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: 0, - }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}) - if err != nil { - logError(err, "setting interface flags") - return - } + setInterfaceStatus(ch, index, true) + setInterfaceStatus(ch, index, false) // disable interface events in VPP err = ch.SendRequest(&interfaces.WantInterfaceEvents{ @@ -276,19 +233,41 @@ func interfaceNotifications(ch api.Channel, index interface_types.InterfaceIndex EnableDisable: 0, }).ReceiveReply(&interfaces.WantInterfaceEventsReply{}) if err != nil { - logError(err, "setting interface flags") + logError(err, "disabling interface events") return } - // unsubscribe from delivery of the notifications + // unsubscribe from receiving events err = sub.Unsubscribe() if err != nil { logError(err, "unsubscribing from interface events") return } - fmt.Println("OK") - fmt.Println() + // generate ignored events in VPP + setInterfaceStatus(ch, index, true) + + wg.Wait() +} + +func setInterfaceStatus(ch api.Channel, ifIdx interface_types.InterfaceIndex, up bool) { + var flags interface_types.IfStatusFlags + if up { + flags = interface_types.IF_STATUS_API_FLAG_ADMIN_UP + } else { + flags = 0 + } + if err := ch.SendRequest(&interfaces.SwInterfaceSetFlags{ + SwIfIndex: ifIdx, + Flags: flags, + }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}); err != nil { + log.Fatalln("ERROR: setting interface flags failed:", err) + } + if up { + fmt.Printf("interface status set to UP") + } else { + fmt.Printf("interface status set to DOWN") + } } func marshal(v interface{}) { diff --git a/examples/stream-client/stream_client.go b/examples/stream-client/stream_client.go index 40eaedb9..49249f59 100644 --- a/examples/stream-client/stream_client.go +++ b/examples/stream-client/stream_client.go @@ -21,7 +21,9 @@ import ( "flag" "fmt" "log" + "net" "os" + "sync" "time" "go.fd.io/govpp" @@ -45,7 +47,6 @@ func main() { flag.Parse() fmt.Println("Starting stream client example") - fmt.Println() // connect to VPP asynchronously conn, connEv, err := govpp.AsyncConnect(*sockAddr, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval) @@ -96,68 +97,71 @@ func main() { logError(err, "closing the stream") } }() + getVppVersion(stream) idx := createLoopback(stream) interfaceDump(stream) addIPAddress(stream, idx) - //ipAddressDump(stream, idx) - //mactimeDump(stream) - interfaceNotifications(conn, stream, idx) + ipAddressDump(stream, idx) + mactimeDump(stream) + interfaceNotifications(conn, idx) } func getVppVersion(stream api.Stream) { - fmt.Println("Retrieving version..") + fmt.Println("Retrieving version") - req := &vpe.ShowVersion{} - if err := stream.SendMsg(req); err != nil { - logError(err, "ShowVersion sending message") + if err := stream.SendMsg(&vpe.ShowVersion{}); err != nil { + logError(err, "get version request") return } - recv, err := stream.RecvMsg() + recvMsg, err := stream.RecvMsg() if err != nil { - logError(err, "ShowVersion receive message") + logError(err, "get version reply") + return + } + reply := recvMsg.(*vpe.ShowVersionReply) + if api.RetvalToVPPApiError(reply.Retval) != nil { + logError(err, "get version reply retval") return } - recvMsg := recv.(*vpe.ShowVersionReply) - fmt.Printf("Retrieved VPP version: %q\n", recvMsg.Version) - fmt.Println("OK") - fmt.Println() + fmt.Printf("VPP version: %v\n", reply.Version) } func createLoopback(stream api.Stream) (ifIdx interface_types.InterfaceIndex) { - fmt.Println("Creating the loopback interface..") + fmt.Println("Creating loopback interface..") - req := &interfaces.CreateLoopback{} - if err := stream.SendMsg(req); err != nil { - logError(err, "CreateLoopback sending message") + if err := stream.SendMsg(&interfaces.CreateLoopback{}); err != nil { + logError(err, "create loopback request") return } recv, err := stream.RecvMsg() if err != nil { - logError(err, "CreateLoopback receive message") + logError(err, "create loopback reply") + return + } + reply := recv.(*interfaces.CreateLoopbackReply) + if api.RetvalToVPPApiError(reply.Retval) != nil { + logError(err, "create loopback reply retval") return } - recvMsg := recv.(*interfaces.CreateLoopbackReply) - fmt.Printf("Loopback interface index: %v\n", recvMsg.SwIfIndex) - fmt.Println("OK") - fmt.Println() + fmt.Printf("Loopback interface created: %v\n", reply.SwIfIndex) - return recvMsg.SwIfIndex + return reply.SwIfIndex } func interfaceDump(stream api.Stream) { - fmt.Println("Dumping interfaces..") + fmt.Println("Listing interfaces") if err := stream.SendMsg(&interfaces.SwInterfaceDump{ SwIfIndex: ^interface_types.InterfaceIndex(0), }); err != nil { - logError(err, "SwInterfaceDump sending message") + logError(err, "list interfaces request") return } if err := stream.SendMsg(&memclnt.ControlPing{}); err != nil { - logError(err, "ControlPing sending message") + logError(err, "ControlPing request") return } @@ -165,16 +169,16 @@ Loop: for { msg, err := stream.RecvMsg() if err != nil { - logError(err, "SwInterfaceDump receiving message ") + logError(err, "receiving interface list") return } - switch msg.(type) { + switch m := msg.(type) { case *interfaces.SwInterfaceDetails: - fmt.Printf(" - SwInterfaceDetails: %+v\n", msg) + fmt.Printf("- interface: %s (index: %v)\n", m.InterfaceName, m.SwIfIndex) case *memclnt.ControlPingReply: - fmt.Printf(" - ControlPingReply: %+v\n", msg) + fmt.Printf(" - ControlPingReply: %+v\n", m) break Loop default: @@ -182,52 +186,47 @@ Loop: return } } - - fmt.Println("OK") - fmt.Println() } func addIPAddress(stream api.Stream, index interface_types.InterfaceIndex) { - fmt.Printf("Adding IP address to the interface index %d..\n", index) + addr := ip_types.NewAddress(net.IPv4(10, 10, 0, byte(index))) + + fmt.Printf("Adding IP address %v to interface (index %d)\n", addr, index) if err := stream.SendMsg(&interfaces.SwInterfaceAddDelAddress{ SwIfIndex: index, IsAdd: true, - Prefix: ip_types.AddressWithPrefix{ - Address: ip_types.Address{ - Af: ip_types.ADDRESS_IP4, - Un: ip_types.AddressUnionIP4(ip_types.IP4Address{10, 10, 0, uint8(index)}), - }, - Len: 32, - }, + Prefix: ip_types.AddressWithPrefix{Address: addr, Len: 32}, }); err != nil { - logError(err, "SwInterfaceAddDelAddress sending message") + logError(err, "add IP address request") return } recv, err := stream.RecvMsg() if err != nil { - logError(err, "SwInterfaceAddDelAddressReply receiving message") + logError(err, "add IP address reply") + return + } + reply := recv.(*interfaces.SwInterfaceAddDelAddressReply) + if api.RetvalToVPPApiError(reply.Retval) != nil { + logError(err, "add IP address reply retval") return } - recvMsg := recv.(*interfaces.SwInterfaceAddDelAddressReply) - fmt.Printf("Added IP address to interface: %v (return value: %d)\n", index, recvMsg.Retval) - fmt.Println("OK") - fmt.Println() + fmt.Printf("IP address %v added\n", addr) } func ipAddressDump(stream api.Stream, index interface_types.InterfaceIndex) { - fmt.Printf("Dumping IP addresses for interface index %d..\n", index) + fmt.Printf("Listing IP addresses for interface (index %d)\n", index) if err := stream.SendMsg(&ip.IPAddressDump{ SwIfIndex: index, }); err != nil { - logError(err, "IPAddressDump sending message") + logError(err, "dump IP address request") return } if err := stream.SendMsg(&memclnt.ControlPing{}); err != nil { - logError(err, "ControlPing sending sending message") + logError(err, "sending ControlPing") return } @@ -235,7 +234,7 @@ Loop: for { msg, err := stream.RecvMsg() if err != nil { - logError(err, "IPAddressDump receiving message ") + logError(err, "receiving IP addresses") return } @@ -252,18 +251,15 @@ Loop: return } } - - fmt.Println("OK") - fmt.Println() } // Mactime dump uses MactimeDumpReply message as an end of the stream // notification instead of the control ping. func mactimeDump(stream api.Stream) { - fmt.Println("Sending mactime dump..") + fmt.Println("Sending mactime dump") if err := stream.SendMsg(&mactime.MactimeDump{}); err != nil { - logError(err, "sending mactime dump") + logError(err, "mactime dump request") return } @@ -271,16 +267,20 @@ Loop: for { msg, err := stream.RecvMsg() if err != nil { - logError(err, "MactimeDump receiving message") + logError(err, "receiving mactime dump") return } - switch msg.(type) { + switch m := msg.(type) { case *mactime.MactimeDetails: - fmt.Printf(" - MactimeDetails: %+v\n", msg) + fmt.Printf(" - MactimeDetails: %+v\n", m) case *mactime.MactimeDumpReply: - fmt.Printf(" - MactimeDumpReply: %+v\n", msg) + if err := api.RetvalToVPPApiError(m.Retval); err != nil && err != api.NO_CHANGE { + logError(err, "mactime dump reply retval") + return + } + fmt.Printf(" - MactimeDumpReply: %+v\n", m) break Loop default: @@ -288,180 +288,87 @@ Loop: return } } - - fmt.Println("OK") - fmt.Println() } // interfaceNotifications shows the usage of notification API. Note that for notifications, // you are supposed to create your own Go channel with your preferred buffer size. If the channel's // buffer is full, the notifications will not be delivered into it. -func interfaceNotifications(conn api.Connection, stream api.Stream, index interface_types.InterfaceIndex) { - fmt.Printf("Subscribing to notificaiton events for interface index %d\n", index) +func interfaceNotifications(conn api.Connection, index interface_types.InterfaceIndex) { - ctx := context.Background() - - watcher, err := conn.WatchEvent(ctx, (*interfaces.SwInterfaceEvent)(nil)) + // start watcher for specific event message + watcher, err := conn.WatchEvent(context.Background(), (*interfaces.SwInterfaceEvent)(nil)) if err != nil { - logError(err, "watch interface events") + logError(err, "watching interface events") return - } else { - fmt.Println("watching events OK") } - //notifChan := make(chan api.Message, 100) - - // subscribe for specific notification message - /*sub, err := ch.SubscribeNotification(notifChan, (*interfaces.SwInterfaceEvent)(nil)) - if err != nil { - logError(err, "subscribing to interface events") - return - } else { - fmt.Println("subscribed to notifications OK") - }*/ - - // enable interface events in VPP - /*err = ch.SendRequest(&interfaces.WantInterfaceEvents{ - PID: 0, - EnableDisable: 1, - }).ReceiveReply(&interfaces.WantInterfaceEventsReply{}) - if err != nil { - logError(err, "enabling interface events") - return - } else { - fmt.Println("enabled interface events OK") - }*/ // enable interface events in VPP var reply interfaces.WantInterfaceEventsReply - if err := conn.Invoke(ctx, &interfaces.WantInterfaceEvents{ - //PID: uint32(os.Getpid()), + err = conn.Invoke(context.Background(), &interfaces.WantInterfaceEvents{ + PID: uint32(os.Getpid()), EnableDisable: 1, - }, &reply); err != nil { + }, &reply) + if err != nil || api.RetvalToVPPApiError(reply.Retval) != nil { logError(err, "enabling interface events") return - } else { - fmt.Println("enabled interface events OK") } - /*err = ch.SendRequest(&interfaces.WantInterfaceEvents{ - //PID: uint32(os.Getpid()), - EnableDisable: 1, - }).ReceiveReply(&interfaces.WantInterfaceEventsReply{}) - if err != nil { - logError(err, "enabling interface events") - return - } else { - fmt.Println("enabled interface events OK") - }*/ + fmt.Printf("watching interface events for index %d\n", index) + + var wg sync.WaitGroup // receive notifications + wg.Add(1) go func() { + defer wg.Done() for notif := range watcher.Events() { e := notif.(*interfaces.SwInterfaceEvent) - fmt.Printf("incoming event: %+v\n", e) + fmt.Printf("incoming interface event: %+v\n", e) } - fmt.Println("all events processed OK") + fmt.Println("watcher done") }() // generate some events in VPP - var setReply interfaces.SwInterfaceSetFlagsReply - if err := conn.Invoke(ctx, &interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP, - }, &setReply); err != nil { - logError(err, "setting interface flags") - return - } else if err = api.RetvalToVPPApiError(setReply.Retval); err != nil { - logError(err, "setting interface flags retval") - return - } - - setReply.Reset() - if err := conn.Invoke(ctx, &interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: 0, - }, &setReply); err != nil { - logError(err, "setting interface flags") - return - } else if err = api.RetvalToVPPApiError(setReply.Retval); err != nil { - logError(err, "setting interface flags retval") - return - } - - /*err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP, - }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}) - if err != nil { - logError(err, "setting interface flags") - return - } - err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: 0, - }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}) - if err != nil { - logError(err, "setting interface flags") - return - }*/ + setInterfaceStatus(conn, index, true) + setInterfaceStatus(conn, index, false) + // disable interface events in VPP reply.Reset() - if err := conn.Invoke(ctx, &interfaces.WantInterfaceEvents{ - //PID: uint32(os.Getpid()), + if err := conn.Invoke(context.Background(), &interfaces.WantInterfaceEvents{ + PID: uint32(os.Getpid()), EnableDisable: 0, - }, &reply); err != nil { + }, &reply); err != nil || api.RetvalToVPPApiError(reply.Retval) != nil { logError(err, "disabling interface events") return - } else { - fmt.Println("disabling interface events OK") } - // disable interface events in VPP - /*err = ch.SendRequest(&interfaces.WantInterfaceEvents{ - //PID: uint32(os.Getpid()), - EnableDisable: 0, - }).ReceiveReply(&interfaces.WantInterfaceEventsReply{}) - if err != nil { - logError(err, "setting interface flags") - return - }*/ + // unsubscribe from delivery of the notifications + watcher.Close() - setReply.Reset() - if err := conn.Invoke(ctx, &interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP, - }, &setReply); err != nil { - logError(err, "setting interface flags") - return - } else if err = api.RetvalToVPPApiError(setReply.Retval); err != nil { - logError(err, "setting interface flags retval") - return - } + // generate ignored events in VPP + setInterfaceStatus(conn, index, true) - /*err = ch.SendRequest(&interfaces.SwInterfaceSetFlags{ - SwIfIndex: index, - Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP, - }).ReceiveReply(&interfaces.SwInterfaceSetFlagsReply{}) - if err != nil { + wg.Wait() +} + +func setInterfaceStatus(conn api.Connection, ifIdx interface_types.InterfaceIndex, up bool) { + var flags interface_types.IfStatusFlags + if up { + flags = interface_types.IF_STATUS_API_FLAG_ADMIN_UP + } else { + flags = 0 + } + var reply interfaces.SwInterfaceSetFlagsReply + if err := conn.Invoke(context.Background(), &interfaces.SwInterfaceSetFlags{ + SwIfIndex: ifIdx, + Flags: flags, + }, &reply); err != nil { logError(err, "setting interface flags") return - } else { - fmt.Println("disabled interface events OK") - }*/ - - // unsubscribe from delivery of the notifications - watcher.Close() - if err != nil { - logError(err, "closing interface events watcher") + } else if err = api.RetvalToVPPApiError(reply.Retval); err != nil { + logError(err, "setting interface flags retval") return - } else { - fmt.Println("closing interface events watcher OK") } - - fmt.Println("OK") - fmt.Println() - - time.Sleep(time.Second) } var errors []error diff --git a/test/integration/examples_test.go b/test/integration/examples_test.go index 9825119f..ec976a0a 100644 --- a/test/integration/examples_test.go +++ b/test/integration/examples_test.go @@ -32,7 +32,7 @@ func TestExamples(t *testing.T) { } example := filepath.Base(d.Name()) t.Run(example, func(tt *testing.T) { - testExample(tt, example) + runExample(tt, example) }) return nil }); err != nil { @@ -40,7 +40,7 @@ func TestExamples(t *testing.T) { } } -func testExample(t *testing.T, example string) { +func runExample(t *testing.T, example string) { vpptesting.SetupVPP(t) cmd := exec.Command("go", "run", "./examples/"+example)