go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/l3plugin/descriptor/dhcp_proxy.go (about)

     1  // Copyright (c) 2019 PANTHEON.tech
     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 descriptor
    16  
    17  import (
    18  	"fmt"
    19  	"net"
    20  
    21  	"github.com/pkg/errors"
    22  	"go.ligato.io/cn-infra/v2/logging"
    23  	"go.ligato.io/cn-infra/v2/utils/addrs"
    24  
    25  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    26  	"go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/descriptor/adapter"
    27  	"go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls"
    28  	l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3"
    29  )
    30  
    31  const (
    32  	// ProxyArpInterfaceDescriptorName is the name of the descriptor.
    33  	DHCPProxyDescriptorName = "dhcp-proxy"
    34  
    35  	//dependecy labels
    36  	rxVrfTableDependency = "rx-vrf-table-exists"
    37  	dhcpSrvVrfTableDependency = "vrf-table-%d-used-by-dhcp-server-exists"
    38  )
    39  
    40  // DHCPProxyDescriptor teaches KVScheduler how to configure VPP DHCP proxy.
    41  type DHCPProxyDescriptor struct {
    42  	log              logging.Logger
    43  	dhcpProxyHandler vppcalls.DHCPProxyAPI
    44  	scheduler        kvs.KVScheduler
    45  }
    46  
    47  // NewDHCPProxyDescriptor creates a new instance of the DHCPProxyDescriptor.
    48  func NewDHCPProxyDescriptor(scheduler kvs.KVScheduler,
    49  	dhcpProxyHandler vppcalls.DHCPProxyAPI, log logging.PluginLogger) *kvs.KVDescriptor {
    50  
    51  	ctx := &DHCPProxyDescriptor{
    52  		scheduler:        scheduler,
    53  		dhcpProxyHandler: dhcpProxyHandler,
    54  		log:              log.NewLogger("dhcp-proxy-descriptor"),
    55  	}
    56  
    57  	typedDescr := &adapter.DHCPProxyDescriptor{
    58  		Name:          DHCPProxyDescriptorName,
    59  		KeySelector:   l3.ModelDHCPProxy.IsKeyValid,
    60  		KeyLabel:      l3.ModelDHCPProxy.StripKeyPrefix,
    61  		NBKeyPrefix:   l3.ModelDHCPProxy.KeyPrefix(),
    62  		ValueTypeName: l3.ModelDHCPProxy.ProtoName(),
    63  		Create:        ctx.Create,
    64  		Delete:        ctx.Delete,
    65  		Retrieve:      ctx.Retrieve,
    66  		Dependencies:  ctx.Dependencies,
    67  		Validate:      ctx.Validate,
    68  	}
    69  	return adapter.NewDHCPProxyDescriptor(typedDescr)
    70  }
    71  
    72  func (d *DHCPProxyDescriptor) Validate(key string, value *l3.DHCPProxy) error {
    73  
    74  	ipAddr := net.ParseIP(value.SourceIpAddress)
    75  	if ipAddr == nil {
    76  		return errors.Errorf("invalid source IP address: %q", value.SourceIpAddress)
    77  	}
    78  
    79  	for _, server := range value.Servers {
    80  		serverIPAddr := net.ParseIP(server.IpAddress)
    81  		if serverIPAddr == nil {
    82  			return errors.Errorf("invalid server IP address: %q", server.IpAddress)
    83  		}
    84  
    85  		if ipAddr.To4() != nil && serverIPAddr.To4() == nil || serverIPAddr.To4() != nil && ipAddr.To4() == nil {
    86  			return errors.Errorf("Server address %s must use same IP protocol as source address %s",
    87  				serverIPAddr, ipAddr)
    88  		}
    89  	}
    90  	return nil
    91  }
    92  
    93  // Dependencies lists dependencies for a VPP DHCP proxy.
    94  func (d *DHCPProxyDescriptor) Dependencies(key string, value *l3.DHCPProxy) (deps []kvs.Dependency) {
    95  	// non-zero VRFs
    96  	var protocol l3.VrfTable_Protocol
    97  	_, isIPv6, _ := addrs.ParseIPWithPrefix(value.SourceIpAddress)
    98  	if isIPv6 {
    99  		protocol = l3.VrfTable_IPV6
   100  	}
   101  
   102  	if value.RxVrfId != 0 {
   103  		deps = append(deps, kvs.Dependency{
   104  			Label: rxVrfTableDependency,
   105  			Key:   l3.VrfTableKey(value.RxVrfId, protocol),
   106  		})
   107  	}
   108  
   109  	for _, server := range value.Servers {
   110  		if server.VrfId != 0 {
   111  			deps = append(deps, kvs.Dependency{
   112  				Label: fmt.Sprintf(dhcpSrvVrfTableDependency, server.VrfId),
   113  				Key:   l3.VrfTableKey(server.VrfId, protocol),
   114  			})
   115  		}
   116  	}
   117  
   118  	return deps
   119  }
   120  
   121  // Create enables VPP DHCP proxy.
   122  func (d *DHCPProxyDescriptor) Create(key string, value *l3.DHCPProxy) (metadata interface{}, err error) {
   123  	if err := d.dhcpProxyHandler.CreateDHCPProxy(value); err != nil {
   124  		return nil, errors.Errorf("failed to create DHCP proxy %v", err)
   125  	}
   126  	return nil, nil
   127  }
   128  
   129  // Delete disables VPP DHCP proxy.
   130  func (d *DHCPProxyDescriptor) Delete(key string, value *l3.DHCPProxy, metadata interface{}) error {
   131  	if err := d.dhcpProxyHandler.DeleteDHCPProxy(value); err != nil {
   132  		return errors.Errorf("failed to delete DHCP proxy %v", err)
   133  	}
   134  	return nil
   135  }
   136  
   137  // Retrieve returns current VPP DHCP proxy configuration.
   138  func (d *DHCPProxyDescriptor) Retrieve(correlate []adapter.DHCPProxyKVWithMetadata) (retrieved []adapter.DHCPProxyKVWithMetadata, err error) {
   139  	// Retrieve VPP configuration
   140  	dhcpProxyDetails, err := d.dhcpProxyHandler.DumpDHCPProxy()
   141  
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  
   146  	if dhcpProxyDetails == nil {
   147  		return nil, nil
   148  	}
   149  
   150  	for _, detail := range dhcpProxyDetails {
   151  		retrieved = append(retrieved, adapter.DHCPProxyKVWithMetadata{
   152  			Key:    l3.DHCPProxyKey(detail.DHCPProxy.SourceIpAddress, detail.DHCPProxy.RxVrfId),
   153  			Value:  detail.DHCPProxy,
   154  			Origin: kvs.FromNB,
   155  		})
   156  	}
   157  
   158  	return retrieved, nil
   159  }