go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ipsecplugin/descriptor/tun_protect.go (about) 1 // Copyright (c) 2020 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 "fmt" 19 20 "github.com/pkg/errors" 21 22 "go.ligato.io/cn-infra/v2/logging" 23 "go.ligato.io/vpp-agent/v3/pkg/models" 24 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/descriptor/adapter" 26 "go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/vppcalls" 27 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 28 ipsec "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipsec" 29 ) 30 31 const ( 32 // TunProtectDescriptorName is the name of the descriptor for VPP tunnel protection. 33 TunProtectDescriptorName = "vpp-tun-protect" 34 35 // dependency labels 36 ipsecSADep = "ipsec-sa-exists" 37 ) 38 39 // A list of non-retriable errors: 40 var ( 41 // ErrTunProtectNoInterface is returned when VPP tunnel protection was defined without an interface. 42 ErrTunProtectNoInterface = errors.New("VPP tunnel protection defined without interface") 43 // ErrTunProtectNoSaOut is returned when VPP tunnel protection was defined without outbound SAs. 44 ErrTunProtectNoSaOut = errors.New("VPP tunnel protection defined without outbound SAs") 45 // ErrTunProtectNoSaIn is returned when VPP tunnel protection was defined without inbound SAs. 46 ErrTunProtectNoSaIn = errors.New("VPP tunnel protection defined without inbound SAs") 47 // ErrTunProtectUpdateIfMismatch is returned if old and new tunnel interface names are not matching by update operation. 48 ErrTunProtectUpdateIfMismatch = errors.New("old/new tunnel interface mismatch") 49 ) 50 51 // TunnelProtectDescriptor teaches KVScheduler how to configure VPP IPSec tunnel protections. 52 type TunnelProtectDescriptor struct { 53 // dependencies 54 log logging.Logger 55 ipSecHandler vppcalls.IPSecVppAPI 56 } 57 58 // NewTunnelProtectDescriptor creates a new instance of the IPSec tunnel protect descriptor. 59 func NewTunnelProtectDescriptor(ipSecHandler vppcalls.IPSecVppAPI, log logging.PluginLogger) *TunnelProtectDescriptor { 60 return &TunnelProtectDescriptor{ 61 ipSecHandler: ipSecHandler, 62 log: log.NewLogger("tun-protect-descriptor"), 63 } 64 } 65 66 // GetDescriptor returns a new tunnel protect descriptor suitable for registration with the KVScheduler. 67 func (d *TunnelProtectDescriptor) GetDescriptor() *adapter.TunProtectDescriptor { 68 return &adapter.TunProtectDescriptor{ 69 Name: TunProtectDescriptorName, 70 NBKeyPrefix: ipsec.ModelTunnelProtection.KeyPrefix(), 71 ValueTypeName: ipsec.ModelTunnelProtection.ProtoName(), 72 KeySelector: ipsec.ModelTunnelProtection.IsKeyValid, 73 KeyLabel: ipsec.ModelTunnelProtection.StripKeyPrefix, 74 Validate: d.Validate, 75 Create: d.Create, 76 Update: d.Update, 77 Delete: d.Delete, 78 Retrieve: d.Retrieve, 79 Dependencies: d.Dependencies, 80 } 81 } 82 83 // Validate validates VPP tunnel protect configuration. 84 func (d *TunnelProtectDescriptor) Validate(key string, tp *ipsec.TunnelProtection) error { 85 if tp.Interface == "" { 86 return kvs.NewInvalidValueError(ErrTunProtectNoInterface, "interface") 87 } 88 if len(tp.SaOut) == 0 { 89 return kvs.NewInvalidValueError(ErrTunProtectNoSaOut, "sa_out") 90 } 91 if len(tp.SaIn) == 0 { 92 return kvs.NewInvalidValueError(ErrTunProtectNoSaIn, "sa_in") 93 } 94 return nil 95 } 96 97 // Create adds a new IPSec tunnel protection. 98 func (d *TunnelProtectDescriptor) Create(key string, tp *ipsec.TunnelProtection) (metadata interface{}, err error) { 99 return nil, d.ipSecHandler.AddTunnelProtection(tp) 100 } 101 102 // Update updates an existing IPSec tunnel protection. 103 func (d *TunnelProtectDescriptor) Update(key string, oldTp, newTp *ipsec.TunnelProtection, oldMeta interface{}) ( 104 metadata interface{}, err error) { 105 if oldTp.Interface != newTp.Interface { 106 return nil, ErrTunProtectUpdateIfMismatch 107 } 108 return nil, d.ipSecHandler.AddTunnelProtection(newTp) 109 } 110 111 // Delete removes an IPSec tunnel protection. 112 func (d *TunnelProtectDescriptor) Delete(key string, tp *ipsec.TunnelProtection, metadata interface{}) error { 113 return d.ipSecHandler.DeleteTunnelProtection(tp) 114 } 115 116 // Retrieve returns all configured IPSec tunnel protections. 117 func (d *TunnelProtectDescriptor) Retrieve(correlate []adapter.TunProtectKVWithMetadata) (dump []adapter.TunProtectKVWithMetadata, err error) { 118 tps, err := d.ipSecHandler.DumpTunnelProtections() 119 for _, tp := range tps { 120 dump = append(dump, adapter.TunProtectKVWithMetadata{ 121 Key: models.Key(tp), 122 Value: tp, 123 Origin: kvs.FromNB, 124 }) 125 } 126 return 127 } 128 129 // Dependencies lists the interface and SAs as the dependencies for the binding. 130 func (d *TunnelProtectDescriptor) Dependencies(key string, value *ipsec.TunnelProtection) []kvs.Dependency { 131 deps := []kvs.Dependency{ 132 { 133 Label: interfaceDep, 134 Key: interfaces.InterfaceKey(value.Interface), 135 }, 136 } 137 for i, sa := range value.SaOut { 138 deps = append(deps, kvs.Dependency{ 139 Label: fmt.Sprintf("%s-out-%d", ipsecSADep, i), 140 Key: ipsec.SAKey(sa), 141 }) 142 } 143 for i, sa := range value.SaIn { 144 deps = append(deps, kvs.Dependency{ 145 Label: fmt.Sprintf("%s-in-%d", ipsecSADep, i), 146 Key: ipsec.SAKey(sa), 147 }) 148 } 149 return deps 150 }