go.ligato.io/vpp-agent/v3@v3.5.0/examples/govpp_call/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 "log" 19 "time" 20 21 govppapi "go.fd.io/govpp/api" 22 "go.ligato.io/cn-infra/v2/agent" 23 "go.ligato.io/cn-infra/v2/logging" 24 "go.ligato.io/cn-infra/v2/logging/logrus" 25 "go.ligato.io/cn-infra/v2/utils/safeclose" 26 27 "go.ligato.io/vpp-agent/v3/cmd/vpp-agent/app" 28 "go.ligato.io/vpp-agent/v3/plugins/govppmux" 29 l2Api "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/l2" 30 l2 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l2" 31 ) 32 33 // ************************************************************************* 34 // This file contains examples of GOVPP operations, conversion of a proto 35 // data to a binary api message and demonstration of sending the message 36 // to the VPP with: 37 // 38 // requestContext = goVppChannel.SendRequest(requestMessage) 39 // requestContext.ReceiveReply(replyMessage) 40 // 41 // Note: this example shows how to work with VPP, so real proto message 42 // structure is used (bridge domains). 43 // ************************************************************************/ 44 45 // Main allows running Example Plugin as a statically linked binary with Agent Core Plugins. Close channel and plugins 46 // required for the example are initialized. Agent is instantiated with generic plugins (etcd, Kafka, Status check, 47 // HTTP and Log), and GOVPP, and resync plugin, and example plugin which demonstrates GOVPP call functionality. 48 func main() { 49 // Init close channel to stop the example. 50 closeChannel := make(chan struct{}) 51 52 // Inject dependencies to example plugin 53 ep := &ExamplePlugin{ 54 Log: logrus.DefaultLogger(), 55 closeChannel: closeChannel, 56 } 57 ep.Deps.VPP = app.DefaultVPP() 58 ep.Deps.GoVppMux = &govppmux.DefaultPlugin 59 60 // Start Agent 61 a := agent.NewAgent( 62 agent.AllPlugins(ep), 63 agent.QuitOnClose(closeChannel), 64 ) 65 if err := a.Run(); err != nil { 66 log.Fatal() 67 } 68 } 69 70 // PluginName represents name of plugin. 71 const PluginName = "govpp-example" 72 73 // ExamplePlugin implements Plugin interface which is used to pass custom plugin instances to the Agent. 74 type ExamplePlugin struct { 75 Deps 76 77 exampleIDSeq uint32 // Plugin-specific ID initialization 78 vppChannel govppapi.Channel // Vpp channel to communicate with VPP 79 // Fields below are used to properly finish the example. 80 closeChannel chan struct{} 81 Log logging.Logger 82 } 83 84 // Deps is example plugin dependencies. 85 type Deps struct { 86 GoVppMux *govppmux.Plugin 87 VPP app.VPP 88 } 89 90 // Init members of plugin. 91 func (plugin *ExamplePlugin) Init() (err error) { 92 // NewAPIChannel returns a new API channel for communication with VPP via govpp core. 93 // It uses default buffer sizes for the request and reply Go channels. 94 plugin.vppChannel, err = plugin.Deps.GoVppMux.NewAPIChannel() 95 96 plugin.Log.Info("Default plugin plugin ready") 97 98 // Make VPP call 99 go plugin.VppCall() 100 101 return err 102 } 103 104 // Close is called by Agent Core when the Agent is shutting down. It is supposed 105 // to clean up resources that were allocated by the plugin during its lifetime. 106 func (plugin *ExamplePlugin) Close() error { 107 return safeclose.Close(plugin.vppChannel) 108 } 109 110 // String returns plugin name 111 func (plugin *ExamplePlugin) String() string { 112 return PluginName 113 } 114 115 /*********** 116 * VPPCall * 117 ***********/ 118 119 // VppCall uses created data to convert it to the binary api call. In the example, 120 // a bridge domain data are built and transformed to the BridgeDomainAddDel binary api call 121 // which is then sent to the VPP. 122 func (plugin *ExamplePlugin) VppCall() { 123 time.Sleep(3 * time.Second) 124 125 // Prepare a simple data. 126 plugin.Log.Info("Preparing data ...") 127 bds1 := buildData("br1") 128 bds2 := buildData("br2") 129 bds3 := buildData("br3") 130 131 // Prepare binary api message from the data. 132 req1 := buildBinapiMessage(bds1, plugin.exampleIDSeq) 133 plugin.exampleIDSeq++ // Change (raise) index to ensure every message uses unique ID. 134 req2 := buildBinapiMessage(bds2, plugin.exampleIDSeq) 135 plugin.exampleIDSeq++ 136 req3 := buildBinapiMessage(bds3, plugin.exampleIDSeq) 137 plugin.exampleIDSeq++ 138 139 // Generic bin api reply (request: BridgeDomainAddDel) 140 reply := &l2Api.BridgeDomainAddDelReply{} 141 142 plugin.Log.Info("Sending data to VPP ...") 143 144 // 1. Send the request and receive a reply directly (in one line). 145 plugin.vppChannel.SendRequest(req1).ReceiveReply(reply) 146 147 // 2. Send multiple different requests. Every request returns it's own request context. 148 reqCtx2 := plugin.vppChannel.SendRequest(req2) 149 reqCtx3 := plugin.vppChannel.SendRequest(req3) 150 // The context can be used later to get reply. 151 reqCtx2.ReceiveReply(reply) 152 reqCtx3.ReceiveReply(reply) 153 154 plugin.Log.Info("Data successfully sent to VPP") 155 // End the example. 156 plugin.Log.Infof("etcd/datasync example finished, sending shutdown ...") 157 close(plugin.closeChannel) 158 } 159 160 // Auxiliary function to build bridge domain data 161 func buildData(name string) *l2.BridgeDomain { 162 return &l2.BridgeDomain{ 163 Name: name, 164 Flood: false, 165 UnknownUnicastFlood: true, 166 Forward: true, 167 Learn: true, 168 ArpTermination: true, 169 MacAge: 0, 170 Interfaces: []*l2.BridgeDomain_Interface{ 171 { 172 Name: "memif1", 173 }, 174 }, 175 } 176 } 177 178 // Auxiliary method to transform agent model data to binary api format 179 func buildBinapiMessage(data *l2.BridgeDomain, id uint32) *l2Api.BridgeDomainAddDel { 180 req := &l2Api.BridgeDomainAddDel{} 181 req.IsAdd = true 182 req.BdID = id 183 req.Flood = data.Flood 184 req.UuFlood = data.UnknownUnicastFlood 185 req.Forward = data.Forward 186 req.Learn = data.Learn 187 req.ArpTerm = data.ArpTermination 188 req.MacAge = uint8(data.MacAge) 189 190 return req 191 }