/* * 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_HW_H__ #define __VOM_HW_H__ #include #include #include #include #include #include #include "vom/cmd.hpp" #include "vom/connection.hpp" #include "vom/types.hpp" namespace VOM { class stat_reader; class cmd; class HW { public: /** * A HW::item is data that is either to be written to or read from * VPP/HW. * The item is a pair of the data written/read and the result of that * operation. */ template class item { public: /** * Constructor */ item(const T& data) : item_data(data) , item_rc(rc_t::NOOP) { } /** * Constructor */ item() : item_data() , item_rc(rc_t::UNSET) { } /** * Constructor */ item(rc_t rc) : item_data() , item_rc(rc) { } /** * Constructor */ item(const T& data, rc_t rc) : item_data(data) , item_rc(rc) { } /** * Destructor */ ~item() = default; /** * Comparison operator */ bool operator==(const item& i) const { return (item_data == i.item_data); } /** * Copy assignment */ item& operator=(const item& other) { item_data = other.item_data; item_rc = other.item_rc; return (*this); } /** * Return the data read/written */ T& data() { return (item_data); } /** * Const reference to the data */ const T& data() const { return (item_data); } /** * Get the HW return code */ rc_t rc() const { return (item_rc); } /** * Set the HW return code - should only be called from the * family of Command objects */ void set(const rc_t& rc) { item_rc = rc; } /** * Return true if the HW item is configred in HW */ operator bool() const { return (rc_t::OK == item_rc); } /** * update the item to the desired state. * return true if a HW update is required */ bool update(const item& desired) { bool need_hw_update = false; /* * if the deisred set is unset (i.e. defaulted, we've * no update to make */ if (rc_t::UNSET == desired.rc()) { return (false); } /* * A HW update is needed if thestate is different * or the state is not yet in HW */ need_hw_update = (item_data != desired.data() || rc_t::OK != rc()); item_data = desired.data(); return (need_hw_update); } /** * convert to string format for debug purposes */ std::string to_string() const { std::ostringstream os; os << "hw-item:[" << "rc:" << item_rc.to_string() << " data:" << item_data.to_string() << "]"; return (os.str()); } private: /** * The data */ T item_data; /** * The result when the item was written */ rc_t item_rc; }; /** * The pipe to VPP into which we write the commands */ class cmd_q { public: /** * Constructor */ cmd_q(); /** * Destructor */ ~cmd_q(); /** * Copy assignement - only used in UT */ cmd_q& operator=(const cmd_q& f); /** * Enqueue a command into the Q. */ virtual void enqueue(cmd* c); /** * Enqueue a command into the Q. */ virtual void enqueue(std::shared_ptr c); /** * Enqueue a set of commands */ virtual void enqueue(std::queue& c); /** * Write all the commands to HW */ virtual rc_t write(); /** * Blocking Connect to VPP - call once at bootup */ virtual bool connect(); /** * Disconnect to VPP */ virtual void disconnect(); /** * Disable the passing of commands to VPP. Whilst disabled all * writes will be discarded. Use this during the reset phase. */ void disable(); /** * Enable the passing of commands to VPP - undoes the disable. * The Q is enabled by default. */ void enable(); private: /** * A queue of enqueued commands, ready to be written */ std::deque> m_queue; /** * A map of issued, but uncompleted, commands. * i.e. those that we are waiting, async stylee, * for VPP to complete */ std::map> m_pending; /** * VPP Q poll function */ void rx_run(); /** * The thread object running the poll/dispatch/connect thread */ std::unique_ptr m_rx_thread; /** * A flag indicating the client has disabled the cmd Q. */ bool m_enabled; /** * A flag for the thread to poll to see if the queue is still alive */ bool m_connected; /** * The connection to VPP */ connection m_conn; }; /** * Initialise the HW connection to VPP - the UT version passing * a mock Q. */ static void init(cmd_q* f); /** * Initialise the HW connection to VPP - the UT version passing * a mock Q. */ static void init(cmd_q* f, stat_reader* s); /** * Initialise the HW */ static void init(); /** * Enqueue A command for execution */ static void enqueue(cmd* f); /** * Enqueue A command for execution */ static void enqueue(std::shared_ptr c); /** * Enqueue A set of commands for execution */ static void enqueue(std::queue& c); /** * Write/Execute all commands hitherto enqueued. */ static rc_t write(); /** * Blocking Connect to VPP */ static bool connect(); /** * Disconnect to VPP */ static void disconnect(); /** * Blocking pool of the HW connection */ static bool poll(); /** * read stats from stat segment */ static void read_stats(); private: /** * The command Q toward HW */ static cmd_q* m_cmdQ; /** * The stat reader toward HW */ static stat_reader* m_statReader; /** * HW::item representing the connection state as determined by polling */ static HW::item m_poll_state; /** * Disable the passing of commands to VPP. Whilst disabled all writes * will be discarded. Use this during the reset phase. */ static void disable(); /** * Enable the passing of commands to VPP - undoes the disable. * The Q is enabled by default. */ static void enable(); /** * Only the OM can enable/disable HW */ friend class OM; }; /** * bool Specialisation for HW::item to_string */ template <> std::string HW::item::to_string() const; /** * uint Specialisation for HW::item to_string */ template <> std::string HW::item::to_string() const; }; /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "mozilla") * End: */ #endif