aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYohanPipereau <ypiperea@cisco.com>2019-06-05 11:21:14 +0200
committerHongjun Ni <hongjun.ni@intel.com>2019-06-13 02:43:00 +0000
commitec995e056d985f9ef54f92adbcbe626967912592 (patch)
tree38f50dddfebdf8af34daa0273ecae75f8bc644f7
parent86af475f838adff5c44bb8eccdfba2d665975451 (diff)
Support for ietf-interfaces statistics
-Add connection to VPP STAT API -Support a few statistic counters from ietf-interfaces Change-Id: I77372ea562e73311effd5b08fd36b0d90ababdac Signed-off-by: YohanPipereau <ypiperea@cisco.com>
-rw-r--r--src/plugins/ietf/ietf_interface.c180
-rw-r--r--src/plugins/sc_plugins.c18
2 files changed, 195 insertions, 3 deletions
diff --git a/src/plugins/ietf/ietf_interface.c b/src/plugins/ietf/ietf_interface.c
index 4d13d13..b4a2bc7 100644
--- a/src/plugins/ietf/ietf_interface.c
+++ b/src/plugins/ietf/ietf_interface.c
@@ -21,6 +21,8 @@
#include <scvpp/interface.h>
#include <scvpp/ip.h>
+#include <vpp-api/client/stat_client.h>
+
/**
* @brief Callback to be called by any config change of
* "/ietf-interfaces:interfaces/interface/enabled" leaf.
@@ -259,6 +261,8 @@ ietf_interface_change_cb(sr_session_ctx_t *session, const char *xpath,
/**
* @brief Callback to be called by any request for state data under "/ietf-interfaces:interfaces-state/interface" path.
+ * Here we reply systematically with all interfaces, it the responsability of
+ * sysrepo apply a filter not to answer undesired interfaces.
*/
static int
ietf_interface_state_cb(const char *xpath, sr_val_t **values,
@@ -292,7 +296,7 @@ ietf_interface_state_cb(const char *xpath, sr_val_t **values,
foreach_stack_elt(stack) {
dump = (sw_interface_dump_t *) data;
- SRP_LOG_DBG("State of interface %s", dump->interface_name);
+ SRP_LOG_DBG("State of interface %s, xpath %s", dump->interface_name, xpath);
//TODO need support for type propvirtual
sr_val_build_xpath(&val[cnt], "%s[name='%s']/type", xpath, dump->interface_name);
sr_val_set_str_data(&val[cnt], SR_IDENTITYREF_T, "iana-if-type:ethernetCsmacd");
@@ -338,6 +342,174 @@ nothing_todo:
return rc;
}
+static inline stat_segment_data_t* fetch_stat_index(const char *path) {
+ stat_segment_data_t *r;
+ u32 *stats = NULL;
+ u8 **patterns = NULL;
+
+ patterns = stat_segment_string_vector(patterns, path);
+ if (!patterns)
+ return NULL;
+
+ do {
+ stats = stat_segment_ls(patterns);
+ if (!stats)
+ return NULL;
+
+ r = stat_segment_dump(stats);
+ } while (r == NULL); /* Memory layout has changed */
+
+ return r;
+}
+
+static inline uint64_t get_counter(stat_segment_data_t *r, int itf_idx)
+{
+ if (r == NULL) {
+ SRP_LOG_ERR_MSG("stat segment can not be NULL");
+ return 0;
+ }
+
+ if (r->type != STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE) {
+ SRP_LOG_ERR_MSG("Only simple counter");
+ return 0;
+ }
+
+ return r->simple_counter_vec[0][itf_idx];
+}
+
+static inline uint64_t get_bytes(stat_segment_data_t *r, int itf_idx)
+{
+ if (r->type != STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED) {
+ SRP_LOG_ERR_MSG("Only combined counter");
+ return 0;
+ }
+
+ return r->combined_counter_vec[0][itf_idx].bytes;
+}
+
+static inline uint64_t get_packets(stat_segment_data_t *r, int itf_idx)
+{
+ if (r->type != STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED) {
+ SRP_LOG_ERR_MSG("Only combined counter");
+ return 0;
+ }
+
+ return r->combined_counter_vec[0][itf_idx].packets;
+}
+
+/**
+ * @brief Callback to be called by any request for state data under
+ * "/ietf-interfaces:interfaces-state/interface/statistics" path.
+ */
+static int
+interface_statistics_cb(const char *xpath, sr_val_t **values,
+ size_t *values_cnt, uint64_t request_id,
+ const char *original_xpath, void *private_ctx)
+{
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ sr_val_t *val = NULL;
+ int vc = 10;
+ int cnt = 0; //value counter
+ int rc = SR_ERR_OK;
+ sr_xpath_ctx_t state = {0};
+ char *tmp;
+ char interface_name[VPP_INTFC_NAME_LEN] = {0};
+ uint32_t itf_idx;
+ stat_segment_data_t *r;
+
+ SRP_LOG_INF("In %s", __FUNCTION__);
+
+ /* Retrieve the interface asked */
+ tmp = sr_xpath_key_value((char*) xpath, "interface", "name", &state);
+ if (!tmp) {
+ SRP_LOG_ERR_MSG("XPATH interface name not found");
+ return SR_ERR_INVAL_ARG;
+ }
+ strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN);
+ sr_xpath_recover(&state);
+
+ /* allocate array of values to be returned */
+ rc = sr_new_values(vc, &val);
+ if (0 != rc)
+ goto nothing_todo;
+
+ rc = get_interface_id(interface_name, &itf_idx);
+ if (rc != 0)
+ goto nothing_todo;
+
+ SRP_LOG_DBG("name:%s index:%d", interface_name, itf_idx);
+
+ r = fetch_stat_index("/if");
+ if (!r)
+ goto nothing_todo;
+
+ for (int i = 0; i < stat_segment_vec_len(r); i++) {
+ if (strcmp(r[i].name, "/if/rx") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/in-octets", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_bytes(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/rx-unicast") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/in-unicast-pkts", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_packets(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/rx-broadcast") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/in-broadcast-pkts", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_packets(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/rx-multicast") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/in-multicast-pkts", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_packets(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/rx-error") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/in-errors", xpath, 5);
+ val[cnt].type = SR_UINT32_T;
+ //Be carefeul cast uint64 to uint32
+ val[cnt].data.uint32_val = get_counter(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/tx") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/out-octets", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_bytes(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/tx-unicast") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/out-unicast-pkts", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_packets(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/tx-broadcast") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/out-broadcast-pkts", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_packets(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/tx-multicast") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/out-multicast-pkts", xpath, 5);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = get_packets(&r[i], itf_idx);
+ cnt++;
+ } else if (strcmp(r[i].name, "/if/tx-error") == 0) {
+ sr_val_build_xpath(&val[cnt], "%s/out-errors", xpath, 5);
+ val[cnt].type = SR_UINT32_T;
+ //Be carefeul cast uint64 to uint32
+ val[cnt].data.uint32_val = get_counter(&r[i], itf_idx);
+ cnt++;
+ }
+ }
+
+ *values = val;
+ *values_cnt = cnt;
+
+ return SR_ERR_OK;
+
+nothing_todo:
+ *values = NULL;
+ *values_cnt = 0;
+ return rc;
+}
+
int
ietf_interface_init(sc_plugin_main_t *pm)
@@ -375,6 +547,12 @@ ietf_interface_init(sc_plugin_main_t *pm)
goto error;
}
+ rc = sr_dp_get_items_subscribe(pm->session, "/ietf-interfaces:interfaces-state/interface/statistics",
+ interface_statistics_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription);
+ if (SR_ERR_OK != rc) {
+ goto error;
+ }
+
SRP_LOG_DBG_MSG("ietf-interface plugin initialized successfully.");
return SR_ERR_OK;
diff --git a/src/plugins/sc_plugins.c b/src/plugins/sc_plugins.c
index e0de0f6..7fc5975 100644
--- a/src/plugins/sc_plugins.c
+++ b/src/plugins/sc_plugins.c
@@ -17,6 +17,8 @@
#include <dirent.h>
+#include <vpp-api/client/stat_client.h>
+
sc_plugin_main_t sc_plugin_main;
static int vpp_pid_start;
@@ -73,9 +75,17 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx)
sc_plugin_main.session = session;
+ /* Connect to VAPI */
rc = sc_connect_vpp();
if (0 != rc) {
- SRP_LOG_ERR("vpp connect error , with return %d.", rc);
+ SRP_LOG_ERR("vpp vapi connect error , with return %d.", rc);
+ return SR_ERR_INTERNAL;
+ }
+
+ /* Connect to STAT API */
+ rc = stat_segment_connect(STAT_SEGMENT_SOCKET_FILE);
+ if (rc != 0) {
+ SRP_LOG_ERR("vpp stat connect error , with return %d.", rc);
return SR_ERR_INTERNAL;
}
@@ -94,13 +104,17 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx)
void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx)
{
- sc_call_all_exit_function(&sc_plugin_main);
+ sc_call_all_exit_function(&sc_plugin_main);
/* subscription was set as our private context */
if (private_ctx != NULL)
sr_unsubscribe(session, private_ctx);
SRP_LOG_DBG_MSG("unload plugin ok.");
+ /* Disconnect from STAT API */
+ stat_segment_disconnect();
+
+ /* Disconnect from VAPI */
sc_disconnect_vpp();
SRP_LOG_DBG_MSG("plugin disconnect vpp ok.");
}