summaryrefslogtreecommitdiffstats
path: root/src/vnet/lisp-gpe
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 /src/vnet/lisp-gpe
parent1dc2f9284e5b5eb8b300d63cdb8f74ee36cdecb0 (diff)
LISP statistics
Change-Id: I399cac46d279e020ba33459ef759d9d29d3ac716 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'src/vnet/lisp-gpe')
-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
5 files changed, 199 insertions, 22 deletions
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
/*