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  }