go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/stnplugin/descriptor/stn.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/logging" 20 "google.golang.org/protobuf/proto" 21 22 "go.ligato.io/vpp-agent/v3/pkg/models" 23 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 24 ifDescriptor "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor" 25 "go.ligato.io/vpp-agent/v3/plugins/vpp/stnplugin/descriptor/adapter" 26 "go.ligato.io/vpp-agent/v3/plugins/vpp/stnplugin/vppcalls" 27 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 28 stn "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/stn" 29 ) 30 31 const ( 32 // STNDescriptorName is the name of the descriptor for VPP STN rules 33 STNDescriptorName = "vpp-stn-rules" 34 35 // dependency labels 36 stnInterfaceDep = "stn-interface-exists" 37 ) 38 39 // A list of non-retriable errors: 40 var ( 41 // ErrSTNWithoutInterface is returned when VPP STN rule has undefined interface. 42 ErrSTNWithoutInterface = errors.New("VPP STN rule defined without interface") 43 44 // ErrSTNWithoutIPAddress is returned when VPP STN rule has undefined IP address. 45 ErrSTNWithoutIPAddress = errors.New("VPP STN rule defined without IP address") 46 ) 47 48 // STNDescriptor teaches KVScheduler how to configure VPP STN rules. 49 type STNDescriptor struct { 50 // dependencies 51 log logging.Logger 52 stnHandler vppcalls.StnVppAPI 53 } 54 55 // NewSTNDescriptor creates a new instance of the STN descriptor. 56 func NewSTNDescriptor(stnHandler vppcalls.StnVppAPI, log logging.PluginLogger) *STNDescriptor { 57 return &STNDescriptor{ 58 log: log.NewLogger("stn-descriptor"), 59 stnHandler: stnHandler, 60 } 61 } 62 63 // GetDescriptor returns descriptor suitable for registration (via adapter) with 64 // the KVScheduler. 65 func (d *STNDescriptor) GetDescriptor() *adapter.STNDescriptor { 66 return &adapter.STNDescriptor{ 67 Name: STNDescriptorName, 68 NBKeyPrefix: stn.ModelRule.KeyPrefix(), 69 ValueTypeName: stn.ModelRule.ProtoName(), 70 KeySelector: stn.ModelRule.IsKeyValid, 71 KeyLabel: stn.ModelRule.StripKeyPrefix, 72 ValueComparator: d.EquivalentSTNs, 73 Validate: d.Validate, 74 Create: d.Create, 75 Delete: d.Delete, 76 Retrieve: d.Retrieve, 77 Dependencies: d.Dependencies, 78 RetrieveDependencies: []string{ifDescriptor.InterfaceDescriptorName}, 79 } 80 } 81 82 // EquivalentSTNs is case-insensitive comparison function for stn.Rule. 83 func (d *STNDescriptor) EquivalentSTNs(key string, oldSTN, newSTN *stn.Rule) bool { 84 // parameters compared by proto equal 85 return proto.Equal(oldSTN, newSTN) 86 } 87 88 // Validate validates VPP STN rule configuration. 89 func (d *STNDescriptor) Validate(key string, stn *stn.Rule) error { 90 if stn.Interface == "" { 91 return kvs.NewInvalidValueError(ErrSTNWithoutInterface, "interface") 92 } 93 if stn.IpAddress == "" { 94 return kvs.NewInvalidValueError(ErrSTNWithoutIPAddress, "ip_address") 95 } 96 return nil 97 } 98 99 // Create adds new STN rule. 100 func (d *STNDescriptor) Create(key string, stn *stn.Rule) (metadata interface{}, err error) { 101 // add STN rule 102 err = d.stnHandler.AddSTNRule(stn) 103 if err != nil { 104 d.log.Error(err) 105 } 106 return nil, err 107 } 108 109 // Delete removes VPP STN rule. 110 func (d *STNDescriptor) Delete(key string, stn *stn.Rule, metadata interface{}) error { 111 err := d.stnHandler.DeleteSTNRule(stn) 112 if err != nil { 113 d.log.Error(err) 114 } 115 return err 116 } 117 118 // Dependencies for STN rule are represented by interface 119 func (d *STNDescriptor) Dependencies(key string, stn *stn.Rule) (dependencies []kvs.Dependency) { 120 dependencies = append(dependencies, kvs.Dependency{ 121 Label: stnInterfaceDep, 122 Key: interfaces.InterfaceKey(stn.Interface), 123 }) 124 return dependencies 125 } 126 127 // Retrieve returns all configured VPP STN rules. 128 func (d *STNDescriptor) Retrieve(correlate []adapter.STNKVWithMetadata) (retrieved []adapter.STNKVWithMetadata, err error) { 129 stnRules, err := d.stnHandler.DumpSTNRules() 130 if err != nil { 131 d.log.Error(err) 132 return retrieved, err 133 } 134 for _, stnRule := range stnRules { 135 retrieved = append(retrieved, adapter.STNKVWithMetadata{ 136 Key: models.Key(stnRule.Rule), //stn.Key(stnRule.Rule.Interface, stnRule.Rule.IpAddress), 137 Value: stnRule.Rule, 138 Origin: kvs.FromNB, // all STN rules are configured from NB 139 }) 140 } 141 142 return retrieved, nil 143 }