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

     1  // Copyright (c) 2018 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  	"go.ligato.io/cn-infra/v2/logging"
    19  
    20  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    21  	"go.ligato.io/vpp-agent/v3/plugins/vpp/natplugin/descriptor/adapter"
    22  	"go.ligato.io/vpp-agent/v3/plugins/vpp/natplugin/vppcalls"
    23  	interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    24  	nat "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/nat"
    25  )
    26  
    27  const (
    28  	// NAT44InterfaceDescriptorName is the name of the descriptor for VPP NAT44 features applied to interfaces.
    29  	NAT44InterfaceDescriptorName = "vpp-nat44-interface"
    30  )
    31  
    32  // NAT44InterfaceDescriptor teaches KVScheduler how to configure VPP NAT interface features.
    33  type NAT44InterfaceDescriptor struct {
    34  	log             logging.Logger
    35  	natHandler      vppcalls.NatVppAPI
    36  	nat44GlobalDesc *NAT44GlobalDescriptor
    37  }
    38  
    39  // NewNAT44InterfaceDescriptor creates a new instance of the NAT44Interface descriptor.
    40  func NewNAT44InterfaceDescriptor(nat44GlobalDesc *NAT44GlobalDescriptor,
    41  	natHandler vppcalls.NatVppAPI, log logging.PluginLogger) *kvs.KVDescriptor {
    42  	ctx := &NAT44InterfaceDescriptor{
    43  		nat44GlobalDesc: nat44GlobalDesc,
    44  		natHandler:      natHandler,
    45  		log:             log.NewLogger("nat44-iface-descriptor"),
    46  	}
    47  
    48  	typedDescr := &adapter.NAT44InterfaceDescriptor{
    49  		Name:          NAT44InterfaceDescriptorName,
    50  		NBKeyPrefix:   nat.ModelNat44Interface.KeyPrefix(),
    51  		ValueTypeName: nat.ModelNat44Interface.ProtoName(),
    52  		KeySelector:   nat.ModelNat44Interface.IsKeyValid,
    53  		KeyLabel:      nat.ModelNat44Interface.StripKeyPrefix,
    54  		Validate:      ctx.Validate,
    55  		Create:        ctx.Create,
    56  		Delete:        ctx.Delete,
    57  		Retrieve:      ctx.Retrieve,
    58  		Dependencies:  ctx.Dependencies,
    59  		// retrieve global NAT config first (required for deprecated global NAT interface & address API)
    60  		RetrieveDependencies: []string{NAT44GlobalDescriptorName},
    61  	}
    62  	return adapter.NewNAT44InterfaceDescriptor(typedDescr)
    63  }
    64  
    65  // TODO: Maybe we should split the Nat44Interface type into two types:
    66  // Nat44Interface and Nat44OutputInterface. Currently Nat44Interface contains 3
    67  // flags: inside, outside and output. When output flag is set the other two
    68  // flags should be false for VPP >= 22.10 (? need to investigate this more in VPP).
    69  // This is currently not enforced and it can create problems with the configuration of
    70  // NAT interfaces. With the type split into two, Nat44Interface would contain 2
    71  // flags: inside and outside. Nat44OutputInterface would contain 0 flags
    72  // (output is implicit in the type itself).
    73  
    74  // Validate validates VPP NAT44 interface configuration.
    75  func (d *NAT44InterfaceDescriptor) Validate(key string, natIface *nat.Nat44Interface) error {
    76  	if natIface.NatOutside && natIface.NatInside && natIface.OutputFeature {
    77  		// output feature cannot be enabled on interface with both inside & outside NAT enabled
    78  		return kvs.NewInvalidValueError(ErrNATInterfaceFeatureCollision, "output_feature")
    79  	}
    80  	return nil
    81  }
    82  
    83  // Create enables NAT44 on an interface.
    84  func (d *NAT44InterfaceDescriptor) Create(key string, natIface *nat.Nat44Interface) (metadata interface{}, err error) {
    85  	if natIface.NatInside {
    86  		err = d.natHandler.EnableNat44Interface(natIface.Name, true, natIface.OutputFeature)
    87  		if err != nil {
    88  			return
    89  		}
    90  	}
    91  	if natIface.NatOutside {
    92  		err = d.natHandler.EnableNat44Interface(natIface.Name, false, natIface.OutputFeature)
    93  		if err != nil {
    94  			return
    95  		}
    96  	}
    97  	if natIface.OutputFeature && !natIface.NatInside && !natIface.NatOutside {
    98  		err = d.natHandler.EnableNat44Interface(natIface.Name, false, natIface.OutputFeature)
    99  		if err != nil {
   100  			return
   101  		}
   102  	}
   103  	return
   104  }
   105  
   106  // Delete disables NAT44 on an interface.
   107  func (d *NAT44InterfaceDescriptor) Delete(key string, natIface *nat.Nat44Interface, metadata interface{}) (err error) {
   108  	if natIface.NatInside {
   109  		err = d.natHandler.DisableNat44Interface(natIface.Name, true, natIface.OutputFeature)
   110  		if err != nil {
   111  			return
   112  		}
   113  	}
   114  	if natIface.NatOutside {
   115  		err = d.natHandler.DisableNat44Interface(natIface.Name, false, natIface.OutputFeature)
   116  		if err != nil {
   117  			return
   118  		}
   119  	}
   120  	if natIface.OutputFeature && !natIface.NatOutside && !natIface.NatInside {
   121  		err = d.natHandler.DisableNat44Interface(natIface.Name, false, natIface.OutputFeature)
   122  		if err != nil {
   123  			return
   124  		}
   125  	}
   126  	return
   127  }
   128  
   129  // Retrieve returns the current NAT44 interface configuration.
   130  func (d *NAT44InterfaceDescriptor) Retrieve(correlate []adapter.NAT44InterfaceKVWithMetadata) (
   131  	retrieved []adapter.NAT44InterfaceKVWithMetadata, err error) {
   132  	if d.nat44GlobalDesc.UseDeprecatedAPI {
   133  		return nil, nil // NAT interfaces already dumped by global descriptor (deprecated API is in use)
   134  	}
   135  	natIfs, err := d.natHandler.Nat44InterfacesDump()
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	for _, natIf := range natIfs {
   140  		retrieved = append(retrieved, adapter.NAT44InterfaceKVWithMetadata{
   141  			Key:    nat.Nat44InterfaceKey(natIf.Name),
   142  			Value:  natIf,
   143  			Origin: kvs.FromNB,
   144  		})
   145  	}
   146  	return
   147  }
   148  
   149  // Dependencies lists the interface and the NAT44 global configuration as dependencies.
   150  func (d *NAT44InterfaceDescriptor) Dependencies(key string, natIface *nat.Nat44Interface) (deps []kvs.Dependency) {
   151  	if !d.natHandler.WithLegacyStartupConf() {
   152  		deps = append(deps, kvs.Dependency{
   153  			Label: natInterfaceGlobalCfgDep,
   154  			Key:   nat.GlobalNAT44Key(),
   155  		})
   156  	}
   157  	deps = append(deps, kvs.Dependency{
   158  		Label: natInterfaceDep,
   159  		Key:   interfaces.InterfaceKey(natIface.Name),
   160  	})
   161  	return deps
   162  }