go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/puntplugin/puntplugin.go (about)

     1  // Copyright (c) 2021 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  //go:generate descriptor-adapter --descriptor-name IPPuntRedirect --value-type *vpp_punt.IPRedirect --import "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/punt" --output-dir "descriptor"
    16  //go:generate descriptor-adapter --descriptor-name PuntToHost --value-type *vpp_punt.ToHost --import "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/punt" --output-dir "descriptor"
    17  //go:generate descriptor-adapter --descriptor-name PuntException --value-type *vpp_punt.Exception --import "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/punt" --output-dir "descriptor"
    18  
    19  package puntplugin
    20  
    21  import (
    22  	"strings"
    23  
    24  	"go.ligato.io/cn-infra/v2/datasync"
    25  	"go.ligato.io/cn-infra/v2/health/statuscheck"
    26  	"go.ligato.io/cn-infra/v2/infra"
    27  	"google.golang.org/protobuf/proto"
    28  
    29  	"go.ligato.io/vpp-agent/v3/pkg/models"
    30  	"go.ligato.io/vpp-agent/v3/plugins/govppmux"
    31  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    32  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin"
    33  	"go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/descriptor"
    34  	"go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/descriptor/adapter"
    35  	"go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/vppcalls"
    36  	vpp_punt "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/punt"
    37  
    38  	_ "go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/vppcalls/vpp2101"
    39  	_ "go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/vppcalls/vpp2106"
    40  	_ "go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/vppcalls/vpp2202"
    41  	_ "go.ligato.io/vpp-agent/v3/plugins/vpp/puntplugin/vppcalls/vpp2210"
    42  )
    43  
    44  // PuntPlugin configures VPP punt to host or unix domain socket entries and IP redirect entries using GoVPP.
    45  type PuntPlugin struct {
    46  	Deps
    47  
    48  	// handler
    49  	puntHandler vppcalls.PuntVppAPI
    50  
    51  	// descriptors
    52  	ipRedirectDescriptor    *descriptor.IPRedirectDescriptor
    53  	toHostDescriptor        *descriptor.PuntToHostDescriptor
    54  	puntExceptionDescriptor *descriptor.PuntExceptionDescriptor
    55  }
    56  
    57  // Deps lists dependencies of the punt plugin.
    58  type Deps struct {
    59  	infra.PluginDeps
    60  	KVScheduler  kvs.KVScheduler
    61  	VPP          govppmux.API
    62  	IfPlugin     ifplugin.API
    63  	PublishState datasync.KeyProtoValWriter     // optional
    64  	StatusCheck  statuscheck.PluginStatusWriter // optional
    65  }
    66  
    67  // Init registers STN-related descriptors.
    68  func (p *PuntPlugin) Init() (err error) {
    69  	// init punt handler
    70  	p.puntHandler = vppcalls.CompatiblePuntVppHandler(p.VPP, p.IfPlugin.GetInterfaceIndex(), p.Log)
    71  
    72  	// init and register IP punt redirect
    73  	p.ipRedirectDescriptor = descriptor.NewIPRedirectDescriptor(p.puntHandler, p.Log)
    74  	ipRedirectDescriptor := adapter.NewIPPuntRedirectDescriptor(p.ipRedirectDescriptor.GetDescriptor())
    75  	err = p.KVScheduler.RegisterKVDescriptor(ipRedirectDescriptor)
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	// init and register punt descriptor
    81  	p.toHostDescriptor = descriptor.NewPuntToHostDescriptor(p.puntHandler, p.Log)
    82  	toHostDescriptor := adapter.NewPuntToHostDescriptor(p.toHostDescriptor.GetDescriptor())
    83  	err = p.KVScheduler.RegisterKVDescriptor(toHostDescriptor)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	// init and register punt exception descriptor
    89  	p.puntExceptionDescriptor = descriptor.NewPuntExceptionDescriptor(p.puntHandler, p.Log)
    90  	exceptionDescriptor := adapter.NewPuntExceptionDescriptor(p.puntExceptionDescriptor.GetDescriptor())
    91  	err = p.KVScheduler.RegisterKVDescriptor(exceptionDescriptor)
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	// FIXME: temporary workaround for publishing registered sockets
    97  	p.toHostDescriptor.RegisterSocketFn = func(register bool, toHost *vpp_punt.ToHost, socketPath string) {
    98  		if p.PublishState == nil {
    99  			return
   100  		}
   101  		key := strings.Replace(models.Key(toHost), "config/", "status/", -1)
   102  		if register {
   103  			puntToHost := proto.Clone(toHost).(*vpp_punt.Exception)
   104  			puntToHost.SocketPath = socketPath
   105  			if err := p.PublishState.Put(key, puntToHost, datasync.WithClientLifetimeTTL()); err != nil {
   106  				p.Log.Errorf("publishing registered punt socket failed: %v", err)
   107  			}
   108  		} else {
   109  			if err := p.PublishState.Put(key, nil); err != nil {
   110  				p.Log.Errorf("publishing unregistered punt socket failed: %v", err)
   111  			}
   112  		}
   113  	}
   114  	p.puntExceptionDescriptor.RegisterSocketFn = func(register bool, puntExc *vpp_punt.Exception, socketPath string) {
   115  		if p.PublishState == nil {
   116  			return
   117  		}
   118  		key := strings.Replace(models.Key(puntExc), "config/", "status/", -1)
   119  		if register {
   120  			punt := proto.Clone(puntExc).(*vpp_punt.Exception)
   121  			punt.SocketPath = socketPath
   122  			if err := p.PublishState.Put(key, punt, datasync.WithClientLifetimeTTL()); err != nil {
   123  				p.Log.Errorf("publishing registered punt exception socket failed: %v", err)
   124  			}
   125  		} else {
   126  			if err := p.PublishState.Put(key, nil); err != nil {
   127  				p.Log.Errorf("publishing unregistered punt exception socket failed: %v", err)
   128  			}
   129  		}
   130  	}
   131  
   132  	return nil
   133  }
   134  
   135  // AfterInit registers plugin with StatusCheck.
   136  func (p *PuntPlugin) AfterInit() error {
   137  	if p.StatusCheck != nil {
   138  		p.StatusCheck.Register(p.PluginName, nil)
   139  	}
   140  	return nil
   141  }