go.ligato.io/vpp-agent/v3@v3.5.0/clientv2/vpp/dbadapter/data_resync_db.go (about) 1 // Copyright (c) 2017 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 dbadapter 16 17 import ( 18 "context" 19 20 "go.ligato.io/cn-infra/v2/db/keyval" 21 "go.ligato.io/vpp-agent/v3/pkg/models" 22 "go.ligato.io/vpp-agent/v3/plugins/orchestrator/contextdecorator" 23 24 vppclient "go.ligato.io/vpp-agent/v3/clientv2/vpp" 25 abf "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/abf" 26 acl "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/acl" 27 intf "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 28 ipfix "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipfix" 29 ipsec "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipsec" 30 l2 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l2" 31 l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 32 nat "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/nat" 33 punt "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/punt" 34 stn "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/stn" 35 ) 36 37 // NewDataResyncDSL returns a new instance of DataResyncDSL which implements 38 // the data RESYNC DSL for VPP configuration. 39 // Transaction <txn> is used to propagate changes to plugins. 40 // Function <listKeys> is used to list keys with already existing configuration. 41 func NewDataResyncDSL(txn keyval.ProtoTxn, listKeys func(prefix string) (keyval.ProtoKeyIterator, error)) *DataResyncDSL { 42 return &DataResyncDSL{txn, []string{}, listKeys} 43 } 44 45 // DataResyncDSL is an implementation of Domain Specific Language (DSL) for data 46 // RESYNC of VPP configuration. 47 type DataResyncDSL struct { 48 txn keyval.ProtoTxn 49 txnKeys []string 50 listKeys func(prefix string) (keyval.ProtoKeyIterator, error) 51 } 52 53 // Interface adds VPP interface to the RESYNC request. 54 func (dsl *DataResyncDSL) Interface(val *intf.Interface) vppclient.DataResyncDSL { 55 key := intf.InterfaceKey(val.Name) 56 dsl.txn.Put(key, val) 57 dsl.txnKeys = append(dsl.txnKeys, key) 58 59 return dsl 60 } 61 62 // Span adds VPP span to the RESYNC request. 63 func (dsl *DataResyncDSL) Span(val *intf.Span) vppclient.DataResyncDSL { 64 key := intf.SpanKey(val.InterfaceFrom, val.InterfaceTo) 65 dsl.txn.Put(key, val) 66 dsl.txnKeys = append(dsl.txnKeys, key) 67 68 return dsl 69 } 70 71 // ACL adds Access Control List to the RESYNC request. 72 func (dsl *DataResyncDSL) ACL(val *acl.ACL) vppclient.DataResyncDSL { 73 key := acl.Key(val.Name) 74 dsl.txn.Put(key, val) 75 dsl.txnKeys = append(dsl.txnKeys, key) 76 77 return dsl 78 } 79 80 // ABF adds ACL-based forwarding to the RESYNC request. 81 func (dsl *DataResyncDSL) ABF(val *abf.ABF) vppclient.DataResyncDSL { 82 key := models.Key(val) 83 dsl.txn.Put(key, val) 84 dsl.txnKeys = append(dsl.txnKeys, key) 85 86 return dsl 87 } 88 89 // BD adds Bridge Domain to the RESYNC request. 90 func (dsl *DataResyncDSL) BD(val *l2.BridgeDomain) vppclient.DataResyncDSL { 91 key := l2.BridgeDomainKey(val.Name) 92 dsl.txn.Put(key, val) 93 dsl.txnKeys = append(dsl.txnKeys, key) 94 95 return dsl 96 } 97 98 // BDFIB adds Bridge Domain to the RESYNC request. 99 func (dsl *DataResyncDSL) BDFIB(val *l2.FIBEntry) vppclient.DataResyncDSL { 100 key := l2.FIBKey(val.BridgeDomain, val.PhysAddress) 101 dsl.txn.Put(key, val) 102 dsl.txnKeys = append(dsl.txnKeys, key) 103 104 return dsl 105 } 106 107 // VrfTable adds VRF table to the RESYNC request. 108 func (dsl *DataResyncDSL) VrfTable(val *l3.VrfTable) vppclient.DataResyncDSL { 109 key := l3.VrfTableKey(val.Id, val.Protocol) 110 dsl.txn.Put(key, val) 111 dsl.txnKeys = append(dsl.txnKeys, key) 112 113 return dsl 114 } 115 116 // XConnect adds Cross Connect to the RESYNC request. 117 func (dsl *DataResyncDSL) XConnect(val *l2.XConnectPair) vppclient.DataResyncDSL { 118 key := l2.XConnectKey(val.ReceiveInterface) 119 dsl.txn.Put(key, val) 120 dsl.txnKeys = append(dsl.txnKeys, key) 121 122 return dsl 123 } 124 125 // StaticRoute adds L3 Static Route to the RESYNC request. 126 func (dsl *DataResyncDSL) StaticRoute(val *l3.Route) vppclient.DataResyncDSL { 127 key := models.Key(val) 128 dsl.txn.Put(key, val) 129 dsl.txnKeys = append(dsl.txnKeys, key) 130 131 return dsl 132 } 133 134 // ProxyArp adds L3 proxy ARP to the RESYNC request. 135 func (dsl *DataResyncDSL) ProxyArp(proxyArp *l3.ProxyARP) vppclient.DataResyncDSL { 136 key := models.Key(&l3.ProxyARP{}) 137 dsl.txn.Put(key, proxyArp) 138 dsl.txnKeys = append(dsl.txnKeys, key) 139 140 return dsl 141 } 142 143 // Arp adds L3 ARP entry to the RESYNC request. 144 func (dsl *DataResyncDSL) Arp(val *l3.ARPEntry) vppclient.DataResyncDSL { 145 key := l3.ArpEntryKey(val.Interface, val.IpAddress) 146 dsl.txn.Put(key, val) 147 dsl.txnKeys = append(dsl.txnKeys, key) 148 149 return dsl 150 } 151 152 // IPScanNeighbor adds L3 IP Scan Neighbor to the RESYNC request. 153 func (dsl *DataResyncDSL) IPScanNeighbor(ipScanNeigh *l3.IPScanNeighbor) vppclient.DataResyncDSL { 154 key := models.Key(&l3.IPScanNeighbor{}) 155 dsl.txn.Put(key, ipScanNeigh) 156 dsl.txnKeys = append(dsl.txnKeys, key) 157 158 return dsl 159 } 160 161 // StnRule adds Stn rule to the RESYNC request. 162 func (dsl *DataResyncDSL) StnRule(val *stn.Rule) vppclient.DataResyncDSL { 163 key := stn.Key(val.Interface, val.IpAddress) 164 dsl.txn.Put(key, val) 165 dsl.txnKeys = append(dsl.txnKeys, key) 166 167 return dsl 168 } 169 170 // NAT44Global adds global NAT44 configuration to the RESYNC request. 171 func (dsl *DataResyncDSL) NAT44Global(nat44 *nat.Nat44Global) vppclient.DataResyncDSL { 172 key := models.Key(&nat.Nat44Global{}) 173 dsl.txn.Put(key, nat44) 174 dsl.txnKeys = append(dsl.txnKeys, key) 175 176 return dsl 177 } 178 179 // DNAT44 adds DNAT44 configuration to the RESYNC request 180 func (dsl *DataResyncDSL) DNAT44(nat44 *nat.DNat44) vppclient.DataResyncDSL { 181 key := nat.DNAT44Key(nat44.Label) 182 dsl.txn.Put(key, nat44) 183 dsl.txnKeys = append(dsl.txnKeys, key) 184 185 return dsl 186 } 187 188 // NAT44Interface adds NAT44 interface configuration to the RESYNC request. 189 func (dsl *DataResyncDSL) NAT44Interface(natIf *nat.Nat44Interface) vppclient.DataResyncDSL { 190 key := models.Key(natIf) 191 dsl.txn.Put(key, natIf) 192 dsl.txnKeys = append(dsl.txnKeys, key) 193 194 return dsl 195 } 196 197 // NAT44AddressPool adds NAT44 address pool configuration to the RESYNC request. 198 func (dsl *DataResyncDSL) NAT44AddressPool(pool *nat.Nat44AddressPool) vppclient.DataResyncDSL { 199 key := models.Key(pool) 200 dsl.txn.Put(key, pool) 201 dsl.txnKeys = append(dsl.txnKeys, key) 202 203 return dsl 204 } 205 206 // IPSecSA adds request to create a new Security Association 207 func (dsl *DataResyncDSL) IPSecSA(sa *ipsec.SecurityAssociation) vppclient.DataResyncDSL { 208 key := ipsec.SAKey(sa.Index) 209 dsl.txn.Put(key, sa) 210 dsl.txnKeys = append(dsl.txnKeys, key) 211 212 return dsl 213 } 214 215 // IPSecSPD adds request to create a new Security Policy Database 216 func (dsl *DataResyncDSL) IPSecSPD(spd *ipsec.SecurityPolicyDatabase) vppclient.DataResyncDSL { 217 key := ipsec.SPDKey(spd.Index) 218 dsl.txn.Put(key, spd) 219 dsl.txnKeys = append(dsl.txnKeys, key) 220 221 return dsl 222 } 223 224 // IPSecSP adds request to RESYNC a Security Policy 225 func (dsl *DataResyncDSL) IPSecSP(sp *ipsec.SecurityPolicy) vppclient.DataResyncDSL { 226 key := models.Key(sp) 227 dsl.txn.Put(key, sp) 228 dsl.txnKeys = append(dsl.txnKeys, key) 229 230 return dsl 231 } 232 233 // IPSecTunnelProtection adds request to RESYNC an IPSec tunnel protection 234 func (dsl *DataResyncDSL) IPSecTunnelProtection(tp *ipsec.TunnelProtection) vppclient.DataResyncDSL { 235 key := models.Key(tp) 236 dsl.txn.Put(key, tp) 237 dsl.txnKeys = append(dsl.txnKeys, key) 238 return dsl 239 } 240 241 // PuntIPRedirect adds request to RESYNC a rule used to punt L3 traffic via interface. 242 func (dsl *DataResyncDSL) PuntIPRedirect(val *punt.IPRedirect) vppclient.DataResyncDSL { 243 key := punt.IPRedirectKey(val.L3Protocol, val.TxInterface) 244 dsl.txn.Put(key, val) 245 dsl.txnKeys = append(dsl.txnKeys, key) 246 247 return dsl 248 } 249 250 // PuntToHost adds request to RESYNC a rule used to punt L4 traffic to a host. 251 func (dsl *DataResyncDSL) PuntToHost(val *punt.ToHost) vppclient.DataResyncDSL { 252 key := punt.ToHostKey(val.L3Protocol, val.L4Protocol, val.Port) 253 dsl.txn.Put(key, val) 254 dsl.txnKeys = append(dsl.txnKeys, key) 255 256 return dsl 257 } 258 259 // PuntException adds request to create or update exception to punt specific packets. 260 func (dsl *DataResyncDSL) PuntException(val *punt.Exception) vppclient.DataResyncDSL { 261 key := models.Key(val) 262 dsl.txn.Put(key, val) 263 dsl.txnKeys = append(dsl.txnKeys, key) 264 265 return dsl 266 } 267 268 // IPFIX adds IPFIX configuration to the RESYNC request. 269 func (dsl *DataResyncDSL) IPFIX(val *ipfix.IPFIX) vppclient.DataResyncDSL { 270 key := models.Key(val) 271 dsl.txn.Put(key, val) 272 dsl.txnKeys = append(dsl.txnKeys, key) 273 274 return dsl 275 } 276 277 // FlowprobeParams adds Flowprobe Params configuration to the RESYNC request. 278 func (dsl *DataResyncDSL) FlowprobeParams(val *ipfix.FlowProbeParams) vppclient.DataResyncDSL { 279 key := models.Key(val) 280 dsl.txn.Put(key, val) 281 dsl.txnKeys = append(dsl.txnKeys, key) 282 283 return dsl 284 } 285 286 // FlowprobeFeature adds Flowprobe Feature configuration to the RESYNC request. 287 func (dsl *DataResyncDSL) FlowprobeFeature(val *ipfix.FlowProbeFeature) vppclient.DataResyncDSL { 288 key := models.Key(val) 289 dsl.txn.Put(key, val) 290 dsl.txnKeys = append(dsl.txnKeys, key) 291 292 return dsl 293 } 294 295 // VRRP adds L3 proxy VRRP to the RESYNC request. 296 func (dsl *DataResyncDSL) VRRP(vrrp *l3.VRRPEntry) vppclient.DataResyncDSL { 297 key := l3.VrrpEntryKey(vrrp.Interface, vrrp.VrId) 298 dsl.txn.Put(key, vrrp) 299 dsl.txnKeys = append(dsl.txnKeys, key) 300 301 return dsl 302 } 303 304 // AppendKeys is a helper function that fills the keySet <keys> with values 305 // pointed to by the iterator <it>. 306 func appendKeys(keys *keySet, it keyval.ProtoKeyIterator) { 307 for { 308 k, _, stop := it.GetNext() 309 if stop { 310 break 311 } 312 313 (*keys)[k] = nil 314 } 315 } 316 317 // KeySet is a helper type that reuses map keys to store values as a set. 318 // The values of the map are nil. 319 type keySet map[string] /*key*/ interface{} /*nil*/ 320 321 // Send propagates the request to the plugins. 322 // It deletes obsolete keys if listKeys() (from constructor) function is not nil. 323 func (dsl *DataResyncDSL) Send() vppclient.Reply { 324 325 for dsl.listKeys != nil { 326 toBeDeleted := keySet{} 327 328 // fill all known keys of one VPP: 329 330 keys, err := dsl.listKeys(intf.ModelInterface.KeyPrefix()) 331 if err != nil { 332 break 333 } 334 appendKeys(&toBeDeleted, keys) 335 keys, err = dsl.listKeys(l2.ModelBridgeDomain.KeyPrefix()) 336 if err != nil { 337 break 338 } 339 appendKeys(&toBeDeleted, keys) 340 keys, err = dsl.listKeys(l2.ModelXConnectPair.KeyPrefix()) 341 if err != nil { 342 break 343 } 344 appendKeys(&toBeDeleted, keys) 345 keys, err = dsl.listKeys(l3.ModelRoute.KeyPrefix()) 346 if err != nil { 347 break 348 } 349 appendKeys(&toBeDeleted, keys) 350 keys, err = dsl.listKeys(l3.ModelARPEntry.KeyPrefix()) 351 if err != nil { 352 break 353 } 354 appendKeys(&toBeDeleted, keys) 355 356 // remove keys that are part of the transaction 357 for _, txnKey := range dsl.txnKeys { 358 delete(toBeDeleted, txnKey) 359 } 360 361 for delKey := range toBeDeleted { 362 dsl.txn.Delete(delKey) 363 } 364 365 break 366 } 367 368 ctx := context.Background() 369 ctx = contextdecorator.DataSrcContext(ctx, "localclient") 370 err := dsl.txn.Commit(ctx) 371 372 return &Reply{err: err} 373 }