mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
647 lines
30 KiB
C
647 lines
30 KiB
C
/*
|
|
* BNG Blaster (BBL) - Interactive Mode
|
|
*
|
|
* Hannes Gredler, July 2020
|
|
* Christian Giese, October 2020
|
|
*
|
|
* Copyright (C) 2020-2022, RtBrick, Inc.
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "bbl.h"
|
|
#include "bbl_stats.h"
|
|
#include "bbl_session.h"
|
|
#include "bbl_stream.h"
|
|
|
|
#define PROGRESS_BAR_SIZE 60
|
|
#define STATS_WIN_SIZE 90
|
|
#define STRING_SP_SIZE 64
|
|
|
|
#define VISIBLE(_expression) \
|
|
visible = false; \
|
|
if(_expression) { \
|
|
if(pos > stats_win_postion) { \
|
|
visible = true; \
|
|
} \
|
|
pos++; \
|
|
} \
|
|
if(visible)
|
|
|
|
typedef enum {
|
|
UI_VIEW_DEFAULT = 0,
|
|
UI_VIEW_ACCESS_IF_STATS,
|
|
UI_VIEW_SESSION,
|
|
UI_VIEW_MAX,
|
|
} __attribute__ ((__packed__)) bbl_ui_view;
|
|
|
|
/* ncurses */
|
|
WINDOW *stats_win = NULL;
|
|
WINDOW *log_win = NULL;
|
|
|
|
int stats_win_postion;
|
|
|
|
extern volatile bool g_teardown;
|
|
extern volatile bool g_teardown_request;
|
|
extern bool g_banner;
|
|
extern bool g_interactive;
|
|
|
|
/* This global variable is used to switch between access interfaces. */
|
|
uint8_t g_access_if_selected = 0;
|
|
uint8_t g_network_if_selected = 0;
|
|
uint8_t g_a10nsp_if_selected = 0;
|
|
/* This global variable is used to switch between views. */
|
|
bbl_ui_view g_view_selected = 0;
|
|
/* This global variable is used to switch vetween sessions in some views. */
|
|
uint32_t g_session_selected = 1;
|
|
|
|
extern const char banner[];
|
|
|
|
void
|
|
bbl_init_stats_win(bbl_ctx_s *ctx)
|
|
{
|
|
wclear(stats_win);
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, "F1: Select View F7/F8: Start/Stop Traffic F9: Terminate Sessions\n");
|
|
if(g_view_selected == UI_VIEW_SESSION) {
|
|
wprintw(stats_win, "Left/Right: Select Session\n");
|
|
} else {
|
|
if(ctx->interfaces.network_if_count) {
|
|
wprintw(stats_win, "F2: Network Interface ");
|
|
}
|
|
if(ctx->interfaces.a10nsp_if_count) {
|
|
wprintw(stats_win, "F3: Select A10NSP Interface ");
|
|
}
|
|
if(ctx->interfaces.access_if_count) {
|
|
wprintw(stats_win, "Left/Right: Access Interface");
|
|
}
|
|
wprintw(stats_win, "\n");
|
|
}
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
if(g_banner) {
|
|
wprintw(stats_win, "%s", banner);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Interactive keyboard reader
|
|
*/
|
|
void
|
|
bbl_read_key_job (timer_s *timer)
|
|
{
|
|
bbl_ctx_s *ctx = timer->data;
|
|
int ch;
|
|
|
|
ch = getch();
|
|
switch (ch) {
|
|
case KEY_F(1):
|
|
stats_win_postion = 0;
|
|
g_view_selected++;
|
|
if(g_view_selected >= UI_VIEW_MAX) {
|
|
g_view_selected = UI_VIEW_DEFAULT;
|
|
}
|
|
/* Skip access interface and session views
|
|
* if there is no access interface. */
|
|
if(ctx->interfaces.access_if_count == 0) {
|
|
switch (g_view_selected) {
|
|
case UI_VIEW_ACCESS_IF_STATS:
|
|
case UI_VIEW_SESSION:
|
|
g_view_selected = UI_VIEW_DEFAULT;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
bbl_init_stats_win(ctx);
|
|
break;
|
|
case KEY_F(2):
|
|
if(ctx->interfaces.network_if_count > 1) {
|
|
g_network_if_selected++;
|
|
if(g_network_if_selected >= ctx->interfaces.network_if_count) {
|
|
g_network_if_selected = 0;
|
|
}
|
|
bbl_init_stats_win(ctx);
|
|
}
|
|
break;
|
|
case KEY_F(3):
|
|
if(ctx->interfaces.a10nsp_if_count > 1) {
|
|
g_a10nsp_if_selected++;
|
|
if(g_a10nsp_if_selected >= ctx->interfaces.a10nsp_if_count) {
|
|
g_a10nsp_if_selected = 0;
|
|
}
|
|
bbl_init_stats_win(ctx);
|
|
}
|
|
break;
|
|
case KEY_LEFT:
|
|
if(g_view_selected == UI_VIEW_SESSION) {
|
|
if(g_session_selected > 1) {
|
|
g_session_selected--;
|
|
} else {
|
|
g_session_selected = ctx->sessions;
|
|
}
|
|
} else {
|
|
if(g_access_if_selected == 0) {
|
|
g_access_if_selected = ctx->interfaces.access_if_count;
|
|
}
|
|
g_access_if_selected--;
|
|
}
|
|
bbl_init_stats_win(ctx);
|
|
break;
|
|
case KEY_RIGHT:
|
|
if(g_view_selected == UI_VIEW_SESSION) {
|
|
g_session_selected++;
|
|
if(g_session_selected > ctx->sessions) {
|
|
g_session_selected = 1;
|
|
}
|
|
} else {
|
|
g_access_if_selected++;
|
|
if(g_access_if_selected >= ctx->interfaces.access_if_count) {
|
|
g_access_if_selected = 0;
|
|
}
|
|
}
|
|
bbl_init_stats_win(ctx);
|
|
break;
|
|
case KEY_F(7):
|
|
enable_disable_traffic(ctx, true);
|
|
LOG_NOARG(INFO, "Start traffic\n");
|
|
break;
|
|
case KEY_F(8):
|
|
enable_disable_traffic(ctx, false);
|
|
LOG_NOARG(INFO, "Stop traffic\n");
|
|
break;
|
|
case KEY_F(9):
|
|
g_teardown = true;
|
|
g_teardown_request = true;
|
|
LOG_NOARG(INFO, "Teardown request\n");
|
|
break;
|
|
case KEY_DOWN:
|
|
if(g_view_selected == UI_VIEW_DEFAULT) {
|
|
if(stats_win_postion < 6) {
|
|
stats_win_postion++;
|
|
}
|
|
bbl_init_stats_win(ctx);
|
|
}
|
|
break;
|
|
case KEY_UP:
|
|
if(stats_win_postion) stats_win_postion--;
|
|
bbl_init_stats_win(ctx);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Format a progress bar.
|
|
*/
|
|
static char *
|
|
bbl_format_progress (uint32_t complete, uint32_t current)
|
|
{
|
|
static char buf[PROGRESS_BAR_SIZE+1];
|
|
float percentage;
|
|
uint16_t idx;
|
|
|
|
if (!complete || !current) {
|
|
memset(buf, ' ', sizeof(buf));
|
|
goto EXIT;
|
|
}
|
|
|
|
percentage = (float)current / (float)complete;
|
|
for (idx = 0; idx < sizeof(buf); idx++) {
|
|
if (idx <= (percentage * PROGRESS_BAR_SIZE)) {
|
|
buf[idx] = '#';
|
|
continue;
|
|
}
|
|
buf[idx] = ' ';
|
|
}
|
|
|
|
EXIT:
|
|
buf[PROGRESS_BAR_SIZE] = 0;
|
|
return buf;
|
|
}
|
|
|
|
/*
|
|
* Display meaningful stats in a curses window.
|
|
*/
|
|
void
|
|
bbl_stats_job (timer_s *timer)
|
|
{
|
|
bbl_ctx_s *ctx = timer->data;
|
|
struct bbl_interface_ *access_if;
|
|
struct bbl_interface_ *network_if;
|
|
struct bbl_interface_ *a10nsp_if;
|
|
|
|
char strsp[STRING_SP_SIZE];
|
|
|
|
bbl_session_s *session;
|
|
int i;
|
|
|
|
int pos = 1; /* position */
|
|
bool visible = false;
|
|
|
|
access_if = ctx->interfaces.access_if[g_access_if_selected];
|
|
network_if = ctx->interfaces.network_if[g_network_if_selected];
|
|
a10nsp_if = ctx->interfaces.a10nsp_if[g_a10nsp_if_selected];
|
|
|
|
if(g_banner) {
|
|
wmove(stats_win, 14, 0);
|
|
} else {
|
|
wmove(stats_win, 2, 0);
|
|
}
|
|
|
|
if(g_view_selected == UI_VIEW_DEFAULT) {
|
|
VISIBLE((ctx->sessions)) {
|
|
wprintw(stats_win, "\nSessions %10lu (%lu PPPoE / %lu IPoE)\n", ctx->sessions, ctx->sessions_pppoe, ctx->sessions_ipoe);
|
|
|
|
/* Progress bar established sessions */
|
|
wprintw(stats_win, " Established %10lu [", ctx->sessions_established);
|
|
if(ctx->sessions == ctx->sessions_established) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->sessions, ctx->sessions_established));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
} else {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->sessions, ctx->sessions_established));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
}
|
|
wprintw(stats_win, "]\n");
|
|
|
|
/* Progress bar outstanding sessions */
|
|
wprintw(stats_win, " Outstanding %10lu [", ctx->sessions_outstanding);
|
|
wattron(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->config.sessions_max_outstanding, ctx->sessions_outstanding));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
wprintw(stats_win, "]\n");
|
|
|
|
/* Progress bar terminated sessions */
|
|
wprintw(stats_win, " Terminated %10lu [", ctx->sessions_terminated);
|
|
wattron(stats_win, COLOR_PAIR(COLOR_RED));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->sessions, ctx->sessions_terminated));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_RED));
|
|
wprintw(stats_win, "]\n");
|
|
|
|
/* DHCPv4 */
|
|
if(ctx->dhcp_requested || ctx->dhcp_established_max) {
|
|
|
|
snprintf(strsp, STRING_SP_SIZE, "%u/%u", ctx->dhcp_established, ctx->dhcp_requested);
|
|
wprintw(stats_win, " DHCPv4 %15s [", strsp);
|
|
if(ctx->dhcp_requested == ctx->dhcp_established) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->dhcp_requested, ctx->dhcp_established));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
} else {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->dhcp_requested, ctx->dhcp_established));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
}
|
|
wprintw(stats_win, "]\n");
|
|
}
|
|
/* DHCPv6 */
|
|
if(ctx->dhcpv6_requested || ctx->dhcpv6_established_max) {
|
|
snprintf(strsp, STRING_SP_SIZE, "%u/%u", ctx->dhcpv6_established, ctx->dhcpv6_requested);
|
|
wprintw(stats_win, " DHCPv6 %15s [", strsp);
|
|
if(ctx->dhcpv6_requested == ctx->dhcpv6_established) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->dhcpv6_requested, ctx->dhcpv6_established));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
} else {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->dhcpv6_requested, ctx->dhcpv6_established));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
}
|
|
wprintw(stats_win, "]\n");
|
|
}
|
|
/* Session stats */
|
|
wprintw(stats_win, " Setup Time %10lu ms\n", ctx->stats.setup_time);
|
|
wprintw(stats_win, " Setup Rate %10.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);
|
|
wprintw(stats_win, " Flapped %10lu\n", ctx->sessions_flapped);
|
|
}
|
|
|
|
if(network_if) {
|
|
VISIBLE((dict_count(ctx->li_flow_dict))) {
|
|
wprintw(stats_win, "\nLI Statistics\n");
|
|
wprintw(stats_win, " Flows %10lu\n", dict_count(ctx->li_flow_dict));
|
|
wprintw(stats_win, " Rx Packets %10lu (%7lu PPS)\n",
|
|
network_if->stats.li_rx, network_if->stats.rate_li_rx.avg);
|
|
}
|
|
VISIBLE((ctx->config.l2tp_server)) {
|
|
wprintw(stats_win, "\nL2TP LNS Statistics\n");
|
|
wprintw(stats_win, " Tunnels %10lu\n", ctx->l2tp_tunnels);
|
|
wprintw(stats_win, " Established %10lu\n", ctx->l2tp_tunnels_established);
|
|
wprintw(stats_win, " Sessions %10lu\n", ctx->l2tp_sessions);
|
|
wprintw(stats_win, " Packets:\n");
|
|
wprintw(stats_win, " Tx Control %10lu Retries: %lu\n",
|
|
network_if->stats.l2tp_control_tx, network_if->stats.l2tp_control_retry);
|
|
wprintw(stats_win, " Rx Control %10lu Duplicate: %lu Out-of-Order: %lu\n",
|
|
network_if->stats.l2tp_control_rx,
|
|
network_if->stats.l2tp_control_rx_dup,
|
|
network_if->stats.l2tp_control_rx_ooo);
|
|
wprintw(stats_win, " Tx Data %10lu (%7lu PPS)\n",
|
|
network_if->stats.l2tp_data_tx, network_if->stats.rate_l2tp_data_tx.avg);
|
|
wprintw(stats_win, " Rx Data %10lu (%7lu PPS)\n",
|
|
network_if->stats.l2tp_data_rx, network_if->stats.rate_l2tp_data_rx.avg);
|
|
}
|
|
}
|
|
|
|
VISIBLE((ctx->stats.session_traffic_flows || ctx->stats.stream_traffic_flows)) {
|
|
wprintw(stats_win, "\nTraffic Flows Verified\n");
|
|
if(ctx->stats.session_traffic_flows) {
|
|
snprintf(strsp, STRING_SP_SIZE, "%u/%u", ctx->stats.session_traffic_flows_verified, ctx->stats.session_traffic_flows);
|
|
wprintw(stats_win, " Session %14s [", strsp);
|
|
if(ctx->stats.session_traffic_flows == ctx->stats.session_traffic_flows_verified) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, "%s", bbl_format_progress(ctx->stats.session_traffic_flows, ctx->stats.session_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.session_traffic_flows, ctx->stats.session_traffic_flows_verified));
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_BLACK));
|
|
}
|
|
wprintw(stats_win, "]\n");
|
|
}
|
|
if(ctx->stats.stream_traffic_flows) {
|
|
snprintf(strsp, STRING_SP_SIZE, "%u/%u", ctx->stats.stream_traffic_flows_verified, ctx->stats.stream_traffic_flows);
|
|
wprintw(stats_win, " Stream %15s [", strsp);
|
|
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");
|
|
}
|
|
}
|
|
|
|
VISIBLE(network_if) {
|
|
wprintw(stats_win, "\nNetwork Interface (");
|
|
for(i = 0; i < ctx->interfaces.network_if_count; i++) {
|
|
if(i == g_network_if_selected) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, " %s", ctx->interfaces.network_if[i]->name);
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
} else {
|
|
wprintw(stats_win, " %s", ctx->interfaces.network_if[i]->name);
|
|
}
|
|
}
|
|
wprintw(stats_win, " )\n Tx Packets %10lu |%7lu PPS %10lu Kbps\n",
|
|
network_if->stats.packets_tx, network_if->stats.rate_packets_tx.avg,
|
|
network_if->stats.rate_bytes_tx.avg * 8 / 1000);
|
|
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);
|
|
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);
|
|
}
|
|
VISIBLE(a10nsp_if) {
|
|
wprintw(stats_win, "\nA10NSP Interface (");
|
|
for(i = 0; i < ctx->interfaces.a10nsp_if_count; i++) {
|
|
if(i == g_a10nsp_if_selected) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, " %s", ctx->interfaces.a10nsp_if[i]->name);
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
} else {
|
|
wprintw(stats_win, " %s", ctx->interfaces.a10nsp_if[i]->name);
|
|
}
|
|
}
|
|
wprintw(stats_win, " )\n Tx Packets %10lu |%7lu PPS %10lu Kbps\n",
|
|
a10nsp_if->stats.packets_tx, a10nsp_if->stats.rate_packets_tx.avg,
|
|
a10nsp_if->stats.rate_bytes_tx.avg * 8 / 1000);
|
|
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);
|
|
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);
|
|
}
|
|
}
|
|
VISIBLE(access_if) {
|
|
wprintw(stats_win, "\nAccess Interface (");
|
|
for(i = 0; i < ctx->interfaces.access_if_count; i++) {
|
|
if(i == g_access_if_selected) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, " %s", ctx->interfaces.access_if[i]->name);
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
} else {
|
|
wprintw(stats_win, " %s", ctx->interfaces.access_if[i]->name);
|
|
}
|
|
}
|
|
wprintw(stats_win, " )\n Tx Packets %10lu |%7lu PPS %10lu Kbps\n",
|
|
access_if->stats.packets_tx, access_if->stats.rate_packets_tx.avg,
|
|
access_if->stats.rate_bytes_tx.avg * 8 / 1000);
|
|
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);
|
|
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);
|
|
}
|
|
} else if(g_view_selected == UI_VIEW_ACCESS_IF_STATS) {
|
|
if(access_if) {
|
|
wprintw(stats_win, "\nAccess Interface Protocol Stats (");
|
|
for(i = 0; i < ctx->interfaces.access_if_count; i++) {
|
|
if(i == g_access_if_selected) {
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, " %s", ctx->interfaces.access_if[i]->name);
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
} else {
|
|
wprintw(stats_win, " %s", ctx->interfaces.access_if[i]->name);
|
|
}
|
|
}
|
|
wprintw(stats_win, " )\n");
|
|
wprintw(stats_win, "\nPacket Stats\n");
|
|
wprintw(stats_win, " ARP TX: %10u RX: %10u\n", access_if->stats.arp_tx, access_if->stats.arp_rx);
|
|
wprintw(stats_win, " PADI TX: %10u RX: %10u\n", access_if->stats.padi_tx, 0);
|
|
wprintw(stats_win, " PADO TX: %10u RX: %10u\n", 0, access_if->stats.pado_rx);
|
|
wprintw(stats_win, " PADR TX: %10u RX: %10u\n", access_if->stats.padr_tx, 0);
|
|
wprintw(stats_win, " PADS TX: %10u RX: %10u\n", 0, access_if->stats.pads_rx);
|
|
wprintw(stats_win, " PADT TX: %10u RX: %10u\n", access_if->stats.padt_tx, access_if->stats.padt_rx);
|
|
wprintw(stats_win, " LCP TX: %10u RX: %10u\n", access_if->stats.lcp_tx, access_if->stats.lcp_rx);
|
|
wprintw(stats_win, " PAP TX: %10u RX: %10u\n", access_if->stats.pap_tx, access_if->stats.pap_rx);
|
|
wprintw(stats_win, " CHAP TX: %10u RX: %10u\n", access_if->stats.chap_tx, access_if->stats.chap_rx);
|
|
wprintw(stats_win, " IPCP TX: %10u RX: %10u\n", access_if->stats.ipcp_tx, access_if->stats.ipcp_rx);
|
|
wprintw(stats_win, " IP6CP TX: %10u RX: %10u\n", access_if->stats.ip6cp_tx, access_if->stats.ip6cp_rx);
|
|
wprintw(stats_win, " IGMP TX: %10u RX: %10u\n", access_if->stats.igmp_tx, access_if->stats.igmp_rx);
|
|
wprintw(stats_win, " ICMP TX: %10u RX: %10u\n", access_if->stats.icmp_tx, access_if->stats.icmp_rx);
|
|
wprintw(stats_win, " DHCP TX: %10u RX: %10u\n", access_if->stats.dhcp_tx, access_if->stats.dhcp_rx);
|
|
wprintw(stats_win, " DHCPv6 TX: %10u RX: %10u\n", access_if->stats.dhcpv6_tx, access_if->stats.dhcpv6_rx);
|
|
wprintw(stats_win, " ICMPv6 TX: %10u RX: %10u\n", access_if->stats.icmpv6_tx, access_if->stats.icmpv6_rx);
|
|
|
|
wprintw(stats_win, "\nTimeout Stats\n");
|
|
wprintw(stats_win, " LCP Echo Request: %10u\n", access_if->stats.lcp_echo_timeout);
|
|
wprintw(stats_win, " LCP Request: %10u\n", access_if->stats.lcp_timeout);
|
|
wprintw(stats_win, " IPCP Request: %10u\n", access_if->stats.ipcp_timeout);
|
|
wprintw(stats_win, " IP6CP Request: %10u\n", access_if->stats.ip6cp_timeout);
|
|
wprintw(stats_win, " PAP: %10u\n", access_if->stats.pap_timeout);
|
|
wprintw(stats_win, " CHAP: %10u\n", access_if->stats.chap_timeout);
|
|
wprintw(stats_win, " DHCP Request: %10u\n", access_if->stats.dhcp_timeout);
|
|
wprintw(stats_win, " DHCPv6 Request: %10u\n", access_if->stats.dhcpv6_timeout);
|
|
wprintw(stats_win, " ICMPv6 RS: %10u\n", access_if->stats.icmpv6_rs_timeout);
|
|
} else {
|
|
wprintw(stats_win, "\nAccess Interface Protocol Stats");
|
|
}
|
|
|
|
} else if(g_view_selected == UI_VIEW_SESSION) {
|
|
wprintw(stats_win, "\nSession and Streams ( Session-Id: ", g_session_selected);
|
|
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, "%u", g_session_selected);
|
|
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
|
|
wprintw(stats_win, " )\n", g_session_selected);
|
|
session = bbl_session_get(ctx, g_session_selected);
|
|
if(session) {
|
|
wprintw(stats_win, "\n State: %s \n", session_state_string(session->session_state));
|
|
if(session->username) {
|
|
wprintw(stats_win, " Username: %s \n", session->username);
|
|
}
|
|
if(session->agent_remote_id) {
|
|
wprintw(stats_win, " ARI: %s \n", session->agent_remote_id);
|
|
}
|
|
if(session->agent_remote_id) {
|
|
wprintw(stats_win, " ACI: %s \n", session->agent_circuit_id);
|
|
}
|
|
if(session->connections_status_message || session->reply_message) {
|
|
wprintw(stats_win, "\n");
|
|
if(session->reply_message) {
|
|
wprintw(stats_win, " Reply-Message: %s \n", session->reply_message);
|
|
}
|
|
if(session->connections_status_message) {
|
|
wprintw(stats_win, " Connection-Status-Message: %s \n", session->connections_status_message);
|
|
}
|
|
}
|
|
wprintw(stats_win, "\n Access Client Interface\n");
|
|
wprintw(stats_win, " Tx Packets %10lu | %7lu PPS | %10lu Kbps\n",
|
|
session->stats.packets_tx, session->stats.rate_packets_tx.avg,
|
|
session->stats.rate_bytes_tx.avg * 8 / 1000);
|
|
wprintw(stats_win, " Rx Packets %10lu | %7lu PPS | %10lu Kbps\n",
|
|
session->stats.packets_rx, session->stats.rate_packets_rx.avg,
|
|
session->stats.rate_bytes_rx.avg * 8 / 1000);
|
|
|
|
if(session->stream) {
|
|
wprintw(stats_win, "\n Stream | Direction | Tx PPS | Tx Kbps | Rx PPS | Rx Kbps | Loss\n");
|
|
wprintw(stats_win, " -------------------------------------------------------------------------------------\n");
|
|
|
|
uint64_t tx_kbps;
|
|
uint64_t rx_kbps;
|
|
uint64_t stream_sum_up_tx_pps = 0;
|
|
uint64_t stream_sum_up_tx_kbps = 0;
|
|
uint64_t stream_sum_up_rx_pps = 0;
|
|
uint64_t stream_sum_up_rx_kbps = 0;
|
|
uint64_t stream_sum_up_loss = 0;
|
|
uint64_t stream_sum_down_tx_pps = 0;
|
|
uint64_t stream_sum_down_rx_pps = 0;
|
|
uint64_t stream_sum_down_tx_kbps = 0;
|
|
uint64_t stream_sum_down_rx_kbps = 0;
|
|
uint64_t stream_sum_down_loss = 0;
|
|
|
|
bbl_stream *stream = session->stream;
|
|
while(stream) {
|
|
tx_kbps = stream->rate_packets_tx.avg * stream->tx_len * 8 / 1000;
|
|
rx_kbps = stream->rate_packets_rx.avg * stream->rx_len * 8 / 1000;
|
|
wprintw(stats_win, " %-16.16s | %-9.9s | %7lu | %10lu | %7lu | %10lu | %8lu\n", stream->config->name,
|
|
stream->direction == STREAM_DIRECTION_UP ? "up" : "down",
|
|
stream->rate_packets_tx.avg, tx_kbps, stream->rate_packets_rx.avg, rx_kbps, stream->loss);
|
|
|
|
if(stream->direction == STREAM_DIRECTION_UP) {
|
|
stream_sum_up_tx_pps += stream->rate_packets_tx.avg;
|
|
stream_sum_up_tx_kbps += tx_kbps;
|
|
stream_sum_up_rx_pps += stream->rate_packets_rx.avg;
|
|
stream_sum_up_rx_kbps += rx_kbps;
|
|
stream_sum_up_loss += stream->loss;
|
|
} else {
|
|
stream_sum_down_tx_pps += stream->rate_packets_tx.avg;
|
|
stream_sum_down_tx_kbps += tx_kbps;
|
|
stream_sum_down_rx_pps += stream->rate_packets_rx.avg;
|
|
stream_sum_down_rx_kbps += rx_kbps;
|
|
stream_sum_down_loss += stream->loss;
|
|
}
|
|
stream = stream->next;
|
|
}
|
|
wprintw(stats_win, " =====================================================================================\n");
|
|
wprintw(stats_win, " SUM | up | %7lu | %10lu | %7lu | %10lu | %8lu\n",
|
|
stream_sum_up_tx_pps, stream_sum_up_tx_kbps, stream_sum_up_rx_pps, stream_sum_up_rx_kbps, stream_sum_up_loss);
|
|
wprintw(stats_win, " | down | %7lu | %10lu | %7lu | %10lu | %8lu\n",
|
|
stream_sum_down_tx_pps, stream_sum_down_tx_kbps, stream_sum_down_rx_pps, stream_sum_down_rx_kbps, stream_sum_down_loss);
|
|
}
|
|
}
|
|
}
|
|
wrefresh(stats_win);
|
|
}
|
|
|
|
/*
|
|
* Curses init.
|
|
*/
|
|
void
|
|
bbl_init_curses (bbl_ctx_s *ctx)
|
|
{
|
|
initscr();
|
|
cbreak();
|
|
noecho();
|
|
keypad(stdscr, TRUE);
|
|
|
|
/* Stats window */
|
|
stats_win = newwin(LINES, STATS_WIN_SIZE, 0, 0);
|
|
stats_win_postion = 0;
|
|
|
|
/* Log window */
|
|
log_win = newwin(LINES, COLS-STATS_WIN_SIZE, 0, STATS_WIN_SIZE);
|
|
scrollok(log_win, TRUE);
|
|
|
|
start_color();
|
|
init_pair(1, COLOR_RED, COLOR_BLACK);
|
|
init_pair(2, COLOR_GREEN, COLOR_BLACK);
|
|
init_pair(3, COLOR_BLACK, COLOR_CYAN);
|
|
init_pair(4, COLOR_BLACK, COLOR_BLUE);
|
|
|
|
curs_set(0); /* cursor off */
|
|
refresh();
|
|
|
|
timeout(0);
|
|
bbl_init_stats_win(ctx);
|
|
wrefresh(stats_win);
|
|
|
|
timer_add_periodic(&ctx->timer_root, &ctx->stats_timer, "Statistics Timer",
|
|
0, 100 * MSEC, ctx, &bbl_stats_job);
|
|
timer_add_periodic(&ctx->timer_root, &ctx->keyboard_timer, "Keyboard Reader",
|
|
0, 100 * MSEC, ctx, &bbl_read_key_job);
|
|
|
|
g_interactive = true;
|
|
} |