go.ligato.io/vpp-agent/v3@v3.5.0/examples/grpc_vpp/notifications/main.go (about) 1 // Copyright (c) 2017 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "context" 19 "io" 20 "log" 21 "net" 22 "time" 23 24 "github.com/namsral/flag" 25 "go.ligato.io/cn-infra/v2/agent" 26 "go.ligato.io/cn-infra/v2/infra" 27 "go.ligato.io/cn-infra/v2/logging/logrus" 28 "google.golang.org/grpc" 29 30 "go.ligato.io/vpp-agent/v3/proto/ligato/configurator" 31 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp" 32 vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 33 ) 34 35 var ( 36 address = flag.String("address", "localhost:9111", "address of GRPC server") 37 socketType = flag.String("socket-type", "tcp", "[tcp, tcp4, tcp6, unix, unixpacket]") 38 reqPer = flag.Int("request-period", 3, "notification request period in seconds") 39 ) 40 41 // Start Agent plugins selected for this example. 42 func main() { 43 // Inject dependencies to example plugin 44 ep := &ExamplePlugin{} 45 ep.SetName("remote-client-example") 46 ep.Setup() 47 48 // Start Agent 49 a := agent.NewAgent( 50 agent.AllPlugins(ep), 51 ) 52 if err := a.Run(); err != nil { 53 log.Fatal() 54 } 55 } 56 57 // ExamplePlugin demonstrates the use of grpc to watch on VPP notifications using vpp-agent. 58 type ExamplePlugin struct { 59 infra.PluginDeps 60 61 conn *grpc.ClientConn 62 } 63 64 // Init initializes example plugin. 65 func (p *ExamplePlugin) Init() (err error) { 66 // Set up connection to the server. 67 p.conn, err = grpc.Dial("unix", 68 grpc.WithInsecure(), 69 grpc.WithDialer(dialer(*socketType, *address, 2*time.Second))) 70 71 if err != nil { 72 return err 73 } 74 75 client := configurator.NewConfiguratorServiceClient(p.conn) 76 77 // Start notification watcher. 78 go p.watchNotifications(client) 79 80 logrus.DefaultLogger().Info("Initialization of the example plugin has completed") 81 return err 82 } 83 84 // Get is an implementation of client-side statistics streaming. 85 func (p *ExamplePlugin) watchNotifications(client configurator.ConfiguratorServiceClient) { 86 var nextIdx uint32 87 88 logrus.DefaultLogger().Info("Watching..") 89 for { 90 // Prepare request with the initial index 91 request := &configurator.NotifyRequest{ 92 Idx: nextIdx, 93 Filters: []*configurator.Notification{ 94 {Notification: &configurator.Notification_VppNotification{ 95 VppNotification: &vpp.Notification{ 96 Interface: &vpp_interfaces.InterfaceNotification{ 97 Type: vpp_interfaces.InterfaceNotification_UPDOWN, 98 }, 99 }, 100 }}, 101 }, 102 } 103 104 // Get stream object 105 stream, err := client.Notify(context.Background(), request) 106 if err != nil { 107 logrus.DefaultLogger().Error(err) 108 return 109 } 110 // Receive all message from the stream 111 var recvNotifs int 112 for { 113 notif, err := stream.Recv() 114 if err == io.EOF { 115 if recvNotifs == 0 { 116 //logrus.DefaultLogger().Info("No new notifications") 117 } else { 118 logrus.DefaultLogger().Infof("%d new notifications received", recvNotifs) 119 } 120 break 121 } 122 if err != nil { 123 logrus.DefaultLogger().Error(err) 124 return 125 } 126 127 logrus.DefaultLogger().Infof("Notification[%d]: %v", 128 notif.NextIdx-1, notif.Notification) 129 nextIdx = notif.NextIdx 130 recvNotifs++ 131 } 132 133 logrus.DefaultLogger().Warnf("sleeping..") 134 // Wait till next request 135 time.Sleep(time.Duration(*reqPer) * time.Second) 136 } 137 } 138 139 // Dialer for unix domain socket 140 func dialer(socket, address string, timeoutVal time.Duration) func(string, time.Duration) (net.Conn, error) { 141 return func(addr string, timeout time.Duration) (net.Conn, error) { 142 // Pass values 143 addr, timeout = address, timeoutVal 144 // Dial with timeout 145 return net.DialTimeout(socket, addr, timeoutVal) 146 } 147 }