summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2017-03-09 16:48:39 +0100
committerFlorin Coras <florin.coras@gmail.com>2017-03-21 15:31:56 +0000
commit4868ff65eddfd694a1485d6c6c355f9a8ca9011d (patch)
tree37a32136a23428e0fddcf50dd244c11ba67378f2
parent1dc2f9284e5b5eb8b300d63cdb8f74ee36cdecb0 (diff)
LISP statistics
Change-Id: I399cac46d279e020ba33459ef759d9d29d3ac716 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
-rw-r--r--src/vat/api_format.c208
-rw-r--r--src/vnet/adj/adj_l2.c1
-rw-r--r--src/vnet/lisp-cp/control.c72
-rw-r--r--src/vnet/lisp-cp/control.h14
-rw-r--r--src/vnet/lisp-cp/lisp_types.c38
-rw-r--r--src/vnet/lisp-cp/lisp_types.h3
-rw-r--r--src/vnet/lisp-cp/one_api.c67
-rw-r--r--src/vnet/lisp-cp/one_cli.c61
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.c2
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.h30
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_adjacency.c100
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c86
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h3
13 files changed, 639 insertions, 46 deletions
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index 391fe9cf7c4..d34a97f65cb 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -2611,6 +2611,92 @@ vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t
}
static void
+vl_api_one_stats_details_t_handler (vl_api_one_stats_details_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ u8 *seid = 0, *deid = 0;
+ u8 *(*format_ip_address_fcn) (u8 *, va_list *) = 0;
+
+ deid = format (0, "%U", format_lisp_eid_vat,
+ mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0);
+
+ seid = format (0, "%U", format_lisp_eid_vat,
+ mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0);
+
+ vec_add1 (deid, 0);
+ vec_add1 (seid, 0);
+
+ if (mp->is_ip4)
+ format_ip_address_fcn = format_ip4_address;
+ else
+ format_ip_address_fcn = format_ip6_address;
+
+
+ print (vam->ofp, "([%d] %s %s) (%U %U) %u %u",
+ clib_net_to_host_u32 (mp->vni),
+ seid, deid,
+ format_ip_address_fcn, mp->lloc,
+ format_ip_address_fcn, mp->rloc,
+ clib_net_to_host_u32 (mp->pkt_count),
+ clib_net_to_host_u32 (mp->bytes));
+
+ vec_free (deid);
+ vec_free (seid);
+}
+
+static void
+vl_api_one_stats_details_t_handler_json (vl_api_one_stats_details_t * mp)
+{
+ struct in6_addr ip6;
+ struct in_addr ip4;
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t *node = 0;
+ u8 *deid = 0, *seid = 0;
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type)
+ {
+ ASSERT (VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array (&vam->json_tree);
+ }
+ node = vat_json_array_add (&vam->json_tree);
+
+ vat_json_init_object (node);
+ deid = format (0, "%U", format_lisp_eid_vat,
+ mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0);
+
+ seid = format (0, "%U", format_lisp_eid_vat,
+ mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0);
+
+ vec_add1 (deid, 0);
+ vec_add1 (seid, 0);
+
+ vat_json_object_add_string_copy (node, "seid", seid);
+ vat_json_object_add_string_copy (node, "deid", deid);
+ vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni));
+
+ if (mp->is_ip4)
+ {
+ clib_memcpy (&ip4, mp->lloc, sizeof (ip4));
+ vat_json_object_add_ip4 (node, "lloc", ip4);
+ clib_memcpy (&ip4, mp->rloc, sizeof (ip4));
+ vat_json_object_add_ip4 (node, "rloc", ip4);
+ }
+ else
+ {
+ clib_memcpy (&ip6, mp->lloc, sizeof (ip6));
+ vat_json_object_add_ip6 (node, "lloc", ip6);
+ clib_memcpy (&ip6, mp->rloc, sizeof (ip6));
+ vat_json_object_add_ip6 (node, "rloc", ip6);
+ }
+ vat_json_object_add_uint (node, "pkt_count",
+ clib_net_to_host_u32 (mp->pkt_count));
+ vat_json_object_add_uint (node, "bytes", clib_net_to_host_u32 (mp->bytes));
+
+ vec_free (deid);
+ vec_free (seid);
+}
+
+static void
vl_api_one_eid_table_map_details_t_handler
(vl_api_one_eid_table_map_details_t * mp)
{
@@ -2741,6 +2827,42 @@ static void
}
static void
+ vl_api_show_one_stats_enable_disable_reply_t_handler
+ (vl_api_show_one_stats_enable_disable_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ int retval = clib_net_to_host_u32 (mp->retval);
+
+ if (retval)
+ goto end;
+
+ print (vam->ofp, "%s", mp->is_en ? "enabled" : "disabled");
+end:
+ vam->retval = retval;
+ vam->result_ready = 1;
+}
+
+static void
+ vl_api_show_one_stats_enable_disable_reply_t_handler_json
+ (vl_api_show_one_stats_enable_disable_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t _node, *node = &_node;
+ int retval = clib_net_to_host_u32 (mp->retval);
+
+ u8 *s = format (0, "%s", mp->is_en ? "enabled" : "disabled");
+ vat_json_init_object (node);
+ vat_json_object_add_string_copy (node, "state", s);
+
+ vat_json_print (vam->ofp, node);
+ vat_json_free (node);
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+ vec_free (s);
+}
+
+static void
api_gpe_fwd_entry_net_to_host (vl_api_gpe_fwd_entry_t * e)
{
e->dp_table = clib_net_to_host_u32 (e->dp_table);
@@ -4040,6 +4162,7 @@ _(one_map_request_mode_reply) \
_(one_add_del_map_request_itr_rlocs_reply) \
_(one_eid_table_add_del_map_reply) \
_(one_use_petr_reply) \
+_(one_stats_enable_disable_reply) \
_(gpe_add_del_fwd_entry_reply) \
_(gpe_enable_disable_reply) \
_(gpe_set_encap_mode_reply) \
@@ -4263,6 +4386,10 @@ _(ONE_EID_TABLE_VNI_DETAILS, one_eid_table_vni_details) \
_(ONE_MAP_RESOLVER_DETAILS, one_map_resolver_details) \
_(ONE_MAP_SERVER_DETAILS, one_map_server_details) \
_(ONE_ADJACENCIES_GET_REPLY, one_adjacencies_get_reply) \
+_(ONE_STATS_DETAILS, one_stats_details) \
+_(ONE_STATS_ENABLE_DISABLE_REPLY, one_stats_enable_disable_reply) \
+_(SHOW_ONE_STATS_ENABLE_DISABLE_REPLY, \
+ show_one_stats_enable_disable_reply) \
_(GPE_SET_ENCAP_MODE_REPLY, gpe_set_encap_mode_reply) \
_(GPE_GET_ENCAP_MODE_REPLY, gpe_get_encap_mode_reply) \
_(GPE_ADD_DEL_IFACE_REPLY, gpe_add_del_iface_reply) \
@@ -14215,6 +14342,64 @@ api_show_one_rloc_probe_state (vat_main_t * vam)
#define api_show_lisp_rloc_probe_state api_show_one_rloc_probe_state
static int
+api_one_stats_enable_disable (vat_main_t * vam)
+{
+ vl_api_one_stats_enable_disable_t *mp;
+ unformat_input_t *input = vam->input;
+ u8 is_set = 0;
+ u8 is_en = 0;
+ int ret;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "enable"))
+ {
+ is_set = 1;
+ is_en = 1;
+ }
+ else if (unformat (input, "disable"))
+ {
+ is_set = 1;
+ }
+ else
+ break;
+ }
+
+ if (!is_set)
+ {
+ errmsg ("Value not set");
+ return -99;
+ }
+
+ M (ONE_STATS_ENABLE_DISABLE, mp);
+ mp->is_en = is_en;
+
+ /* send */
+ S (mp);
+
+ /* wait for reply */
+ W (ret);
+ return ret;
+}
+
+static int
+api_show_one_stats_enable_disable (vat_main_t * vam)
+{
+ vl_api_show_one_stats_enable_disable_t *mp;
+ int ret;
+
+ M (SHOW_ONE_STATS_ENABLE_DISABLE, mp);
+
+ /* send */
+ S (mp);
+
+ /* wait for reply */
+ W (ret);
+ return ret;
+}
+
+static int
api_show_one_map_request_mode (vat_main_t * vam)
{
vl_api_show_one_map_request_mode_t *mp;
@@ -15422,6 +15607,26 @@ api_one_map_resolver_dump (vat_main_t * vam)
#define api_lisp_map_resolver_dump api_one_map_resolver_dump
static int
+api_one_stats_dump (vat_main_t * vam)
+{
+ vl_api_one_stats_dump_t *mp;
+ vl_api_control_ping_t *mp_ping;
+ int ret;
+
+ M (ONE_STATS_DUMP, mp);
+ /* send it... */
+ S (mp);
+
+ /* Use a control ping for synchronization */
+ M (CONTROL_PING, mp_ping);
+ S (mp_ping);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
+static int
api_show_one_status (vat_main_t * vam)
{
vl_api_show_one_status_t *mp;
@@ -18389,6 +18594,8 @@ _(one_locator_set_dump, "[local | remote]") \
_(one_locator_dump, "ls_index <index> | ls_name <name>") \
_(one_eid_table_dump, "[eid <ipv4|ipv6>/<prefix> | <mac>] [vni] " \
"[local] | [remote]") \
+_(one_stats_enable_disable, "enable|disalbe") \
+_(show_one_stats_enable_disable, "") \
_(one_eid_table_vni_dump, "") \
_(one_eid_table_map_dump, "l2|l3") \
_(one_map_resolver_dump, "") \
@@ -18397,6 +18604,7 @@ _(one_adjacencies_get, "vni <vni>") \
_(show_one_rloc_probe_state, "") \
_(show_one_map_register_state, "") \
_(show_one_status, "") \
+_(one_stats_dump, "") \
_(one_get_map_request_itr_rlocs, "") \
_(show_one_pitr, "") \
_(show_one_use_petr, "") \
diff --git a/src/vnet/adj/adj_l2.c b/src/vnet/adj/adj_l2.c
index 5a083643302..fb64e505633 100644
--- a/src/vnet/adj/adj_l2.c
+++ b/src/vnet/adj/adj_l2.c
@@ -93,6 +93,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
/* Update packet buffer attributes/set output interface. */
rw_len0 = adj0[0].rewrite_header.data_bytes;
vnet_buffer(p0)->ip.save_rewrite_length = rw_len0;
+ vnet_buffer(p0)->sw_if_index[VLIB_TX] = adj0->rewrite_header.sw_if_index;
vlib_increment_combined_counter(&adjacency_counters,
cpu_index,
diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c
index 5c90c03b9f0..47badeb9163 100644
--- a/src/vnet/lisp-cp/control.c
+++ b/src/vnet/lisp-cp/control.c
@@ -19,6 +19,7 @@
#include <vnet/lisp-cp/lisp_msg_serdes.h>
#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
#include <vnet/lisp-gpe/lisp_gpe_tenant.h>
+#include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
#include <vnet/fib/fib_entry.h>
#include <vnet/fib/fib_table.h>
@@ -284,6 +285,7 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
if (fe->is_src_dst)
gid_address_copy (&a->lcl_eid, &fe->leid);
+ vnet_lisp_del_fwd_stats (a, feip[0]);
vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
/* delete entry in fwd table */
@@ -1228,9 +1230,6 @@ vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a)
if (a->is_add)
{
- /* TODO 1) check if src/dst 2) once we have src/dst working, use it in
- * delete*/
-
/* check if source eid has an associated mapping. If pitr mode is on,
* just use the pitr's mapping */
local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
@@ -2654,16 +2653,15 @@ lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b)
return vni;
}
-always_inline void
+void
get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
- gid_address_t * src, gid_address_t * dst)
+ gid_address_t * src, gid_address_t * dst,
+ u16 type)
{
u32 vni = 0;
- u16 type;
memset (src, 0, sizeof (*src));
memset (dst, 0, sizeof (*dst));
- type = vnet_buffer (b)->lisp.overlay_afi;
if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
{
@@ -2742,10 +2740,9 @@ lisp_cp_lookup_inline (vlib_main_t * vm,
b0 = vlib_get_buffer (vm, pi0);
b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
- vnet_buffer (b0)->lisp.overlay_afi = overlay;
/* src/dst eid pair */
- get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst);
+ get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst, overlay);
/* if we have remote mapping for destination already in map-chache
add forwarding tunnel directly. If not send a map-request */
@@ -3605,6 +3602,55 @@ lisp_cp_init (vlib_main_t * vm)
return 0;
}
+static int
+lisp_stats_api_fill (lisp_cp_main_t * lcm, lisp_gpe_main_t * lgm,
+ lisp_api_stats_t * stat, lisp_stats_key_t * key,
+ u32 stats_index)
+{
+ lisp_stats_t *s;
+ lisp_gpe_fwd_entry_key_t fwd_key;
+ const lisp_gpe_tunnel_t *lgt;
+ fwd_entry_t *fe;
+
+ memset (stat, 0, sizeof (*stat));
+ memset (&fwd_key, 0, sizeof (fwd_key));
+
+ fe = pool_elt_at_index (lcm->fwd_entry_pool, key->fwd_entry_index);
+ ASSERT (fe != 0);
+
+ gid_to_dp_address (&fe->reid, &stat->deid);
+ gid_to_dp_address (&fe->leid, &stat->seid);
+ stat->vni = gid_address_vni (&fe->reid);
+
+ lgt = lisp_gpe_tunnel_get (key->tunnel_index);
+ stat->loc_rloc = lgt->key->lcl;
+ stat->rmt_rloc = lgt->key->rmt;
+
+ s = pool_elt_at_index (lgm->lisp_stats_pool, stats_index);
+ stat->stats = *s;
+ return 1;
+}
+
+lisp_api_stats_t *
+vnet_lisp_get_stats (void)
+{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lisp_api_stats_t *stats = 0, stat;
+ lisp_stats_key_t *key;
+ u32 index;
+
+ /* *INDENT-OFF* */
+ hash_foreach_mem (key, index, lgm->lisp_stats_index_by_key,
+ {
+ if (lisp_stats_api_fill (lcm, lgm, &stat, key, index))
+ vec_add1 (stats, stat);
+ });
+ /* *INDENT-ON* */
+
+ return stats;
+}
+
static void *
send_map_request_thread_fn (void *arg)
{
@@ -3810,7 +3856,11 @@ vnet_lisp_stats_enable_disable (u8 enable)
if (vnet_lisp_enable_disable_status () == 0)
return VNET_API_ERROR_LISP_DISABLED;
- lcm->stats_enabled = enable;
+ if (enable)
+ lcm->flags |= LISP_FLAG_STATS_ENABLED;
+ else
+ lcm->flags &= ~LISP_FLAG_STATS_ENABLED;
+
return 0;
}
@@ -3822,7 +3872,7 @@ vnet_lisp_stats_enable_disable_state (void)
if (vnet_lisp_enable_disable_status () == 0)
return VNET_API_ERROR_LISP_DISABLED;
- return lcm->stats_enabled;
+ return lcm->flags & LISP_FLAG_STATS_ENABLED;
}
/* *INDENT-OFF* */
diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h
index 933b34b66bc..eae8a184f76 100644
--- a/src/vnet/lisp-cp/control.h
+++ b/src/vnet/lisp-cp/control.h
@@ -95,7 +95,8 @@ typedef enum
} map_request_mode_t;
#define foreach_lisp_flag_bit \
- _(USE_PETR, "Use Proxy-ETR")
+ _(USE_PETR, "Use Proxy-ETR") \
+ _(STATS_ENABLED, "Statistics enabled")
typedef enum lisp_flag_bits
{
@@ -210,9 +211,6 @@ typedef struct
/* timing wheel for mappping timeouts */
timing_wheel_t wheel;
- /* statistics */
- u8 stats_enabled;
-
/* commodity */
ip4_main_t *im4;
ip6_main_t *im6;
@@ -235,6 +233,11 @@ vnet_lisp_cp_get_main ()
return &lisp_control_main;
}
+void
+get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
+ gid_address_t * src, gid_address_t * dst,
+ u16 type);
+
typedef struct
{
u8 is_add;
@@ -335,9 +338,6 @@ lisp_get_petr_mapping (lisp_cp_main_t * lcm)
return pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index);
}
-u8 vnet_lisp_stats_enable_disable_state (void);
-vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable);
-
#endif /* VNET_CONTROL_H_ */
/*
diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c
index b6466686009..ad3a4bdf149 100644
--- a/src/vnet/lisp-cp/lisp_types.c
+++ b/src/vnet/lisp-cp/lisp_types.c
@@ -573,6 +573,44 @@ ip_address_parse (void *offset, u16 iana_afi, ip_address_t * dst)
return (sizeof (u16) + size);
}
+void
+gid_to_dp_address (gid_address_t * g, dp_address_t * d)
+{
+ switch (gid_address_type (g))
+ {
+ case GID_ADDR_SRC_DST:
+ switch (gid_address_sd_dst_type (g))
+ {
+ case FID_ADDR_IP_PREF:
+ ip_prefix_copy (&d->ippref, &gid_address_sd_dst_ippref (g));
+ d->type = FID_ADDR_IP_PREF;
+ break;
+ case FID_ADDR_MAC:
+ mac_copy (&d->mac, &gid_address_sd_dst_mac (g));
+ d->type = FID_ADDR_MAC;
+ break;
+ default:
+ clib_warning ("Source/Dest address type %d not supported!",
+ gid_address_sd_dst_type (g));
+ break;
+ }
+ break;
+ case GID_ADDR_IP_PREFIX:
+ ip_prefix_copy (&d->ippref, &gid_address_ippref (g));
+ d->type = FID_ADDR_IP_PREF;
+ break;
+ case GID_ADDR_MAC:
+ mac_copy (&d->mac, &gid_address_mac (g));
+ d->type = FID_ADDR_MAC;
+ break;
+ case GID_ADDR_NSH:
+ default:
+ d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si;
+ d->type = FID_ADDR_NSH;
+ break;
+ }
+}
+
u32
lcaf_hdr_parse (void *offset, lcaf_t * lcaf)
{
diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h
index 672835bd760..a65a479e533 100644
--- a/src/vnet/lisp-cp/lisp_types.h
+++ b/src/vnet/lisp-cp/lisp_types.h
@@ -126,6 +126,8 @@ typedef struct
typedef fid_address_t dp_address_t;
#define fid_addr_ippref(_a) (_a)->ippref
+#define fid_addr_prefix_length(_a) ip_prefix_len(&fid_addr_ippref(_a))
+#define fid_addr_ip_version(_a) ip_prefix_version(&fid_addr_ippref(_a))
#define fid_addr_mac(_a) (_a)->mac
#define fid_addr_nsh(_a) (_a)->nsh
#define fid_addr_type(_a) (_a)->type
@@ -359,6 +361,7 @@ void
build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst);
void gid_address_from_ip (gid_address_t * g, ip_address_t * ip);
+void gid_to_dp_address (gid_address_t * g, dp_address_t * d);
#endif /* VNET_LISP_GPE_LISP_TYPES_H_ */
diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c
index 4faf624014b..ab9e7a635ce 100644
--- a/src/vnet/lisp-cp/one_api.c
+++ b/src/vnet/lisp-cp/one_api.c
@@ -58,6 +58,21 @@
#include <vlibapi/api_helper_macros.h>
+#define REPLY_DETAILS(t, body) \
+do { \
+ unix_shared_memory_queue_t * q; \
+ rv = vl_msg_api_pd_handler (mp, rv); \
+ q = vl_api_client_index_to_input_queue (mp->client_index); \
+ if (!q) \
+ return; \
+ \
+ rmp = vl_msg_api_alloc (sizeof (*rmp)); \
+ rmp->_vl_msg_id = ntohs((t)); \
+ rmp->context = mp->context; \
+ do {body;} while (0); \
+ vl_msg_api_send_shmem (q, (u8 *)&rmp); \
+} while(0);
+
#define foreach_vpe_api_msg \
_(ONE_ADD_DEL_LOCATOR_SET, one_add_del_locator_set) \
_(ONE_ADD_DEL_LOCATOR, one_add_del_locator) \
@@ -1301,9 +1316,61 @@ static void
}
static void
+lisp_fid_addr_to_api (fid_address_t * fid, u8 * dst, u8 * api_eid_type,
+ u8 * prefix_length)
+{
+ switch (fid_addr_type (fid))
+ {
+ case FID_ADDR_IP_PREF:
+ *prefix_length = fid_addr_prefix_length (fid);
+ if (fid_addr_ip_version (fid) == IP4)
+ {
+ *api_eid_type = 0; /* ipv4 type */
+ clib_memcpy (dst, &fid_addr_ippref (fid), 4);
+ }
+ else
+ {
+ *api_eid_type = 1; /* ipv6 type */
+ clib_memcpy (dst, &fid_addr_ippref (fid), 16);
+ }
+ break;
+ case FID_ADDR_MAC:
+ *api_eid_type = 2; /* l2 mac type */
+ mac_copy (dst, fid_addr_mac (fid));
+ break;
+ default:
+ ASSERT (0);
+ }
+}
+
+static void
vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp)
{
+ vl_api_one_stats_details_t *rmp;
+ lisp_api_stats_t *stats, *stat;
+ u8 rv = 0;
+ stats = vnet_lisp_get_stats ();
+ vec_foreach (stat, stats)
+ {
+ /* *INDENT-OFF* */
+ REPLY_DETAILS (VL_API_ONE_STATS_DETAILS,
+ ({
+ lisp_fid_addr_to_api (&stat->deid, rmp->deid, &rmp->eid_type,
+ &rmp->deid_pref_len);
+ lisp_fid_addr_to_api (&stat->seid, rmp->seid, &rmp->eid_type,
+ &rmp->seid_pref_len);
+ rmp->vni = clib_host_to_net_u32 (stat->vni);
+
+ rmp->is_ip4 = ip_addr_version (&stat->rmt_rloc) == IP4 ? 1 : 0;
+ ip_address_copy_addr (rmp->rloc, &stat->rmt_rloc);
+ ip_address_copy_addr (rmp->lloc, &stat->loc_rloc);
+
+ rmp->pkt_count = clib_host_to_net_u32 (stat->stats.pkt_count);
+ rmp->bytes = clib_host_to_net_u32 (stat->stats.bytes);
+ }));
+ /* *INDENT-ON* */
+ }
}
/*
diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c
index 2ceeaf42fa7..b5bc5292fad 100644
--- a/src/vnet/lisp-cp/one_cli.c
+++ b/src/vnet/lisp-cp/one_cli.c
@@ -352,7 +352,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
}
}
- if (!eid_set)
+ if (!del_all && !eid_set)
{
clib_warning ("missing eid!");
goto done;
@@ -372,8 +372,6 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
goto done;
}
- /* TODO build src/dst with seid */
-
/* if it's a delete, clean forwarding */
if (!is_add)
{
@@ -1654,13 +1652,47 @@ lisp_show_stats_command_fn (vlib_main_t * vm,
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (one_show_stats_command) = {
- .path = "show one stats",
- .short_help = "show ONE statistics",
+ .path = "show one statistics status",
+ .short_help = "show ONE statistics enable/disable status",
.function = lisp_show_stats_command_fn,
};
/* *INDENT-ON* */
static clib_error_t *
+lisp_show_stats_details_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ lisp_api_stats_t *stat, *stats = vnet_lisp_get_stats ();
+
+ if (vec_len (stats) > 0)
+ vlib_cli_output (vm,
+ "[src-EID, dst-EID] [loc-rloc, rmt-rloc] count bytes\n");
+ else
+ vlib_cli_output (vm, "No statistics found.\n");
+
+ vec_foreach (stat, stats)
+ {
+ vlib_cli_output (vm, "[%U, %U] [%U, %U] %7u %7u\n",
+ format_fid_address, &stat->seid,
+ format_fid_address, &stat->deid,
+ format_ip_address, &stat->loc_rloc,
+ format_ip_address, &stat->rmt_rloc,
+ stat->stats.pkt_count, stat->stats.bytes);
+ }
+ vec_free (stats);
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (one_show_stats_details_command) = {
+ .path = "show one statistics details",
+ .short_help = "show ONE statistics",
+ .function = lisp_show_stats_details_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
lisp_stats_enable_disable_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
@@ -1692,12 +1724,29 @@ done:
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (one_stats_enable_disable_command) = {
- .path = "one stats",
+ .path = "one statistics",
.short_help = "enable/disable ONE statistics collecting",
.function = lisp_stats_enable_disable_command_fn,
};
/* *INDENT-ON* */
+static clib_error_t *
+lisp_stats_flush_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vnet_lisp_flush_stats ();
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (one_stats_flush_command) = {
+ .path = "one statistics flush",
+ .short_help = "Flush ONE statistics",
+ .function = lisp_stats_flush_command_fn,
+};
+/* *INDENT-ON* */
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/vnet/lisp-gpe/lisp_gpe.c b/src/vnet/lisp-gpe/lisp_gpe.c
index 446ad445592..1241ab9caec 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.c
+++ b/src/vnet/lisp-gpe/lisp_gpe.c
@@ -424,6 +424,8 @@ lisp_gpe_init (vlib_main_t * vm)
udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe6,
lisp_gpe_ip6_input_node.index, 0 /* is_ip4 */ );
+ lgm->lisp_stats_index_by_key =
+ hash_create_mem (0, sizeof (lisp_stats_key_t), sizeof (uword));
return 0;
}
diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h
index b5a50ec6884..be447024cb9 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.h
+++ b/src/vnet/lisp-gpe/lisp_gpe.h
@@ -90,6 +90,28 @@ typedef struct tunnel_lookup
uword *vni_by_sw_if_index;
} tunnel_lookup_t;
+typedef struct
+{
+ u32 fwd_entry_index;
+ u32 tunnel_index;
+} lisp_stats_key_t;
+
+typedef struct
+{
+ u32 pkt_count;
+ u32 bytes;
+} lisp_stats_t;
+
+typedef struct
+{
+ u32 vni;
+ dp_address_t deid;
+ dp_address_t seid;
+ ip_address_t loc_rloc;
+ ip_address_t rmt_rloc;
+
+ lisp_stats_t stats;
+} lisp_api_stats_t;
typedef enum gpe_encap_mode_e
{
@@ -143,6 +165,9 @@ typedef struct lisp_gpe_main
gpe_encap_mode_t encap_mode;
+ lisp_stats_t *lisp_stats_pool;
+ uword *lisp_stats_index_by_key;
+
/** convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
@@ -283,6 +308,11 @@ lisp_api_gpe_fwd_entry_t *vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni);
gpe_encap_mode_t vnet_gpe_get_encap_mode (void);
int vnet_gpe_set_encap_mode (gpe_encap_mode_t mode);
+u8 vnet_lisp_stats_enable_disable_state (void);
+vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable);
+lisp_api_stats_t *vnet_lisp_get_stats (void);
+void vnet_lisp_flush_stats (void);
+
#endif /* included_vnet_lisp_gpe_h */
/*
diff --git a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c
index dbcf7134103..50662dd679f 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c
@@ -19,6 +19,7 @@
*/
#include <vnet/dpo/load_balance.h>
+#include <vnet/lisp-cp/control.h>
#include <vnet/lisp-cp/lisp_types.h>
#include <vnet/lisp-gpe/lisp_gpe_sub_interface.h>
#include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
@@ -223,9 +224,108 @@ lisp_gpe_adj_proto_from_vnet_link_type (vnet_link_t linkt)
#define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40
+static lisp_afi_e
+lisp_afi_from_vnet_link_type (vnet_link_t link)
+{
+ switch (link)
+ {
+ case VNET_LINK_IP4:
+ return LISP_AFI_IP;
+ case VNET_LINK_IP6:
+ return LISP_AFI_IP6;
+ case VNET_LINK_ETHERNET:
+ return LISP_AFI_MAC;
+ default:
+ return LISP_AFI_NO_ADDR;
+ }
+}
+
+static void
+lisp_gpe_increment_stats_counters (lisp_cp_main_t * lcm, ip_adjacency_t * adj,
+ vlib_buffer_t * b)
+{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ lisp_gpe_adjacency_t *ladj;
+ ip_address_t rloc;
+ index_t lai;
+ u32 si, di;
+ gid_address_t src, dst;
+ lisp_stats_t *stats;
+ uword *feip;
+
+ ip46_address_to_ip_address (&adj->sub_type.nbr.next_hop, &rloc);
+ si = vnet_buffer (b)->sw_if_index[VLIB_TX];
+ lai = lisp_adj_find (&rloc, si);
+ ASSERT (INDEX_INVALID != lai);
+
+ ladj = pool_elt_at_index (lisp_adj_pool, lai);
+
+ u8 *lisp_data = (u8 *) vlib_buffer_get_current (b);
+
+ /* skip IP header */
+ if (is_v4_packet (lisp_data))
+ lisp_data += sizeof (ip4_header_t);
+ else
+ lisp_data += sizeof (ip6_header_t);
+
+ /* skip UDP header */
+ lisp_data += sizeof (udp_header_t);
+ // TODO: skip TCP?
+
+ /* skip LISP GPE header */
+ lisp_data += sizeof (lisp_gpe_header_t);
+
+ i16 saved_current_data = b->current_data;
+ b->current_data = lisp_data - b->data;
+
+ lisp_afi_e afi = lisp_afi_from_vnet_link_type (adj->ia_link);
+ get_src_and_dst_eids_from_buffer (lcm, b, &src, &dst, afi);
+ b->current_data = saved_current_data;
+ di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst, &src);
+ if (PREDICT_FALSE (~0 == di))
+ {
+ clib_warning ("dst mapping not found (%U, %U)", format_gid_address,
+ &src, format_gid_address, &dst);
+ return;
+ }
+
+ feip = hash_get (lcm->fwd_entry_by_mapping_index, di);
+ if (PREDICT_FALSE (!feip))
+ return;
+
+ lisp_stats_key_t key;
+ memset (&key, 0, sizeof (key));
+ key.fwd_entry_index = feip[0];
+ key.tunnel_index = ladj->tunnel_index;
+
+ uword *p = hash_get_mem (lgm->lisp_stats_index_by_key, &key);
+ if (p)
+ {
+ stats = pool_elt_at_index (lgm->lisp_stats_pool, p[0]);
+ }
+ else
+ {
+ pool_get (lgm->lisp_stats_pool, stats);
+ memset (stats, 0, sizeof (*stats));
+
+ lisp_stats_key_t *key_copy = clib_mem_alloc (sizeof (*key_copy));
+ memcpy (key_copy, &key, sizeof (*key_copy));
+ hash_set_mem (lgm->lisp_stats_index_by_key, key_copy,
+ stats - lgm->lisp_stats_pool);
+ }
+ stats->pkt_count++;
+ /* compute payload length starting after GPE */
+ stats->bytes += b->current_length - (lisp_data - b->data - b->current_data);
+}
+
static void
lisp_gpe_fixup (vlib_main_t * vm, ip_adjacency_t * adj, vlib_buffer_t * b)
{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+
+ if (lcm->flags & LISP_FLAG_STATS_ENABLED)
+ lisp_gpe_increment_stats_counters (lcm, adj, b);
+
/* Fixup the checksum and len fields in the LISP tunnel encap
* that was applied at the midchain node */
ip_udp_fixup_one (vm, b, is_v4_packet (vlib_buffer_get_current (b)));
diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
index 2eb5ced60b0..f458a14c86b 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
@@ -329,28 +329,6 @@ delete_fib_entries (lisp_gpe_fwd_entry_t * lfe)
lfe->eid_fib_index, &lfe->key->rmt.ippref);
}
-static void
-gid_to_dp_address (gid_address_t * g, dp_address_t * d)
-{
- switch (gid_address_type (g))
- {
- case GID_ADDR_IP_PREFIX:
- case GID_ADDR_SRC_DST:
- ip_prefix_copy (&d->ippref, &gid_address_ippref (g));
- d->type = FID_ADDR_IP_PREF;
- break;
- case GID_ADDR_MAC:
- mac_copy (&d->mac, &gid_address_mac (g));
- d->type = FID_ADDR_MAC;
- break;
- case GID_ADDR_NSH:
- default:
- d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si;
- d->type = FID_ADDR_NSH;
- break;
- }
-}
-
static lisp_gpe_fwd_entry_t *
find_fwd_entry (lisp_gpe_main_t * lgm,
vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
@@ -1177,6 +1155,70 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
}
}
+void
+vnet_lisp_flush_stats (void)
+{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ lisp_stats_t *stat;
+
+ /* *INDENT-OFF* */
+ pool_foreach (stat, lgm->lisp_stats_pool,
+ {
+ stat->pkt_count = 0;
+ stat->bytes = 0;
+ });
+ /* *INDENT-ON* */
+}
+
+static void
+lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti)
+{
+ hash_pair_t *hp;
+ lisp_stats_key_t key;
+ void *key_copy;
+ uword *p;
+ lisp_stats_t *s;
+
+ memset (&key, 0, sizeof (key));
+ key.fwd_entry_index = fwd_entry_index;
+ key.tunnel_index = ti;
+
+ p = hash_get_mem (lgm->lisp_stats_index_by_key, &key);
+ if (p)
+ {
+ s = pool_elt_at_index (lgm->lisp_stats_pool, p[0]);
+ hp = hash_get_pair (lgm->lisp_stats_index_by_key, &key);
+ key_copy = (void *) (hp->key);
+ hash_unset_mem (lgm->lisp_stats_index_by_key, &key);
+ clib_mem_free (key_copy);
+ pool_put (lgm->lisp_stats_pool, s);
+ }
+}
+
+void
+vnet_lisp_del_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+ u32 fwd_entry_index)
+{
+ lisp_gpe_main_t *lgm = &lisp_gpe_main;
+ lisp_gpe_fwd_entry_key_t fe_key;
+ lisp_gpe_fwd_entry_t *lfe;
+ lisp_fwd_path_t *path;
+ const lisp_gpe_adjacency_t *ladj;
+
+ lfe = find_fwd_entry (lgm, a, &fe_key);
+ if (!lfe)
+ return;
+
+ if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type)
+ return;
+
+ vec_foreach (path, lfe->paths)
+ {
+ ladj = lisp_gpe_adjacency_get (path->lisp_adj);
+ lisp_del_adj_stats (lgm, fwd_entry_index, ladj->tunnel_index);
+ }
+}
+
/**
* @brief Flush all the forwrding entries
*/
diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h
index d58895a3e28..618f7b5393d 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h
+++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h
@@ -206,6 +206,9 @@ extern u32 lisp_l2_fib_lookup (lisp_gpe_main_t * lgm,
extern const dpo_id_t *lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm,
u32 spi_si);
+extern void
+vnet_lisp_del_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a,
+ u32 fwd_entry_index);
#endif
/*