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  )