ARP proxy dumps 93/12693/4
authorNeale Ranns <nranns@cisco.com>
Tue, 22 May 2018 15:40:52 +0000 (08:40 -0700)
committerDamjan Marion <dmarion.lists@gmail.com>
Fri, 25 May 2018 11:45:48 +0000 (11:45 +0000)
Change-Id: I8335ebf266becf2f42bb3f28a17dfed8d9b08f97
Signed-off-by: Neale Ranns <nranns@cisco.com>
23 files changed:
extras/vom/vom/arp_proxy_binding.cpp
extras/vom/vom/arp_proxy_binding.hpp
extras/vom/vom/arp_proxy_binding_cmds.cpp
extras/vom/vom/arp_proxy_binding_cmds.hpp
extras/vom/vom/arp_proxy_config.cpp
extras/vom/vom/arp_proxy_config_cmds.cpp
extras/vom/vom/arp_proxy_config_cmds.hpp
src/vat/api_format.c
src/vnet/adj/adj.c
src/vnet/adj/adj_glean.c
src/vnet/adj/adj_mcast.c
src/vnet/adj/adj_nbr.c
src/vnet/ethernet/arp.c
src/vnet/ethernet/arp.h [new file with mode: 0644]
src/vnet/ethernet/ethernet.h
src/vnet/interface.c
src/vnet/interface_funcs.h
src/vnet/ip/ip.api
src/vnet/ip/ip_api.c
src/vnet/ip/ip_neighbor.c
src/vpp/api/custom_dump.c
test/ext/vom_test.cpp
test/vpp_papi_provider.py

index 73d3d84..bbae9f6 100644 (file)
@@ -26,17 +26,14 @@ singular_db<interface::key_t, arp_proxy_binding> arp_proxy_binding::m_db;
 
 arp_proxy_binding::event_handler arp_proxy_binding::m_evh;
 
-arp_proxy_binding::arp_proxy_binding(const interface& itf,
-                                     const arp_proxy_config& proxy_cfg)
+arp_proxy_binding::arp_proxy_binding(const interface& itf)
   : m_itf(itf.singular())
-  , m_arp_proxy_cfg(proxy_cfg.singular())
   , m_binding(true)
 {
 }
 
 arp_proxy_binding::arp_proxy_binding(const arp_proxy_binding& o)
   : m_itf(o.m_itf)
-  , m_arp_proxy_cfg(o.m_arp_proxy_cfg)
   , m_binding(o.m_binding)
 {
 }
@@ -44,8 +41,6 @@ arp_proxy_binding::arp_proxy_binding(const arp_proxy_binding& o)
 arp_proxy_binding::~arp_proxy_binding()
 {
   sweep();
-
-  // not in the DB anymore.
   m_db.release(m_itf->key(), this);
 }
 
@@ -123,7 +118,25 @@ arp_proxy_binding::event_handler::handle_replay()
 void
 arp_proxy_binding::event_handler::handle_populate(const client_db::key_t& key)
 {
-  // FIXME
+  std::shared_ptr<arp_proxy_binding_cmds::dump_cmd> cmd =
+    std::make_shared<arp_proxy_binding_cmds::dump_cmd>();
+
+  HW::enqueue(cmd);
+  HW::write();
+
+  for (auto& record : *cmd) {
+    auto& payload = record.get_payload();
+
+    std::shared_ptr<interface> itf = interface::find(payload.sw_if_index);
+
+    if (itf) {
+      arp_proxy_binding ab(*itf);
+      OM::commit(key, ab);
+    } else {
+      VOM_LOG(log_level_t::ERROR) << "arp-proxy-binding dump:"
+                                  << " itf:" << payload.sw_if_index;
+    }
+  }
 }
 
 dependency_t
index f57f697..284cf73 100644 (file)
@@ -34,7 +34,7 @@ public:
   /**
    * Construct a new object matching the desried state
    */
-  arp_proxy_binding(const interface& itf, const arp_proxy_config& proxy_cfg);
+  arp_proxy_binding(const interface& itf);
 
   /**
    * Copy Constructor
@@ -135,11 +135,6 @@ private:
    */
   const std::shared_ptr<interface> m_itf;
 
-  /**
-   * A reference counting pointer to the prxy config.
-   */
-  const std::shared_ptr<arp_proxy_config> m_arp_proxy_cfg;
-
   /**
    * HW configuration for the binding. The bool representing the
    * do/don't bind.
index 675feef..2314d53 100644 (file)
@@ -95,6 +95,30 @@ unbind_cmd::to_string() const
   return (s.str());
 }
 
+bool
+dump_cmd::operator==(const dump_cmd& other) const
+{
+  return (true);
+}
+
+rc_t
+dump_cmd::issue(connection& con)
+{
+  m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
+
+  VAPI_CALL(m_dump->execute());
+
+  wait();
+
+  return rc_t::OK;
+}
+
+std::string
+dump_cmd::to_string() const
+{
+  return ("ARP-proxy-binding-dump");
+}
+
 }; // namespace arp_proxy_binding_cmds
 }; // namespace VOM
 
index c73bb13..fcf0a4a 100644 (file)
@@ -17,6 +17,7 @@
 #define __VOM_ARP_PROXY_BINDING_CMDS_H__
 
 #include "vom/arp_proxy_binding.hpp"
+#include "vom/dump_cmd.hpp"
 
 #include <vapi/vpe.api.vapi.hpp>
 
@@ -87,8 +88,41 @@ private:
    */
   const handle_t& m_itf;
 };
+
+/**
+ * A cmd class that Dumps all the Proxy ARP configs
+ */
+class dump_cmd : public VOM::dump_cmd<vapi::Proxy_arp_intfc_dump>
+{
+public:
+  /**
+   * Constructor
+   */
+  dump_cmd() = default;
+
+  /**
+   * 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 dump_cmd& i) const;
+
+private:
+  /**
+   * HW reutrn code
+   */
+  HW::item<bool> item;
 };
-};
+
+}; // namespace cmds
+}; // namespace VOM
 
 /*
  * fd.io coding-style-patch-verification: ON
index 3973eba..275d9f9 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "vom/arp_proxy_config.hpp"
 #include "vom/arp_proxy_config_cmds.hpp"
+#include "vom/prefix.hpp"
 #include "vom/singular_db_funcs.hpp"
 
 namespace VOM {
@@ -115,7 +116,21 @@ arp_proxy_config::event_handler::handle_replay()
 void
 arp_proxy_config::event_handler::handle_populate(const client_db::key_t& key)
 {
-  // VPP provides no dump for ARP proxy.
+  std::shared_ptr<arp_proxy_config_cmds::dump_cmd> cmd =
+    std::make_shared<arp_proxy_config_cmds::dump_cmd>();
+
+  HW::enqueue(cmd);
+  HW::write();
+
+  for (auto& record : *cmd) {
+    auto& payload = record.get_payload();
+
+    boost::asio::ip::address lo = from_bytes(0, payload.proxy.low_address);
+    boost::asio::ip::address hi = from_bytes(0, payload.proxy.hi_address);
+
+    arp_proxy_config ap(lo.to_v4(), hi.to_v4());
+    OM::commit(key, ap);
+  }
 }
 
 dependency_t
index cf7fad5..122c51b 100644 (file)
@@ -42,9 +42,9 @@ config_cmd::issue(connection& con)
   payload.is_add = 1;
 
   std::copy_n(std::begin(m_low.to_bytes()), m_low.to_bytes().size(),
-              payload.low_address);
+              payload.proxy.low_address);
   std::copy_n(std::begin(m_high.to_bytes()), m_high.to_bytes().size(),
-              payload.hi_address);
+              payload.proxy.hi_address);
 
   VAPI_CALL(req.execute());
 
@@ -87,9 +87,9 @@ unconfig_cmd::issue(connection& con)
   payload.is_add = 0;
 
   std::copy_n(std::begin(m_low.to_bytes()), m_low.to_bytes().size(),
-              payload.low_address);
+              payload.proxy.low_address);
   std::copy_n(std::begin(m_high.to_bytes()), m_high.to_bytes().size(),
-              payload.hi_address);
+              payload.proxy.hi_address);
 
   VAPI_CALL(req.execute());
 
@@ -108,9 +108,34 @@ unconfig_cmd::to_string() const
 
   return (s.str());
 }
+
+bool
+dump_cmd::operator==(const dump_cmd& other) const
+{
+  return (true);
 }
+
+rc_t
+dump_cmd::issue(connection& con)
+{
+  m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
+
+  VAPI_CALL(m_dump->execute());
+
+  wait();
+
+  return rc_t::OK;
 }
 
+std::string
+dump_cmd::to_string() const
+{
+  return ("ARP-proxy-dump");
+}
+
+}; // namesapce cmds
+}; // namespace VOM
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index ac0e1fd..77abc74 100644 (file)
@@ -94,8 +94,41 @@ private:
   const boost::asio::ip::address_v4 m_low;
   const boost::asio::ip::address_v4 m_high;
 };
+
+/**
+ * A cmd class that Dumps all the Proxy ARP configs
+ */
+class dump_cmd : public VOM::dump_cmd<vapi::Proxy_arp_dump>
+{
+public:
+  /**
+   * Constructor
+   */
+  dump_cmd() = default;
+
+  /**
+   * 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 dump_cmd& i) const;
+
+private:
+  /**
+   * HW reutrn code
+   */
+  HW::item<bool> item;
 };
-};
+
+}; // namespace cmds
+}; // namespace VOM
 
 /*
  * fd.io coding-style-patch-verification: ON
index b1aaa69..c3ba701 100644 (file)
@@ -9287,10 +9287,10 @@ api_proxy_arp_add_del (vat_main_t * vam)
 
   M (PROXY_ARP_ADD_DEL, mp);
 
-  mp->vrf_id = ntohl (vrf_id);
+  mp->proxy.vrf_id = ntohl (vrf_id);
   mp->is_add = is_add;
-  clib_memcpy (mp->low_address, &lo, sizeof (mp->low_address));
-  clib_memcpy (mp->hi_address, &hi, sizeof (mp->hi_address));
+  clib_memcpy (mp->proxy.low_address, &lo, sizeof (mp->proxy.low_address));
+  clib_memcpy (mp->proxy.hi_address, &hi, sizeof (mp->proxy.hi_address));
 
   S (mp);
   W (ret);
index ed4bada..abfe872 100644 (file)
@@ -353,7 +353,7 @@ adj_mtu_update_walk_cb (adj_index_t ai,
     return (ADJ_WALK_RC_CONTINUE);
 }
 
-static void
+static walk_rc_t
 adj_sw_mtu_update (vnet_main_t * vnm,
                    u32 sw_if_index,
                    void *ctx)
@@ -362,6 +362,8 @@ adj_sw_mtu_update (vnet_main_t * vnm,
      * Walk all the adjacencies on the interface to update the cached MTU
      */
     adj_walk (sw_if_index, adj_mtu_update_walk_cb, NULL);
+
+    return (WALK_CONTINUE);
 }
 
 void
index 41bc4c9..74881d7 100644 (file)
@@ -173,12 +173,14 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_glean_interface_state_change);
  * @brief Invoked on each SW interface of a HW interface when the
  * HW interface state changes
  */
-static void
+static walk_rc_t
 adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm,
                                       u32 sw_if_index,
                                       void *arg)
 {
     adj_glean_interface_state_change(vnm, sw_if_index, (uword) arg);
+
+    return (WALK_CONTINUE);
 }
 
 /**
index deaa7fc..593c1b6 100644 (file)
@@ -220,12 +220,14 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_mcast_interface_state_change);
  * @brief Invoked on each SW interface of a HW interface when the
  * HW interface state changes
  */
-static void
+static walk_rc_t
 adj_mcast_hw_sw_interface_state_change (vnet_main_t * vnm,
                                         u32 sw_if_index,
                                         void *arg)
 {
     adj_mcast_interface_state_change(vnm, sw_if_index, (uword) arg);
+
+    return (WALK_CONTINUE);
 }
 
 /**
index eff7d4c..6fd9b40 100644 (file)
@@ -751,7 +751,7 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION_PRIO(
  * @brief Invoked on each SW interface of a HW interface when the
  * HW interface state changes
  */
-static void
+static walk_rc_t
 adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm,
                                       u32 sw_if_index,
                                       void *arg)
@@ -768,6 +768,7 @@ adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm,
                     adj_nbr_interface_state_change_one,
                     ctx);
     }
+    return (WALK_CONTINUE);
 }
 
 /**
index 55beb70..49a16f7 100644 (file)
@@ -18,7 +18,7 @@
 #include <vnet/ip/ip.h>
 #include <vnet/ip/ip6.h>
 #include <vnet/ethernet/ethernet.h>
-#include <vnet/ethernet/arp_packet.h>
+#include <vnet/ethernet/arp.h>
 #include <vnet/l2/l2_input.h>
 #include <vppinfra/mhash.h>
 #include <vnet/fib/ip4_fib.h>
@@ -52,8 +52,8 @@ typedef struct ethernet_arp_interface_t_
 
 typedef struct
 {
-  u32 lo_addr;
-  u32 hi_addr;
+  ip4_address_t lo_addr;
+  ip4_address_t hi_addr;
   u32 fib_index;
 } ethernet_proxy_arp_t;
 
@@ -1226,8 +1226,8 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
 
              vec_foreach (pa, am->proxy_arps)
              {
-               u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
-               u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
+               u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr.as_u32);
+               u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr.as_u32);
 
                /* an ARP request hit in the proxy-arp table? */
                if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
@@ -1963,6 +1963,19 @@ vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
   return 0;
 }
 
+void
+proxy_arp_walk (proxy_arp_walk_t cb, void *data)
+{
+  ethernet_arp_main_t *am = &ethernet_arp_main;
+  ethernet_proxy_arp_t *pa;
+
+  vec_foreach (pa, am->proxy_arps)
+  {
+    if (!cb (&pa->lo_addr, &pa->hi_addr, pa->fib_index, data))
+      break;
+  }
+}
+
 int
 vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
                        ip4_address_t * hi_addr, u32 fib_index, int is_del)
@@ -1973,8 +1986,8 @@ vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
 
   vec_foreach (pa, am->proxy_arps)
   {
-    if (pa->lo_addr == lo_addr->as_u32
-       && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index)
+    if (pa->lo_addr.as_u32 == lo_addr->as_u32 &&
+       pa->hi_addr.as_u32 == hi_addr->as_u32 && pa->fib_index == fib_index)
       {
        found_at_index = pa - am->proxy_arps;
        break;
@@ -1994,8 +2007,8 @@ vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
 
   /* add, not in table */
   vec_add2 (am->proxy_arps, pa, 1);
-  pa->lo_addr = lo_addr->as_u32;
-  pa->hi_addr = hi_addr->as_u32;
+  pa->lo_addr.as_u32 = lo_addr->as_u32;
+  pa->hi_addr.as_u32 = hi_addr->as_u32;
   pa->fib_index = fib_index;
   return 0;
 }
diff --git a/src/vnet/ethernet/arp.h b/src/vnet/ethernet/arp.h
new file mode 100644 (file)
index 0000000..7b50ed7
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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 __ARP_H__
+#define __ARP_H__
+
+#include <vnet/ethernet/ethernet.h>
+#include <vnet/ethernet/arp_packet.h>
+#include <vnet/ip/ip.h>
+
+extern int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
+                                  ip4_address_t * hi_addr,
+                                  u32 fib_index, int is_del);
+
+extern int vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
+                                          u32 sw_if_index,
+                                          void *a_arg,
+                                          int is_static,
+                                          int is_no_fib_entry);
+
+extern int vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
+                                            u32 sw_if_index, void *a_arg);
+
+extern int vnet_proxy_arp_fib_reset (u32 fib_id);
+
+/**
+ * call back function when walking the DB of proxy ARPs
+ * @return 0 to stop the walk !0 to continue
+ */
+typedef walk_rc_t (proxy_arp_walk_t) (const ip4_address_t * lo_addr,
+                                     const ip4_address_t * hi_addr,
+                                     u32 fib_index, void *dat);
+
+extern void proxy_arp_walk (proxy_arp_walk_t cb, void *data);
+
+#endif
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
index fb7e2c5..79ae7e6 100644 (file)
@@ -435,17 +435,6 @@ void ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
 void ethernet_set_rx_redirect (vnet_main_t * vnm, vnet_hw_interface_t * hi,
                               u32 enable);
 
-int
-vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
-                               u32 sw_if_index, void *a_arg,
-                               int is_static, int is_no_fib_entry);
-
-int
-vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
-                                 u32 sw_if_index, void *a_arg);
-
-int vnet_proxy_arp_fib_reset (u32 fib_id);
-
 clib_error_t *next_by_ethertype_init (next_by_ethertype_t * l3_next);
 clib_error_t *next_by_ethertype_register (next_by_ethertype_t * l3_next,
                                          u32 ethertype, u32 next_index);
index d3ad896..36793f1 100644 (file)
@@ -998,11 +998,30 @@ vnet_hw_interface_walk_sw (vnet_main_t * vnm,
   hash_foreach (id, sw_if_index,
                 hi->sub_interface_sw_if_index_by_id,
   ({
-    fn (vnm, sw_if_index, ctx);
+    if (WALK_STOP == fn (vnm, sw_if_index, ctx))
+      break;
   }));
   /* *INDENT-ON* */
 }
 
+void
+vnet_sw_interface_walk (vnet_main_t * vnm,
+                       vnet_sw_interface_walk_t fn, void *ctx)
+{
+  vnet_interface_main_t *im;
+  vnet_sw_interface_t *si;
+
+  im = &vnm->interface_main;
+
+  /* *INDENT-OFF* */
+  pool_foreach (si, im->sw_interfaces,
+  {
+    if (WALK_STOP == fn (vnm, si, ctx))
+      break;
+  });
+  /* *INDENT-ON* */
+}
+
 static void
 serialize_vnet_hw_interface_set_class (serialize_main_t * m, va_list * va)
 {
index 3f910f9..e1568e3 100644 (file)
@@ -147,11 +147,20 @@ vnet_clear_sw_interface_tag (vnet_main_t * vnm, u32 sw_if_index)
     }
 }
 
+/**
+ * Walk return code
+ */
+typedef enum walk_rc_t_
+{
+  WALK_STOP,
+  WALK_CONTINUE,
+} walk_rc_t;
+
 /**
  * Call back walk type for walking SW indices on a HW interface
  */
-typedef void (*vnet_hw_sw_interface_walk_t) (vnet_main_t * vnm,
-                                            u32 sw_if_index, void *ctx);
+typedef walk_rc_t (*vnet_hw_sw_interface_walk_t) (vnet_main_t * vnm,
+                                                 u32 sw_if_index, void *ctx);
 
 /**
  * @brief
@@ -162,6 +171,20 @@ void vnet_hw_interface_walk_sw (vnet_main_t * vnm,
                                u32 hw_if_index,
                                vnet_hw_sw_interface_walk_t fn, void *ctx);
 
+/**
+ * Call back walk type for walking SW indices on a HW interface
+ */
+typedef walk_rc_t (*vnet_sw_interface_walk_t) (vnet_main_t * vnm,
+                                              vnet_sw_interface_t * si,
+                                              void *ctx);
+
+/**
+ * @brief
+ * Walk all the SW interfaces in the system.
+ */
+void vnet_sw_interface_walk (vnet_main_t * vnm,
+                            vnet_sw_interface_walk_t fn, void *ctx);
+
 /* Register a hardware interface instance. */
 u32 vnet_register_interface (vnet_main_t * vnm,
                             u32 dev_class_index,
index 7f4f030..c5be0c6 100644 (file)
@@ -860,18 +860,13 @@ service {
     events ip6_nd_event;
 };
 
-/** \brief Proxy ARP add / del request
-    @param client_index - opaque cookie to identify the sender
-    @param context - sender context, to match reply w/ request
+/** \brief Proxy ARP configuration type
     @param vrf_id - VRF / Fib table ID
-    @param is_add - 1 if adding the Proxy ARP range, 0 if deleting
     @param low_address[4] - Low address of the Proxy ARP range
     @param hi_address[4] - High address of the Proxy ARP range
 */
-autoreply define proxy_arp_add_del
+typeonly define proxy_arp
 {
-  u32 client_index;
-  u32 context;
   u32 vrf_id;
   u8 is_add;
   u8 low_address[4];
@@ -879,6 +874,37 @@ autoreply define proxy_arp_add_del
 };
 
 /** \brief Proxy ARP add / del request
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param is_add - 1 if adding the Proxy ARP range, 0 if deleting
+    @param proxy - Proxy configuration
+*/
+autoreply define proxy_arp_add_del
+{
+  u32 client_index;
+  u32 context;
+  u8 is_add;
+  vl_api_proxy_arp_t proxy;
+};
+
+/** \brief Proxy ARP dump request
+ */
+define proxy_arp_dump
+{
+  u32 client_index;
+  u32 context;
+};
+
+/** \brief Proxy ARP dump details reply
+ * @param proxy - Same data as used to configure
+ */
+define proxy_arp_details
+{
+  u32 context;
+  vl_api_proxy_arp_t proxy;
+};
+
+/** \brief Proxy ARP add / del interface request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
     @param sw_if_index - Which interface to enable / disable Proxy Arp on
@@ -893,6 +919,23 @@ autoreply define proxy_arp_intfc_enable_disable
   u8 enable_disable;
 };
 
+/** \brief Proxy ARP interface dump request
+ */
+define proxy_arp_intfc_dump
+{
+  u32 client_index;
+  u32 context;
+};
+
+/** \brief Proxy ARP interface dump details reply
+ * @param sw_if_index The interface on which ARP proxy is enabled.
+ */
+define proxy_arp_intfc_details
+{
+  u32 context;
+  u32 sw_if_index;
+};
+
 /** \brief Reset fib table request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
index ce3ff79..8464b1d 100644 (file)
@@ -45,6 +45,7 @@
 #include <vnet/ip/ip6_hop_by_hop.h>
 #include <vnet/ip/ip4_reassembly.h>
 #include <vnet/ip/ip6_reassembly.h>
+#include <vnet/ethernet/arp.h>
 
 #include <vnet/vnet_msg_enum.h>
 
@@ -84,7 +85,9 @@ _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
 _(WANT_IP6_RA_EVENTS, want_ip6_ra_events)                               \
 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
+_(PROXY_ARP_DUMP, proxy_arp_dump)                                       \
 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
+ _(PROXY_ARP_INTFC_DUMP, proxy_arp_intfc_dump)                          \
 _(RESET_FIB, reset_fib)                                                        \
 _(IP_ADD_DEL_ROUTE, ip_add_del_route)                                   \
 _(IP_TABLE_ADD_DEL, ip_table_add_del)                                   \
@@ -2715,14 +2718,11 @@ vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
   u32 fib_index;
   int rv;
   ip4_main_t *im = &ip4_main;
-  int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
-                             ip4_address_t * hi_addr,
-                             u32 fib_index, int is_del);
   uword *p;
 
   stats_dslock_with_hint (1 /* release hint */ , 6 /* tag */ );
 
-  p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
+  p = hash_get (im->fib_index_by_table_id, ntohl (mp->proxy.vrf_id));
 
   if (!p)
     {
@@ -2732,8 +2732,8 @@ vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
 
   fib_index = p[0];
 
-  rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
-                              (ip4_address_t *) mp->hi_address,
+  rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->proxy.low_address,
+                              (ip4_address_t *) mp->proxy.hi_address,
                               fib_index, mp->is_add == 0);
 
 out:
@@ -2741,6 +2741,94 @@ out:
   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
 }
 
+typedef struct proxy_arp_walk_ctx_t_
+{
+  vl_api_registration_t *reg;
+  u32 context;
+} proxy_arp_walk_ctx_t;
+
+static walk_rc_t
+send_proxy_arp_details (const ip4_address_t * lo_addr,
+                       const ip4_address_t * hi_addr,
+                       u32 fib_index, void *data)
+{
+  vl_api_proxy_arp_details_t *mp;
+  proxy_arp_walk_ctx_t *ctx;
+
+  ctx = data;
+
+  mp = vl_msg_api_alloc (sizeof (*mp));
+  memset (mp, 0, sizeof (*mp));
+  mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_DETAILS);
+  mp->context = ctx->context;
+  mp->proxy.vrf_id = htonl (fib_index);
+  clib_memcpy (mp->proxy.low_address, lo_addr,
+              sizeof (mp->proxy.low_address));
+  clib_memcpy (mp->proxy.hi_address, hi_addr, sizeof (mp->proxy.hi_address));
+
+  vl_api_send_msg (ctx->reg, (u8 *) mp);
+
+  return (WALK_CONTINUE);
+}
+
+static void
+vl_api_proxy_arp_dump_t_handler (vl_api_proxy_arp_dump_t * mp)
+{
+  vl_api_registration_t *reg;
+
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
+
+  proxy_arp_walk_ctx_t wctx = {
+    .reg = reg,
+    .context = mp->context,
+  };
+
+  proxy_arp_walk (send_proxy_arp_details, &wctx);
+}
+
+static walk_rc_t
+send_proxy_arp_intfc_details (vnet_main_t * vnm,
+                             vnet_sw_interface_t * si, void *data)
+{
+  vl_api_proxy_arp_intfc_details_t *mp;
+  proxy_arp_walk_ctx_t *ctx;
+
+  if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
+    return (WALK_CONTINUE);
+
+  ctx = data;
+
+  mp = vl_msg_api_alloc (sizeof (*mp));
+  memset (mp, 0, sizeof (*mp));
+  mp->_vl_msg_id = ntohs (VL_API_PROXY_ARP_INTFC_DETAILS);
+  mp->context = ctx->context;
+  mp->sw_if_index = htonl (si->sw_if_index);
+
+  vl_api_send_msg (ctx->reg, (u8 *) mp);
+
+  return (WALK_CONTINUE);
+}
+
+static void
+vl_api_proxy_arp_intfc_dump_t_handler (vl_api_proxy_arp_intfc_dump_t * mp)
+{
+  vl_api_registration_t *reg;
+
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
+
+  proxy_arp_walk_ctx_t wctx = {
+    .reg = reg,
+    .context = mp->context,
+  };
+
+  vnet_sw_interface_walk (vnet_get_main (),
+                         send_proxy_arp_intfc_details, &wctx);
+}
+
 static void
   vl_api_proxy_arp_intfc_enable_disable_t_handler
   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
index a43fdfd..b9c03aa 100644 (file)
@@ -19,7 +19,7 @@
 #include <vnet/ip/ip.h>
 #include <vnet/ip/ip6_neighbor.h>
 #include <vnet/ip/ip_neighbor.h>
-#include <vnet/ethernet/arp_packet.h>
+#include <vnet/ethernet/arp.h>
 
 /*
  * IP neighbor scan parameter defaults are as follows:
index ba55150..15b1f69 100644 (file)
@@ -747,11 +747,12 @@ static void *vl_api_proxy_arp_add_del_t_print
 
   s = format (0, "SCRIPT: proxy_arp_add_del ");
 
-  s = format (s, "%U - %U ", format_ip4_address, mp->low_address,
-             format_ip4_address, mp->hi_address);
+  s = format (s, "%U - %U ",
+             format_ip4_address, mp->proxy.low_address,
+             format_ip4_address, mp->proxy.hi_address);
 
-  if (mp->vrf_id)
-    s = format (s, "vrf %d ", ntohl (mp->vrf_id));
+  if (mp->proxy.vrf_id)
+    s = format (s, "vrf %d ", ntohl (mp->proxy.vrf_id));
 
   if (mp->is_add == 0)
     s = format (s, "del ");
index 6958eb1..44df243 100644 (file)
@@ -1237,7 +1237,7 @@ BOOST_AUTO_TEST_CASE(test_arp_proxy) {
     ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_up, hw_ifh));
     TRY_CHECK_RC(OM::write(kurt, itf3));
 
-    arp_proxy_binding *apb = new arp_proxy_binding(itf3, ap);
+    arp_proxy_binding *apb = new arp_proxy_binding(itf3);
     HW::item<bool> hw_binding(true, rc_t::OK);
     ADD_EXPECT(arp_proxy_binding_cmds::bind_cmd(hw_binding, hw_ifh.data()));
     TRY_CHECK_RC(OM::write(kurt, *apb));
index f72d37d..6dbed29 100644 (file)
@@ -939,12 +939,13 @@ class VppPapiProvider(object):
 
         return self.api(
             self.papi.proxy_arp_add_del,
-            {'vrf_id': vrf_id,
-             'is_add': is_add,
-             'low_address': low_address,
-             'hi_address': hi_address,
-             }
-        )
+            {'proxy':
+             {
+                 'vrf_id': vrf_id,
+                 'low_address': low_address,
+                 'hi_address': hi_address,
+             },
+             'is_add': is_add})
 
     def proxy_arp_intfc_enable_disable(self,
                                        sw_if_index,