go.ligato.io/vpp-agent/v3@v3.5.0/examples/kvscheduler/mock_plugins/l2plugin/descriptor/bridgedomain.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 "github.com/pkg/errors" 19 "go.ligato.io/cn-infra/v2/idxmap" 20 "go.ligato.io/cn-infra/v2/logging" 21 22 ifdescriptor "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/ifplugin/descriptor" 23 "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin/descriptor/adapter" 24 "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin/mockcalls" 25 l2 "go.ligato.io/vpp-agent/v3/examples/kvscheduler/mock_plugins/l2plugin/model" 26 "go.ligato.io/vpp-agent/v3/pkg/idxvpp" 27 "go.ligato.io/vpp-agent/v3/pkg/models" 28 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 29 ) 30 31 const ( 32 // BridgeDomainDescriptorName is the name of the descriptor for mock bridge domains. 33 BridgeDomainDescriptorName = "mock-bridge-domain" 34 ) 35 36 // Example of some validation errors: 37 var ( 38 // ErrBridgeDomainWithoutName is returned when mock bridge domain configuration 39 // has undefined Name attribute. 40 ErrBridgeDomainWithoutName = errors.New("mock bridge domain defined without logical name") 41 42 // ErrBridgeDomainWithMultipleBVI is returned when mock bridge domain is defined with 43 // multiple BVI interfaces. 44 ErrBridgeDomainWithMultipleBVI = errors.New("mock bridge domain defined with mutliple BVIs") 45 ) 46 47 // BridgeDomainDescriptor teaches KVScheduler how to configure bridge domains 48 // in the mock SB. 49 type BridgeDomainDescriptor struct { 50 // dependencies 51 log logging.Logger 52 bdHandler mockcalls.MockBDAPI 53 } 54 55 // NewBridgeDomainDescriptor creates a new instance of the BridgeDomain descriptor. 56 func NewBridgeDomainDescriptor(bdHandler mockcalls.MockBDAPI, log logging.PluginLogger) *kvs.KVDescriptor { 57 // descriptors are supposed to be stateless and this principle is not broken 58 // here - we only need to keep context consisting of references to logger 59 // and the BD handler for mock SB, to be used inside the CRUD methods. 60 descrCtx := &BridgeDomainDescriptor{ 61 bdHandler: bdHandler, 62 log: log.NewLogger("mock-bd-descriptor"), 63 } 64 65 // use adapter to convert typed descriptor into generic descriptor API 66 typedDescr := &adapter.BridgeDomainDescriptor{ 67 Name: BridgeDomainDescriptorName, 68 NBKeyPrefix: l2.ModelBridgeDomain.KeyPrefix(), 69 ValueTypeName: l2.ModelBridgeDomain.ProtoName(), 70 KeySelector: l2.ModelBridgeDomain.IsKeyValid, 71 KeyLabel: l2.ModelBridgeDomain.StripKeyPrefix, 72 ValueComparator: descrCtx.EquivalentBridgeDomains, 73 WithMetadata: true, 74 MetadataMapFactory: descrCtx.MetadataFactory, 75 Validate: descrCtx.Validate, 76 Create: descrCtx.Create, 77 Delete: descrCtx.Delete, 78 79 // Note: no need for Update operation - the interfaces are derived out 80 // and updated as separate key-value pairs, whereas a change in 81 // the Name actually results in a different key and creates a new 82 // BD altogether. 83 84 Retrieve: descrCtx.Retrieve, 85 DerivedValues: descrCtx.DerivedValues, 86 87 // Retrieve interfaces first to have the index with interface metadata 88 // up-to-date when Retrieve for bridge domains is called, which then uses 89 // the index to translate interface names to the corresponding integer 90 // handles used in the mock SB. 91 RetrieveDependencies: []string{ifdescriptor.InterfaceDescriptorName}, 92 } 93 return adapter.NewBridgeDomainDescriptor(typedDescr) 94 } 95 96 // EquivalentBridgeDomains always returns true - this may seems strange, but 97 // two revisions of the same BD have the same key, therefore they must equal 98 // in Name, which is included in the key. The interfaces may differ, but 99 // they are derived out and updated as separate key-value pairs. 100 func (d *BridgeDomainDescriptor) EquivalentBridgeDomains(key string, oldBD, newBD *l2.BridgeDomain) bool { 101 return true 102 } 103 104 // MetadataFactory is a factory for index-map customized for mock bridge domains. 105 func (d *BridgeDomainDescriptor) MetadataFactory() idxmap.NamedMappingRW { 106 return idxvpp.NewNameToIndex(d.log, "mock-bd-index", nil) 107 } 108 109 // Validate validates mock bridge domain configuration. 110 func (d *BridgeDomainDescriptor) Validate(key string, bd *l2.BridgeDomain) error { 111 if bd.Name == "" { 112 return kvs.NewInvalidValueError(ErrBridgeDomainWithoutName, "name") 113 } 114 115 // check that BD has defined at most one BVI 116 var hasBVI bool 117 for _, bdIface := range bd.Interfaces { 118 if bdIface.BridgedVirtualInterface { 119 if hasBVI { 120 return kvs.NewInvalidValueError(ErrBridgeDomainWithMultipleBVI, 121 "interfaces.bridged_virtual_interface") 122 } 123 hasBVI = true 124 } 125 } 126 return nil 127 } 128 129 // Create adds new bridge domain. 130 func (d *BridgeDomainDescriptor) Create(key string, bd *l2.BridgeDomain) (metadata *idxvpp.OnlyIndex, err error) { 131 sbBDHandle, err := d.bdHandler.CreateBridgeDomain(bd.Name) 132 if err != nil { 133 d.log.Error(err) 134 return nil, err 135 } 136 137 // fill the metadata and return 138 metadata = &idxvpp.OnlyIndex{ 139 Index: sbBDHandle, 140 } 141 return metadata, nil 142 } 143 144 // Delete removes VPP bridge domain. 145 func (d *BridgeDomainDescriptor) Delete(key string, bd *l2.BridgeDomain, metadata *idxvpp.OnlyIndex) error { 146 err := d.bdHandler.DeleteBridgeDomain(metadata.GetIndex()) 147 if err != nil { 148 d.log.Error(err) 149 } 150 return err 151 } 152 153 // Retrieve returns all configured mock bridge domains. 154 func (d *BridgeDomainDescriptor) Retrieve(correlate []adapter.BridgeDomainKVWithMetadata) (retrieved []adapter.BridgeDomainKVWithMetadata, err error) { 155 bds, err := d.bdHandler.DumpBridgeDomains() 156 if err != nil { 157 return nil, err 158 } 159 160 for sbBDHandle, bd := range bds { 161 retrieved = append(retrieved, adapter.BridgeDomainKVWithMetadata{ 162 Key: models.Key(bd), 163 Value: bd, 164 Metadata: &idxvpp.OnlyIndex{Index: sbBDHandle}, 165 Origin: kvs.FromNB, // not considering OBTAINED BDs in our simplified example 166 }) 167 } 168 return retrieved, nil 169 } 170 171 // DerivedValues derives l2.BridgeDomain_Interface for every interface assigned 172 // to the bridge domain. 173 func (d *BridgeDomainDescriptor) DerivedValues(key string, bd *l2.BridgeDomain) (derValues []kvs.KeyValuePair) { 174 // BD interfaces 175 for _, bdIface := range bd.Interfaces { 176 derValues = append(derValues, kvs.KeyValuePair{ 177 Key: l2.BDInterfaceKey(bd.Name, bdIface.Name), 178 Value: bdIface, 179 }) 180 } 181 return derValues 182 }