vom: Add support for vtr in xconnect

Change-Id: Ib168a1d20c4609e4e64f472f75e9463161638e3e
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
diff --git a/extras/vom/vom/CMakeLists.txt b/extras/vom/vom/CMakeLists.txt
index 475672a..8c87167 100644
--- a/extras/vom/vom/CMakeLists.txt
+++ b/extras/vom/vom/CMakeLists.txt
@@ -146,6 +146,8 @@
   ip_unnumbered.cpp
   l2_binding_cmds.cpp
   l2_binding.cpp
+  l2_vtr.cpp
+  l2_vtr_cmds.cpp
   l2_xconnect_cmds.cpp
   l2_xconnect.cpp
   l3_binding_cmds.cpp
@@ -252,6 +254,7 @@
   ip_punt_redirect.hpp
   ip_unnumbered.hpp
   l2_binding.hpp
+  l2_vtr.hpp
   l2_xconnect.hpp
   l3_binding.hpp
   lldp_binding.hpp
diff --git a/extras/vom/vom/l2_binding.cpp b/extras/vom/vom/l2_binding.cpp
index 9e2c722..5f0c7a7 100644
--- a/extras/vom/vom/l2_binding.cpp
+++ b/extras/vom/vom/l2_binding.cpp
@@ -15,6 +15,7 @@
 
 #include "vom/l2_binding.hpp"
 #include "vom/l2_binding_cmds.hpp"
+#include "vom/l2_vtr_cmds.hpp"
 #include "vom/singular_db_funcs.hpp"
 
 namespace VOM {
@@ -25,36 +26,6 @@
 
 l2_binding::event_handler l2_binding::m_evh;
 
-/*
- * Make sure these are in sync with the smae enum in VPP
- */
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_DISABLED(
-  0,
-  "disabled");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_PUSH_1(1,
-                                                                     "push-1");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_PUSH_2(2,
-                                                                     "push-2");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_POP_1(3, "pop-1");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_POP_2(4, "pop-2");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_1_1(
-  5,
-  "translate-1-1");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_1_2(
-  6,
-  "translate-1-2");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_2_1(
-  7,
-  "translate-2-1");
-const l2_binding::l2_vtr_op_t l2_binding::l2_vtr_op_t::L2_VTR_TRANSLATE_2_2(
-  5,
-  "translate-2-2");
-
-l2_binding::l2_vtr_op_t::l2_vtr_op_t(int v, const std::string s)
-  : enum_base<l2_binding::l2_vtr_op_t>(v, s)
-{
-}
-
 const l2_binding::l2_port_type_t
   l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL(0, "normal");
 const l2_binding::l2_port_type_t l2_binding::l2_port_type_t::L2_PORT_TYPE_BVI(
@@ -148,8 +119,7 @@
   }
 
   if (m_vtr_op && handle_t::INVALID != m_itf->handle()) {
-    HW::enqueue(new l2_binding_cmds::set_vtr_op_cmd(m_vtr_op, m_itf->handle(),
-                                                    m_vtr_op_tag));
+    HW::enqueue(new set_vtr_op_cmd(m_vtr_op, m_itf->handle(), m_vtr_op_tag));
   }
 }
 
@@ -204,8 +174,7 @@
    * set the VTR operation if request
    */
   if (m_vtr_op.update(desired.m_vtr_op)) {
-    HW::enqueue(new l2_binding_cmds::set_vtr_op_cmd(m_vtr_op, m_itf->handle(),
-                                                    m_vtr_op_tag));
+    HW::enqueue(new set_vtr_op_cmd(m_vtr_op, m_itf->handle(), m_vtr_op_tag));
   }
 }
 
diff --git a/extras/vom/vom/l2_binding.hpp b/extras/vom/vom/l2_binding.hpp
index 0a30a0c..1908289 100644
--- a/extras/vom/vom/l2_binding.hpp
+++ b/extras/vom/vom/l2_binding.hpp
@@ -20,6 +20,7 @@
 #include "vom/hw.hpp"
 #include "vom/inspect.hpp"
 #include "vom/interface.hpp"
+#include "vom/l2_vtr.hpp"
 #include "vom/object_base.hpp"
 #include "vom/om.hpp"
 #include "vom/singular_db.hpp"
@@ -37,25 +38,6 @@
    */
   typedef interface::key_t key_t;
 
-  struct l2_vtr_op_t : public enum_base<l2_vtr_op_t>
-  {
-    l2_vtr_op_t(const l2_vtr_op_t& l) = default;
-    ~l2_vtr_op_t() = default;
-
-    const static l2_vtr_op_t L2_VTR_DISABLED;
-    const static l2_vtr_op_t L2_VTR_PUSH_1;
-    const static l2_vtr_op_t L2_VTR_PUSH_2;
-    const static l2_vtr_op_t L2_VTR_POP_1;
-    const static l2_vtr_op_t L2_VTR_POP_2;
-    const static l2_vtr_op_t L2_VTR_TRANSLATE_1_1;
-    const static l2_vtr_op_t L2_VTR_TRANSLATE_1_2;
-    const static l2_vtr_op_t L2_VTR_TRANSLATE_2_1;
-    const static l2_vtr_op_t L2_VTR_TRANSLATE_2_2;
-
-  private:
-    l2_vtr_op_t(int v, const std::string s);
-  };
-
   struct l2_port_type_t : public enum_base<l2_port_type_t>
   {
     l2_port_type_t(const l2_port_type_t& l) = default;
diff --git a/extras/vom/vom/l2_binding_cmds.cpp b/extras/vom/vom/l2_binding_cmds.cpp
index 8769444..70413ad 100644
--- a/extras/vom/vom/l2_binding_cmds.cpp
+++ b/extras/vom/vom/l2_binding_cmds.cpp
@@ -121,50 +121,6 @@
 
   return (s.str());
 }
-
-set_vtr_op_cmd::set_vtr_op_cmd(HW::item<l2_binding::l2_vtr_op_t>& item,
-                               const handle_t& itf,
-                               uint16_t tag)
-  : rpc_cmd(item)
-  , m_itf(itf)
-  , m_tag(tag)
-{
-}
-
-bool
-set_vtr_op_cmd::operator==(const set_vtr_op_cmd& other) const
-{
-  return (
-    (m_hw_item.data() == other.m_hw_item.data() && m_itf == other.m_itf) &&
-    (m_tag == other.m_tag));
-}
-
-rc_t
-set_vtr_op_cmd::issue(connection& con)
-{
-  msg_t req(con.ctx(), std::ref(*this));
-
-  auto& payload = req.get_request().get_payload();
-  payload.sw_if_index = m_itf.value();
-  payload.vtr_op = m_hw_item.data().value();
-  payload.push_dot1q = 1;
-  payload.tag1 = m_tag;
-
-  VAPI_CALL(req.execute());
-
-  return (wait());
-}
-
-std::string
-set_vtr_op_cmd::to_string() const
-{
-  std::ostringstream s;
-  s << "L2-set-vtr-op: " << m_hw_item.to_string()
-    << " itf:" << m_itf.to_string() << " tag:" << m_tag;
-
-  return (s.str());
-}
-
 }; // namespace l2_binding_cmds
 }; // namespace VOM
 
diff --git a/extras/vom/vom/l2_binding_cmds.hpp b/extras/vom/vom/l2_binding_cmds.hpp
index e864f9d..45f90b0 100644
--- a/extras/vom/vom/l2_binding_cmds.hpp
+++ b/extras/vom/vom/l2_binding_cmds.hpp
@@ -117,47 +117,6 @@
   const l2_binding::l2_port_type_t& m_port_type;
 };
 
-/**
- * A cmd class sets the VTR operation
- */
-class set_vtr_op_cmd : public rpc_cmd<HW::item<l2_binding::l2_vtr_op_t>,
-                                      vapi::L2_interface_vlan_tag_rewrite>
-{
-public:
-  /**
-   * Constructor
-   */
-  set_vtr_op_cmd(HW::item<l2_binding::l2_vtr_op_t>& item,
-                 const handle_t& itf,
-                 uint16_t tag);
-
-  /**
-   * Issue the command to VPP/HW
-   */
-  rc_t issue(connection& con);
-
-  /**
-   * convert to string format for debug purposes
-   */
-  std::string to_string() const;
-
-  /**
-   * Comparison operator - only used for UT
-   */
-  bool operator==(const set_vtr_op_cmd& i) const;
-
-private:
-  /**
-   * The interface to bind
-   */
-  const handle_t m_itf;
-
-  /**
-   * The tag for the operation
-   */
-  uint16_t m_tag;
-};
-
 }; // namespace l2_binding_cmds
 }; // namespace VOM
 
diff --git a/extras/vom/vom/l2_vtr.cpp b/extras/vom/vom/l2_vtr.cpp
new file mode 100644
index 0000000..707a223
--- /dev/null
+++ b/extras/vom/vom/l2_vtr.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#include "vom/l2_vtr.hpp"
+
+namespace VOM {
+
+/*
+ * Make sure these are in sync with the smae enum in VPP
+ */
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_DISABLED(0, "disabled");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_PUSH_1(1, "push-1");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_PUSH_2(2, "push-2");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_POP_1(3, "pop-1");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_POP_2(4, "pop-2");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_TRANSLATE_1_1(5, "translate-1-1");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_TRANSLATE_1_2(6, "translate-1-2");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_TRANSLATE_2_1(7, "translate-2-1");
+const l2_vtr_op_t l2_vtr_op_t::L2_VTR_TRANSLATE_2_2(5, "translate-2-2");
+
+l2_vtr_op_t::l2_vtr_op_t(int v, const std::string s)
+  : enum_base<l2_vtr_op_t>(v, s)
+{
+}
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/extras/vom/vom/l2_vtr.hpp b/extras/vom/vom/l2_vtr.hpp
new file mode 100644
index 0000000..540cc83
--- /dev/null
+++ b/extras/vom/vom/l2_vtr.hpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 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_L2_VTR_H__
+#define __VOM_L2_VTR_H__
+
+#include "vom/hw.hpp"
+#include "vom/object_base.hpp"
+#include "vom/om.hpp"
+
+namespace VOM {
+struct l2_vtr_op_t : public enum_base<l2_vtr_op_t>
+{
+  l2_vtr_op_t(const l2_vtr_op_t& l) = default;
+  ~l2_vtr_op_t() = default;
+
+  const static l2_vtr_op_t L2_VTR_DISABLED;
+  const static l2_vtr_op_t L2_VTR_PUSH_1;
+  const static l2_vtr_op_t L2_VTR_PUSH_2;
+  const static l2_vtr_op_t L2_VTR_POP_1;
+  const static l2_vtr_op_t L2_VTR_POP_2;
+  const static l2_vtr_op_t L2_VTR_TRANSLATE_1_1;
+  const static l2_vtr_op_t L2_VTR_TRANSLATE_1_2;
+  const static l2_vtr_op_t L2_VTR_TRANSLATE_2_1;
+  const static l2_vtr_op_t L2_VTR_TRANSLATE_2_2;
+
+private:
+  l2_vtr_op_t(int v, const std::string s);
+};
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+#endif
diff --git a/extras/vom/vom/l2_vtr_cmds.cpp b/extras/vom/vom/l2_vtr_cmds.cpp
new file mode 100644
index 0000000..df50ae4
--- /dev/null
+++ b/extras/vom/vom/l2_vtr_cmds.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 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.
+ */
+
+#include "vom/l2_vtr_cmds.hpp"
+
+namespace VOM {
+
+set_vtr_op_cmd::set_vtr_op_cmd(HW::item<l2_vtr_op_t>& item,
+                               const handle_t& itf,
+                               uint16_t tag)
+  : rpc_cmd(item)
+  , m_itf(itf)
+  , m_tag(tag)
+{
+}
+
+bool
+set_vtr_op_cmd::operator==(const set_vtr_op_cmd& other) const
+{
+  return (
+    (m_hw_item.data() == other.m_hw_item.data() && m_itf == other.m_itf) &&
+    (m_tag == other.m_tag));
+}
+
+rc_t
+set_vtr_op_cmd::issue(connection& con)
+{
+  msg_t req(con.ctx(), std::ref(*this));
+
+  auto& payload = req.get_request().get_payload();
+  payload.sw_if_index = m_itf.value();
+  payload.vtr_op = m_hw_item.data().value();
+  payload.push_dot1q = 1;
+  payload.tag1 = m_tag;
+
+  VAPI_CALL(req.execute());
+
+  return (wait());
+}
+
+std::string
+set_vtr_op_cmd::to_string() const
+{
+  std::ostringstream s;
+  s << "L2-set-vtr-op: " << m_hw_item.to_string()
+    << " itf:" << m_itf.to_string() << " tag:" << m_tag;
+
+  return (s.str());
+}
+
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/extras/vom/vom/l2_vtr_cmds.hpp b/extras/vom/vom/l2_vtr_cmds.hpp
new file mode 100644
index 0000000..d26b719
--- /dev/null
+++ b/extras/vom/vom/l2_vtr_cmds.hpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019 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_L2_VTR_CMDS_H__
+#define __VOM_L2_VTR_CMDS_H__
+
+#include "vom/l2_vtr.hpp"
+#include "vom/rpc_cmd.hpp"
+
+#include <vapi/l2.api.vapi.hpp>
+#include <vapi/vpe.api.vapi.hpp>
+
+namespace VOM {
+
+/**
+ * A cmd class sets the VTR operation
+ */
+class set_vtr_op_cmd
+  : public rpc_cmd<HW::item<l2_vtr_op_t>, vapi::L2_interface_vlan_tag_rewrite>
+{
+public:
+  /**
+   * Constructor
+   */
+  set_vtr_op_cmd(HW::item<l2_vtr_op_t>& item,
+                 const handle_t& itf,
+                 uint16_t tag);
+
+  /**
+   * Issue the command to VPP/HW
+   */
+  rc_t issue(connection& con);
+
+  /**
+   * convert to string format for debug purposes
+   */
+  std::string to_string() const;
+
+  /**
+   * Comparison operator - only used for UT
+   */
+  bool operator==(const set_vtr_op_cmd& i) const;
+
+private:
+  /**
+   * The interface to bind
+   */
+  const handle_t m_itf;
+
+  /**
+   * The tag for the operation
+   */
+  uint16_t m_tag;
+};
+
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+
+#endif
diff --git a/extras/vom/vom/l2_xconnect.cpp b/extras/vom/vom/l2_xconnect.cpp
index 83d6541..1bdb651 100644
--- a/extras/vom/vom/l2_xconnect.cpp
+++ b/extras/vom/vom/l2_xconnect.cpp
@@ -14,6 +14,7 @@
  */
 
 #include "vom/l2_xconnect.hpp"
+#include "vom/l2_vtr_cmds.hpp"
 #include "vom/l2_xconnect_cmds.hpp"
 #include "vom/singular_db_funcs.hpp"
 
@@ -33,6 +34,8 @@
   , m_west_itf(west_itf.singular())
   , m_xconnect_east(0)
   , m_xconnect_west(0)
+  , m_vtr_op(l2_vtr_op_t::L2_VTR_DISABLED, rc_t::UNSET)
+  , m_vtr_op_tag(0)
 {
 }
 
@@ -41,6 +44,8 @@
   , m_west_itf(o.m_west_itf)
   , m_xconnect_east(o.m_xconnect_east)
   , m_xconnect_west(o.m_xconnect_west)
+  , m_vtr_op(o.m_vtr_op)
+  , m_vtr_op_tag(o.m_vtr_op_tag)
 {
 }
 
@@ -90,6 +95,11 @@
     HW::enqueue(new l2_xconnect_cmds::bind_cmd(
       m_xconnect_west, m_west_itf->handle(), m_east_itf->handle()));
   }
+
+  if (m_vtr_op && handle_t::INVALID != m_east_itf->handle()) {
+    HW::enqueue(
+      new set_vtr_op_cmd(m_vtr_op, m_east_itf->handle(), m_vtr_op_tag));
+  }
 }
 
 l2_xconnect::~l2_xconnect()
@@ -112,6 +122,15 @@
 }
 
 void
+l2_xconnect::set(const l2_vtr_op_t& op, uint16_t tag)
+{
+  assert(rc_t::UNSET == m_vtr_op.rc());
+  m_vtr_op.set(rc_t::NOOP);
+  m_vtr_op.update(op);
+  m_vtr_op_tag = tag;
+}
+
+void
 l2_xconnect::update(const l2_xconnect& desired)
 {
   /*
@@ -123,6 +142,14 @@
     HW::enqueue(new l2_xconnect_cmds::bind_cmd(
       m_xconnect_west, m_west_itf->handle(), m_east_itf->handle()));
   }
+
+  /*
+   * set the VTR operation if request
+   */
+  if (m_vtr_op.update(desired.m_vtr_op)) {
+    HW::enqueue(
+      new set_vtr_op_cmd(m_vtr_op, m_east_itf->handle(), m_vtr_op_tag));
+  }
 }
 
 std::shared_ptr<l2_xconnect>
diff --git a/extras/vom/vom/l2_xconnect.hpp b/extras/vom/vom/l2_xconnect.hpp
index 0699869..32acd61 100644
--- a/extras/vom/vom/l2_xconnect.hpp
+++ b/extras/vom/vom/l2_xconnect.hpp
@@ -19,6 +19,7 @@
 #include "vom/hw.hpp"
 #include "vom/inspect.hpp"
 #include "vom/interface.hpp"
+#include "vom/l2_vtr.hpp"
 #include "vom/object_base.hpp"
 #include "vom/om.hpp"
 #include "vom/singular_db.hpp"
@@ -78,6 +79,11 @@
   static void dump(std::ostream& os);
 
   /**
+   * Set the VTR operation on the binding/interface
+   */
+  void set(const l2_vtr_op_t& op, uint16_t tag);
+
+  /**
    * Static function to find the bridge_domain in the model
    */
   static std::shared_ptr<l2_xconnect> find(const key_t& key);
@@ -175,6 +181,16 @@
   HW::item<bool> m_xconnect_west;
 
   /**
+   * HW configuration for the VTR option
+   */
+  HW::item<l2_vtr_op_t> m_vtr_op;
+
+  /**
+   * The Dot1q tag for the VTR operation
+   */
+  uint16_t m_vtr_op_tag;
+
+  /**
    * A map of all L2 interfaces key against the interface's handle_t
    */
   static singular_db<key_t, l2_xconnect> m_db;