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 }