aboutsummaryrefslogtreecommitdiffstats
path: root/src/vpp-api/vom/om.hpp
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2018-04-25 19:11:15 +0200
committerNeale Ranns <nranns@cisco.com>2018-04-27 11:35:07 +0000
commit164e5f8c63652028ecb9c3570e1ea8618b163071 (patch)
tree7423f5abbc61b761df9a679c7974f17613736020 /src/vpp-api/vom/om.hpp
parentaa682a39b76ee043f65313f23e134bf18fe7a47e (diff)
Move VOM to extras/vom
Change-Id: Iea174f03dfba3bd06024db0f0cc373532300dcae Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src/vpp-api/vom/om.hpp')
-rw-r--r--src/vpp-api/vom/om.hpp356
1 files changed, 0 insertions, 356 deletions
diff --git a/src/vpp-api/vom/om.hpp b/src/vpp-api/vom/om.hpp
deleted file mode 100644
index e68d5ea0017..00000000000
--- a/src/vpp-api/vom/om.hpp
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright (c) 2017 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __VOM_OM_H__
-#define __VOM_OM_H__
-
-#include <algorithm>
-#include <memory>
-#include <set>
-
-#include "vom/client_db.hpp"
-#include "vom/hw.hpp"
-
-/**
-
-The VPP Object Model (VOM) library.
-
-Before we begin, a glossary of terms:
- - Agent or client: A user mode process that links to and uses the VOM library
- to programme VPP
- - VPP: A running instance of VPP
- - High Availability (HA): Scenarios where the client and/or VPP restart with
- minimal service interruption.
- - CReate, Update, Delete (CRUD): An API style where the producer issues
- notifications to changes to objects
-
-The VOM is a C++ library that models entities in VPP as C++ classes. The
- relationships between VOM objects and VPP entities is not always 1:1. Some
- effort has been made to construct a higher level, more abstract API to VPP
- programming*.
-The client programming model is simple (or at least I intended it to be..). The
-client deals in ‘desired’ state, that is, it expresses the objects it wants to
-exists (in VPP) and the properties that the object should have, i.e**;
- Interface af1(“my-af-packet-1”, AFPACKET, admin::UP);
-Then the client ‘writes’ this object into the ‘model’
- OM::write(“clients-thing-1”, af1);
-
-“clients-thing-1” is a description of the entity within the client’s domain that
-‘owns’ (or has locked or has a reference to) the VOM object. There can be many
-owners of each VOM object. It will be the last owner’s update that will be
-programmed in VPP. This model means that the client is not burdened with
-maintaining which of its objects have created which VOM objects. If the client
-is itself driven by a CRUD API, then create notifications are implemented as
- above. Update notifications add two extra statements;
- OM::mark(“clients-thing-1”);
- … do writes ….
- OM::sweep(“clients-thing-1”);
-These ‘mark’ and ‘sweep’ statements are indications to OM that firstly, indicate
-that all the objects owned by “clients-thing-1” are now stale, i.e that the
-client may no longer need them. If one of the subsequent writes should update a
-stale object, then it is no longer stale. The sweep statement will ‘remove’ all
-the remaining stale objects. In this model, the client does not need to maintain
-the mapping of VOM objects to its own objects – it can simply express what it
-needs now.
-The delete notification is simply:
- OM::remove(“clients-thing-1”);
-Which will remove all the objects in VOM that are owned by “clients-thing-1”.
-Where ‘remove’ in this sense means unlock and unreference, the VOM object, and
-VPP state, will only be truly removed once there are no more owners. This is
-equivalent to a mark & sweep with no intermediate writes.
-
-To provide this client side model the VOM is a stateful library, meaning that
-for each entity it creates in VPP, VOM maintains its own representation of that
-object. VOM can therefore be memory hungry. The desired state is expressed by
-the client, the ‘actual’ state is maintained by VOM. VOM will consolidate the
-two states when the client writes to the OM and thus issue VPP only the changes
-required.
-
-The concepts of ownership and statefulness also allow the support for HA
-scenarios.
-VPP restart: When VPP restarts, VOM will reconnect and ‘replay’ its state, in
-dependency order, to VPP. The client does not need to regenerate its desired
-state.
-Client restart: when the client restarts, VOM will read/dump the current state
-of all VPP objects and store them in the OM owned by the special owner “boot”.
-As the client reprogrammes its desired state, objects will become owned by both
-the boot process and the client. At the point in time, as determined by the
-client, all stale state, that owned only by boot, can be purged. Hence the
-system reaches the correct final state, with no interruption to VPP forwarding.
-
-
-Basic Design:
-
-Each object in VOM (i.e. an interface, route, bridge-domain, etc) is stored in a
-per-type object database, with an object-type specific key. This ‘singular’ DB
-has a value-type of a weak pointer to the object. I use the term ‘singular’ to
-refer to the instance of the object stored in these databases, to be distinct
-from the instances the client constructs to represent desired state.
-The ‘client’ DB maintains the mapping of owner to object. The value type of the
-client DB is a shared pointer to the singular instance of the owned object.
-Once all the owners are gone, and all the shared pointers are destroyed, the
-singular instance is also destroyed.
-
-Each VOM object has some basic behaviour:
- update: issue to VPP an update to this object’s state. This could include the
- create
- sweep: delete the VPP entity – called when the object is destroyed.
- replay: issue to VPP all the commands needed to re-programme (VPP restart HA
- scenario)
- populate: read state from VPP and add it to the OM (client restart HA
-scenario)
-
-The object code is boiler-plate, in some cases (like the ACLs) even template.
-The objects are purposefully left as simple, functionality free as possible.
-
-Communication with VPP is through a ‘queue’ of ‘commands’. A command is
-essentially an object wrapper around a VPP binary API call (although we do use
-the VAPI C++ bindings too). Commands come in three flavours:
- RPC: do this; done.
- DUMP: give me all of these things; here you go
- EVENT; tell me about these events; here’s one …. Here’s one…. Oh here’s
- another….. etc.
-
-RPC and DUMP commands are handled synchronously. Therefore on return from
-OM::write(…) VPP has been issued with the request and responded. EVENTs are
-asynchronous and will be delivered to the listeners in a different thread – so
-beware!!
-
-* As such VOM provides some level of insulation to the changes to the VPP
- binary API.
-** some of the type names are shorten for brevity’s sake.
-
-*/
-namespace VOM {
-/**
- * The interface to writing objects into VPP OM.
- */
-class OM
-{
-public:
- /**
- * A class providing the RAII pattern for mark and sweep
- */
- class mark_n_sweep
- {
- public:
- /**
- * Constructor - will call mark on the key
- */
- mark_n_sweep(const client_db::key_t& key);
-
- /**
- * Destructor - will call sweep on the key
- */
- ~mark_n_sweep();
-
- private:
- /**
- * no copies
- */
- mark_n_sweep(const mark_n_sweep& ms) = delete;
-
- /**
- * The client whose state we are guarding.
- */
- client_db::key_t m_key;
- };
-
- /**
- * Init
- */
- static void init();
-
- /**
- * populate the OM with state read from HW.
- */
- static void populate(const client_db::key_t& key);
-
- /**
- * Mark all state owned by this key as stale
- */
- static void mark(const client_db::key_t& key);
-
- /**
- * Sweep all the key's objects that are stale
- */
- static void sweep(const client_db::key_t& key);
-
- /**
- * Replay all of the objects to HW.
- */
- static void replay(void);
-
- /**
- * Make the State in VPP reflect the expressed desired state.
- * But don't call the HW - use this whilst processing dumped
- * data from HW
- */
- template <typename OBJ>
- static rc_t commit(const client_db::key_t& key, const OBJ& obj)
- {
- rc_t rc = rc_t::OK;
-
- HW::disable();
- rc = OM::write(key, obj);
- HW::enable();
-
- return (rc);
- }
-
- /**
- * Make the State in VPP reflect the expressed desired state.
- * After processing all the objects in the queue, in FIFO order,
- * any remaining state owned by the client_db::key_t is purged.
- * This is a template function so the object's update() function is
- * always called with the derived type.
- */
- template <typename OBJ>
- static rc_t write(const client_db::key_t& key, const OBJ& obj)
- {
- rc_t rc = rc_t::OK;
-
- /*
- * Find the singular instance another owner may have created.
- * this always returns something.
- */
- std::shared_ptr<OBJ> inst = obj.singular();
-
- /*
- * Update the existing object with the new desired state
- */
- inst->update(obj);
-
- /*
- * Find if the object already stored on behalf of this key.
- * and mark them stale
- */
- object_ref_list& objs = m_db->find(key);
-
- /*
- * Iterate through this list to find a matchin' object
- * to the one requested.
- */
- auto match_ptr = [inst](const object_ref& oref) {
- return (inst == oref.obj());
- };
- auto it = std::find_if(objs.begin(), objs.end(), match_ptr);
-
- if (it != objs.end()) {
- /*
- * yes, this key already owns this object.
- */
- it->clear();
- } else {
- /*
- * Add the singular instance to the owners list
- */
- objs.insert(object_ref(inst));
- }
-
- return (HW::write());
- }
-
- /**
- * Remove all object in the OM referenced by the key
- */
- static void remove(const client_db::key_t& key);
-
- /**
- * Print each of the object in the DB into the stream provided
- */
- static void dump(const client_db::key_t& key, std::ostream& os);
-
- /**
- * Print each of the KEYS
- */
- static void dump(std::ostream& os);
-
- /**
- * Class definition for listeners to OM events
- */
- class listener
- {
- public:
- listener() = default;
- virtual ~listener() = default;
-
- /**
- * Handle a populate event
- */
- virtual void handle_populate(const client_db::key_t& key) = 0;
-
- /**
- * Handle a replay event
- */
- virtual void handle_replay() = 0;
-
- /**
- * Get the sortable Id of the listener
- */
- virtual dependency_t order() const = 0;
-
- /**
- * less than operator for set sorting
- */
- bool operator<(const listener& listener) const
- {
- return (order() < listener.order());
- }
- };
-
- /**
- * Register a listener of events
- */
- static bool register_listener(listener* listener);
-
-private:
- /**
- * Database of object state created for each key
- */
- static client_db* m_db;
-
- /**
- * Comparator to keep the pointers to listeners in sorted order
- */
- struct listener_comparator_t
- {
- bool operator()(const listener* l1, const listener* l2) const
- {
- return (l1->order() < l2->order());
- }
- };
-
- /**
- * convenient typedef for the sorted set of listeners
- */
- typedef std::multiset<listener*, listener_comparator_t> listener_list;
-
- /**
- * The listeners for events
- */
- static std::unique_ptr<listener_list> m_listeners;
-};
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "mozilla")
- * End:
- */
-
-#endif