go.ligato.io/vpp-agent/v3@v3.5.0/examples/customize/custom_api_model/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  	"fmt"
    20  	"log"
    21  	"net"
    22  	"os"
    23  	"time"
    24  
    25  	"github.com/namsral/flag"
    26  	"go.ligato.io/cn-infra/v2/agent"
    27  	"go.ligato.io/cn-infra/v2/infra"
    28  	"go.ligato.io/cn-infra/v2/logging"
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/protobuf/encoding/prototext"
    31  
    32  	"go.ligato.io/vpp-agent/v3/client"
    33  	"go.ligato.io/vpp-agent/v3/client/remoteclient"
    34  	"go.ligato.io/vpp-agent/v3/cmd/vpp-agent/app"
    35  	"go.ligato.io/vpp-agent/v3/examples/customize/custom_api_model/proto/custom"
    36  	"go.ligato.io/vpp-agent/v3/plugins/orchestrator"
    37  	"go.ligato.io/vpp-agent/v3/proto/ligato/linux"
    38  	linux_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/linux/interfaces"
    39  	linux_l3 "go.ligato.io/vpp-agent/v3/proto/ligato/linux/l3"
    40  	"go.ligato.io/vpp-agent/v3/proto/ligato/vpp"
    41  	interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    42  	vpp_l2 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l2"
    43  )
    44  
    45  //go:generate protoc --proto_path=. --go_out=paths=source_relative:. proto/custom/model.proto
    46  
    47  var (
    48  	clientType = flag.String("client", "local", "Client type used in demonstration [local, remote]")
    49  )
    50  
    51  func init() {
    52  	log.SetFlags(log.Lshortfile | log.Lmicroseconds)
    53  }
    54  
    55  func main() {
    56  	example := NewExample()
    57  
    58  	a := agent.NewAgent(
    59  		agent.AllPlugins(example),
    60  	)
    61  
    62  	if err := a.Start(); err != nil {
    63  		log.Fatal(err)
    64  	}
    65  
    66  	var c client.ConfigClient
    67  
    68  	switch *clientType {
    69  	case "local":
    70  		// Local client - using direct in-process calls.
    71  		c = client.LocalClient
    72  		logging.Info("Using Local Client - in-process calls")
    73  
    74  	case "remote":
    75  		// Remote client - using gRPC connection to the agent.
    76  		conn, err := grpc.Dial("unix",
    77  			grpc.WithInsecure(),
    78  			grpc.WithDialer(dialer("tcp", "127.0.0.1:9111", time.Second*3)),
    79  		)
    80  		if err != nil {
    81  			log.Fatal(err)
    82  		}
    83  		defer conn.Close()
    84  
    85  		c, err = remoteclient.NewClientGRPC(conn)
    86  		if err != nil {
    87  			log.Fatal(err)
    88  		}
    89  		logging.Info("Using Remote Client - gRPC API")
    90  
    91  	default:
    92  		log.Printf("unknown client type: %q", *clientType)
    93  		flag.Usage()
    94  		os.Exit(1)
    95  	}
    96  
    97  	demonstrateClient(c)
    98  
    99  	if err := a.Stop(); err != nil {
   100  		log.Fatal(err)
   101  	}
   102  }
   103  
   104  // Example demonstrates the use of the remoteclient to locally transport example configuration into the default VPP plugins.
   105  type Example struct {
   106  	infra.PluginDeps
   107  	app.VPP
   108  	app.Linux
   109  	Orchestrator *orchestrator.Plugin
   110  }
   111  
   112  func NewExample() *Example {
   113  	ep := &Example{
   114  		VPP:          app.DefaultVPP(),
   115  		Linux:        app.DefaultLinux(),
   116  		Orchestrator: &orchestrator.DefaultPlugin,
   117  	}
   118  	ep.SetName("custom-api-model-example")
   119  	ep.SetupLog()
   120  	return ep
   121  }
   122  
   123  // Init initializes example plugin.
   124  func (p *Example) Init() (err error) {
   125  	p.Log.Info("Initialization complete")
   126  	return nil
   127  }
   128  
   129  func demonstrateClient(c client.ConfigClient) {
   130  	// List known models
   131  	fmt.Println("# ==========================================")
   132  	fmt.Println("# List known models..")
   133  	fmt.Println("# ==========================================")
   134  	knownModels, err := c.KnownModels("config")
   135  	if err != nil {
   136  		log.Println("KnownModels failed:", err)
   137  	}
   138  	fmt.Printf("listing %d models\n", len(knownModels))
   139  	for _, model := range knownModels {
   140  		fmt.Printf(" - %v\n", model.String())
   141  	}
   142  	time.Sleep(time.Second * 1)
   143  
   144  	// Resync config
   145  	fmt.Println("# ==========================================")
   146  	fmt.Println("# Requesting config resync..")
   147  	fmt.Println("# ==========================================")
   148  	customModel := &custom.MyModel{
   149  		Name: "TheModel",
   150  	}
   151  	err = c.ResyncConfig(
   152  		memif1, memif2,
   153  		veth1, veth2,
   154  		routeX, routeCache,
   155  		customModel,
   156  	)
   157  	if err != nil {
   158  		log.Println("ResyncConfig failed:", err)
   159  	}
   160  	time.Sleep(time.Second * 2)
   161  
   162  	// Change config
   163  	fmt.Println("# ==========================================")
   164  	fmt.Println("# Requesting config change..")
   165  	fmt.Println("# ==========================================")
   166  	memif1.Enabled = false
   167  	memif1.Mtu = 666
   168  	mymodel := &custom.MyModel{
   169  		Name:  "my1",
   170  		Value: 33,
   171  	}
   172  
   173  	req := c.ChangeRequest()
   174  	req.Update(afp1, memif1, bd1, vppRoute1, mymodel)
   175  	req.Delete(memif2)
   176  	if err := req.Send(context.Background()); err != nil {
   177  		log.Fatalln(err)
   178  	}
   179  	time.Sleep(time.Second * 2)
   180  
   181  	// Get config
   182  	fmt.Println("# ==========================================")
   183  	fmt.Println("# Retrieving config..")
   184  	fmt.Println("# ==========================================")
   185  	type config struct {
   186  		VPP      vpp.ConfigData
   187  		Linux    linux.ConfigData
   188  		MyModels []*custom.MyModel
   189  	}
   190  	var cfg config
   191  	if err := c.GetConfig(&cfg.VPP, &cfg.Linux, &cfg); err != nil {
   192  		log.Println("GetConfig failed:", err)
   193  	}
   194  	fmt.Printf("Retrieved config:\n%+v\n", &cfg)
   195  
   196  	// Dump state
   197  	fmt.Println("# ==========================================")
   198  	fmt.Println("# Dumping state..")
   199  	fmt.Println("# ==========================================")
   200  	states, err := c.DumpState()
   201  	if err != nil {
   202  		log.Println("DumpState failed:", err)
   203  	}
   204  	fmt.Printf("Dumping %d states\n", len(states))
   205  	for _, state := range states {
   206  		fmt.Printf(" - %v\n", prototext.Format(state))
   207  	}
   208  }
   209  
   210  // Dialer for unix domain socket
   211  func dialer(socket, address string, timeoutVal time.Duration) func(string, time.Duration) (net.Conn, error) {
   212  	return func(addr string, timeout time.Duration) (net.Conn, error) {
   213  		// Pass values
   214  		addr, timeout = address, timeoutVal
   215  		// Dial with timeout
   216  		return net.DialTimeout(socket, addr, timeoutVal)
   217  	}
   218  }
   219  
   220  var (
   221  	memif1 = &vpp.Interface{
   222  		Name:        "memif1",
   223  		Enabled:     true,
   224  		IpAddresses: []string{"3.3.0.1/16"},
   225  		Type:        interfaces.Interface_MEMIF,
   226  		Link: &interfaces.Interface_Memif{
   227  			Memif: &interfaces.MemifLink{
   228  				Id:             1,
   229  				Master:         true,
   230  				Secret:         "secret",
   231  				SocketFilename: "/tmp/memif1.sock",
   232  			},
   233  		},
   234  	}
   235  	memif2 = &vpp.Interface{
   236  		Name:        "memif1.1",
   237  		Enabled:     true,
   238  		Type:        interfaces.Interface_SUB_INTERFACE,
   239  		IpAddresses: []string{"3.10.0.1/24"},
   240  		Link: &interfaces.Interface_Sub{
   241  			Sub: &interfaces.SubInterface{
   242  				ParentName: "memif1",
   243  				SubId:      10,
   244  			},
   245  		},
   246  	}
   247  	bd1 = &vpp.BridgeDomain{
   248  		Name: "bd1",
   249  		Interfaces: []*vpp_l2.BridgeDomain_Interface{
   250  			{Name: "memif1"},
   251  		},
   252  	}
   253  	vppRoute1 = &vpp.Route{
   254  		OutgoingInterface: "memif1",
   255  		DstNetwork:        "4.4.10.0/24",
   256  		NextHopAddr:       "3.10.0.5",
   257  	}
   258  	afp1 = &vpp.Interface{
   259  		Name:        "afp1",
   260  		Enabled:     true,
   261  		Type:        interfaces.Interface_AF_PACKET,
   262  		IpAddresses: []string{"10.10.3.5/24"},
   263  		Link: &interfaces.Interface_Afpacket{
   264  			Afpacket: &interfaces.AfpacketLink{
   265  				HostIfName: "veth1",
   266  			},
   267  		},
   268  	}
   269  	veth1 = &linux.Interface{
   270  		Name:        "myVETH1",
   271  		Type:        linux_interfaces.Interface_VETH,
   272  		Enabled:     true,
   273  		HostIfName:  "veth1",
   274  		IpAddresses: []string{"10.10.3.1/24"},
   275  		Link: &linux_interfaces.Interface_Veth{
   276  			Veth: &linux_interfaces.VethLink{
   277  				PeerIfName: "myVETH2",
   278  			},
   279  		},
   280  	}
   281  	veth2 = &linux.Interface{
   282  		Name:       "myVETH2",
   283  		Type:       linux_interfaces.Interface_VETH,
   284  		Enabled:    true,
   285  		HostIfName: "veth2",
   286  		Link: &linux_interfaces.Interface_Veth{
   287  			Veth: &linux_interfaces.VethLink{
   288  				PeerIfName: "myVETH1",
   289  			},
   290  		},
   291  	}
   292  	routeX = &linux.Route{
   293  		DstNetwork:        "192.168.5.0/24",
   294  		OutgoingInterface: "myVETH1",
   295  		GwAddr:            "10.10.3.254",
   296  		Scope:             linux_l3.Route_GLOBAL,
   297  	}
   298  	routeCache = &linux.Route{
   299  		DstNetwork:        "10.10.5.0/24",
   300  		OutgoingInterface: "if10",
   301  		GwAddr:            "10.10.5.254",
   302  		Scope:             linux_l3.Route_GLOBAL,
   303  	}
   304  )