ncsi: make Interface virtual

Now that we have encapsulation for passing NCSI commands and responses
to/from an interface, we can make the Interface object virtual, and have
the Netlink implementation as a subclass.

We keep the netlink-specific operations in NetlinkInterface; getInfo(),
setChannel(), clearInterface(), and the channel/package mask operations
are all netlink-specific items to control kernel state.

Change-Id: I30b9cec41712d2e32d12685dd8406e08c6dea1f0
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
diff --git a/src/ncsi_util.hpp b/src/ncsi_util.hpp
index 0ca0df1..250c096 100644
--- a/src/ncsi_util.hpp
+++ b/src/ncsi_util.hpp
@@ -83,7 +83,26 @@
      * @param[in] payload - OEM data to send.
      * @returns the NCSI response message to this command, or no value on error.
      */
+    virtual std::optional<NCSIResponse> sendCommand(NCSICommand& cmd) = 0;
+
+    /**
+     * @brief Create a string representation of this interface
+     *
+     * @returns a string containing an interface identifier, for logging
+     */
+    virtual std::string toString() = 0;
+
+    /* virtual destructor for vtable */
+    virtual ~Interface() {};
+};
+
+std::string to_string(Interface& interface);
+
+struct NetlinkInterface : Interface
+{
+    /* implementations for Interface */
     std::optional<NCSIResponse> sendCommand(NCSICommand& cmd);
+    std::string toString();
 
     /* @brief  This function will ask underlying NCSI driver
      *         to set a specific  package or package/channel
@@ -129,11 +148,11 @@
      */
     int setChannelMask(int package, unsigned int mask);
 
+    NetlinkInterface(int ifindex);
+
     int ifindex;
 };
 
-std::string to_string(Interface& interface);
-
 } // namespace ncsi
 } // namespace network
 } // namespace phosphor