go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ipfixplugin/descriptor/ipfix.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 "errors" 19 20 "go.ligato.io/cn-infra/v2/logging" 21 22 "go.ligato.io/vpp-agent/v3/pkg/models" 23 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 24 "go.ligato.io/vpp-agent/v3/plugins/vpp/ipfixplugin/descriptor/adapter" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/ipfixplugin/vppcalls" 26 ipfix "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipfix" 27 ) 28 29 const ( 30 // IPFIXDescriptorName is the name of the descriptor for 31 // VPP IP Flow Information eXport (IPFIX) configuration. 32 IPFIXDescriptorName = "vpp-ipfix" 33 ) 34 35 // Validation errors: 36 var ( 37 // ErrColAddrNotDefined returned when collector address in confiugration is empty string. 38 ErrColAddrNotDefined = errors.New("address of a collector was not provided") 39 // ErrSrcAddrNotDefined returned when source address in confiugration is empty string. 40 ErrSrcAddrNotDefined = errors.New("address of a source was not provided") 41 // ErrTooBigMTU informs about the maximum value for Path MTU. 42 ErrTooBigMTU = errors.New("too big value, maximum is 1450") 43 // ErrTooSmlMTU informs about the minimum value for Path MTU. 44 ErrTooSmlMTU = errors.New("too small value, minimum is 68") 45 ) 46 47 // IPFIXDescriptor configures IPFIX for VPP. 48 type IPFIXDescriptor struct { 49 ipfixHandler vppcalls.IpfixVppAPI 50 log logging.Logger 51 } 52 53 // NewIPFIXDescriptor creates a new instance of IPFIXDescriptor. 54 func NewIPFIXDescriptor(ipfixHandler vppcalls.IpfixVppAPI, log logging.PluginLogger) *kvs.KVDescriptor { 55 ctx := &IPFIXDescriptor{ 56 ipfixHandler: ipfixHandler, 57 log: log.NewLogger("ipfix-descriptor"), 58 } 59 typedDescr := &adapter.IPFIXDescriptor{ 60 Name: IPFIXDescriptorName, 61 NBKeyPrefix: ipfix.ModelIPFIX.KeyPrefix(), 62 ValueTypeName: ipfix.ModelIPFIX.ProtoName(), 63 KeySelector: ipfix.ModelIPFIX.IsKeyValid, 64 KeyLabel: ipfix.ModelIPFIX.StripKeyPrefix, 65 ValueComparator: ctx.EquivalentIPFIX, 66 Validate: ctx.Validate, 67 Create: ctx.Create, 68 Delete: ctx.Delete, 69 Retrieve: ctx.Retrieve, 70 Update: ctx.Update, 71 } 72 return adapter.NewIPFIXDescriptor(typedDescr) 73 } 74 75 // EquivalentIPFIX returns true if two IPFIX configurations are equal. 76 func (d *IPFIXDescriptor) EquivalentIPFIX(key string, oldValue, newValue *ipfix.IPFIX) bool { 77 if oldValue.GetCollector().GetAddress() != newValue.GetCollector().GetAddress() { 78 return false 79 } 80 81 if oldValue.GetSourceAddress() != newValue.GetSourceAddress() { 82 return false 83 } 84 85 oldPort := oldValue.GetCollector().GetPort() 86 newPort := newValue.GetCollector().GetPort() 87 if oldPort != newPort { 88 defaultPort := uint32(4739) 89 oldIsNotDefault := oldPort != 0 && oldPort != defaultPort 90 newIsNotDefault := newPort != 0 && newPort != defaultPort 91 92 if oldIsNotDefault || newIsNotDefault { 93 return false 94 } 95 } 96 97 if oldValue.GetVrfId() != newValue.GetVrfId() { 98 return false 99 } 100 101 oldMTU := oldValue.GetPathMtu() 102 newMTU := newValue.GetPathMtu() 103 if oldMTU != newMTU { 104 defaultMTU := uint32(512) 105 oldIsNotDefault := oldMTU != 0 && oldMTU != defaultMTU 106 newIsNotDefault := newMTU != 0 && newMTU != defaultMTU 107 108 if oldIsNotDefault || newIsNotDefault { 109 return false 110 } 111 } 112 113 oldInterval := oldValue.GetTemplateInterval() 114 newInterval := newValue.GetTemplateInterval() 115 if oldInterval != newInterval { 116 defaultInterval := uint32(20) 117 oldIsNotDefault := oldInterval != 0 && oldInterval != defaultInterval 118 newIsNotDefault := newInterval != 0 && newInterval != defaultInterval 119 120 if oldIsNotDefault || newIsNotDefault { 121 return false 122 } 123 } 124 125 return true 126 } 127 128 // Validate does basic check of VPP IPFIX configuration. 129 func (d *IPFIXDescriptor) Validate(key string, value *ipfix.IPFIX) error { 130 if value.GetCollector().GetAddress() == "" { 131 return kvs.NewInvalidValueError(ErrColAddrNotDefined, "collector.address") 132 } 133 134 if value.GetSourceAddress() == "" { 135 return kvs.NewInvalidValueError(ErrSrcAddrNotDefined, "source_address") 136 } 137 138 if mtu := value.GetPathMtu(); mtu == 0 { 139 // That's okay. No worries. VPP will use the default Path MTU value. 140 } else if mtu > vppcalls.MaxPathMTU { 141 return kvs.NewInvalidValueError(ErrTooBigMTU, "path_mtu") 142 } else if mtu < vppcalls.MinPathMTU { 143 return kvs.NewInvalidValueError(ErrTooSmlMTU, "path_mtu") 144 } 145 146 return nil 147 } 148 149 // Create calls Update method, because IPFIX configuration is always there and can not be created. 150 func (d *IPFIXDescriptor) Create(key string, val *ipfix.IPFIX) (metadata interface{}, err error) { 151 _, err = d.Update(key, nil, val, nil) 152 return 153 } 154 155 // Update sets VPP IPFIX configuration. 156 func (d *IPFIXDescriptor) Update(key string, oldVal, newVal *ipfix.IPFIX, oldMetadata interface{}) (newMetadata interface{}, err error) { 157 err = d.ipfixHandler.SetExporter(newVal) 158 return 159 } 160 161 // Delete does nothing, because there are neither ability 162 // nor reasons to delete VPP IPFIX configuration. 163 // You can only configure exporting in a way you want to. 164 func (d *IPFIXDescriptor) Delete(key string, val *ipfix.IPFIX, metadata interface{}) (err error) { 165 return nil 166 } 167 168 // Retrieve returns configuration of IP Flow Infromation eXporter. 169 func (d *IPFIXDescriptor) Retrieve(correlate []adapter.IPFIXKVWithMetadata) (retrieved []adapter.IPFIXKVWithMetadata, err error) { 170 ipfixes, err := d.ipfixHandler.DumpExporters() 171 if err != nil { 172 return nil, err 173 } 174 175 for _, e := range ipfixes { 176 retrieved = append(retrieved, adapter.IPFIXKVWithMetadata{ 177 Key: models.Key(e), 178 Value: e, 179 Origin: kvs.FromSB, 180 }) 181 } 182 183 return retrieved, nil 184 }