From 0053de63ec4bf8b9bce7817f1b61c9791baf6c26 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 22 May 2018 08:40:52 -0700 Subject: [PATCH] ARP proxy dumps Change-Id: I8335ebf266becf2f42bb3f28a17dfed8d9b08f97 Signed-off-by: Neale Ranns --- extras/vom/vom/arp_proxy_binding.cpp | 27 +++++--- extras/vom/vom/arp_proxy_binding.hpp | 7 +-- extras/vom/vom/arp_proxy_binding_cmds.cpp | 24 +++++++ extras/vom/vom/arp_proxy_binding_cmds.hpp | 36 ++++++++++- extras/vom/vom/arp_proxy_config.cpp | 17 ++++- extras/vom/vom/arp_proxy_config_cmds.cpp | 33 ++++++++-- extras/vom/vom/arp_proxy_config_cmds.hpp | 35 ++++++++++- src/vat/api_format.c | 6 +- src/vnet/adj/adj.c | 4 +- src/vnet/adj/adj_glean.c | 4 +- src/vnet/adj/adj_mcast.c | 4 +- src/vnet/adj/adj_nbr.c | 3 +- src/vnet/ethernet/arp.c | 31 ++++++--- src/vnet/ethernet/arp.h | 56 +++++++++++++++++ src/vnet/ethernet/ethernet.h | 11 ---- src/vnet/interface.c | 21 ++++++- src/vnet/interface_funcs.h | 27 +++++++- src/vnet/ip/ip.api | 57 ++++++++++++++--- src/vnet/ip/ip_api.c | 100 ++++++++++++++++++++++++++++-- src/vnet/ip/ip_neighbor.c | 2 +- src/vpp/api/custom_dump.c | 9 +-- test/ext/vom_test.cpp | 2 +- test/vpp_papi_provider.py | 13 ++-- 23 files changed, 454 insertions(+), 75 deletions(-) create mode 100644 src/vnet/ethernet/arp.h diff --git a/extras/vom/vom/arp_proxy_binding.cpp b/extras/vom/vom/arp_proxy_binding.cpp index 73d3d844f53..bbae9f683eb 100644 --- a/extras/vom/vom/arp_proxy_binding.cpp +++ b/extras/vom/vom/arp_proxy_binding.cpp @@ -26,17 +26,14 @@ singular_db 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 cmd = + std::make_shared(); + + HW::enqueue(cmd); + HW::write(); + + for (auto& record : *cmd) { + auto& payload = record.get_payload(); + + std::shared_ptr 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 diff --git a/extras/vom/vom/arp_proxy_binding.hpp b/extras/vom/vom/arp_proxy_binding.hpp index f57f6971991..284cf7371fa 100644 --- a/extras/vom/vom/arp_proxy_binding.hpp +++ b/extras/vom/vom/arp_proxy_binding.hpp @@ -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 m_itf; - /** - * A reference counting pointer to the prxy config. - */ - const std::shared_ptr m_arp_proxy_cfg; - /** * HW configuration for the binding. The bool representing the * do/don't bind. diff --git a/extras/vom/vom/arp_proxy_binding_cmds.cpp b/extras/vom/vom/arp_proxy_binding_cmds.cpp index 675feef9b8d..2314d531add 100644 --- a/extras/vom/vom/arp_proxy_binding_cmds.cpp +++ b/extras/vom/vom/arp_proxy_binding_cmds.cpp @@ -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 diff --git a/extras/vom/vom/arp_proxy_binding_cmds.hpp b/extras/vom/vom/arp_proxy_binding_cmds.hpp index c73bb13aee3..fcf0a4a2530 100644 --- a/extras/vom/vom/arp_proxy_binding_cmds.hpp +++ b/extras/vom/vom/arp_proxy_binding_cmds.hpp @@ -17,6 +17,7 @@ #define __VOM_ARP_PROXY_BINDING_CMDS_H__ #include "vom/arp_proxy_binding.hpp" +#include "vom/dump_cmd.hpp" #include @@ -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 +{ +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 item; }; -}; + +}; // namespace cmds +}; // namespace VOM /* * fd.io coding-style-patch-verification: ON diff --git a/extras/vom/vom/arp_proxy_config.cpp b/extras/vom/vom/arp_proxy_config.cpp index 3973eba55f9..275d9f9bf74 100644 --- a/extras/vom/vom/arp_proxy_config.cpp +++ b/extras/vom/vom/arp_proxy_config.cpp @@ -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 cmd = + std::make_shared(); + + 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 diff --git a/extras/vom/vom/arp_proxy_config_cmds.cpp b/extras/vom/vom/arp_proxy_config_cmds.cpp index cf7fad5d90d..122c51bdb95 100644 --- a/extras/vom/vom/arp_proxy_config_cmds.cpp +++ b/extras/vom/vom/arp_proxy_config_cmds.cpp @@ -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 * diff --git a/extras/vom/vom/arp_proxy_config_cmds.hpp b/extras/vom/vom/arp_proxy_config_cmds.hpp index ac0e1fd1702..77abc74556b 100644 --- a/extras/vom/vom/arp_proxy_config_cmds.hpp +++ b/extras/vom/vom/arp_proxy_config_cmds.hpp @@ -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 +{ +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 item; }; -}; + +}; // namespace cmds +}; // namespace VOM /* * fd.io coding-style-patch-verification: ON diff --git a/src/vat/api_format.c b/src/vat/api_format.c index b1aaa6992c5..c3ba701b58e 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -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); diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c index ed4bada6f24..abfe8729b39 100644 --- a/src/vnet/adj/adj.c +++ b/src/vnet/adj/adj.c @@ -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 diff --git a/src/vnet/adj/adj_glean.c b/src/vnet/adj/adj_glean.c index 41bc4c9f68d..74881d7f67c 100644 --- a/src/vnet/adj/adj_glean.c +++ b/src/vnet/adj/adj_glean.c @@ -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); } /** diff --git a/src/vnet/adj/adj_mcast.c b/src/vnet/adj/adj_mcast.c index deaa7fcffa4..593c1b66a8a 100644 --- a/src/vnet/adj/adj_mcast.c +++ b/src/vnet/adj/adj_mcast.c @@ -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); } /** diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c index eff7d4ce1fb..6fd9b40efc3 100644 --- a/src/vnet/adj/adj_nbr.c +++ b/src/vnet/adj/adj_nbr.c @@ -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); } /** diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index 55beb7025dd..49a16f764f3 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -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 = ðernet_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 index 00000000000..7b50ed77538 --- /dev/null +++ b/src/vnet/ethernet/arp.h @@ -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 +#include +#include + +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: + */ diff --git a/src/vnet/ethernet/ethernet.h b/src/vnet/ethernet/ethernet.h index fb7e2c5ba81..79ae7e6e909 100644 --- a/src/vnet/ethernet/ethernet.h +++ b/src/vnet/ethernet/ethernet.h @@ -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); diff --git a/src/vnet/interface.c b/src/vnet/interface.c index d3ad896be12..36793f1177e 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -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) { diff --git a/src/vnet/interface_funcs.h b/src/vnet/interface_funcs.h index 3f910f9d13f..e1568e33b5d 100644 --- a/src/vnet/interface_funcs.h +++ b/src/vnet/interface_funcs.h @@ -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, diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index 7f4f030882d..c5be0c67fbb 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -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 diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index ce3ff79acfa..8464b1ddc98 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -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) diff --git a/src/vnet/ip/ip_neighbor.c b/src/vnet/ip/ip_neighbor.c index a43fdfd58b3..b9c03aa703c 100644 --- a/src/vnet/ip/ip_neighbor.c +++ b/src/vnet/ip/ip_neighbor.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include /* * IP neighbor scan parameter defaults are as follows: diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c index ba5515044e0..15b1f69f1ce 100644 --- a/src/vpp/api/custom_dump.c +++ b/src/vpp/api/custom_dump.c @@ -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 "); diff --git a/test/ext/vom_test.cpp b/test/ext/vom_test.cpp index 6958eb117a4..44df2436c80 100644 --- a/test/ext/vom_test.cpp +++ b/test/ext/vom_test.cpp @@ -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 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)); diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index f72d37df7b2..6dbed297de7 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -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, -- 2.16.6