go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/l3plugin/descriptor/dhcp_proxy.go (about) 1 // Copyright (c) 2019 PANTHEON.tech 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 "net" 20 21 "github.com/pkg/errors" 22 "go.ligato.io/cn-infra/v2/logging" 23 "go.ligato.io/cn-infra/v2/utils/addrs" 24 25 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 26 "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/descriptor/adapter" 27 "go.ligato.io/vpp-agent/v3/plugins/vpp/l3plugin/vppcalls" 28 l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 29 ) 30 31 const ( 32 // ProxyArpInterfaceDescriptorName is the name of the descriptor. 33 DHCPProxyDescriptorName = "dhcp-proxy" 34 35 //dependecy labels 36 rxVrfTableDependency = "rx-vrf-table-exists" 37 dhcpSrvVrfTableDependency = "vrf-table-%d-used-by-dhcp-server-exists" 38 ) 39 40 // DHCPProxyDescriptor teaches KVScheduler how to configure VPP DHCP proxy. 41 type DHCPProxyDescriptor struct { 42 log logging.Logger 43 dhcpProxyHandler vppcalls.DHCPProxyAPI 44 scheduler kvs.KVScheduler 45 } 46 47 // NewDHCPProxyDescriptor creates a new instance of the DHCPProxyDescriptor. 48 func NewDHCPProxyDescriptor(scheduler kvs.KVScheduler, 49 dhcpProxyHandler vppcalls.DHCPProxyAPI, log logging.PluginLogger) *kvs.KVDescriptor { 50 51 ctx := &DHCPProxyDescriptor{ 52 scheduler: scheduler, 53 dhcpProxyHandler: dhcpProxyHandler, 54 log: log.NewLogger("dhcp-proxy-descriptor"), 55 } 56 57 typedDescr := &adapter.DHCPProxyDescriptor{ 58 Name: DHCPProxyDescriptorName, 59 KeySelector: l3.ModelDHCPProxy.IsKeyValid, 60 KeyLabel: l3.ModelDHCPProxy.StripKeyPrefix, 61 NBKeyPrefix: l3.ModelDHCPProxy.KeyPrefix(), 62 ValueTypeName: l3.ModelDHCPProxy.ProtoName(), 63 Create: ctx.Create, 64 Delete: ctx.Delete, 65 Retrieve: ctx.Retrieve, 66 Dependencies: ctx.Dependencies, 67 Validate: ctx.Validate, 68 } 69 return adapter.NewDHCPProxyDescriptor(typedDescr) 70 } 71 72 func (d *DHCPProxyDescriptor) Validate(key string, value *l3.DHCPProxy) error { 73 74 ipAddr := net.ParseIP(value.SourceIpAddress) 75 if ipAddr == nil { 76 return errors.Errorf("invalid source IP address: %q", value.SourceIpAddress) 77 } 78 79 for _, server := range value.Servers { 80 serverIPAddr := net.ParseIP(server.IpAddress) 81 if serverIPAddr == nil { 82 return errors.Errorf("invalid server IP address: %q", server.IpAddress) 83 } 84 85 if ipAddr.To4() != nil && serverIPAddr.To4() == nil || serverIPAddr.To4() != nil && ipAddr.To4() == nil { 86 return errors.Errorf("Server address %s must use same IP protocol as source address %s", 87 serverIPAddr, ipAddr) 88 } 89 } 90 return nil 91 } 92 93 // Dependencies lists dependencies for a VPP DHCP proxy. 94 func (d *DHCPProxyDescriptor) Dependencies(key string, value *l3.DHCPProxy) (deps []kvs.Dependency) { 95 // non-zero VRFs 96 var protocol l3.VrfTable_Protocol 97 _, isIPv6, _ := addrs.ParseIPWithPrefix(value.SourceIpAddress) 98 if isIPv6 { 99 protocol = l3.VrfTable_IPV6 100 } 101 102 if value.RxVrfId != 0 { 103 deps = append(deps, kvs.Dependency{ 104 Label: rxVrfTableDependency, 105 Key: l3.VrfTableKey(value.RxVrfId, protocol), 106 }) 107 } 108 109 for _, server := range value.Servers { 110 if server.VrfId != 0 { 111 deps = append(deps, kvs.Dependency{ 112 Label: fmt.Sprintf(dhcpSrvVrfTableDependency, server.VrfId), 113 Key: l3.VrfTableKey(server.VrfId, protocol), 114 }) 115 } 116 } 117 118 return deps 119 } 120 121 // Create enables VPP DHCP proxy. 122 func (d *DHCPProxyDescriptor) Create(key string, value *l3.DHCPProxy) (metadata interface{}, err error) { 123 if err := d.dhcpProxyHandler.CreateDHCPProxy(value); err != nil { 124 return nil, errors.Errorf("failed to create DHCP proxy %v", err) 125 } 126 return nil, nil 127 } 128 129 // Delete disables VPP DHCP proxy. 130 func (d *DHCPProxyDescriptor) Delete(key string, value *l3.DHCPProxy, metadata interface{}) error { 131 if err := d.dhcpProxyHandler.DeleteDHCPProxy(value); err != nil { 132 return errors.Errorf("failed to delete DHCP proxy %v", err) 133 } 134 return nil 135 } 136 137 // Retrieve returns current VPP DHCP proxy configuration. 138 func (d *DHCPProxyDescriptor) Retrieve(correlate []adapter.DHCPProxyKVWithMetadata) (retrieved []adapter.DHCPProxyKVWithMetadata, err error) { 139 // Retrieve VPP configuration 140 dhcpProxyDetails, err := d.dhcpProxyHandler.DumpDHCPProxy() 141 142 if err != nil { 143 return nil, err 144 } 145 146 if dhcpProxyDetails == nil { 147 return nil, nil 148 } 149 150 for _, detail := range dhcpProxyDetails { 151 retrieved = append(retrieved, adapter.DHCPProxyKVWithMetadata{ 152 Key: l3.DHCPProxyKey(detail.DHCPProxy.SourceIpAddress, detail.DHCPProxy.RxVrfId), 153 Value: detail.DHCPProxy, 154 Origin: kvs.FromNB, 155 }) 156 } 157 158 return retrieved, nil 159 }