go.ligato.io/vpp-agent/v3@v3.5.0/plugins/netalloc/descriptor/ip_alloc.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 descriptor
    16  
    17  import (
    18  	"net"
    19  
    20  	"go.ligato.io/cn-infra/v2/logging"
    21  	"google.golang.org/protobuf/types/known/emptypb"
    22  
    23  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    24  	"go.ligato.io/vpp-agent/v3/plugins/netalloc/descriptor/adapter"
    25  	"go.ligato.io/vpp-agent/v3/plugins/netalloc/utils"
    26  	"go.ligato.io/vpp-agent/v3/proto/ligato/netalloc"
    27  )
    28  
    29  const (
    30  	// IPAllocDescriptorName is the name of the descriptor for allocating
    31  	// IP addresses.
    32  	IPAllocDescriptorName = "netalloc-ip-address"
    33  )
    34  
    35  // IPAllocDescriptor just validates and parses allocated IP addresses.
    36  type IPAllocDescriptor struct {
    37  	log logging.Logger
    38  }
    39  
    40  // NewAddrAllocDescriptor creates a new instance of IPAllocDescriptor.
    41  func NewAddrAllocDescriptor(log logging.PluginLogger) (descr *kvs.KVDescriptor) {
    42  	ctx := &IPAllocDescriptor{
    43  		log: log.NewLogger("ip-address-alloc-descriptor"),
    44  	}
    45  	typedDescr := &adapter.IPAllocDescriptor{
    46  		Name:          IPAllocDescriptorName,
    47  		NBKeyPrefix:   netalloc.ModelIPAllocation.KeyPrefix(),
    48  		ValueTypeName: netalloc.ModelIPAllocation.ProtoName(),
    49  		KeySelector:   netalloc.ModelIPAllocation.IsKeyValid,
    50  		KeyLabel:      netalloc.ModelIPAllocation.StripKeyPrefix,
    51  		WithMetadata:  true,
    52  		Validate:      ctx.Validate,
    53  		Create:        ctx.Create,
    54  		Delete:        ctx.Delete,
    55  		Retrieve:      ctx.Retrieve,
    56  		DerivedValues: ctx.DerivedValues,
    57  	}
    58  	descr = adapter.NewIPAllocDescriptor(typedDescr)
    59  	return
    60  }
    61  
    62  // Validate checks if the address can be parsed.
    63  func (d *IPAllocDescriptor) Validate(key string, addrAlloc *netalloc.IPAllocation) (err error) {
    64  	_, _, err = d.parseAddr(addrAlloc)
    65  	return err
    66  }
    67  
    68  // Create parses the address and stores it into the metadata.
    69  func (d *IPAllocDescriptor) Create(key string, addrAlloc *netalloc.IPAllocation) (metadata *netalloc.IPAllocMetadata, err error) {
    70  	metadata, _, err = d.parseAddr(addrAlloc)
    71  	return
    72  }
    73  
    74  // Delete is NOOP.
    75  func (d *IPAllocDescriptor) Delete(key string, addrAlloc *netalloc.IPAllocation, metadata *netalloc.IPAllocMetadata) (err error) {
    76  	return err
    77  }
    78  
    79  // DerivedValues derives "neighbour-gateway" key if GW is a neighbour of the interface
    80  // (addresses are from the same IP network).
    81  func (d *IPAllocDescriptor) DerivedValues(key string, addrAlloc *netalloc.IPAllocation) (derValues []kvs.KeyValuePair) {
    82  	_, neighGw, _ := d.parseAddr(addrAlloc)
    83  	if neighGw {
    84  		derValues = append(derValues, kvs.KeyValuePair{
    85  			Key:   netalloc.NeighGwKey(addrAlloc.NetworkName, addrAlloc.InterfaceName),
    86  			Value: &emptypb.Empty{},
    87  		})
    88  	}
    89  	return derValues
    90  }
    91  
    92  // Retrieve always returns what is expected to exists since Create doesn't really change
    93  // anything in SB.
    94  func (d *IPAllocDescriptor) Retrieve(correlate []adapter.IPAllocKVWithMetadata) (valid []adapter.IPAllocKVWithMetadata, err error) {
    95  	for _, addrAlloc := range correlate {
    96  		if meta, _, err := d.parseAddr(addrAlloc.Value); err == nil {
    97  			valid = append(valid, adapter.IPAllocKVWithMetadata{
    98  				Key:      addrAlloc.Key,
    99  				Value:    addrAlloc.Value,
   100  				Metadata: meta,
   101  				Origin:   kvs.FromNB,
   102  			})
   103  		}
   104  	}
   105  	return valid, nil
   106  }
   107  
   108  // parseAddr tries to parse the allocated address.
   109  func (d *IPAllocDescriptor) parseAddr(addrAlloc *netalloc.IPAllocation) (parsed *netalloc.IPAllocMetadata, neighGw bool, err error) {
   110  	ifaceAddr, _, err := utils.ParseIPAddr(addrAlloc.Address, nil)
   111  	if err != nil {
   112  		return nil, false, err
   113  	}
   114  	var gwAddr *net.IPNet
   115  	if addrAlloc.Gw != "" {
   116  		gwAddr, neighGw, err = utils.ParseIPAddr(addrAlloc.Gw, ifaceAddr)
   117  		if err != nil {
   118  			return nil, false, err
   119  		}
   120  	}
   121  	return &netalloc.IPAllocMetadata{IfaceAddr: ifaceAddr, GwAddr: gwAddr}, neighGw, nil
   122  }