Stats refactor

- added per-interface simple/combined counters
- refactored fib/nbr API to use common registration scheme
- refactored "want_stats" and "want_interface" to use
  per interface registration scheme
- fixed issues with SEGV when client disconnects abruptly.

Change-Id: Ib701bd8e4105d03548259217bfc809bd738b7c72
Signed-off-by: Keith Burns (alagalah) <alagalah@gmail.com>
This commit is contained in:
Keith Burns (alagalah)
2017-09-12 15:12:17 -07:00
committed by Florin Coras
parent 7c5c40db2a
commit 831fb59f2e
5 changed files with 1232 additions and 463 deletions

View File

@ -227,16 +227,61 @@ typeonly manual_print manual_endian define vlib_counter
u64 bytes; /**< byte counter */
};
/** \brief Combined interface counter data type for vnet_interface_combined_counters
@param sw_if_index - interface indexes for counters
@param rx_packets - received packet count
@param rx_bytes - received byte count
@param tx_packets - transmitted packet count
@param tx_bytes - transmitted byte count
*/
typeonly manual_print manual_endian define vnet_combined_counter
{
u32 sw_if_index;
u64 rx_packets; /**< packet counter */
u64 rx_bytes; /**< byte counter */
u64 tx_packets; /**< packet counter */
u64 tx_bytes; /**< byte counter */
};
/** \brief Simple interface counter data type for vnet_interface_simple_counters
@param sw_if_index - interface indexes for counters
@param drop - RX or TX drops due to buffer starvation
@param punt - used with VNET "punt" disposition
@param rx_ip4 - received IP4 packets
@param rx_ip6 - received IP6 packets
@param rx_no_buffer - no RX buffers available
@param rx_miss - receive misses
@param rx_error - receive errors
@param tx_error - transmit errors
@param rx_mpls - received MPLS packet
*/
typeonly manual_print manual_endian define vnet_simple_counter
{
u32 sw_if_index;
u64 drop;
u64 punt;
u64 rx_ip4;
u64 rx_ip6;
u64 rx_no_buffer;
u64 rx_miss;
u64 rx_error;
u64 tx_error;
u64 rx_mpls;
};
/** \brief Simple stats counters structure
@param vnet_counter_type- such as ip4, ip6, punts, etc
@param first_sw_if_index - first sw index in block of index, counts
@param count - number of counters, equal to the number of interfaces in
this stats block
@param data - contiguous block of u64 counters
vnet_counter_type defined in enums - plural - in vnet/interface.h
*/
manual_print manual_endian define vnet_interface_simple_counters
{
/* enums - plural - in vnet/interface.h */
u8 vnet_counter_type;
u32 first_sw_if_index;
u32 count;
@ -249,16 +294,43 @@ manual_print manual_endian define vnet_interface_simple_counters
@param count - number of counters, equal to the number of interfaces in
this stats block
@param data - contiguous block of vlib_counter_t structures
vnet_counter_type defined in enums - plural - in vnet/interface.h
*/
manual_print manual_endian define vnet_interface_combined_counters
{
/* enums - plural - in vnet/interface.h */
u8 vnet_counter_type;
u32 first_sw_if_index;
u32 count;
vl_api_vlib_counter_t data[count];
};
/** \brief Simple per interface stats counters structure
@param count - number of elements in message
@param timestamp - u32 vlib timestamp for control plane
@param data[count] - vl_api_vnet_simple_counter_t
*/
manual_print manual_endian define vnet_per_interface_simple_counters
{
u32 count;
u32 timestamp;
vl_api_vnet_simple_counter_t data[count];
};
/** \brief Combined stats counters structure per interface
@param count - number of elements in message
@param timestamp - u32 vlib timestamp for control plane
@param data[count] - vl_api_vnet_combined_counter_t
*/
manual_print manual_endian define vnet_per_interface_combined_counters
{
u32 count;
u32 timestamp;
vl_api_vnet_combined_counter_t data[count];
};
/** \brief Set unnumbered interface add / del request
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request

View File

@ -38,6 +38,8 @@ autoreply define want_stats
@param context - sender context, to match reply w/ request
@param enable_disable - 1 = enable stats, 0 = disable
@param pid - pid of process requesting stats updates
Please consider using want_per_interface_simple_stats with sw_if_index=~0
*/
autoreply define want_interface_simple_stats
{
@ -47,11 +49,33 @@ autoreply define want_interface_simple_stats
u32 pid;
};
/** \brief Want Per Interface simple Stats, register for continuous stats
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param enable_disable - 1 = enable stats, 0 = disable
@param pid - pid of process requesting stats updates
@param num - number of sw_if_indexes
@param sw_ifs - array of sw_if_index
*/
autoreply define want_per_interface_simple_stats
{
u32 client_index;
u32 context;
u32 enable_disable;
u32 pid;
u32 num;
u32 sw_ifs[num];
};
/** \brief Want Interface Combined Stats, register for continuous stats
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param enable_disable - 1 = enable stats, 0 = disable
@param pid - pid of process requesting stats updates
Please consider using want_per_interface_combined_stats with sw_if_index=~0
*/
autoreply define want_interface_combined_stats
{
@ -61,6 +85,25 @@ autoreply define want_interface_combined_stats
u32 pid;
};
/** \brief Want Per Interface Combined Stats, register for continuous stats
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param enable_disable - 1 = enable stats, 0 = disable
@param pid - pid of process requesting stats updates
@param num - number of sw_if_indexes
@param sw_ifs - array of sw_if_index
*/
autoreply define want_per_interface_combined_stats
{
u32 client_index;
u32 context;
u32 enable_disable;
u32 pid;
u32 num;
u32 sw_ifs[num];
};
/** \brief Want IP4 FIB Stats, register for continuous stats
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request

File diff suppressed because it is too large Load Diff

View File

@ -36,19 +36,10 @@ typedef struct
int tag;
} data_structure_lock_t;
typedef struct
{
vpe_client_registration_t client;
u8 stats_registrations;
#define INTERFACE_SIMPLE_COUNTERS (1 << 0)
#define INTERFACE_COMBINED_COUNTERS (1 << 1)
#define IP4_FIB_COUNTERS (1 << 2)
#define IP4_NBR_COUNTERS (1 << 3)
#define IP6_FIB_COUNTERS (1 << 4)
#define IP6_NBR_COUNTERS (1 << 5)
} vpe_client_stats_registration_t;
/**
* @brief stats request registration indexes
*
*/
/* from .../vnet/vnet/ip/lookup.c. Yuck */
typedef CLIB_PACKED (struct
{
@ -57,6 +48,30 @@ u32 address_length: 6;
u32 index: 26;
}) ip4_route_t;
/* see interface.api */
typedef struct
{
u32 sw_if_index;
u64 drop;
u64 punt;
u64 rx_ip4;
u64 rx_ip6;
u64 rx_no_buffer;
u64 rx_miss;
u64 rx_error;
u64 tx_error;
u64 rx_mpls;
} vnet_simple_counter_t;
typedef struct
{
u32 sw_if_index;
u64 rx_packets; /**< packet counter */
u64 rx_bytes; /**< byte counter */
u64 tx_packets; /**< packet counter */
u64 tx_bytes; /**< byte counter */
} vnet_combined_counter_t;
typedef struct
{
ip6_address_t address;
@ -74,6 +89,33 @@ typedef struct
uword *results;
} do_ip46_fibs_t;
typedef struct
{
u16 msg_id;
u32 size;
u32 client_index;
u32 context;
i32 retval;
} client_registration_reply_t;
typedef enum
{
#define stats_reg(n) IDX_##n,
#include <vpp/stats/stats.reg>
#undef stats_reg
STATS_REG_N_IDX,
} stats_reg_index_t;
typedef struct
{
//Standard client information
uword *client_hash;
vpe_client_registration_t *clients;
u32 item;
} vpe_client_stats_registration_t;
typedef struct
{
void *mheap;
@ -83,9 +125,41 @@ typedef struct
u32 stats_poll_interval_in_seconds;
u32 enable_poller;
uword *stats_registration_hash;
vpe_client_stats_registration_t *stats_registrations;
vpe_client_stats_registration_t **regs;
/*
* stats_registrations is a vector, indexed by
* IDX_xxxx_COUNTER generated for each streaming
* stat a client can register for. (see stats.reg)
*
* The values in the vector refer to pools.
*
* The pool is of type vpe_client_stats_registration_t
*
* This typedef consists of:
*
* u32 item: This is the instance of the IDX_xxxx_COUNTER a
* client is interested in.
* vpe_client_registration_t *clients: The list of clients interested.
*
* e.g.
* stats_registrations[IDX_INTERFACE_SIMPLE_COUNTERS] refers to a pool
* containing elements:
*
* u32 item = sw_if_index1
* clients = ["clienta","clientb"]
*
* When clients == NULL the pool element is freed. When the pool is empty
*
* ie
* 0 == pool_elts(stats_registrations[IDX_INTERFACE_SIMPLE_COUNTERS]
*
* then there is no need to process INTERFACE_SIMPLE_COUNTERS
*
* Note that u32 item = ~0 is the simple case for ALL interfaces or fibs.
*
*/
uword **stats_registration_hash;
vpe_client_stats_registration_t **stats_registrations;
/* control-plane data structure lock */
data_structure_lock_t *data_structure_lock;
@ -96,6 +170,13 @@ typedef struct
/* Vectors for Distribution funcs: do_ip4_fibs and do_ip6_fibs. */
do_ip46_fibs_t do_ip46_fibs;
/*
Working vector vars so as to not thrash memory allocator.
Has effect of making "static"
*/
vpe_client_stats_registration_t **regs_tmp;
vpe_client_registration_t **clients_tmp;
/* convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;

42
src/vpp/stats/stats.reg Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2017 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.
*/
/**
* @file
* @brief Client stats registrations
*
* Each entry is a specific REGISTRATION as
* opposed to an API call.
*
* For instance:
* want_stats()
* enables/disables ALL stats entries below for all
* ITEM.
*
* An item is the an incident of the thing we want stats for
* such as a FIB or sw_if_index for interface. In each case the
* value ~0 is treated as ALL ITEMs.
*
* As such want_interface_simple_counters() is translated to
* want_per_interface_simple_counters(item=~0)
*/
stats_reg (IP4_FIB_COUNTERS)
stats_reg (IP4_NBR_COUNTERS)
stats_reg (IP6_FIB_COUNTERS)
stats_reg (IP6_NBR_COUNTERS)
stats_reg (PER_INTERFACE_COMBINED_COUNTERS)
stats_reg (PER_INTERFACE_SIMPLE_COUNTERS)