go.ligato.io/vpp-agent/v3@v3.5.0/examples/kvscheduler/rxplacement/main.go (about) 1 // Copyright (c) 2019 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 "fmt" 19 "log" 20 "time" 21 22 "go.ligato.io/cn-infra/v2/agent" 23 24 "go.ligato.io/vpp-agent/v3/clientv2/linux/localclient" 25 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler" 26 kvs_api "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 27 "go.ligato.io/vpp-agent/v3/plugins/orchestrator" 28 vpp_ifplugin "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin" 29 "go.ligato.io/vpp-agent/v3/proto/ligato/kvscheduler" 30 vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 31 ) 32 33 /* 34 * VPP1 (configured by this example): 35 - startup config: 36 unix { 37 interactive 38 cli-listen 0.0.0.0:5002 39 cli-no-pager 40 coredump-size unlimited 41 full-coredump 42 poll-sleep-usec 50 43 } 44 api-trace { 45 on 46 } 47 socksvr { 48 socket-name "/tmp/vpp1.sock" 49 } 50 statseg { 51 default 52 per-node-counters on 53 } 54 cpu { 55 workers 2 56 } 57 58 * VPP2 (configured manually to connect with myMemif): 59 - startup config: 60 unix { 61 interactive 62 cli-listen 0.0.0.0:5003 63 cli-no-pager 64 coredump-size unlimited 65 full-coredump 66 poll-sleep-usec 50 67 } 68 api-trace { 69 on 70 } 71 socksvr { 72 socket-name "/tmp/vpp2.sock" 73 } 74 statseg { 75 default 76 per-node-counters on 77 } 78 cpu { 79 workers 2 80 } 81 82 - configuration to be applied via CLI: 83 $ create interface memif id 0 slave rx-queues 5 tx-queues 5 84 $ set int state memif0/0 up 85 $ set int ip address memif0/0 192.168.1.2/24 86 */ 87 func main() { 88 //vpp_ifplugin.DefaultPlugin.PublishStatistics = &Publisher{} 89 ep := &ExamplePlugin{ 90 KVScheduler: &kvs.DefaultPlugin, 91 VPPIfPlugin: &vpp_ifplugin.DefaultPlugin, 92 Orchestrator: &orchestrator.DefaultPlugin, 93 } 94 95 a := agent.NewAgent( 96 agent.AllPlugins(ep), 97 ) 98 if err := a.Run(); err != nil { 99 log.Fatal(err) 100 } 101 } 102 103 // ExamplePlugin is the main plugin which 104 // handles resync and changes in this example. 105 type ExamplePlugin struct { 106 KVScheduler *kvs.Scheduler 107 VPPIfPlugin *vpp_ifplugin.IfPlugin 108 Orchestrator *orchestrator.Plugin 109 } 110 111 /* 112 type Publisher struct { 113 } 114 115 func (p *Publisher) Put(key string, data proto.Message, opts ...datasync.PutOption) error { 116 fmt.Printf("Publishing key=%s, data=%+v\n", key, data) 117 return nil 118 } 119 */ 120 121 // String returns plugin name 122 func (p *ExamplePlugin) String() string { 123 return "rx-placement-example" 124 } 125 126 // Init handles initialization phase. 127 func (p *ExamplePlugin) Init() error { 128 return nil 129 } 130 131 // AfterInit handles phase after initialization. 132 func (p *ExamplePlugin) AfterInit() error { 133 ch := make(chan *kvscheduler.BaseValueStatus, 100) 134 p.KVScheduler.WatchValueStatus(ch, nil) 135 go watchValueStatus(ch) 136 go testLocalClientWithScheduler(p.KVScheduler) 137 return nil 138 } 139 140 // Close cleans up the resources. 141 func (p *ExamplePlugin) Close() error { 142 return nil 143 } 144 145 func watchValueStatus(ch <-chan *kvscheduler.BaseValueStatus) { 146 for { 147 select { 148 case status := <-ch: 149 fmt.Printf("Value status change: %v\n", status.String()) 150 } 151 } 152 } 153 154 func testLocalClientWithScheduler(kvscheduler kvs_api.KVScheduler) { 155 // initial resync 156 time.Sleep(time.Second * 2) 157 fmt.Println("=== RESYNC WITH MEMIF ===") 158 159 txn := localclient.DataResyncRequest("example") 160 err := txn. 161 VppInterface(myMemif). 162 Send().ReceiveReply() 163 if err != nil { 164 fmt.Println(err) 165 return 166 } 167 168 // data change #1 169 time.Sleep(time.Second * 10) 170 fmt.Println("=== CHANGE ===") 171 172 myMemif.RxModes[0].Mode = vpp_interfaces.Interface_RxMode_INTERRUPT // change default 173 myMemif.RxModes = append(myMemif.RxModes, &vpp_interfaces.Interface_RxMode{ 174 Queue: 3, 175 Mode: vpp_interfaces.Interface_RxMode_POLLING, 176 }) 177 myMemif.RxPlacements = append(myMemif.RxPlacements, &vpp_interfaces.Interface_RxPlacement{ 178 Queue: 3, 179 MainThread: true, 180 Worker: 100, // ignored 181 }) 182 183 txn2 := localclient.DataChangeRequest("example") 184 err = txn2.Put(). 185 VppInterface(myMemif). 186 Send().ReceiveReply() 187 if err != nil { 188 fmt.Println(err) 189 return 190 } 191 192 // data change #2 193 time.Sleep(time.Second * 20) 194 fmt.Println("=== CHANGE ===") 195 196 myMemif.GetMemif().RxQueues = 5 197 myMemif.GetMemif().TxQueues = 5 198 myMemif.RxPlacements = append(myMemif.RxPlacements, &vpp_interfaces.Interface_RxPlacement{ 199 Queue: 4, 200 MainThread: true, 201 }) 202 203 /* Re-create will fail - that is expected and it is due to the link-state key 204 being updated AFTER the transaction, not during. The subsequent retry/notification 205 should fix all the errors. 206 */ 207 208 txn3 := localclient.DataChangeRequest("example") 209 err = txn3.Put(). 210 VppInterface(myMemif). // re-create 211 Send().ReceiveReply() 212 if err != nil { 213 fmt.Println(err) 214 return 215 } 216 } 217 218 var ( 219 myMemif = &vpp_interfaces.Interface{ 220 Name: "my-memif", 221 Type: vpp_interfaces.Interface_MEMIF, 222 Enabled: true, 223 IpAddresses: []string{"192.168.1.1/24"}, 224 225 RxPlacements: []*vpp_interfaces.Interface_RxPlacement{ 226 { 227 Queue: 0, 228 Worker: 0, 229 }, 230 { 231 Queue: 1, 232 MainThread: true, 233 }, 234 { 235 Queue: 2, 236 Worker: 1, 237 }, 238 }, 239 240 RxModes: []*vpp_interfaces.Interface_RxMode{ 241 { 242 DefaultMode: true, 243 Mode: vpp_interfaces.Interface_RxMode_POLLING, 244 }, 245 { 246 Queue: 1, 247 Mode: vpp_interfaces.Interface_RxMode_INTERRUPT, 248 }, 249 { 250 Queue: 2, 251 Mode: vpp_interfaces.Interface_RxMode_INTERRUPT, 252 }, 253 }, 254 255 Link: &vpp_interfaces.Interface_Memif{ 256 Memif: &vpp_interfaces.MemifLink{ 257 Mode: vpp_interfaces.MemifLink_ETHERNET, 258 Master: true, 259 Id: 0, 260 RxQueues: 4, 261 TxQueues: 4, 262 }, 263 }, 264 } 265 )