From b3b1edefede6efcc1d5eff920fd9ea155cc5b977 Mon Sep 17 00:00:00 2001 From: Christian Giese Date: Wed, 20 Oct 2021 18:34:17 +0200 Subject: [PATCH] Traffic Streams and Fixes + count/report validated traffic streams + add sessions stats to JSON report + add stream stats to JSON report + add argument -T for traffic stream file + fix network interface ARP + ... --- docs/intro.md | 6 +- src/bbl.c | 71 +++-- src/bbl.h | 1 + src/bbl_a10nsp.c | 1 + src/bbl_config.c | 129 ++++++--- src/bbl_config.h | 3 + src/bbl_ctrl.c | 289 +------------------- src/bbl_ctx.h | 4 + src/bbl_interactive.c | 115 ++++---- src/bbl_l2tp.c | 1 + src/bbl_rx.c | 12 + src/bbl_session.c | 263 +++++++++++++++++++ src/bbl_session.h | 3 + src/bbl_session_traffic.c | 8 +- src/bbl_stats.c | 540 +++++++++++++++++++++----------------- src/bbl_stream.c | 53 +++- src/bbl_stream.h | 3 + src/bbl_tx.c | 2 +- 18 files changed, 872 insertions(+), 632 deletions(-) diff --git a/docs/intro.md b/docs/intro.md index 8bbaa9e4..40f0e6e1 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -22,6 +22,7 @@ IPTV, L2TPv2, QoS, forwarding verification and convergence testing capabilities. ``` $ bngblaster --help + ____ __ ____ _ __ ,/ / __ \ / /_ / __ ) _____ (_)_____ / /__ ,'/ / /_/ // __// __ |/ ___// // ___// //_/ ,' / @@ -38,12 +39,14 @@ Usage: bngblaster [OPTIONS] -v --version -h --help -C --config + -T --stream-config -l --logging debug|error|igmp|io|pppoe|info|pcap|timer|timer-detail|ip|loss|l2tp|dhcp -L --log-file -u --username -p --password -P --pcap-capture - -J --json-report + -j --json-report-content sessions|streams + -J --json-report-file -c --session-count -g --mc-group -s --mc-source @@ -53,6 +56,7 @@ Usage: bngblaster [OPTIONS] -I --interactive -b --hide-banner -f --force + ``` The BNG Blaster includes an optional interactive mode (`-I`) with realtime stats and diff --git a/src/bbl.c b/src/bbl.c index 7393c8ba..a740af12 100644 --- a/src/bbl.c +++ b/src/bbl.c @@ -22,6 +22,7 @@ /* Global Variables */ bool g_interactive = false; /* interactive mode using ncurses */ bool g_init_phase = true; +bool g_traffic = true; bool g_banner = true; char *g_log_file = NULL; @@ -132,17 +133,19 @@ bbl_add_multicast_packets(bbl_ctx_s *ctx) /* * Command line options. */ -const char *optstring = "vhC:l:L:u:p:P:J:c:g:s:r:z:S:Ibf"; +const char *optstring = "vhC:T:l:L:u:p:P:j:J:c:g:s:r:z:S:Ibf"; static struct option long_options[] = { { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { "config", required_argument, NULL, 'C' }, + { "stream-config", required_argument, NULL, 'T' }, { "logging", required_argument, NULL, 'l' }, { "log-file", required_argument, NULL, 'L' }, { "username", required_argument, NULL, 'u' }, { "password", required_argument, NULL, 'p' }, { "pcap-capture", required_argument, NULL, 'P' }, - { "json-report", required_argument, NULL, 'J' }, + { "json-report-content", required_argument, NULL, 'j' }, + { "json-report-file", required_argument, NULL, 'J' }, { "session-count", required_argument, NULL, 'c' }, { "mc-group", required_argument, NULL, 'g' }, { "mc-source", required_argument, NULL, 's' }, @@ -162,7 +165,9 @@ bbl_print_usage_arg (struct option *option) if (strcmp(option->name, "logging") == 0) { return log_usage(); } - + if (strcmp(option->name, "json-report-content") == 0) { + return " sessions|streams"; + } return " "; } return ""; @@ -226,6 +231,29 @@ bbl_ctrl_job (timer_s *timer) int rate = 0; uint32_t i; + /* Setup phase ... + * Wait for all network interfaces to be resolved. */ + if(g_init_phase && !g_teardown) { + LOG(INFO, "Resolve network interfaces\n"); + for(i = 0; i < ctx->interfaces.network_if_count; i++) { + interface = ctx->interfaces.network_if[i]; + if(interface->gateway_resolve_wait == false) { + continue; + } + if(interface->gateway6.len && !interface->icmpv6_nd_resolved) { + LOG(DEBUG, "Wait for %s IPv6 gateway %s to be resolved\n", + interface->name, format_ipv6_prefix(&interface->gateway6)); + return; + } + if(interface->gateway && !interface->arp_resolved) { + LOG(DEBUG, "Wait for %s IPv4 gateway %s to be resolved\n", + interface->name, format_ipv4_address(&interface->gateway)); + return; + } + } + g_init_phase = false; + LOG(INFO, "All network interfaces resolved\n"); + } if(ctx->sessions_outstanding) ctx->sessions_outstanding--; @@ -286,25 +314,6 @@ bbl_ctrl_job (timer_s *timer) } } } else { - /* Setup phase ... - * Wait for all network interfaces to be resolved. */ - if(g_init_phase) { - LOG(INFO, "Resolve network interfaces\n"); - for(i = 0; i < ctx->interfaces.network_if_count; i++) { - interface = ctx->interfaces.network_if[i]; - if(interface->gateway_resolve_wait == false) { - continue; - } - if(interface->gateway6.len && !interface->icmpv6_nd_resolved) { - return; - } - if(interface->gateway && !interface->arp_resolved) { - return; - } - } - g_init_phase = false; - LOG(INFO, "Start sessions\n"); - } /* Iterate over all idle session (list of pending sessions) * and start as much as permitted per interval based on max * outstanding and setup rate. Sessions started will be removed @@ -380,6 +389,7 @@ main (int argc, char *argv[]) bbl_stats_t stats = {0}; const char *config_file = NULL; + const char *config_streams_file = NULL; const char *username = NULL; const char *password = NULL; const char *sessions = NULL; @@ -418,12 +428,22 @@ main (int argc, char *argv[]) case 'P': ctx->pcap.filename = optarg; break; + case 'j': + if (strcmp("sessions", optarg) == 0) { + ctx->config.json_report_sessions = true; + } else if (strcmp("streams", optarg) == 0) { + ctx->config.json_report_streams = true; + } + break; case 'J': ctx->config.json_report_filename = optarg; break; case 'C': config_file = optarg; break; + case 'T': + config_streams_file = optarg; + break; case 'l': log_enable(optarg); break; @@ -485,6 +505,13 @@ main (int argc, char *argv[]) fprintf(stderr, "Error: Failed to load configuration file %s\n", config_file); exit(1); } + if(config_streams_file) { + if(!bbl_config_streams_load_json(config_streams_file, ctx)) { + fprintf(stderr, "Error: Failed to load stream configuration file %s\n", config_file); + exit(1); + } + } + if(username) ctx->config.username = username; if(password) ctx->config.password = password; if(sessions) ctx->config.sessions = atoi(sessions); diff --git a/src/bbl.h b/src/bbl.h index eb076d9a..3a7b7319 100644 --- a/src/bbl.h +++ b/src/bbl.h @@ -34,6 +34,7 @@ #include #include #include +#include #define NCURSES_NOMACROS 1 #include diff --git a/src/bbl_a10nsp.c b/src/bbl_a10nsp.c index c0bf6905..9aecb622 100644 --- a/src/bbl_a10nsp.c +++ b/src/bbl_a10nsp.c @@ -287,6 +287,7 @@ bbl_a10nsp_pppoes_handler(bbl_interface_s *interface, } if(!stream->rx_first_seq) { stream->rx_first_seq = bbl->flow_seq; + interface->ctx->stats.stream_traffic_flows_verified++; } else { if(stream->rx_last_seq +1 != bbl->flow_seq) { stream->loss++; diff --git a/src/bbl_config.c b/src/bbl_config.c index a0ae9e5a..824c7536 100644 --- a/src/bbl_config.c +++ b/src/bbl_config.c @@ -11,7 +11,6 @@ #include "bbl.h" #include "bbl_config.h" #include "bbl_stream.h" -#include #include const char g_default_user[] = "user{session-global}@rtbrick.com"; @@ -40,8 +39,7 @@ add_secondary_ipv4(bbl_ctx_s *ctx, uint32_t ipv4) { secondary_ip = secondary_ip->next; } else { /* Append secondary address ... */ - secondary_ip->next = malloc(sizeof(bbl_secondary_ip_s)); - memset(secondary_ip->next, 0x0, sizeof(bbl_secondary_ip_s)); + secondary_ip->next = calloc(1, sizeof(bbl_secondary_ip_s)); secondary_ip = secondary_ip->next; secondary_ip->ip = ipv4; break; @@ -49,8 +47,7 @@ add_secondary_ipv4(bbl_ctx_s *ctx, uint32_t ipv4) { } } else { /* Add first secondary address */ - ctx->config.secondary_ip_addresses = malloc(sizeof(bbl_secondary_ip_s)); - memset(ctx->config.secondary_ip_addresses, 0x0, sizeof(bbl_secondary_ip_s)); + ctx->config.secondary_ip_addresses = calloc(1, sizeof(bbl_secondary_ip_s)); ctx->config.secondary_ip_addresses->ip = ipv4; } } @@ -78,8 +75,7 @@ add_secondary_ipv6(bbl_ctx_s *ctx, ipv6addr_t ipv6) { secondary_ip6 = secondary_ip6->next; } else { /* Append secondary address ... */ - secondary_ip6->next = malloc(sizeof(bbl_secondary_ip6_s)); - memset(secondary_ip6->next, 0x0, sizeof(bbl_secondary_ip6_s)); + secondary_ip6->next = calloc(1, sizeof(bbl_secondary_ip6_s)); secondary_ip6 = secondary_ip6->next; memcpy(secondary_ip6->ip, ipv6, IPV6_ADDR_LEN); break; @@ -87,8 +83,7 @@ add_secondary_ipv6(bbl_ctx_s *ctx, ipv6addr_t ipv6) { } } else { /* Add first secondary address */ - ctx->config.secondary_ip6_addresses = malloc(sizeof(bbl_secondary_ip6_s)); - memset(ctx->config.secondary_ip6_addresses, 0x0, sizeof(bbl_secondary_ip6_s)); + ctx->config.secondary_ip6_addresses = calloc(1, sizeof(bbl_secondary_ip6_s)); memcpy(ctx->config.secondary_ip6_addresses->ip, ipv6, IPV6_ADDR_LEN); } } @@ -1294,21 +1289,19 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) { size = json_array_size(sub); for (i = 0; i < size; i++) { if (!network_config) { - ctx->config.network_config = malloc(sizeof(bbl_network_config_s)); + ctx->config.network_config = calloc(1, sizeof(bbl_network_config_s)); network_config = ctx->config.network_config; } else { - network_config->next = malloc(sizeof(bbl_network_config_s)); + network_config->next = calloc(1, sizeof(bbl_network_config_s)); network_config = network_config->next; } - memset(network_config, 0x0, sizeof(bbl_network_config_s)); if (!json_parse_network_interface(ctx, json_array_get(sub, i), network_config)) { return false; } } } else if (json_is_object(sub)) { /* Config is provided as object (single network interface) */ - network_config = malloc(sizeof(bbl_network_config_s)); - memset(network_config, 0x0, sizeof(bbl_network_config_s)); + network_config = calloc(1, sizeof(bbl_network_config_s)); if (!ctx->config.network_config) { ctx->config.network_config = network_config; } @@ -1324,21 +1317,19 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) { size = json_array_size(sub); for (i = 0; i < size; i++) { if (!access_config) { - ctx->config.access_config = malloc(sizeof(bbl_access_config_s)); + ctx->config.access_config = calloc(1, sizeof(bbl_access_config_s)); access_config = ctx->config.access_config; } else { - access_config->next = malloc(sizeof(bbl_access_config_s)); + access_config->next = calloc(1, sizeof(bbl_access_config_s)); access_config = access_config->next; } - memset(access_config, 0x0, sizeof(bbl_access_config_s)); if (!json_parse_access_interface(ctx, json_array_get(sub, i), access_config)) { return false; } } } else if (json_is_object(sub)) { /* Config is provided as object (single access range) */ - access_config = malloc(sizeof(bbl_access_config_s)); - memset(access_config, 0x0, sizeof(bbl_access_config_s)); + access_config = calloc(1, sizeof(bbl_access_config_s)); if (!ctx->config.access_config) { ctx->config.access_config = access_config; } @@ -1354,21 +1345,19 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) { size = json_array_size(sub); for (i = 0; i < size; i++) { if (!a10nsp_config) { - ctx->config.a10nsp_config = malloc(sizeof(bbl_a10nsp_config_s)); + ctx->config.a10nsp_config = calloc(1, sizeof(bbl_a10nsp_config_s)); a10nsp_config = ctx->config.a10nsp_config; } else { - a10nsp_config->next = malloc(sizeof(bbl_a10nsp_config_s)); + a10nsp_config->next = calloc(1, sizeof(bbl_a10nsp_config_s)); a10nsp_config = a10nsp_config->next; } - memset(a10nsp_config, 0x0, sizeof(bbl_a10nsp_config_s)); if (!json_parse_a10nsp_interface(ctx, json_array_get(sub, i), a10nsp_config)) { return false; } } } else if (json_is_object(sub)) { /* Config is provided as object (single a10nsp interface) */ - a10nsp_config = malloc(sizeof(bbl_a10nsp_config_s)); - memset(a10nsp_config, 0x0, sizeof(bbl_a10nsp_config_s)); + a10nsp_config = calloc(1, sizeof(bbl_a10nsp_config_s)); if (!ctx->config.a10nsp_config) { ctx->config.a10nsp_config = a10nsp_config; } @@ -1392,13 +1381,12 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) { for (i = 0; i < size; i++) { sub = json_array_get(section, i); if (!l2tp_server) { - ctx->config.l2tp_server = malloc(sizeof(bbl_l2tp_server_t)); + ctx->config.l2tp_server = calloc(1, sizeof(bbl_l2tp_server_t)); l2tp_server = ctx->config.l2tp_server; } else { - l2tp_server->next = malloc(sizeof(bbl_l2tp_server_t)); + l2tp_server->next = calloc(1, sizeof(bbl_l2tp_server_t)); l2tp_server = l2tp_server->next; } - memset(l2tp_server, 0x0, sizeof(bbl_l2tp_server_t)); if (json_unpack(sub, "{s:s}", "name", &s) == 0) { l2tp_server->host_name = strdup(s); } else { @@ -1477,13 +1465,12 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) { size = json_array_size(section); for (i = 0; i < size; i++) { if (!stream_config) { - ctx->config.stream_config = malloc(sizeof(bbl_stream_config)); + ctx->config.stream_config = calloc(1, sizeof(bbl_stream_config)); stream_config = ctx->config.stream_config; } else { - stream_config->next = malloc(sizeof(bbl_stream_config)); + stream_config->next = calloc(1, sizeof(bbl_stream_config)); stream_config = stream_config->next; } - memset(stream_config, 0x0, sizeof(bbl_stream_config)); if (!json_parse_stream(ctx, json_array_get(section, i), stream_config)) { return false; } @@ -1497,13 +1484,12 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) { size = json_array_size(section); for (i = 0; i < size; i++) { if (!access_line_profile) { - ctx->config.access_line_profile = malloc(sizeof(bbl_access_line_profile_s)); + ctx->config.access_line_profile = calloc(1, sizeof(bbl_access_line_profile_s)); access_line_profile = ctx->config.access_line_profile; } else { - access_line_profile->next = malloc(sizeof(bbl_access_line_profile_s)); + access_line_profile->next = calloc(1, sizeof(bbl_access_line_profile_s)); access_line_profile = access_line_profile->next; } - memset(access_line_profile, 0x0, sizeof(bbl_access_line_profile_s)); if (!json_parse_access_line_profile(json_array_get(section, i), access_line_profile)) { return false; } @@ -1513,12 +1499,16 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) { return true; } -/* bbl_config_load_json +/** + * bbl_config_load_json * - * This functions is population the BBL context + * This function populates the BBL context * from given JSON configuration file returning - * true is successfull or false if failed with - * error message printed to stderr. + * true if successfull or false if failed with + * error message printed to stderr. + * + * @param ctx JSON filename + * @param ctx global context */ bool bbl_config_load_json (const char *filename, bbl_ctx_s *ctx) { @@ -1536,10 +1526,73 @@ bbl_config_load_json (const char *filename, bbl_ctx_s *ctx) { return result; } -/* bbl_config_load_json +static bool +json_parse_config_streams (json_t *root, bbl_ctx_s *ctx) { + + json_t *section = NULL; + int i, size; + + bbl_stream_config *stream_config = ctx->config.stream_config; + + if (json_typeof(root) != JSON_OBJECT) { + fprintf(stderr, "JSON config error: Configuration root element must object\n"); + return false; + } + + section = json_object_get(root, "streams"); + if (json_is_array(section)) { + /* Config is provided as array (multiple streams) */ + size = json_array_size(section); + for (i = 0; i < size; i++) { + if (!stream_config) { + ctx->config.stream_config = calloc(1, sizeof(bbl_stream_config)); + stream_config = ctx->config.stream_config; + } else { + stream_config->next = calloc(1, sizeof(bbl_stream_config)); + stream_config = stream_config->next; + } + if (!json_parse_stream(ctx, json_array_get(section, i), stream_config)) { + return false; + } + } + } + return true; +} + +/** + * bbl_config_streams_load_json + * + * This function populates traffic streams + * from given JSON stream configuration file returning + * true if successfull or false if failed with + * error message printed to stderr. + * + * @param ctx JSON filename + * @param ctx global context + */ +bool +bbl_config_streams_load_json (const char *filename, bbl_ctx_s *ctx) { + json_t *root = NULL; + json_error_t error; + bool result = false; + + root = json_load_file(filename, 0, &error); + if (root) { + result = json_parse_config_streams(root, ctx); + json_decref(root); + } else { + fprintf(stderr, "JSON stream config error: File %s Line %d: %s\n", filename, error.line, error.text); + } + return result; +} + +/** + * bbl_config_init_defaults * * This functions is population the BBL context * with default configuration values. + * + * @param ctx global context */ void bbl_config_init_defaults (bbl_ctx_s *ctx) { diff --git a/src/bbl_config.h b/src/bbl_config.h index bd65ad0a..d0fd023b 100644 --- a/src/bbl_config.h +++ b/src/bbl_config.h @@ -154,6 +154,9 @@ typedef struct bbl_a10nsp_config_ bool bbl_config_load_json(const char *filename, bbl_ctx_s *ctx); +bool +bbl_config_streams_load_json(const char *filename, bbl_ctx_s *ctx); + void bbl_config_init_defaults(bbl_ctx_s *ctx); diff --git a/src/bbl_ctrl.c b/src/bbl_ctrl.c index d533fc1f..99959b45 100644 --- a/src/bbl_ctrl.c +++ b/src/bbl_ctrl.c @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include "bbl.h" #include "bbl_ctrl.h" @@ -35,34 +33,10 @@ extern volatile bool g_teardown; extern volatile bool g_teardown_request; +extern bool g_traffic; + typedef ssize_t callback_function(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* arguments); -const char * -ppp_state_string(uint32_t state) { - switch(state) { - case BBL_PPP_CLOSED: return "Closed"; - case BBL_PPP_INIT: return "Init"; - case BBL_PPP_LOCAL_ACK: return "Local-Ack"; - case BBL_PPP_PEER_ACK: return "Peer-Ack"; - case BBL_PPP_OPENED: return "Opened"; - case BBL_PPP_TERMINATE: return "Terminate"; - default: return "N/A"; - } -} - -const char * -dhcp_state_string(uint32_t state) { - switch(state) { - case BBL_DHCP_INIT: return "Init"; - case BBL_DHCP_SELECTING: return "Selecting"; - case BBL_DHCP_REQUESTING: return "Requesting"; - case BBL_DHCP_BOUND: return "Bound"; - case BBL_DHCP_RENEWING: return "Renewing"; - case BBL_DHCP_RELEASE: return "Releasing"; - default: return "N/A"; - } -} - static char * string_or_na(char *string) { if(string) { @@ -392,245 +366,32 @@ ssize_t bbl_ctrl_session_info(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* arguments __attribute__((unused))) { ssize_t result = 0; json_t *root; - json_t *session_traffic = NULL; - json_t *a10nsp_session = NULL; + json_t *session_json; bbl_session_s *session; - struct timespec now; - - const char *ipv4 = NULL; - const char *ipv4_netmask = NULL; - const char *ipv4_gw = NULL; - const char *dns1 = NULL; - const char *dns2 = NULL; - const char *ipv6 = NULL; - const char *ipv6pd = NULL; - const char *ipv6_dns1 = NULL; - const char *ipv6_dns2 = NULL; - const char *dhcpv6_dns1 = NULL; - const char *dhcpv6_dns2 = NULL; - - int flows = 0; - int flows_verified = 0; - uint32_t seconds = 0; - uint32_t dhcp_lease_expire = 0; - uint32_t dhcp_lease_expire_t1 = 0; - uint32_t dhcp_lease_expire_t2 = 0; - uint32_t dhcpv6_lease_expire = 0; - uint32_t dhcpv6_lease_expire_t1 = 0; - uint32_t dhcpv6_lease_expire_t2 = 0; - if(session_id == 0) { /* session-id is mandatory */ return bbl_ctrl_status(fd, "error", 400, "missing session-id"); } session = bbl_session_get(ctx, session_id); - if(session) { - if(session->ip_address) { - ipv4 = format_ipv4_address(&session->ip_address); - } - if(session->ip_netmask) { - ipv4_netmask = format_ipv4_address(&session->ip_netmask); - } - if(session->peer_ip_address) { - ipv4_gw = format_ipv4_address(&session->peer_ip_address); - } - if(session->dns1) { - dns1 = format_ipv4_address(&session->dns1); - } - if(session->dns2) { - dns2 = format_ipv4_address(&session->dns2); - } - if(session->ipv6_prefix.len) { - ipv6 = format_ipv6_prefix(&session->ipv6_prefix); - } - if(session->delegated_ipv6_prefix.len) { - ipv6pd = format_ipv6_prefix(&session->delegated_ipv6_prefix); - } - if(*(uint64_t*)session->ipv6_dns1) { - ipv6_dns1 = format_ipv6_address(&session->ipv6_dns1); - } - if(*(uint64_t*)session->ipv6_dns2) { - ipv6_dns2 = format_ipv6_address(&session->ipv6_dns2); - } - if(*(uint64_t*)session->dhcpv6_dns1) { - dhcpv6_dns1 = format_ipv6_address(&session->dhcpv6_dns1); - } - if(*(uint64_t*)session->dhcpv6_dns2) { - dhcpv6_dns2 = format_ipv6_address(&session->dhcpv6_dns2); + if(session) { + session_json = bbl_session_json(session); + if(!session_json) { + bbl_ctrl_status(fd, "error", 500, "internal error"); } - if(ctx->config.session_traffic_ipv4_pps || ctx->config.session_traffic_ipv6_pps || ctx->config.session_traffic_ipv6pd_pps) { - if(session->access_ipv4_tx_flow_id) flows++; - if(session->access_ipv6_tx_flow_id) flows++; - if(session->access_ipv6pd_tx_flow_id) flows++; - if(session->network_ipv4_tx_flow_id) flows++; - if(session->network_ipv6_tx_flow_id) flows++; - if(session->network_ipv6pd_tx_flow_id) flows++; - if(session->access_ipv4_rx_first_seq) flows_verified++; - if(session->access_ipv6_rx_first_seq) flows_verified++; - if(session->access_ipv6pd_rx_first_seq) flows_verified++; - if(session->network_ipv4_rx_first_seq) flows_verified++; - if(session->network_ipv6_rx_first_seq) flows_verified++; - if(session->network_ipv6pd_rx_first_seq) flows_verified++; + root = json_pack("{ss si so*}", + "status", "ok", + "code", 200, + "session-info", session_json); - session_traffic = json_pack("{si si si si si si si si si si si si si si si si si si si si si si si si si si}", - "total-flows", flows, - "verified-flows", flows_verified, - "first-seq-rx-access-ipv4", session->access_ipv4_rx_first_seq, - "first-seq-rx-access-ipv6", session->access_ipv6_rx_first_seq, - "first-seq-rx-access-ipv6pd", session->access_ipv6pd_rx_first_seq, - "first-seq-rx-network-ipv4", session->network_ipv4_rx_first_seq, - "first-seq-rx-network-ipv6", session->network_ipv6_rx_first_seq, - "first-seq-rx-network-ipv6pd", session->network_ipv6pd_rx_first_seq, - "access-tx-session-packets", session->stats.access_ipv4_tx, - "access-rx-session-packets", session->stats.access_ipv4_rx, - "access-rx-session-packets-loss", session->stats.access_ipv4_loss, - "network-tx-session-packets", session->stats.network_ipv4_tx, - "network-rx-session-packets", session->stats.network_ipv4_rx, - "network-rx-session-packets-loss", session->stats.network_ipv4_loss, - "access-tx-session-packets-ipv6", session->stats.access_ipv6_tx, - "access-rx-session-packets-ipv6", session->stats.access_ipv6_rx, - "access-rx-session-packets-ipv6-loss", session->stats.access_ipv6_loss, - "network-tx-session-packets-ipv6", session->stats.network_ipv6_tx, - "network-rx-session-packets-ipv6", session->stats.network_ipv6_rx, - "network-rx-session-packets-ipv6-loss", session->stats.network_ipv6_loss, - "access-tx-session-packets-ipv6pd", session->stats.access_ipv6pd_tx, - "access-rx-session-packets-ipv6pd", session->stats.access_ipv6pd_rx, - "access-rx-session-packets-ipv6pd-loss", session->stats.access_ipv6pd_loss, - "network-tx-session-packets-ipv6pd", session->stats.network_ipv6pd_tx, - "network-rx-session-packets-ipv6pd", session->stats.network_ipv6pd_rx, - "network-rx-session-packets-ipv6pd-loss", session->stats.network_ipv6pd_loss); - } - - if(session->a10nsp_session) { - a10nsp_session = json_pack("{ss si sb sb ss* ss* si si}", - "interface", session->a10nsp_session->a10nsp_if->name, - "s-vlan", session->a10nsp_session->s_vlan, - "qinq-send", session->a10nsp_session->a10nsp_if->qinq, - "qinq-received", session->a10nsp_session->qinq_received, - "pppoe-aci", session->a10nsp_session->pppoe_aci, - "pppoe-ari", session->a10nsp_session->pppoe_ari, - "tx-packets", session->a10nsp_session->stats.packets_tx, - "rx-packets", session->a10nsp_session->stats.packets_rx); - } - - if(session->access_type == ACCESS_TYPE_PPPOE) { - root = json_pack("{ss si s{ss si ss ss si si ss ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si so* so*}}", - "status", "ok", - "code", 200, - "session-info", - "type", "pppoe", - "session-id", session->session_id, - "session-state", session_state_string(session->session_state), - "interface", session->interface->name, - "outer-vlan", session->vlan_key.outer_vlan_id, - "inner-vlan", session->vlan_key.inner_vlan_id, - "mac", format_mac_address(session->client_mac), - "username", session->username, - "agent-circuit-id", session->agent_circuit_id, - "agent-remote-id", session->agent_remote_id, - "reply-message", session->reply_message, - "connection-status-message", session->connections_status_message, - "lcp-state", ppp_state_string(session->lcp_state), - "ipcp-state", ppp_state_string(session->ipcp_state), - "ip6cp-state", ppp_state_string(session->ip6cp_state), - "ipv4-address", ipv4, - "ipv4-dns1", dns1, - "ipv4-dns2", dns2, - "ipv6-prefix", ipv6, - "ipv6-delegated-prefix", ipv6pd, - "ipv6-dns1", ipv6_dns1, - "ipv6-dns2", ipv6_dns2, - "dhcpv6-state", dhcp_state_string(session->dhcpv6_state), - "dhcpv6-dns1", dhcpv6_dns1, - "dhcpv6-dns2", dhcpv6_dns2, - "tx-packets", session->stats.packets_tx, - "rx-packets", session->stats.packets_rx, - "rx-fragmented-packets", session->stats.ipv4_fragmented_rx, - "session-traffic", session_traffic, - "a10nsp", a10nsp_session); - - } else { - clock_gettime(CLOCK_MONOTONIC, &now); - if(session->dhcp_lease_timestamp.tv_sec && now.tv_sec > session->dhcp_lease_timestamp.tv_sec) { - seconds = now.tv_sec - session->dhcp_lease_timestamp.tv_sec; - } - if(seconds <= session->dhcp_lease_time) dhcp_lease_expire = session->dhcp_lease_time - seconds; - if(seconds <= session->dhcp_t1) dhcp_lease_expire_t1 = session->dhcp_t1 - seconds; - if(seconds <= session->dhcp_t2) dhcp_lease_expire_t2 = session->dhcp_t2 - seconds; - - if(session->dhcpv6_lease_timestamp.tv_sec && now.tv_sec > session->dhcpv6_lease_timestamp.tv_sec) { - seconds = now.tv_sec - session->dhcpv6_lease_timestamp.tv_sec; - } - if(seconds <= session->dhcpv6_lease_time) dhcpv6_lease_expire = session->dhcpv6_lease_time - seconds; - if(seconds <= session->dhcpv6_t1) dhcpv6_lease_expire_t1 = session->dhcpv6_t1 - seconds; - if(seconds <= session->dhcpv6_t2) dhcpv6_lease_expire_t2 = session->dhcpv6_t2 - seconds; - - root = json_pack("{ss si s{ss si ss ss si si ss ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si si si si si si si si si si ss* si si si si si si si si si si si si ss* ss* si si si so* so*}}", - "status", "ok", - "code", 200, - "session-info", - "type", "ipoe", - "session-id", session->session_id, - "session-state", session_state_string(session->session_state), - "interface", session->interface->name, - "outer-vlan", session->vlan_key.outer_vlan_id, - "inner-vlan", session->vlan_key.inner_vlan_id, - "mac", format_mac_address(session->client_mac), - "agent-circuit-id", session->agent_circuit_id, - "agent-remote-id", session->agent_remote_id, - "ipv4-address", ipv4, - "ipv4-netmask", ipv4_netmask, - "ipv4-gateway", ipv4_gw, - "ipv4-dns1", dns1, - "ipv4-dns2", dns2, - "ipv6-prefix", ipv6, - "ipv6-delegated-prefix", ipv6pd, - "ipv6-dns1", ipv6_dns1, - "ipv6-dns2", ipv6_dns2, - "dhcp-state", dhcp_state_string(session->dhcp_state), - "dhcp-server", format_ipv4_address(&session->dhcp_server_identifier), - "dhcp-lease-time", session->dhcp_lease_time, - "dhcp-lease-expire", dhcp_lease_expire, - "dhcp-lease-expire-t1", dhcp_lease_expire_t1, - "dhcp-lease-expire-t2", dhcp_lease_expire_t2, - "dhcp-tx", session->stats.dhcp_tx, - "dhcp-rx", session->stats.dhcp_rx, - "dhcp-tx-discover", session->stats.dhcp_tx_discover, - "dhcp-rx-offer", session->stats.dhcp_rx_offer, - "dhcp-tx-request", session->stats.dhcp_tx_request, - "dhcp-rx-ack", session->stats.dhcp_rx_ack, - "dhcp-rx-nak", session->stats.dhcp_rx_nak, - "dhcp-tx-release", session->stats.dhcp_tx_release, - "dhcpv6-state", dhcp_state_string(session->dhcpv6_state), - "dhcpv6-lease-time", session->dhcpv6_lease_time, - "dhcpv6-lease-expire", dhcpv6_lease_expire, - "dhcpv6-lease-expire-t1", dhcpv6_lease_expire_t1, - "dhcpv6-lease-expire-t2", dhcpv6_lease_expire_t2, - "dhcpv6-tx", session->stats.dhcpv6_tx, - "dhcpv6-rx", session->stats.dhcpv6_rx, - "dhcpv6-tx-solicit", session->stats.dhcpv6_tx_solicit, - "dhcpv6-rx-advertise", session->stats.dhcpv6_rx_advertise, - "dhcpv6-tx-request", session->stats.dhcpv6_tx_request, - "dhcpv6-rx-reply", session->stats.dhcpv6_rx_reply, - "dhcpv6-tx-renew", session->stats.dhcpv6_tx_renew, - "dhcpv6-tx-release", session->stats.dhcpv6_tx_release, - "dhcpv6-dns1", dhcpv6_dns1, - "dhcpv6-dns2", dhcpv6_dns2, - "tx-packets", session->stats.packets_tx, - "rx-packets", session->stats.packets_rx, - "rx-fragmented-packets", session->stats.ipv4_fragmented_rx, - "session-traffic", session_traffic, - "a10nsp", a10nsp_session); - } if(root) { result = json_dumpfd(root, fd, 0); json_decref(root); } else { result = bbl_ctrl_status(fd, "error", 500, "internal error"); - json_decref(session_traffic); + json_decref(session_json); } return result; } else { @@ -1201,31 +962,7 @@ bbl_ctrl_session_streams(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* ar json_streams = json_array(); while(stream) { - json_stream = json_pack("{ss ss si si si si si si si si si si si si si si si si si si sf sf sf}", - "name", stream->config->name, - "direction", stream->direction == STREAM_DIRECTION_UP ? "upstream" : "downstream", - "flow-id", stream->flow_id, - "rx-first-seq", stream->rx_first_seq, - "rx-last-seq", stream->rx_last_seq, - "rx-tos-tc", stream->rx_priority, - "rx-outer-vlan-pbit", stream->rx_outer_vlan_pbit, - "rx-inner-vlan-pbit", stream->rx_inner_vlan_pbit, - "rx-len", stream->rx_len, - "tx-len", stream->tx_len, - "rx-packets", stream->packets_rx, - "tx-packets", stream->packets_tx, - "rx-loss", stream->loss, - "rx-delay-nsec-min", stream->min_delay_ns, - "rx-delay-nsec-max", stream->max_delay_ns, - "rx-pps", stream->rate_packets_rx.avg, - "tx-pps", stream->rate_packets_tx.avg, - "tx-bps-l2", stream->rate_packets_tx.avg * stream->tx_len * 8, - "rx-bps-l2", stream->rate_packets_rx.avg * stream->rx_len * 8, - "rx-bps-l3", stream->rate_packets_rx.avg * stream->config->length * 8, - "tx-mbps-l2", (double)(stream->rate_packets_tx.avg * stream->tx_len * 8) / 1000000.0, - "rx-mbps-l2", (double)(stream->rate_packets_rx.avg * stream->rx_len * 8) / 1000000.0, - "rx-mbps-l3", (double)(stream->rate_packets_rx.avg * stream->config->length * 8) / 1000000.0); - + json_stream = bbl_stream_json(stream); json_array_append(json_streams, json_stream); stream = stream->next; } diff --git a/src/bbl_ctx.h b/src/bbl_ctx.h index b7e6c2ea..4a264649 100644 --- a/src/bbl_ctx.h +++ b/src/bbl_ctx.h @@ -121,6 +121,8 @@ typedef struct bbl_ctx_ uint32_t sessions_established_max; uint32_t session_traffic_flows; uint32_t session_traffic_flows_verified; + uint32_t stream_traffic_flows; + uint32_t stream_traffic_flows_verified; } stats; bool multicast_traffic; @@ -139,6 +141,8 @@ typedef struct bbl_ctx_ bbl_io_mode_t io_mode; char *json_report_filename; + bool json_report_sessions; /* Include sessions */ + bool json_report_streams; /* Include streams */ bbl_secondary_ip_s *secondary_ip_addresses; bbl_secondary_ip6_s *secondary_ip6_addresses; diff --git a/src/bbl_interactive.c b/src/bbl_interactive.c index 1adf756b..cac88fce 100644 --- a/src/bbl_interactive.c +++ b/src/bbl_interactive.c @@ -34,6 +34,8 @@ extern volatile bool g_teardown; extern volatile bool g_teardown_request; extern volatile bool g_banner; +extern bool g_traffic; + /* This global variable is used to switch between access interfaces. */ uint8_t g_access_if_selected = 0; uint8_t g_network_if_selected = 0; @@ -71,22 +73,6 @@ bbl_init_stats_win(bbl_ctx_s *ctx) } } -static void -enable_disable_traffic(bbl_ctx_s *ctx, bool status) -{ - bbl_session_s *session; - uint32_t i; - - /* Iterate over all sessions */ - for(i = 0; i < ctx->sessions; i++) { - session = ctx->session_list[i]; - if(session) { - session->session_traffic = status; - session->stream_traffic = status; - } - } -} - /* * Interactive keyboard reader */ @@ -165,11 +151,11 @@ bbl_read_key_job (timer_s *timer) bbl_init_stats_win(ctx); break; case KEY_F(7): - enable_disable_traffic(ctx, true); + g_traffic = true; LOG(INFO, "Start traffic\n"); break; case KEY_F(8): - enable_disable_traffic(ctx, false); + g_traffic = false; LOG(INFO, "Stop traffic\n"); break; case KEY_F(9): @@ -350,6 +336,23 @@ bbl_stats_job (timer_s *timer) wprintw(stats_win, "]\n"); } + if(ctx->stats.stream_traffic_flows) { + wprintw(stats_win, "\nTraffic Streams\n"); + wprintw(stats_win, " Flows %10lu\n", ctx->stats.stream_traffic_flows); + /* Progress bar traffic stream flows */ + wprintw(stats_win, " Verified %10lu [", ctx->stats.stream_traffic_flows_verified); + if(ctx->stats.stream_traffic_flows == ctx->stats.stream_traffic_flows_verified) { + wattron(stats_win, COLOR_PAIR(COLOR_GREEN)); + wprintw(stats_win, "%s", bbl_format_progress(ctx->stats.stream_traffic_flows, ctx->stats.stream_traffic_flows_verified)); + wattroff(stats_win, COLOR_PAIR(COLOR_GREEN)); + } else { + wattron(stats_win, COLOR_PAIR(COLOR_BLACK)); + wprintw(stats_win, "%s", bbl_format_progress(ctx->stats.stream_traffic_flows, ctx->stats.stream_traffic_flows_verified)); + wattroff(stats_win, COLOR_PAIR(COLOR_BLACK)); + } + wprintw(stats_win, "]\n"); + } + if(network_if) { wprintw(stats_win, "\nNetwork Interface ("); for(i = 0; i < ctx->interfaces.network_if_count; i++) { @@ -367,21 +370,23 @@ bbl_stats_job (timer_s *timer) wprintw(stats_win, " Rx Packets %10lu |%7lu PPS %10lu Kbps\n", network_if->stats.packets_rx, network_if->stats.rate_packets_rx.avg, network_if->stats.rate_bytes_rx.avg * 8 / 1000); - wprintw(stats_win, " Tx Session Packets %10lu |%7lu PPS\n", - network_if->stats.session_ipv4_tx, network_if->stats.rate_session_ipv4_tx.avg); - wprintw(stats_win, " Rx Session Packets %10lu |%7lu PPS %10lu Loss\n", - network_if->stats.session_ipv4_rx, network_if->stats.rate_session_ipv4_rx.avg, - network_if->stats.session_ipv4_loss); - wprintw(stats_win, " Tx Session Packets IPv6 %10lu |%7lu PPS\n", - network_if->stats.session_ipv6_tx, network_if->stats.rate_session_ipv6_tx.avg); - wprintw(stats_win, " Rx Session Packets IPv6 %10lu |%7lu PPS %10lu Loss\n", - network_if->stats.session_ipv6_rx, network_if->stats.rate_session_ipv6_rx.avg, - network_if->stats.session_ipv6_loss); - wprintw(stats_win, " Tx Session Packets IPv6PD %10lu |%7lu PPS\n", - network_if->stats.session_ipv6pd_tx, network_if->stats.rate_session_ipv6pd_tx.avg); - wprintw(stats_win, " Rx Session Packets IPv6PD %10lu |%7lu PPS %10lu Loss\n", - network_if->stats.session_ipv6pd_rx, network_if->stats.rate_session_ipv6pd_rx.avg, - network_if->stats.session_ipv6pd_loss); + if(ctx->stats.session_traffic_flows) { + wprintw(stats_win, " Tx Session Packets %10lu |%7lu PPS\n", + network_if->stats.session_ipv4_tx, network_if->stats.rate_session_ipv4_tx.avg); + wprintw(stats_win, " Rx Session Packets %10lu |%7lu PPS %10lu Loss\n", + network_if->stats.session_ipv4_rx, network_if->stats.rate_session_ipv4_rx.avg, + network_if->stats.session_ipv4_loss); + wprintw(stats_win, " Tx Session Packets IPv6 %10lu |%7lu PPS\n", + network_if->stats.session_ipv6_tx, network_if->stats.rate_session_ipv6_tx.avg); + wprintw(stats_win, " Rx Session Packets IPv6 %10lu |%7lu PPS %10lu Loss\n", + network_if->stats.session_ipv6_rx, network_if->stats.rate_session_ipv6_rx.avg, + network_if->stats.session_ipv6_loss); + wprintw(stats_win, " Tx Session Packets IPv6PD %10lu |%7lu PPS\n", + network_if->stats.session_ipv6pd_tx, network_if->stats.rate_session_ipv6pd_tx.avg); + wprintw(stats_win, " Rx Session Packets IPv6PD %10lu |%7lu PPS %10lu Loss\n", + network_if->stats.session_ipv6pd_rx, network_if->stats.rate_session_ipv6pd_rx.avg, + network_if->stats.session_ipv6pd_loss); + } wprintw(stats_win, " Tx Multicast Packets %10lu |%7lu PPS\n", network_if->stats.mc_tx, network_if->stats.rate_mc_tx.avg); } @@ -403,11 +408,13 @@ bbl_stats_job (timer_s *timer) wprintw(stats_win, " Rx Packets %10lu |%7lu PPS %10lu Kbps\n", a10nsp_if->stats.packets_rx, a10nsp_if->stats.rate_packets_rx.avg, a10nsp_if->stats.rate_bytes_rx.avg * 8 / 1000); - wprintw(stats_win, " Tx Session Packets %10lu |%7lu PPS\n", - a10nsp_if->stats.session_ipv4_tx, a10nsp_if->stats.rate_session_ipv4_tx.avg); - wprintw(stats_win, " Rx Session Packets %10lu |%7lu PPS %10lu Loss\n", - a10nsp_if->stats.session_ipv4_rx, a10nsp_if->stats.rate_session_ipv4_rx.avg, - a10nsp_if->stats.session_ipv4_loss); + if(ctx->stats.session_traffic_flows) { + wprintw(stats_win, " Tx Session Packets %10lu |%7lu PPS\n", + a10nsp_if->stats.session_ipv4_tx, a10nsp_if->stats.rate_session_ipv4_tx.avg); + wprintw(stats_win, " Rx Session Packets %10lu |%7lu PPS %10lu Loss\n", + a10nsp_if->stats.session_ipv4_rx, a10nsp_if->stats.rate_session_ipv4_rx.avg, + a10nsp_if->stats.session_ipv4_loss); + } } if(access_if) { @@ -427,21 +434,23 @@ bbl_stats_job (timer_s *timer) wprintw(stats_win, " Rx Packets %10lu |%7lu PPS %10lu Kbps\n", access_if->stats.packets_rx, access_if->stats.rate_packets_rx.avg, access_if->stats.rate_bytes_rx.avg * 8 / 1000); - wprintw(stats_win, " Tx Session Packets %10lu |%7lu PPS\n", - access_if->stats.session_ipv4_tx, access_if->stats.rate_session_ipv4_tx.avg); - wprintw(stats_win, " Rx Session Packets %10lu |%7lu PPS %10lu Loss %lu Wrong Session\n", - access_if->stats.session_ipv4_rx, access_if->stats.rate_session_ipv4_rx.avg, - access_if->stats.session_ipv4_loss, access_if->stats.session_ipv4_wrong_session); - wprintw(stats_win, " Tx Session Packets IPv6 %10lu |%7lu PPS\n", - access_if->stats.session_ipv6_tx, access_if->stats.rate_session_ipv6_tx.avg); - wprintw(stats_win, " Rx Session Packets IPv6 %10lu |%7lu PPS %10lu Loss %lu Wrong Session\n", - access_if->stats.session_ipv6_rx, access_if->stats.rate_session_ipv6_rx.avg, - access_if->stats.session_ipv6_loss, access_if->stats.session_ipv6_wrong_session); - wprintw(stats_win, " Tx Session Packets IPv6PD %10lu |%7lu PPS\n", - access_if->stats.session_ipv6pd_tx, access_if->stats.rate_session_ipv6pd_tx.avg); - wprintw(stats_win, " Rx Session Packets IPv6PD %10lu |%7lu PPS %10lu Loss %lu Wrong Session\n", - access_if->stats.session_ipv6pd_rx, access_if->stats.rate_session_ipv6pd_rx.avg, - access_if->stats.session_ipv6pd_loss, access_if->stats.session_ipv6pd_wrong_session); + if(ctx->stats.session_traffic_flows) { + wprintw(stats_win, " Tx Session Packets %10lu |%7lu PPS\n", + access_if->stats.session_ipv4_tx, access_if->stats.rate_session_ipv4_tx.avg); + wprintw(stats_win, " Rx Session Packets %10lu |%7lu PPS %10lu Loss %lu Wrong Session\n", + access_if->stats.session_ipv4_rx, access_if->stats.rate_session_ipv4_rx.avg, + access_if->stats.session_ipv4_loss, access_if->stats.session_ipv4_wrong_session); + wprintw(stats_win, " Tx Session Packets IPv6 %10lu |%7lu PPS\n", + access_if->stats.session_ipv6_tx, access_if->stats.rate_session_ipv6_tx.avg); + wprintw(stats_win, " Rx Session Packets IPv6 %10lu |%7lu PPS %10lu Loss %lu Wrong Session\n", + access_if->stats.session_ipv6_rx, access_if->stats.rate_session_ipv6_rx.avg, + access_if->stats.session_ipv6_loss, access_if->stats.session_ipv6_wrong_session); + wprintw(stats_win, " Tx Session Packets IPv6PD %10lu |%7lu PPS\n", + access_if->stats.session_ipv6pd_tx, access_if->stats.rate_session_ipv6pd_tx.avg); + wprintw(stats_win, " Rx Session Packets IPv6PD %10lu |%7lu PPS %10lu Loss %lu Wrong Session\n", + access_if->stats.session_ipv6pd_rx, access_if->stats.rate_session_ipv6pd_rx.avg, + access_if->stats.session_ipv6pd_loss, access_if->stats.session_ipv6pd_wrong_session); + } wprintw(stats_win, " Rx Multicast Packets %10lu |%7lu PPS %10lu Loss\n", access_if->stats.mc_rx, access_if->stats.rate_mc_rx.avg, access_if->stats.mc_loss); diff --git a/src/bbl_l2tp.c b/src/bbl_l2tp.c index f05638e6..383711b1 100644 --- a/src/bbl_l2tp.c +++ b/src/bbl_l2tp.c @@ -1002,6 +1002,7 @@ bbl_l2tp_data_rx(bbl_ethernet_header_t *eth, bbl_l2tp_t *l2tp, bbl_interface_s * } if(!stream->rx_first_seq) { stream->rx_first_seq = bbl->flow_seq; + interface->ctx->stats.stream_traffic_flows_verified++; } else { if(stream->rx_last_seq +1 != bbl->flow_seq) { stream->loss++; diff --git a/src/bbl_rx.c b/src/bbl_rx.c index 7c528327..293bfc47 100644 --- a/src/bbl_rx.c +++ b/src/bbl_rx.c @@ -304,6 +304,7 @@ bbl_rx_stream(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_bbl_t } if(!stream->rx_first_seq) { stream->rx_first_seq = bbl->flow_seq; + interface->ctx->stats.stream_traffic_flows_verified++; } else { if(stream->rx_last_seq +1 != bbl->flow_seq) { stream->loss++; @@ -1880,6 +1881,17 @@ bbl_rx_handler_network(bbl_ethernet_header_t *eth, bbl_interface_s *interface) { default: break; } + } else { + /* Accept RAW streams */ + switch (bbl->sub_type) { + case BBL_SUB_TYPE_IPV4: + if(ipv4) bbl_rx_stream(interface, eth, bbl, ipv4->tos); + break; + case BBL_SUB_TYPE_IPV6: + case BBL_SUB_TYPE_IPV6PD: + if(ipv6) bbl_rx_stream(interface, eth, bbl, ipv6->tos); + break; + } } } } else { diff --git a/src/bbl_session.c b/src/bbl_session.c index e69ec76d..f2aa6e60 100644 --- a/src/bbl_session.c +++ b/src/bbl_session.c @@ -32,6 +32,32 @@ session_state_string(uint32_t state) { } } +const char * +ppp_state_string(uint32_t state) { + switch(state) { + case BBL_PPP_CLOSED: return "Closed"; + case BBL_PPP_INIT: return "Init"; + case BBL_PPP_LOCAL_ACK: return "Local-Ack"; + case BBL_PPP_PEER_ACK: return "Peer-Ack"; + case BBL_PPP_OPENED: return "Opened"; + case BBL_PPP_TERMINATE: return "Terminate"; + default: return "N/A"; + } +} + +const char * +dhcp_state_string(uint32_t state) { + switch(state) { + case BBL_DHCP_INIT: return "Init"; + case BBL_DHCP_SELECTING: return "Selecting"; + case BBL_DHCP_REQUESTING: return "Requesting"; + case BBL_DHCP_BOUND: return "Bound"; + case BBL_DHCP_RENEWING: return "Renewing"; + case BBL_DHCP_RELEASE: return "Releasing"; + default: return "N/A"; + } +} + void bbl_session_tx_qnode_insert(bbl_session_s *session) { @@ -649,4 +675,241 @@ NEXT: } } return true; +} + +json_t * +bbl_session_json(bbl_session_s *session) +{ + json_t *root = NULL; + json_t *session_traffic = NULL; + json_t *a10nsp_session = NULL; + bbl_ctx_s *ctx; + + struct timespec now; + + const char *ipv4 = NULL; + const char *ipv4_netmask = NULL; + const char *ipv4_gw = NULL; + const char *dns1 = NULL; + const char *dns2 = NULL; + const char *ipv6 = NULL; + const char *ipv6pd = NULL; + const char *ipv6_dns1 = NULL; + const char *ipv6_dns2 = NULL; + const char *dhcpv6_dns1 = NULL; + const char *dhcpv6_dns2 = NULL; + + int flows = 0; + int flows_verified = 0; + uint32_t seconds = 0; + uint32_t dhcp_lease_expire = 0; + uint32_t dhcp_lease_expire_t1 = 0; + uint32_t dhcp_lease_expire_t2 = 0; + uint32_t dhcpv6_lease_expire = 0; + uint32_t dhcpv6_lease_expire_t1 = 0; + uint32_t dhcpv6_lease_expire_t2 = 0; + + if(!session) { + return NULL; + } + + ctx = session->interface->ctx; + + if(session->ip_address) { + ipv4 = format_ipv4_address(&session->ip_address); + } + if(session->ip_netmask) { + ipv4_netmask = format_ipv4_address(&session->ip_netmask); + } + if(session->peer_ip_address) { + ipv4_gw = format_ipv4_address(&session->peer_ip_address); + } + if(session->dns1) { + dns1 = format_ipv4_address(&session->dns1); + } + if(session->dns2) { + dns2 = format_ipv4_address(&session->dns2); + } + if(session->ipv6_prefix.len) { + ipv6 = format_ipv6_prefix(&session->ipv6_prefix); + } + if(session->delegated_ipv6_prefix.len) { + ipv6pd = format_ipv6_prefix(&session->delegated_ipv6_prefix); + } + if(*(uint64_t*)session->ipv6_dns1) { + ipv6_dns1 = format_ipv6_address(&session->ipv6_dns1); + } + if(*(uint64_t*)session->ipv6_dns2) { + ipv6_dns2 = format_ipv6_address(&session->ipv6_dns2); + } + if(*(uint64_t*)session->dhcpv6_dns1) { + dhcpv6_dns1 = format_ipv6_address(&session->dhcpv6_dns1); + } + if(*(uint64_t*)session->dhcpv6_dns2) { + dhcpv6_dns2 = format_ipv6_address(&session->dhcpv6_dns2); + } + + if(ctx->config.session_traffic_ipv4_pps || ctx->config.session_traffic_ipv6_pps || ctx->config.session_traffic_ipv6pd_pps) { + if(session->access_ipv4_tx_flow_id) flows++; + if(session->access_ipv6_tx_flow_id) flows++; + if(session->access_ipv6pd_tx_flow_id) flows++; + if(session->network_ipv4_tx_flow_id) flows++; + if(session->network_ipv6_tx_flow_id) flows++; + if(session->network_ipv6pd_tx_flow_id) flows++; + if(session->access_ipv4_rx_first_seq) flows_verified++; + if(session->access_ipv6_rx_first_seq) flows_verified++; + if(session->access_ipv6pd_rx_first_seq) flows_verified++; + if(session->network_ipv4_rx_first_seq) flows_verified++; + if(session->network_ipv6_rx_first_seq) flows_verified++; + if(session->network_ipv6pd_rx_first_seq) flows_verified++; + + session_traffic = json_pack("{si si si si si si si si si si si si si si si si si si si si si si si si si si}", + "total-flows", flows, + "verified-flows", flows_verified, + "first-seq-rx-access-ipv4", session->access_ipv4_rx_first_seq, + "first-seq-rx-access-ipv6", session->access_ipv6_rx_first_seq, + "first-seq-rx-access-ipv6pd", session->access_ipv6pd_rx_first_seq, + "first-seq-rx-network-ipv4", session->network_ipv4_rx_first_seq, + "first-seq-rx-network-ipv6", session->network_ipv6_rx_first_seq, + "first-seq-rx-network-ipv6pd", session->network_ipv6pd_rx_first_seq, + "access-tx-session-packets", session->stats.access_ipv4_tx, + "access-rx-session-packets", session->stats.access_ipv4_rx, + "access-rx-session-packets-loss", session->stats.access_ipv4_loss, + "network-tx-session-packets", session->stats.network_ipv4_tx, + "network-rx-session-packets", session->stats.network_ipv4_rx, + "network-rx-session-packets-loss", session->stats.network_ipv4_loss, + "access-tx-session-packets-ipv6", session->stats.access_ipv6_tx, + "access-rx-session-packets-ipv6", session->stats.access_ipv6_rx, + "access-rx-session-packets-ipv6-loss", session->stats.access_ipv6_loss, + "network-tx-session-packets-ipv6", session->stats.network_ipv6_tx, + "network-rx-session-packets-ipv6", session->stats.network_ipv6_rx, + "network-rx-session-packets-ipv6-loss", session->stats.network_ipv6_loss, + "access-tx-session-packets-ipv6pd", session->stats.access_ipv6pd_tx, + "access-rx-session-packets-ipv6pd", session->stats.access_ipv6pd_rx, + "access-rx-session-packets-ipv6pd-loss", session->stats.access_ipv6pd_loss, + "network-tx-session-packets-ipv6pd", session->stats.network_ipv6pd_tx, + "network-rx-session-packets-ipv6pd", session->stats.network_ipv6pd_rx, + "network-rx-session-packets-ipv6pd-loss", session->stats.network_ipv6pd_loss); + } + + if(session->a10nsp_session) { + a10nsp_session = json_pack("{ss si sb sb ss* ss* si si}", + "interface", session->a10nsp_session->a10nsp_if->name, + "s-vlan", session->a10nsp_session->s_vlan, + "qinq-send", session->a10nsp_session->a10nsp_if->qinq, + "qinq-received", session->a10nsp_session->qinq_received, + "pppoe-aci", session->a10nsp_session->pppoe_aci, + "pppoe-ari", session->a10nsp_session->pppoe_ari, + "tx-packets", session->a10nsp_session->stats.packets_tx, + "rx-packets", session->a10nsp_session->stats.packets_rx); + } + + if(session->access_type == ACCESS_TYPE_PPPOE) { + root = json_pack("{ss si ss ss si si ss ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si so* so*}", + "type", "pppoe", + "session-id", session->session_id, + "session-state", session_state_string(session->session_state), + "interface", session->interface->name, + "outer-vlan", session->vlan_key.outer_vlan_id, + "inner-vlan", session->vlan_key.inner_vlan_id, + "mac", format_mac_address(session->client_mac), + "username", session->username, + "agent-circuit-id", session->agent_circuit_id, + "agent-remote-id", session->agent_remote_id, + "reply-message", session->reply_message, + "connection-status-message", session->connections_status_message, + "lcp-state", ppp_state_string(session->lcp_state), + "ipcp-state", ppp_state_string(session->ipcp_state), + "ip6cp-state", ppp_state_string(session->ip6cp_state), + "ipv4-address", ipv4, + "ipv4-dns1", dns1, + "ipv4-dns2", dns2, + "ipv6-prefix", ipv6, + "ipv6-delegated-prefix", ipv6pd, + "ipv6-dns1", ipv6_dns1, + "ipv6-dns2", ipv6_dns2, + "dhcpv6-state", dhcp_state_string(session->dhcpv6_state), + "dhcpv6-dns1", dhcpv6_dns1, + "dhcpv6-dns2", dhcpv6_dns2, + "tx-packets", session->stats.packets_tx, + "rx-packets", session->stats.packets_rx, + "rx-fragmented-packets", session->stats.ipv4_fragmented_rx, + "session-traffic", session_traffic, + "a10nsp", a10nsp_session); + + } else { + clock_gettime(CLOCK_MONOTONIC, &now); + if(session->dhcp_lease_timestamp.tv_sec && now.tv_sec > session->dhcp_lease_timestamp.tv_sec) { + seconds = now.tv_sec - session->dhcp_lease_timestamp.tv_sec; + } + if(seconds <= session->dhcp_lease_time) dhcp_lease_expire = session->dhcp_lease_time - seconds; + if(seconds <= session->dhcp_t1) dhcp_lease_expire_t1 = session->dhcp_t1 - seconds; + if(seconds <= session->dhcp_t2) dhcp_lease_expire_t2 = session->dhcp_t2 - seconds; + + if(session->dhcpv6_lease_timestamp.tv_sec && now.tv_sec > session->dhcpv6_lease_timestamp.tv_sec) { + seconds = now.tv_sec - session->dhcpv6_lease_timestamp.tv_sec; + } + if(seconds <= session->dhcpv6_lease_time) dhcpv6_lease_expire = session->dhcpv6_lease_time - seconds; + if(seconds <= session->dhcpv6_t1) dhcpv6_lease_expire_t1 = session->dhcpv6_t1 - seconds; + if(seconds <= session->dhcpv6_t2) dhcpv6_lease_expire_t2 = session->dhcpv6_t2 - seconds; + + root = json_pack("{ss si ss ss si si ss ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si si si si si si si si si si ss* si si si si si si si si si si si si ss* ss* si si si so* so*}", + "type", "ipoe", + "session-id", session->session_id, + "session-state", session_state_string(session->session_state), + "interface", session->interface->name, + "outer-vlan", session->vlan_key.outer_vlan_id, + "inner-vlan", session->vlan_key.inner_vlan_id, + "mac", format_mac_address(session->client_mac), + "agent-circuit-id", session->agent_circuit_id, + "agent-remote-id", session->agent_remote_id, + "ipv4-address", ipv4, + "ipv4-netmask", ipv4_netmask, + "ipv4-gateway", ipv4_gw, + "ipv4-dns1", dns1, + "ipv4-dns2", dns2, + "ipv6-prefix", ipv6, + "ipv6-delegated-prefix", ipv6pd, + "ipv6-dns1", ipv6_dns1, + "ipv6-dns2", ipv6_dns2, + "dhcp-state", dhcp_state_string(session->dhcp_state), + "dhcp-server", format_ipv4_address(&session->dhcp_server_identifier), + "dhcp-lease-time", session->dhcp_lease_time, + "dhcp-lease-expire", dhcp_lease_expire, + "dhcp-lease-expire-t1", dhcp_lease_expire_t1, + "dhcp-lease-expire-t2", dhcp_lease_expire_t2, + "dhcp-tx", session->stats.dhcp_tx, + "dhcp-rx", session->stats.dhcp_rx, + "dhcp-tx-discover", session->stats.dhcp_tx_discover, + "dhcp-rx-offer", session->stats.dhcp_rx_offer, + "dhcp-tx-request", session->stats.dhcp_tx_request, + "dhcp-rx-ack", session->stats.dhcp_rx_ack, + "dhcp-rx-nak", session->stats.dhcp_rx_nak, + "dhcp-tx-release", session->stats.dhcp_tx_release, + "dhcpv6-state", dhcp_state_string(session->dhcpv6_state), + "dhcpv6-lease-time", session->dhcpv6_lease_time, + "dhcpv6-lease-expire", dhcpv6_lease_expire, + "dhcpv6-lease-expire-t1", dhcpv6_lease_expire_t1, + "dhcpv6-lease-expire-t2", dhcpv6_lease_expire_t2, + "dhcpv6-tx", session->stats.dhcpv6_tx, + "dhcpv6-rx", session->stats.dhcpv6_rx, + "dhcpv6-tx-solicit", session->stats.dhcpv6_tx_solicit, + "dhcpv6-rx-advertise", session->stats.dhcpv6_rx_advertise, + "dhcpv6-tx-request", session->stats.dhcpv6_tx_request, + "dhcpv6-rx-reply", session->stats.dhcpv6_rx_reply, + "dhcpv6-tx-renew", session->stats.dhcpv6_tx_renew, + "dhcpv6-tx-release", session->stats.dhcpv6_tx_release, + "dhcpv6-dns1", dhcpv6_dns1, + "dhcpv6-dns2", dhcpv6_dns2, + "tx-packets", session->stats.packets_tx, + "rx-packets", session->stats.packets_rx, + "rx-fragmented-packets", session->stats.ipv4_fragmented_rx, + "session-traffic", session_traffic, + "a10nsp", a10nsp_session); + } + if(!root) { + if(a10nsp_session) json_decref(a10nsp_session); + if(session_traffic) json_decref(session_traffic); + } + return root; } \ No newline at end of file diff --git a/src/bbl_session.h b/src/bbl_session.h index 122006ca..9cf5e777 100644 --- a/src/bbl_session.h +++ b/src/bbl_session.h @@ -417,4 +417,7 @@ bbl_session_clear(bbl_ctx_s *ctx, bbl_session_s *session); bool bbl_sessions_init(bbl_ctx_s *ctx); +json_t * +bbl_session_json(bbl_session_s *session); + #endif \ No newline at end of file diff --git a/src/bbl_session_traffic.c b/src/bbl_session_traffic.c index 34519b47..1492721a 100644 --- a/src/bbl_session_traffic.c +++ b/src/bbl_session_traffic.c @@ -10,6 +10,8 @@ #include "bbl.h" #include "bbl_session.h" +extern bool g_traffic; + void bbl_session_traffic_ipv4(timer_s *timer) { @@ -31,7 +33,7 @@ bbl_session_traffic_ipv4(timer_s *timer) return; } } - if(session->session_traffic) { + if(g_traffic && session->session_traffic) { session->send_requests |= BBL_SEND_SESSION_IPV4; bbl_session_tx_qnode_insert(session); session->network_send_requests |= BBL_SEND_SESSION_IPV4; @@ -56,7 +58,7 @@ bbl_session_traffic_ipv6(timer_s *timer) return; } } - if(session->session_traffic) { + if(g_traffic && session->session_traffic) { if(session->ipv6_prefix.len) { session->send_requests |= BBL_SEND_SESSION_IPV6; session->network_send_requests |= BBL_SEND_SESSION_IPV6; @@ -83,7 +85,7 @@ bbl_session_traffic_ipv6pd(timer_s *timer) return; } } - if(session->session_traffic) { + if(g_traffic && session->session_traffic) { if(session->delegated_ipv6_prefix.len) { session->send_requests |= BBL_SEND_SESSION_IPV6PD; session->network_send_requests |= BBL_SEND_SESSION_IPV6PD; diff --git a/src/bbl_stats.c b/src/bbl_stats.c index 7696edd8..c2e05caf 100644 --- a/src/bbl_stats.c +++ b/src/bbl_stats.c @@ -10,7 +10,8 @@ #include "bbl.h" #include "bbl_stats.h" -#include +#include "bbl_session.h" +#include "bbl_stream.h" extern const char banner[]; @@ -196,13 +197,15 @@ bbl_stats_stdout (bbl_ctx_s *ctx, bbl_stats_t * stats) { printf("%s", banner); printf("Report:\n\n"); - printf("Sessions PPPoE: %u IPoE: %u\n", ctx->sessions_pppoe, ctx->sessions_ipoe); - printf("Sessions established: %u/%u\n", ctx->sessions_established_max, ctx->config.sessions); - printf("DHCPv6 sessions established: %u\n", ctx->dhcpv6_established_max); - printf("Setup Time: %u ms\n", ctx->stats.setup_time); - printf("Setup Rate: %0.02lf CPS (MIN: %0.02lf AVG: %0.02lf MAX: %0.02lf)\n", - ctx->stats.cps, ctx->stats.cps_min, ctx->stats.cps_avg, ctx->stats.cps_max); - printf("Flapped: %u\n", ctx->sessions_flapped); + if(ctx->sessions) { + printf("Sessions PPPoE: %u IPoE: %u\n", ctx->sessions_pppoe, ctx->sessions_ipoe); + printf("Sessions established: %u/%u\n", ctx->sessions_established_max, ctx->sessions); + printf("DHCPv6 sessions established: %u\n", ctx->dhcpv6_established_max); + printf("Setup Time: %u ms\n", ctx->stats.setup_time); + printf("Setup Rate: %0.02lf CPS (MIN: %0.02lf AVG: %0.02lf MAX: %0.02lf)\n", + ctx->stats.cps, ctx->stats.cps_min, ctx->stats.cps_avg, ctx->stats.cps_max); + printf("Flapped: %u\n", ctx->sessions_flapped); + } if(dict_count(ctx->li_flow_dict)) { printf("\nLI Statistics:\n"); @@ -229,18 +232,20 @@ bbl_stats_stdout (bbl_ctx_s *ctx, bbl_stats_t * stats) { printf("\nNetwork Interface ( %s ):\n", interface->name); printf(" TX: %10lu packets\n", interface->stats.packets_tx); printf(" RX: %10lu packets\n", interface->stats.packets_rx); - printf(" TX Session: %10lu packets\n", - interface->stats.session_ipv4_tx); - printf(" RX Session: %10lu packets (%lu loss)\n", - interface->stats.session_ipv4_rx, interface->stats.session_ipv4_loss); - printf(" TX Session IPv6: %10lu packets\n", - interface->stats.session_ipv6_tx); - printf(" RX Session IPv6: %10lu packets (%lu loss)\n", - interface->stats.session_ipv6_rx, interface->stats.session_ipv6_loss); - printf(" TX Session IPv6PD: %10lu packets\n", - interface->stats.session_ipv6pd_tx); - printf(" RX Session IPv6PD: %10lu packets (%lu loss)\n", - interface->stats.session_ipv6pd_rx, interface->stats.session_ipv6pd_loss); + if(ctx->stats.session_traffic_flows) { + printf(" TX Session: %10lu packets\n", + interface->stats.session_ipv4_tx); + printf(" RX Session: %10lu packets (%lu loss)\n", + interface->stats.session_ipv4_rx, interface->stats.session_ipv4_loss); + printf(" TX Session IPv6: %10lu packets\n", + interface->stats.session_ipv6_tx); + printf(" RX Session IPv6: %10lu packets (%lu loss)\n", + interface->stats.session_ipv6_rx, interface->stats.session_ipv6_loss); + printf(" TX Session IPv6PD: %10lu packets\n", + interface->stats.session_ipv6pd_tx); + printf(" RX Session IPv6PD: %10lu packets (%lu loss)\n", + interface->stats.session_ipv6pd_rx, interface->stats.session_ipv6pd_loss); + } printf(" TX Multicast: %10lu packets\n", interface->stats.mc_tx); printf(" RX Drop Unknown: %10lu packets\n", @@ -261,15 +266,17 @@ bbl_stats_stdout (bbl_ctx_s *ctx, bbl_stats_t * stats) { printf("\nAccess Interface ( %s ):\n", interface->name); printf(" TX: %10lu packets\n", interface->stats.packets_tx); printf(" RX: %10lu packets\n", interface->stats.packets_rx); - printf(" TX Session: %10lu packets\n", interface->stats.session_ipv4_tx); - printf(" RX Session: %10lu packets (%lu loss, %lu wrong session)\n", interface->stats.session_ipv4_rx, - interface->stats.session_ipv4_loss, interface->stats.session_ipv4_wrong_session); - printf(" TX Session IPv6: %10lu packets\n", interface->stats.session_ipv6_tx); - printf(" RX Session IPv6: %10lu packets (%lu loss, %lu wrong session)\n", interface->stats.session_ipv6_rx, - interface->stats.session_ipv6_loss, interface->stats.session_ipv6_wrong_session); - printf(" TX Session IPv6PD: %10lu packets\n", interface->stats.session_ipv6pd_tx); - printf(" RX Session IPv6PD: %10lu packets (%lu loss, %lu wrong session)\n", interface->stats.session_ipv6pd_rx, - interface->stats.session_ipv6pd_loss, interface->stats.session_ipv6pd_wrong_session); + if(ctx->stats.session_traffic_flows) { + printf(" TX Session: %10lu packets\n", interface->stats.session_ipv4_tx); + printf(" RX Session: %10lu packets (%lu loss, %lu wrong session)\n", interface->stats.session_ipv4_rx, + interface->stats.session_ipv4_loss, interface->stats.session_ipv4_wrong_session); + printf(" TX Session IPv6: %10lu packets\n", interface->stats.session_ipv6_tx); + printf(" RX Session IPv6: %10lu packets (%lu loss, %lu wrong session)\n", interface->stats.session_ipv6_rx, + interface->stats.session_ipv6_loss, interface->stats.session_ipv6_wrong_session); + printf(" TX Session IPv6PD: %10lu packets\n", interface->stats.session_ipv6pd_tx); + printf(" RX Session IPv6PD: %10lu packets (%lu loss, %lu wrong session)\n", interface->stats.session_ipv6pd_rx, + interface->stats.session_ipv6pd_loss, interface->stats.session_ipv6pd_wrong_session); + } printf(" RX Multicast: %10lu packets (%lu loss)\n", interface->stats.mc_rx, interface->stats.mc_loss); printf(" RX Drop Unknown: %10lu packets\n", interface->stats.packets_rx_drop_unknown); @@ -316,9 +323,21 @@ bbl_stats_stdout (bbl_ctx_s *ctx, bbl_stats_t * stats) { printf("\nA10NSP Interface ( %s ):\n", interface->name); printf(" TX: %10lu packets\n", interface->stats.packets_tx); printf(" RX: %10lu packets\n", interface->stats.packets_rx); - printf(" TX Session: %10lu packets\n", interface->stats.session_ipv4_tx); - printf(" RX Session: %10lu packets (%lu loss, %lu wrong session)\n", interface->stats.session_ipv4_rx, - interface->stats.session_ipv4_loss, interface->stats.session_ipv4_wrong_session); + if(ctx->stats.session_traffic_flows) { + printf(" TX Session: %10lu packets\n", + interface->stats.session_ipv4_tx); + printf(" RX Session: %10lu packets (%lu loss)\n", + interface->stats.session_ipv4_rx, interface->stats.session_ipv4_loss); + printf(" TX Session IPv6: %10lu packets\n", + interface->stats.session_ipv6_tx); + printf(" RX Session IPv6: %10lu packets (%lu loss)\n", + interface->stats.session_ipv6_rx, interface->stats.session_ipv6_loss); + printf(" TX Session IPv6PD: %10lu packets\n", + interface->stats.session_ipv6pd_tx); + printf(" RX Session IPv6PD: %10lu packets (%lu loss)\n", + interface->stats.session_ipv6pd_rx, interface->stats.session_ipv6pd_loss); + + } printf(" RX Drop Unknown: %10lu packets\n", interface->stats.packets_rx_drop_unknown); printf(" TX Encode Error: %10lu packets\n", interface->stats.encode_errors); printf(" RX Decode Error: %10lu packets\n", interface->stats.packets_rx_drop_decode_error); @@ -364,6 +383,12 @@ bbl_stats_stdout (bbl_ctx_s *ctx, bbl_stats_t * stats) { stats->max_network_ipv6pd_rx_first_seq, stats->max_network_ipv6pd_rx_seconds); } + if(ctx->stats.stream_traffic_flows) { + printf("\nTraffic Streams:\n"); + printf(" Verified Traffic Flows: %u/%u\n", + ctx->stats.stream_traffic_flows_verified, ctx->stats.stream_traffic_flows); + } + if(ctx->config.igmp_group_count > 1) { printf("\nIGMP Config:\n"); printf(" Version: %d\n", ctx->config.igmp_version); @@ -392,85 +417,85 @@ bbl_stats_stdout (bbl_ctx_s *ctx, bbl_stats_t * stats) { void bbl_stats_json (bbl_ctx_s *ctx, bbl_stats_t * stats) { struct bbl_interface_ *interface; + bbl_session_s *session; + bbl_stream *stream; - int i; + struct dict_itor *itor; + uint32_t i; - json_t *root = NULL; - json_t *jobj = NULL; - json_t *jobj_array = NULL; - json_t *jobj_access_if = NULL; - json_t *jobj_network_if = NULL; - json_t *jobj_a10nsp_if = NULL; - json_t *jobj_l2tp = NULL; - json_t *jobj_li = NULL; - json_t *jobj_straffic = NULL; - json_t *jobj_multicast = NULL; - json_t *jobj_protocols = NULL; + json_t *root = NULL; + json_t *jobj = NULL; + json_t *jobj_array = NULL; + json_t *jobj_sub = NULL; + json_t *jobj_sub2 = NULL; if(!ctx->config.json_report_filename) return; root = json_object(); + jobj = json_object(); - - json_object_set(jobj, "sessions", json_integer(ctx->config.sessions)); - json_object_set(jobj, "sessions-pppoe", json_integer(ctx->sessions_pppoe)); - json_object_set(jobj, "sessions-ipoe", json_integer(ctx->sessions_ipoe)); - json_object_set(jobj, "sessions-established", json_integer(ctx->sessions_established_max)); - json_object_set(jobj, "sessions-flapped", json_integer(ctx->sessions_flapped)); - json_object_set(jobj, "setup-time-ms", json_integer(ctx->stats.setup_time)); - json_object_set(jobj, "setup-rate-cps", json_real(ctx->stats.cps)); - json_object_set(jobj, "setup-rate-cps-min", json_real(ctx->stats.cps_min)); - json_object_set(jobj, "setup-rate-cps-avg", json_real(ctx->stats.cps_avg)); - json_object_set(jobj, "setup-rate-cps-max", json_real(ctx->stats.cps_max)); - json_object_set(jobj, "dhcp-sessions-established", json_integer(ctx->dhcp_established_max)); - json_object_set(jobj, "dhcpv6-sessions-established", json_integer(ctx->dhcpv6_established_max)); - + if(ctx->sessions) { + json_object_set(jobj, "sessions", json_integer(ctx->config.sessions)); + json_object_set(jobj, "sessions-pppoe", json_integer(ctx->sessions_pppoe)); + json_object_set(jobj, "sessions-ipoe", json_integer(ctx->sessions_ipoe)); + json_object_set(jobj, "sessions-established", json_integer(ctx->sessions_established_max)); + json_object_set(jobj, "sessions-flapped", json_integer(ctx->sessions_flapped)); + json_object_set(jobj, "setup-time-ms", json_integer(ctx->stats.setup_time)); + json_object_set(jobj, "setup-rate-cps", json_real(ctx->stats.cps)); + json_object_set(jobj, "setup-rate-cps-min", json_real(ctx->stats.cps_min)); + json_object_set(jobj, "setup-rate-cps-avg", json_real(ctx->stats.cps_avg)); + json_object_set(jobj, "setup-rate-cps-max", json_real(ctx->stats.cps_max)); + json_object_set(jobj, "dhcp-sessions-established", json_integer(ctx->dhcp_established_max)); + json_object_set(jobj, "dhcpv6-sessions-established", json_integer(ctx->dhcpv6_established_max)); + } if(dict_count(ctx->li_flow_dict)) { - jobj_li = json_object(); - json_object_set(jobj_li, "flows", json_integer(dict_count(ctx->li_flow_dict))); - json_object_set(jobj_li, "rx-packets", json_integer(stats->li_rx)); - json_object_set(jobj, "li-statistics", jobj_li); + jobj_sub = json_object(); + json_object_set(jobj_sub, "flows", json_integer(dict_count(ctx->li_flow_dict))); + json_object_set(jobj_sub, "rx-packets", json_integer(stats->li_rx)); + json_object_set(jobj, "li-statistics", jobj_sub); } if(ctx->config.l2tp_server) { - jobj_l2tp = json_object(); - json_object_set(jobj_l2tp, "tunnels", json_integer(ctx->l2tp_tunnels_max)); - json_object_set(jobj_l2tp, "tunnels-established", json_integer(ctx->l2tp_tunnels_established_max)); - json_object_set(jobj_l2tp, "sessions", json_integer(ctx->l2tp_sessions_max)); - json_object_set(jobj_l2tp, "tx-control-packets", json_integer(stats->l2tp_control_tx)); - json_object_set(jobj_l2tp, "tx-control-packets-retry", json_integer(stats->l2tp_control_retry)); - json_object_set(jobj_l2tp, "rx-control-packets", json_integer(stats->l2tp_control_rx)); - json_object_set(jobj_l2tp, "rx-control-packets-duplicate", json_integer(stats->l2tp_control_rx_dup)); - json_object_set(jobj_l2tp, "rx-control-packets-out-of-order", json_integer(stats->l2tp_control_rx_ooo)); - json_object_set(jobj_l2tp, "tx-data-packets", json_integer(stats->l2tp_data_tx)); - json_object_set(jobj_l2tp, "rx-data-packets", json_integer(stats->l2tp_data_rx)); - json_object_set(jobj, "l2tp", jobj_l2tp); + jobj_sub = json_object(); + json_object_set(jobj_sub, "tunnels", json_integer(ctx->l2tp_tunnels_max)); + json_object_set(jobj_sub, "tunnels-established", json_integer(ctx->l2tp_tunnels_established_max)); + json_object_set(jobj_sub, "sessions", json_integer(ctx->l2tp_sessions_max)); + json_object_set(jobj_sub, "tx-control-packets", json_integer(stats->l2tp_control_tx)); + json_object_set(jobj_sub, "tx-control-packets-retry", json_integer(stats->l2tp_control_retry)); + json_object_set(jobj_sub, "rx-control-packets", json_integer(stats->l2tp_control_rx)); + json_object_set(jobj_sub, "rx-control-packets-duplicate", json_integer(stats->l2tp_control_rx_dup)); + json_object_set(jobj_sub, "rx-control-packets-out-of-order", json_integer(stats->l2tp_control_rx_ooo)); + json_object_set(jobj_sub, "tx-data-packets", json_integer(stats->l2tp_data_tx)); + json_object_set(jobj_sub, "rx-data-packets", json_integer(stats->l2tp_data_rx)); + json_object_set(jobj, "l2tp", jobj_sub); } jobj_array = json_array(); for(i=0; i < ctx->interfaces.network_if_count; i++) { interface = ctx->interfaces.network_if[i]; if (interface) { - jobj_network_if = json_object(); - json_object_set(jobj_network_if, "name", json_string(interface->name)); - json_object_set(jobj_network_if, "tx-packets", json_integer(interface->stats.packets_tx)); - json_object_set(jobj_network_if, "rx-packets", json_integer(interface->stats.packets_rx)); - json_object_set(jobj_network_if, "tx-session-packets", json_integer(interface->stats.session_ipv4_tx)); - json_object_set(jobj_network_if, "rx-session-packets", json_integer(interface->stats.session_ipv4_rx)); - json_object_set(jobj_network_if, "rx-session-packets-loss", json_integer(interface->stats.session_ipv4_loss)); - json_object_set(jobj_network_if, "tx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_tx.avg_max)); - json_object_set(jobj_network_if, "rx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_rx.avg_max)); - json_object_set(jobj_network_if, "tx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_tx)); - json_object_set(jobj_network_if, "rx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_rx)); - json_object_set(jobj_network_if, "rx-session-packets-ipv6-loss", json_integer(interface->stats.session_ipv6_loss)); - json_object_set(jobj_network_if, "tx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_tx.avg_max)); - json_object_set(jobj_network_if, "rx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_rx.avg_max)); - json_object_set(jobj_network_if, "tx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_tx)); - json_object_set(jobj_network_if, "rx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_rx)); - json_object_set(jobj_network_if, "rx-session-packets-ipv6pd-loss", json_integer(interface->stats.session_ipv6pd_loss)); - json_object_set(jobj_network_if, "tx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_tx.avg_max)); - json_object_set(jobj_network_if, "rx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_rx.avg_max)); - json_object_set(jobj_network_if, "tx-multicast-packets", json_integer(interface->stats.mc_tx)); - json_array_append(jobj_array, jobj_network_if); + jobj_sub = json_object(); + json_object_set(jobj_sub, "name", json_string(interface->name)); + json_object_set(jobj_sub, "tx-packets", json_integer(interface->stats.packets_tx)); + json_object_set(jobj_sub, "rx-packets", json_integer(interface->stats.packets_rx)); + if(ctx->stats.session_traffic_flows) { + json_object_set(jobj_sub, "tx-session-packets", json_integer(interface->stats.session_ipv4_tx)); + json_object_set(jobj_sub, "rx-session-packets", json_integer(interface->stats.session_ipv4_rx)); + json_object_set(jobj_sub, "rx-session-packets-loss", json_integer(interface->stats.session_ipv4_loss)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_rx.avg_max)); + json_object_set(jobj_sub, "tx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_tx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_rx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6-loss", json_integer(interface->stats.session_ipv6_loss)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_rx.avg_max)); + json_object_set(jobj_sub, "tx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_tx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_rx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6pd-loss", json_integer(interface->stats.session_ipv6pd_loss)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_rx.avg_max)); + } + json_object_set(jobj_sub, "tx-multicast-packets", json_integer(interface->stats.mc_tx)); + json_array_append(jobj_array, jobj_sub); } } json_object_set(jobj, "network-interfaces", jobj_array); @@ -479,71 +504,73 @@ bbl_stats_json (bbl_ctx_s *ctx, bbl_stats_t * stats) { for(i=0; i < ctx->interfaces.access_if_count; i++) { interface = ctx->interfaces.access_if[i]; if (interface) { - jobj_access_if = json_object(); - json_object_set(jobj_access_if, "name", json_string(interface->name)); - json_object_set(jobj_access_if, "tx-packets", json_integer(interface->stats.packets_tx)); - json_object_set(jobj_access_if, "rx-packets", json_integer(interface->stats.packets_rx)); - json_object_set(jobj_access_if, "tx-session-packets", json_integer(interface->stats.session_ipv4_tx)); - json_object_set(jobj_access_if, "rx-session-packets", json_integer(interface->stats.session_ipv4_rx)); - json_object_set(jobj_access_if, "rx-session-packets-loss", json_integer(interface->stats.session_ipv4_loss)); - json_object_set(jobj_access_if, "rx-session-packets-wrong-session", json_integer(interface->stats.session_ipv4_wrong_session)); - json_object_set(jobj_access_if, "tx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_tx.avg_max)); - json_object_set(jobj_access_if, "rx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_rx.avg_max)); - json_object_set(jobj_access_if, "tx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_tx)); - json_object_set(jobj_access_if, "rx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_rx)); - json_object_set(jobj_access_if, "rx-session-packets-ipv6-loss", json_integer(interface->stats.session_ipv6_loss)); - json_object_set(jobj_access_if, "rx-session-packets-ipv6-wrong-session", json_integer(interface->stats.session_ipv6_wrong_session)); - json_object_set(jobj_access_if, "tx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_tx.avg_max)); - json_object_set(jobj_access_if, "rx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_rx.avg_max)); - json_object_set(jobj_access_if, "tx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_tx)); - json_object_set(jobj_access_if, "rx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_rx)); - json_object_set(jobj_access_if, "rx-session-packets-ipv6pd-loss", json_integer(interface->stats.session_ipv6pd_loss)); - json_object_set(jobj_access_if, "rx-session-packets-ipv6pd-wrong-session", json_integer(interface->stats.session_ipv6pd_wrong_session)); - json_object_set(jobj_access_if, "tx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_tx.avg_max)); - json_object_set(jobj_access_if, "rx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_rx.avg_max)); - json_object_set(jobj_access_if, "rx-multicast-packets", json_integer(interface->stats.mc_rx)); - json_object_set(jobj_access_if, "rx-multicast-packets-loss", json_integer(interface->stats.mc_loss)); - jobj_protocols = json_object(); - json_object_set(jobj_protocols, "arp-tx", json_integer(interface->stats.arp_tx)); - json_object_set(jobj_protocols, "arp-rx", json_integer(interface->stats.arp_rx)); - json_object_set(jobj_protocols, "padi-tx", json_integer(interface->stats.padi_tx)); - json_object_set(jobj_protocols, "pado-rx", json_integer(interface->stats.pado_rx)); - json_object_set(jobj_protocols, "padr-tx", json_integer(interface->stats.padr_tx)); - json_object_set(jobj_protocols, "pads-rx", json_integer(interface->stats.pads_rx)); - json_object_set(jobj_protocols, "padt-tx", json_integer(interface->stats.padt_tx)); - json_object_set(jobj_protocols, "padt-rx", json_integer(interface->stats.padt_rx)); - json_object_set(jobj_protocols, "lcp-tx", json_integer(interface->stats.lcp_tx)); - json_object_set(jobj_protocols, "lcp-rx", json_integer(interface->stats.lcp_rx)); - json_object_set(jobj_protocols, "pap-tx", json_integer(interface->stats.pap_tx)); - json_object_set(jobj_protocols, "pap-rx", json_integer(interface->stats.pap_rx)); - json_object_set(jobj_protocols, "chap-tx", json_integer(interface->stats.chap_tx)); - json_object_set(jobj_protocols, "chap-rx", json_integer(interface->stats.chap_rx)); - json_object_set(jobj_protocols, "ipcp-tx", json_integer(interface->stats.ipcp_tx)); - json_object_set(jobj_protocols, "ipcp-rx", json_integer(interface->stats.ipcp_rx)); - json_object_set(jobj_protocols, "ip6cp-tx", json_integer(interface->stats.ip6cp_tx)); - json_object_set(jobj_protocols, "ip6cp-rx", json_integer(interface->stats.ip6cp_rx)); - json_object_set(jobj_protocols, "igmp-tx", json_integer(interface->stats.igmp_tx)); - json_object_set(jobj_protocols, "igmp-rx", json_integer(interface->stats.igmp_rx)); - json_object_set(jobj_protocols, "icmp-tx", json_integer(interface->stats.icmp_tx)); - json_object_set(jobj_protocols, "icmp-rx", json_integer(interface->stats.icmp_rx)); - json_object_set(jobj_protocols, "dhcp-tx", json_integer(interface->stats.dhcp_tx)); - json_object_set(jobj_protocols, "dhcp-rx", json_integer(interface->stats.dhcp_rx)); - json_object_set(jobj_protocols, "dhcpv6-tx", json_integer(interface->stats.dhcpv6_tx)); - json_object_set(jobj_protocols, "dhcpv6-rx", json_integer(interface->stats.dhcpv6_rx)); - json_object_set(jobj_protocols, "icmpv6-tx", json_integer(interface->stats.icmpv6_tx)); - json_object_set(jobj_protocols, "icmpv6-rx", json_integer(interface->stats.icmpv6_rx)); - json_object_set(jobj_protocols, "ipv4-fragmented-rx", json_integer(interface->stats.ipv4_fragmented_rx)); - json_object_set(jobj_protocols, "lcp-echo-timeout", json_integer(interface->stats.lcp_echo_timeout)); - json_object_set(jobj_protocols, "lcp-request-timeout", json_integer(interface->stats.lcp_timeout)); - json_object_set(jobj_protocols, "ipcp-request-timeout", json_integer(interface->stats.ipcp_timeout)); - json_object_set(jobj_protocols, "ip6cp-request-timeout", json_integer(interface->stats.ip6cp_timeout)); - json_object_set(jobj_protocols, "pap-timeout", json_integer(interface->stats.pap_timeout)); - json_object_set(jobj_protocols, "chap-timeout", json_integer(interface->stats.chap_timeout)); - json_object_set(jobj_protocols, "dhcp-timeout", json_integer(interface->stats.dhcp_timeout)); - json_object_set(jobj_protocols, "dhcpv6-timeout", json_integer(interface->stats.dhcpv6_timeout)); - json_object_set(jobj_protocols, "icmpv6-rs-timeout", json_integer(interface->stats.dhcpv6_timeout)); - json_object_set(jobj_access_if, "protocol-stats", jobj_protocols); - json_array_append(jobj_array, jobj_access_if); + jobj_sub = json_object(); + json_object_set(jobj_sub, "name", json_string(interface->name)); + json_object_set(jobj_sub, "tx-packets", json_integer(interface->stats.packets_tx)); + json_object_set(jobj_sub, "rx-packets", json_integer(interface->stats.packets_rx)); + if(ctx->stats.session_traffic_flows) { + json_object_set(jobj_sub, "tx-session-packets", json_integer(interface->stats.session_ipv4_tx)); + json_object_set(jobj_sub, "rx-session-packets", json_integer(interface->stats.session_ipv4_rx)); + json_object_set(jobj_sub, "rx-session-packets-loss", json_integer(interface->stats.session_ipv4_loss)); + json_object_set(jobj_sub, "rx-session-packets-wrong-session", json_integer(interface->stats.session_ipv4_wrong_session)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_rx.avg_max)); + json_object_set(jobj_sub, "tx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_tx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_rx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6-loss", json_integer(interface->stats.session_ipv6_loss)); + json_object_set(jobj_sub, "rx-session-packets-ipv6-wrong-session", json_integer(interface->stats.session_ipv6_wrong_session)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_rx.avg_max)); + json_object_set(jobj_sub, "tx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_tx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_rx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6pd-loss", json_integer(interface->stats.session_ipv6pd_loss)); + json_object_set(jobj_sub, "rx-session-packets-ipv6pd-wrong-session", json_integer(interface->stats.session_ipv6pd_wrong_session)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_rx.avg_max)); + } + json_object_set(jobj_sub, "rx-multicast-packets", json_integer(interface->stats.mc_rx)); + json_object_set(jobj_sub, "rx-multicast-packets-loss", json_integer(interface->stats.mc_loss)); + jobj_sub2 = json_object(); + json_object_set(jobj_sub2, "arp-tx", json_integer(interface->stats.arp_tx)); + json_object_set(jobj_sub2, "arp-rx", json_integer(interface->stats.arp_rx)); + json_object_set(jobj_sub2, "padi-tx", json_integer(interface->stats.padi_tx)); + json_object_set(jobj_sub2, "pado-rx", json_integer(interface->stats.pado_rx)); + json_object_set(jobj_sub2, "padr-tx", json_integer(interface->stats.padr_tx)); + json_object_set(jobj_sub2, "pads-rx", json_integer(interface->stats.pads_rx)); + json_object_set(jobj_sub2, "padt-tx", json_integer(interface->stats.padt_tx)); + json_object_set(jobj_sub2, "padt-rx", json_integer(interface->stats.padt_rx)); + json_object_set(jobj_sub2, "lcp-tx", json_integer(interface->stats.lcp_tx)); + json_object_set(jobj_sub2, "lcp-rx", json_integer(interface->stats.lcp_rx)); + json_object_set(jobj_sub2, "pap-tx", json_integer(interface->stats.pap_tx)); + json_object_set(jobj_sub2, "pap-rx", json_integer(interface->stats.pap_rx)); + json_object_set(jobj_sub2, "chap-tx", json_integer(interface->stats.chap_tx)); + json_object_set(jobj_sub2, "chap-rx", json_integer(interface->stats.chap_rx)); + json_object_set(jobj_sub2, "ipcp-tx", json_integer(interface->stats.ipcp_tx)); + json_object_set(jobj_sub2, "ipcp-rx", json_integer(interface->stats.ipcp_rx)); + json_object_set(jobj_sub2, "ip6cp-tx", json_integer(interface->stats.ip6cp_tx)); + json_object_set(jobj_sub2, "ip6cp-rx", json_integer(interface->stats.ip6cp_rx)); + json_object_set(jobj_sub2, "igmp-tx", json_integer(interface->stats.igmp_tx)); + json_object_set(jobj_sub2, "igmp-rx", json_integer(interface->stats.igmp_rx)); + json_object_set(jobj_sub2, "icmp-tx", json_integer(interface->stats.icmp_tx)); + json_object_set(jobj_sub2, "icmp-rx", json_integer(interface->stats.icmp_rx)); + json_object_set(jobj_sub2, "dhcp-tx", json_integer(interface->stats.dhcp_tx)); + json_object_set(jobj_sub2, "dhcp-rx", json_integer(interface->stats.dhcp_rx)); + json_object_set(jobj_sub2, "dhcpv6-tx", json_integer(interface->stats.dhcpv6_tx)); + json_object_set(jobj_sub2, "dhcpv6-rx", json_integer(interface->stats.dhcpv6_rx)); + json_object_set(jobj_sub2, "icmpv6-tx", json_integer(interface->stats.icmpv6_tx)); + json_object_set(jobj_sub2, "icmpv6-rx", json_integer(interface->stats.icmpv6_rx)); + json_object_set(jobj_sub2, "ipv4-fragmented-rx", json_integer(interface->stats.ipv4_fragmented_rx)); + json_object_set(jobj_sub2, "lcp-echo-timeout", json_integer(interface->stats.lcp_echo_timeout)); + json_object_set(jobj_sub2, "lcp-request-timeout", json_integer(interface->stats.lcp_timeout)); + json_object_set(jobj_sub2, "ipcp-request-timeout", json_integer(interface->stats.ipcp_timeout)); + json_object_set(jobj_sub2, "ip6cp-request-timeout", json_integer(interface->stats.ip6cp_timeout)); + json_object_set(jobj_sub2, "pap-timeout", json_integer(interface->stats.pap_timeout)); + json_object_set(jobj_sub2, "chap-timeout", json_integer(interface->stats.chap_timeout)); + json_object_set(jobj_sub2, "dhcp-timeout", json_integer(interface->stats.dhcp_timeout)); + json_object_set(jobj_sub2, "dhcpv6-timeout", json_integer(interface->stats.dhcpv6_timeout)); + json_object_set(jobj_sub2, "icmpv6-rs-timeout", json_integer(interface->stats.dhcpv6_timeout)); + json_object_set(jobj_sub, "protocol-stats", jobj_sub2); + json_array_append(jobj_array, jobj_sub); } } json_object_set(jobj, "access-interfaces", jobj_array); @@ -552,90 +579,133 @@ bbl_stats_json (bbl_ctx_s *ctx, bbl_stats_t * stats) { for(i=0; i < ctx->interfaces.a10nsp_if_count; i++) { interface = ctx->interfaces.a10nsp_if[i]; if (interface) { - jobj_a10nsp_if = json_object(); - json_object_set(jobj_a10nsp_if, "name", json_string(interface->name)); - json_object_set(jobj_a10nsp_if, "tx-packets", json_integer(interface->stats.packets_tx)); - json_object_set(jobj_a10nsp_if, "rx-packets", json_integer(interface->stats.packets_rx)); - json_object_set(jobj_a10nsp_if, "tx-session-packets", json_integer(interface->stats.session_ipv4_tx)); - json_object_set(jobj_a10nsp_if, "rx-session-packets", json_integer(interface->stats.session_ipv4_rx)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-loss", json_integer(interface->stats.session_ipv4_loss)); - json_object_set(jobj_a10nsp_if, "tx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_tx.avg_max)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_rx.avg_max)); - json_object_set(jobj_a10nsp_if, "tx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_tx)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_rx)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-ipv6-loss", json_integer(interface->stats.session_ipv6_loss)); - json_object_set(jobj_a10nsp_if, "tx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_tx.avg_max)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_rx.avg_max)); - json_object_set(jobj_a10nsp_if, "tx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_tx)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_rx)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-ipv6pd-loss", json_integer(interface->stats.session_ipv6pd_loss)); - json_object_set(jobj_a10nsp_if, "tx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_tx.avg_max)); - json_object_set(jobj_a10nsp_if, "rx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_rx.avg_max)); - json_object_set(jobj_a10nsp_if, "tx-multicast-packets", json_integer(interface->stats.mc_tx)); - json_array_append(jobj_array, jobj_a10nsp_if); + jobj_sub = json_object(); + json_object_set(jobj_sub, "name", json_string(interface->name)); + json_object_set(jobj_sub, "tx-packets", json_integer(interface->stats.packets_tx)); + json_object_set(jobj_sub, "rx-packets", json_integer(interface->stats.packets_rx)); + if(ctx->stats.session_traffic_flows) { + json_object_set(jobj_sub, "tx-session-packets", json_integer(interface->stats.session_ipv4_tx)); + json_object_set(jobj_sub, "rx-session-packets", json_integer(interface->stats.session_ipv4_rx)); + json_object_set(jobj_sub, "rx-session-packets-loss", json_integer(interface->stats.session_ipv4_loss)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max", json_integer(interface->stats.rate_session_ipv4_rx.avg_max)); + json_object_set(jobj_sub, "tx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_tx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6", json_integer(interface->stats.session_ipv6_rx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6-loss", json_integer(interface->stats.session_ipv6_loss)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max-ipv6", json_integer(interface->stats.rate_session_ipv6_rx.avg_max)); + json_object_set(jobj_sub, "tx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_tx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6pd", json_integer(interface->stats.session_ipv6pd_rx)); + json_object_set(jobj_sub, "rx-session-packets-ipv6pd-loss", json_integer(interface->stats.session_ipv6pd_loss)); + json_object_set(jobj_sub, "tx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_tx.avg_max)); + json_object_set(jobj_sub, "rx-session-packets-avg-pps-max-ipv6pd", json_integer(interface->stats.rate_session_ipv6pd_rx.avg_max)); + } + json_array_append(jobj_array, jobj_sub); } } json_object_set(jobj, "a10nsp-interfaces", jobj_array); if(ctx->stats.session_traffic_flows) { - jobj_straffic = json_object(); - json_object_set(jobj_straffic, "config-ipv4-pps", json_integer(ctx->config.session_traffic_ipv4_pps)); - json_object_set(jobj_straffic, "config-ipv6-pps", json_integer(ctx->config.session_traffic_ipv6_pps)); - json_object_set(jobj_straffic, "config-ipv6pd-pps", json_integer(ctx->config.session_traffic_ipv6pd_pps)); - json_object_set(jobj_straffic, "total-flows", json_integer(ctx->stats.session_traffic_flows)); - json_object_set(jobj_straffic, "verified-flows", json_integer(ctx->stats.session_traffic_flows_verified)); - json_object_set(jobj_straffic, "verified-flows-access-ipv4", json_integer(stats->sessions_access_ipv4_rx)); - json_object_set(jobj_straffic, "verified-flows-access-ipv6", json_integer(stats->sessions_access_ipv6_rx)); - json_object_set(jobj_straffic, "verified-flows-access-ipv6pd", json_integer(stats->sessions_access_ipv6pd_rx)); - json_object_set(jobj_straffic, "verified-flows-network-ipv4", json_integer(stats->sessions_network_ipv4_rx)); - json_object_set(jobj_straffic, "verified-flows-network-ipv6", json_integer(stats->sessions_network_ipv6_rx)); - json_object_set(jobj_straffic, "verified-flows-network-ipv6pd", json_integer(stats->sessions_network_ipv6pd_rx)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv4-min", json_integer(stats->min_access_ipv4_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv4-max", json_integer(stats->max_access_ipv4_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6-min", json_integer(stats->min_access_ipv6_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6-max", json_integer(stats->max_access_ipv6_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6pd-min", json_integer(stats->min_access_ipv6pd_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6pd-max", json_integer(stats->max_access_ipv6pd_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv4-min", json_integer(stats->min_network_ipv4_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv4-max", json_integer(stats->max_network_ipv4_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6-min", json_integer(stats->min_network_ipv6_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6-max", json_integer(stats->max_network_ipv6_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6pd-min", json_integer(stats->min_network_ipv6pd_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6pd-max", json_integer(stats->max_network_ipv6pd_rx_first_seq)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv4-min-seconds", json_real(stats->min_access_ipv4_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv4-max-seconds", json_real(stats->max_access_ipv4_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6-min-seconds", json_real(stats->min_access_ipv6_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6-max-seconds", json_real(stats->max_access_ipv6_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6pd-min-seconds", json_real(stats->min_access_ipv6pd_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-access-ipv6pd-max-seconds", json_real(stats->max_access_ipv6pd_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv4-min-seconds", json_real(stats->min_network_ipv4_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv4-max-seconds", json_real(stats->max_network_ipv4_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6-min-seconds", json_real(stats->min_network_ipv6_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6-max-seconds", json_real(stats->max_network_ipv6_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6pd-min-seconds", json_real(stats->min_network_ipv6pd_rx_seconds)); - json_object_set(jobj_straffic, "first-seq-rx-network-ipv6pd-max-seconds", json_real(stats->max_network_ipv6pd_rx_seconds)); - json_object_set(jobj, "session-traffic", jobj_straffic); + jobj_sub = json_object(); + json_object_set(jobj_sub, "config-ipv4-pps", json_integer(ctx->config.session_traffic_ipv4_pps)); + json_object_set(jobj_sub, "config-ipv6-pps", json_integer(ctx->config.session_traffic_ipv6_pps)); + json_object_set(jobj_sub, "config-ipv6pd-pps", json_integer(ctx->config.session_traffic_ipv6pd_pps)); + json_object_set(jobj_sub, "total-flows", json_integer(ctx->stats.session_traffic_flows)); + json_object_set(jobj_sub, "verified-flows", json_integer(ctx->stats.session_traffic_flows_verified)); + json_object_set(jobj_sub, "verified-flows-access-ipv4", json_integer(stats->sessions_access_ipv4_rx)); + json_object_set(jobj_sub, "verified-flows-access-ipv6", json_integer(stats->sessions_access_ipv6_rx)); + json_object_set(jobj_sub, "verified-flows-access-ipv6pd", json_integer(stats->sessions_access_ipv6pd_rx)); + json_object_set(jobj_sub, "verified-flows-network-ipv4", json_integer(stats->sessions_network_ipv4_rx)); + json_object_set(jobj_sub, "verified-flows-network-ipv6", json_integer(stats->sessions_network_ipv6_rx)); + json_object_set(jobj_sub, "verified-flows-network-ipv6pd", json_integer(stats->sessions_network_ipv6pd_rx)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv4-min", json_integer(stats->min_access_ipv4_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv4-max", json_integer(stats->max_access_ipv4_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6-min", json_integer(stats->min_access_ipv6_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6-max", json_integer(stats->max_access_ipv6_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6pd-min", json_integer(stats->min_access_ipv6pd_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6pd-max", json_integer(stats->max_access_ipv6pd_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv4-min", json_integer(stats->min_network_ipv4_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv4-max", json_integer(stats->max_network_ipv4_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6-min", json_integer(stats->min_network_ipv6_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6-max", json_integer(stats->max_network_ipv6_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6pd-min", json_integer(stats->min_network_ipv6pd_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6pd-max", json_integer(stats->max_network_ipv6pd_rx_first_seq)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv4-min-seconds", json_real(stats->min_access_ipv4_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv4-max-seconds", json_real(stats->max_access_ipv4_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6-min-seconds", json_real(stats->min_access_ipv6_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6-max-seconds", json_real(stats->max_access_ipv6_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6pd-min-seconds", json_real(stats->min_access_ipv6pd_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-access-ipv6pd-max-seconds", json_real(stats->max_access_ipv6pd_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv4-min-seconds", json_real(stats->min_network_ipv4_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv4-max-seconds", json_real(stats->max_network_ipv4_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6-min-seconds", json_real(stats->min_network_ipv6_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6-max-seconds", json_real(stats->max_network_ipv6_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6pd-min-seconds", json_real(stats->min_network_ipv6pd_rx_seconds)); + json_object_set(jobj_sub, "first-seq-rx-network-ipv6pd-max-seconds", json_real(stats->max_network_ipv6pd_rx_seconds)); + json_object_set(jobj, "session-traffic", jobj_sub); } + + if(ctx->stats.stream_traffic_flows) { + jobj_sub = json_object(); + json_object_set(jobj_sub, "total-flows", json_integer(ctx->stats.stream_traffic_flows)); + json_object_set(jobj_sub, "verified-flows", json_integer(ctx->stats.stream_traffic_flows_verified)); + json_object_set(jobj, "traffic-streams", jobj_sub); + } + if(ctx->config.igmp_group_count > 1) { - jobj_multicast = json_object(); - json_object_set(jobj_multicast, "config-version", json_integer(ctx->config.igmp_version)); - json_object_set(jobj_multicast, "config-start-delay", json_integer(ctx->config.igmp_start_delay)); - json_object_set(jobj_multicast, "config-group-count", json_integer(ctx->config.igmp_group_count)); - json_object_set(jobj_multicast, "config-zapping-interval", json_integer(ctx->config.igmp_zap_interval)); - json_object_set(jobj_multicast, "config-zapping-count", json_integer(ctx->config.igmp_zap_count)); - json_object_set(jobj_multicast, "config-zapping-view-duration", json_integer(ctx->config.igmp_zap_view_duration)); + jobj_sub = json_object(); + json_object_set(jobj_sub, "config-version", json_integer(ctx->config.igmp_version)); + json_object_set(jobj_sub, "config-start-delay", json_integer(ctx->config.igmp_start_delay)); + json_object_set(jobj_sub, "config-group-count", json_integer(ctx->config.igmp_group_count)); + json_object_set(jobj_sub, "config-zapping-interval", json_integer(ctx->config.igmp_zap_interval)); + json_object_set(jobj_sub, "config-zapping-count", json_integer(ctx->config.igmp_zap_count)); + json_object_set(jobj_sub, "config-zapping-view-duration", json_integer(ctx->config.igmp_zap_view_duration)); if(ctx->config.igmp_zap_interval > 0) { - json_object_set(jobj_multicast, "zapping-join-delay-ms-min", json_integer(stats->min_join_delay)); - json_object_set(jobj_multicast, "zapping-join-delay-ms-avg", json_integer(stats->avg_join_delay)); - json_object_set(jobj_multicast, "zapping-join-delay-ms-max", json_integer(stats->max_join_delay)); - json_object_set(jobj_multicast, "zapping-leave-delay-ms-min", json_integer(stats->min_leave_delay)); - json_object_set(jobj_multicast, "zapping-leave-delay-ms-avg", json_integer(stats->avg_leave_delay)); - json_object_set(jobj_multicast, "zapping-leave-delay-ms-max", json_integer(stats->max_leave_delay)); - json_object_set(jobj_multicast, "zapping-multicast-packets-overlap", json_integer(stats->mc_old_rx_after_first_new)); - json_object_set(jobj_multicast, "zapping-multicast-not-received", json_integer(stats->mc_not_received)); - json_object_set(jobj, "multicast", jobj_multicast); + json_object_set(jobj_sub, "zapping-join-delay-ms-min", json_integer(stats->min_join_delay)); + json_object_set(jobj_sub, "zapping-join-delay-ms-avg", json_integer(stats->avg_join_delay)); + json_object_set(jobj_sub, "zapping-join-delay-ms-max", json_integer(stats->max_join_delay)); + json_object_set(jobj_sub, "zapping-leave-delay-ms-min", json_integer(stats->min_leave_delay)); + json_object_set(jobj_sub, "zapping-leave-delay-ms-avg", json_integer(stats->avg_leave_delay)); + json_object_set(jobj_sub, "zapping-leave-delay-ms-max", json_integer(stats->max_leave_delay)); + json_object_set(jobj_sub, "zapping-multicast-packets-overlap", json_integer(stats->mc_old_rx_after_first_new)); + json_object_set(jobj_sub, "zapping-multicast-not-received", json_integer(stats->mc_not_received)); + json_object_set(jobj, "multicast", jobj_sub); } } + + if(ctx->config.json_report_sessions) { + jobj_array = json_array(); + for(i = 0; i < ctx->sessions; i++) { + session = ctx->session_list[i]; + if(session) { + jobj_sub = bbl_session_json(session); + if(jobj_sub) { + json_array_append(jobj_array, jobj_sub); + } + } + } + json_object_set(jobj, "sessions", jobj_array); + } + + if(ctx->config.json_report_streams) { + jobj_array = json_array(); + + itor = dict_itor_new(ctx->stream_flow_dict); + dict_itor_first(itor); + for (; dict_itor_valid(itor); dict_itor_next(itor)) { + stream = (bbl_stream*)*dict_itor_datum(itor); + if(stream) { + jobj_sub = bbl_stream_json(stream); + if(jobj_sub) { + json_array_append(jobj_array, jobj_sub); + } + } + + } + json_object_set(jobj, "streams", jobj_array); + } + + json_object_set(root, "report", jobj); if(json_dump_file(root, ctx->config.json_report_filename, JSON_REAL_PRECISION(4)) != 0) { LOG(ERROR, "Failed to create JSON report file %s\n", ctx->config.json_report_filename); @@ -644,7 +714,7 @@ bbl_stats_json (bbl_ctx_s *ctx, bbl_stats_t * stats) { } /* - * Compute a pps rate using a moving average of samples. + * Compute a PPS rate using a moving average of samples. */ void bbl_compute_avg_rate (bbl_rate_s *rate, uint64_t current_value) diff --git a/src/bbl_stream.c b/src/bbl_stream.c index ab2502bf..a0327d19 100644 --- a/src/bbl_stream.c +++ b/src/bbl_stream.c @@ -15,10 +15,17 @@ #include extern volatile bool g_teardown; +extern bool g_init_phase; +extern bool g_traffic; -bool +static bool bbl_stream_can_send(bbl_stream *stream) { bbl_session_s *session = stream->session; + + if(g_init_phase) { + return false; + } + if(stream->config->stream_group_id == 0) { /* RAW stream */ return true; @@ -774,7 +781,7 @@ bbl_stream_tx_thread (void *thread_data) { } } - if(stream->session && !stream->session->stream_traffic) { + if(!g_traffic || (stream->session && !stream->session->stream_traffic)) { /* Close send window */ stream->send_window_packets = 0; sleep.tv_nsec = 10 * MSEC; @@ -885,7 +892,7 @@ bbl_stream_tx_job (timer_s *timer) { } } - if(session && !session->stream_traffic) { + if(!g_traffic || (session && !session->stream_traffic)) { /* Close send window */ stream->send_window_packets = 0; return; @@ -1028,6 +1035,7 @@ bbl_stream_add(bbl_ctx_s *ctx, bbl_access_config_s *access_config, bbl_session_s timer_add_periodic(&ctx->timer_root, &stream->timer, config->name, timer_sec, timer_nsec, stream, &bbl_stream_tx_job); } timer_add_periodic(&ctx->timer_root, &stream->timer_rate, "Rate Computation", 1, 0, stream, &bbl_stream_rate_job); + ctx->stats.stream_traffic_flows++; LOG(DEBUG, "Traffic stream %s added in upstream with %u PPS (timer: %lu sec %lu nsec)\n", config->name, config->pps, timer_sec, timer_nsec); } if(config->direction & STREAM_DIRECTION_DOWN) { @@ -1062,6 +1070,7 @@ bbl_stream_add(bbl_ctx_s *ctx, bbl_access_config_s *access_config, bbl_session_s timer_add_periodic(&ctx->timer_root, &stream->timer, config->name, timer_sec, timer_nsec, stream, &bbl_stream_tx_job); } timer_add_periodic(&ctx->timer_root, &stream->timer_rate, "Rate Computation", 1, 0, stream, &bbl_stream_rate_job); + ctx->stats.stream_traffic_flows++; LOG(DEBUG, "Traffic stream %s added in downstream with %u PPS (timer %lu sec %lu nsec)\n", config->name, config->pps, timer_sec, timer_nsec); } timer_smear_bucket(&ctx->timer_root, timer_sec, timer_nsec); @@ -1121,6 +1130,7 @@ bbl_stream_raw_add(bbl_ctx_s *ctx) { timer_add_periodic(&ctx->timer_root, &stream->timer, config->name, timer_sec, timer_nsec, stream, &bbl_stream_tx_job); } timer_add_periodic(&ctx->timer_root, &stream->timer_rate, "Rate Computation", 1, 0, stream, &bbl_stream_rate_job); + ctx->stats.stream_traffic_flows++; LOG(DEBUG, "RAW traffic stream %s added in downstream with %u PPS (timer %lu sec %lu nsec)\n", config->name, config->pps, timer_sec, timer_nsec); } timer_smear_bucket(&ctx->timer_root, timer_sec, timer_nsec); @@ -1129,4 +1139,41 @@ bbl_stream_raw_add(bbl_ctx_s *ctx) { } return true; +} + +json_t * +bbl_stream_json(bbl_stream *stream) +{ + json_t *root = NULL; + + if(!stream) { + return NULL; + } + + root = json_pack("{ss* ss si si si si si si si si si si si si si si si si si si sf sf sf}", + "name", stream->config->name, + "direction", stream->direction == STREAM_DIRECTION_UP ? "upstream" : "downstream", + "flow-id", stream->flow_id, + "rx-first-seq", stream->rx_first_seq, + "rx-last-seq", stream->rx_last_seq, + "rx-tos-tc", stream->rx_priority, + "rx-outer-vlan-pbit", stream->rx_outer_vlan_pbit, + "rx-inner-vlan-pbit", stream->rx_inner_vlan_pbit, + "rx-len", stream->rx_len, + "tx-len", stream->tx_len, + "rx-packets", stream->packets_rx, + "tx-packets", stream->packets_tx, + "rx-loss", stream->loss, + "rx-delay-nsec-min", stream->min_delay_ns, + "rx-delay-nsec-max", stream->max_delay_ns, + "rx-pps", stream->rate_packets_rx.avg, + "tx-pps", stream->rate_packets_tx.avg, + "tx-bps-l2", stream->rate_packets_tx.avg * stream->tx_len * 8, + "rx-bps-l2", stream->rate_packets_rx.avg * stream->rx_len * 8, + "rx-bps-l3", stream->rate_packets_rx.avg * stream->config->length * 8, + "tx-mbps-l2", (double)(stream->rate_packets_tx.avg * stream->tx_len * 8) / 1000000.0, + "rx-mbps-l2", (double)(stream->rate_packets_rx.avg * stream->rx_len * 8) / 1000000.0, + "rx-mbps-l3", (double)(stream->rate_packets_rx.avg * stream->config->length * 8) / 1000000.0); + + return root; } \ No newline at end of file diff --git a/src/bbl_stream.h b/src/bbl_stream.h index 17bcacea..38eaf0bf 100644 --- a/src/bbl_stream.h +++ b/src/bbl_stream.h @@ -99,4 +99,7 @@ bbl_stream_raw_add(bbl_ctx_s *ctx); void bbl_stream_tx_job (timer_s *timer); +json_t * +bbl_stream_json(bbl_stream *stream); + #endif diff --git a/src/bbl_tx.c b/src/bbl_tx.c index e3e44329..fcc64630 100644 --- a/src/bbl_tx.c +++ b/src/bbl_tx.c @@ -1610,7 +1610,7 @@ void bbl_network_arp_timeout (timer_s *timer) { bbl_interface_s *interface = timer->data; - interface->send_requests |= BBL_SEND_ARP_REQUEST; + interface->send_requests |= BBL_IF_SEND_ARP_REQUEST; } void