From 60648a858b83b63e8dbdd1c45bb901d1206ae444 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Thu, 19 Jan 2017 01:09:03 +0200 Subject: flowtop: Add tab control to switch between tables Add ui_tab API to create ui tab control to switch between different ui tables which may contain different aggregated info per unique pid/port/proto/dst/src. Meanwhile there is only 1 ui tab entry for flows table. Added some missing cds_list_{next,prev,last}_entry functions into urcu-list-compat.h header. Signed-off-by: Vadim Kochan Signed-off-by: Tobias Klauser --- flowtop.c | 26 +++++++++++++-- ui.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- ui.h | 34 +++++++++++++++++-- urcu-list-compat.h | 21 ++++++++++++ 4 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 urcu-list-compat.h diff --git a/flowtop.c b/flowtop.c index b2d6546..78ac253 100644 --- a/flowtop.c +++ b/flowtop.c @@ -133,6 +133,8 @@ static struct flow_list flow_list; static struct sysctl_params_ctx sysctl = { -1, -1 }; static unsigned int cols, rows; +static WINDOW *screen; +static int skip_lines; static unsigned int interval = 1; static bool show_src = false; @@ -156,6 +158,10 @@ enum tbl_flow_col { static struct ui_table flows_tbl; +enum tab_entry { + TAB_FLOWS, +}; + static const char *short_options = "vhTUsDIS46ut:nGb"; static const struct option long_options[] = { {"ipv4", no_argument, NULL, '4'}, @@ -1197,11 +1203,15 @@ static void flows_table_init(struct ui_table *tbl) ui_table_header_color_set(&flows_tbl, COLOR(BLACK, GREEN)); } +static void tab_main_on_open(struct ui_tab *tab, enum ui_tab_event_t evt, uint32_t id) +{ + draw_flows(screen, &flow_list, skip_lines); +} + static void presenter(void) { bool show_help = false; - int skip_lines = 0; - WINDOW *screen; + struct ui_tab *tab_main; lookup_init(LT_PORTS_TCP); lookup_init(LT_PORTS_UDP); @@ -1219,6 +1229,12 @@ static void presenter(void) flows_table_init(&flows_tbl); + tab_main = ui_tab_create(); + ui_tab_event_cb_set(tab_main, tab_main_on_open); + ui_tab_pos_set(tab_main, 2, 0); + ui_tab_active_color_set(tab_main, COLOR(BLACK, GREEN)); + ui_tab_entry_add(tab_main, TAB_FLOWS, "Flows"); + rcu_register_thread(); while (!sigint) { int ch; @@ -1278,6 +1294,9 @@ static void presenter(void) show_option_toggle(ch); do_reload_flows = true; break; + case '\t': + ui_tab_event_send(tab_main, UI_EVT_SELECT_NEXT); + break; default: fflush(stdin); break; @@ -1288,13 +1307,14 @@ static void presenter(void) if (show_help) draw_help(); else - draw_flows(screen, &flow_list, skip_lines); + ui_tab_show(tab_main); draw_footer(); } rcu_unregister_thread(); ui_table_uninit(&flows_tbl); + ui_tab_destroy(tab_main); screen_end(); lookup_cleanup(LT_PORTS_UDP); diff --git a/ui.c b/ui.c index 78d1560..e6d1825 100644 --- a/ui.c +++ b/ui.c @@ -7,7 +7,9 @@ #include "ui.h" #include "str.h" +#include "screen.h" #include "xmalloc.h" +#include "urcu-list-compat.h" static struct ui_text *ui_text_alloc(size_t len) { @@ -62,6 +64,7 @@ void ui_table_init(struct ui_table *tbl) tbl->height = LINES - 2; tbl->col_pad = 1; tbl->row = ui_text_alloc(tbl->width); + tbl->delim = " "; CDS_INIT_LIST_HEAD(&tbl->cols); } @@ -106,7 +109,7 @@ static void __ui_table_pos_update(struct ui_table *tbl) } } -void ui_table_col_add(struct ui_table *tbl, uint32_t id, char *name, uint32_t len) +void ui_table_col_add(struct ui_table *tbl, uint32_t id, const char *name, uint32_t len) { struct ui_col *col = xzmalloc(sizeof(*col)); @@ -134,6 +137,11 @@ void ui_table_col_align_set(struct ui_table *tbl, int col_id, enum ui_align alig col->align = align; } +void ui_table_col_delim_set(struct ui_table *tbl, const char *delim) +{ + tbl->delim = delim; +} + void ui_table_row_add(struct ui_table *tbl) { tbl->rows_y++; @@ -166,7 +174,7 @@ static void __ui_table_row_print(struct ui_table *tbl, struct ui_col *col, slprintf(tmp, sizeof(tmp), UI_ALIGN_COL(col), col->len, col->len, str); ui_text_attr_insert(tbl->row, col->pos, color, tmp); - slprintf(tmp, sizeof(tmp), "%*s", tbl->col_pad, " "); + slprintf(tmp, sizeof(tmp), "%*s", tbl->col_pad, tbl->delim); ui_text_attr_insert(tbl->row, col->pos + col->len, color, tmp); } @@ -214,3 +222,88 @@ void ui_table_event_send(struct ui_table *tbl, enum ui_event_id evt_id) tbl->scroll_x = 0; } } + +struct ui_tab *ui_tab_create(void) +{ + struct ui_tab *tab; + + tab = xzmalloc(sizeof(*tab)); + + ui_table_init(&tab->tbl); + ui_table_col_delim_set(&tab->tbl, "|"); + tab->tbl.width = 0; + + return tab; +} + +void ui_tab_destroy(struct ui_tab *tab) +{ + ui_table_uninit(&tab->tbl); + xfree(tab); +} + +void ui_tab_pos_set(struct ui_tab *tab, int y, int x) +{ + ui_table_pos_set(&tab->tbl, y, x); +} + +void ui_tab_event_cb_set(struct ui_tab *tab, ui_tab_event_cb cb) +{ + tab->on_tab_event = cb; +} + +void ui_tab_active_color_set(struct ui_tab *tab, int color) +{ + ui_table_header_color_set(&tab->tbl, color); + tab->color = color; +} + +void ui_tab_show(struct ui_tab *tab) +{ + struct ui_col *col; + + if (tab->on_tab_event) + tab->on_tab_event(tab, UI_TAB_EVT_OPEN, tab->active->id); + + cds_list_for_each_entry(col, &tab->tbl.cols, entry) + __ui_table_row_print(&tab->tbl, col, col->color, col->name); + + ui_table_row_show(&tab->tbl); +} + +void ui_tab_entry_add(struct ui_tab *tab, uint32_t id, const char *name) +{ + struct ui_col *col; + + ui_table_col_add(&tab->tbl, id, name, strlen(name) + 1); + + col = ui_table_col_get(&tab->tbl, id); + + if (!tab->active) + tab->active = col; + + if (tab->active == col) + ui_table_col_color_set(&tab->tbl, id, tab->color); + else + ui_table_col_color_set(&tab->tbl, id, tab->color | A_REVERSE); +} + +void ui_tab_event_send(struct ui_tab *tab, uint32_t id) +{ + struct ui_col *curr, *next; + + if (id != UI_EVT_SELECT_NEXT) + return; + + curr = tab->active; + + if (curr == cds_list_last_entry(&tab->tbl.cols, struct ui_col, entry)) + next = cds_list_first_entry(&tab->tbl.cols, struct ui_col, entry); + else + next = cds_list_next_entry(curr, entry); + + curr->color = tab->color | A_REVERSE; + next->color = tab->color; + + tab->active = next; +} diff --git a/ui.h b/ui.h index 9db3c08..40bf4f1 100644 --- a/ui.h +++ b/ui.h @@ -9,6 +9,7 @@ enum ui_event_id { UI_EVT_SCROLL_LEFT, UI_EVT_SCROLL_RIGHT, + UI_EVT_SELECT_NEXT, }; enum ui_align { @@ -25,7 +26,7 @@ struct ui_text { struct ui_col { struct cds_list_head entry; uint32_t id; - char *name; + const char *name; uint32_t len; int pos; int color; @@ -43,6 +44,25 @@ struct ui_table { int width; int height; int scroll_x; + const char *delim; +}; + +struct ui_tab; + +enum ui_tab_event_t { + UI_TAB_EVT_OPEN, + UI_TAB_EVT_CLOSE, +}; + +typedef void (* ui_tab_event_cb) (struct ui_tab *tab, enum ui_tab_event_t evt, + uint32_t id); + +struct ui_tab { + struct ui_col *active; + struct ui_table tbl; + int color; + + ui_tab_event_cb on_tab_event; }; extern void ui_table_init(struct ui_table *tbl); @@ -51,10 +71,11 @@ extern void ui_table_clear(struct ui_table *tbl); extern void ui_table_pos_set(struct ui_table *tbl, int y, int x); extern void ui_table_height_set(struct ui_table *tbl, int height); -extern void ui_table_col_add(struct ui_table *tbl, uint32_t id, char *name, +extern void ui_table_col_add(struct ui_table *tbl, uint32_t id, const char *name, uint32_t len); extern void ui_table_col_color_set(struct ui_table *tbl, int col_id, int color); extern void ui_table_col_align_set(struct ui_table *tbl, int col_id, enum ui_align align); +extern void ui_table_col_delim_set(struct ui_table *tbl, const char *delim); extern void ui_table_row_add(struct ui_table *tbl); extern void ui_table_row_show(struct ui_table *tbl); @@ -66,4 +87,13 @@ extern void ui_table_header_print(struct ui_table *tbl); extern void ui_table_event_send(struct ui_table *tbl, enum ui_event_id id); +extern struct ui_tab *ui_tab_create(void); +extern void ui_tab_destroy(struct ui_tab *tab); +extern void ui_tab_pos_set(struct ui_tab *tab, int y, int x); +extern void ui_tab_event_cb_set(struct ui_tab *tab, ui_tab_event_cb cb); +extern void ui_tab_active_color_set(struct ui_tab *tab, int color); +extern void ui_tab_show(struct ui_tab *tab); +extern void ui_tab_entry_add(struct ui_tab *tab, uint32_t id, const char *name); +extern void ui_tab_event_send(struct ui_tab *tab, uint32_t id); + #endif /* UI_H */ diff --git a/urcu-list-compat.h b/urcu-list-compat.h new file mode 100644 index 0000000..44117ad --- /dev/null +++ b/urcu-list-compat.h @@ -0,0 +1,21 @@ +#ifndef URCU_LIST_COMPAT_H +#define URCU_LIST_COMPAT_H + +#include + +#ifndef cds_list_last_entry +#define cds_list_last_entry(ptr, type, member) \ + cds_list_entry((ptr)->prev, type, member) +#endif + +#ifndef cds_list_next_entry +#define cds_list_next_entry(pos, member) \ + cds_list_entry((pos)->member.next, typeof(*(pos)), member) +#endif + +#ifndef cds_list_prev_entry +#define cds_list_prev_entry(pos, member) \ + cds_list_entry((pos)->member.prev, typeof(*(pos)), member) +#endif + +#endif /* URCU_LIST_COMPAT_H */ -- cgit v1.2.3-54-g00ecf