From cb1d400d741b49943e15f7e8aed80028d4dc3529 Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Sat, 12 May 2018 10:31:50 +0200 Subject: [PATCH] sar: Allow user to select interfaces to display Add new option "--iface=" to allow the user to specify which network interfaces to display. This option is to be used with options "-n DEV" and "-n EDEV". Sample output: $ sar -n DEV Linux 4.4.14-200.fc22.x86_64 (home) 05/12/18 _x86_64_ (8 CPU) 10:35:29 IFACE rxpck/s txpck/s rxkB/s txkB/s [...] 10:35:31 lo 0.00 0.00 0.00 0.00 10:35:31 virbr0 0.00 0.00 0.00 0.00 10:35:31 wlp5s0 0.00 0.00 0.00 0.00 10:35:31 virbr0-nic 0.00 0.00 0.00 0.00 10:35:31 enp6s0 49.00 41.00 29.17 6.47 10:35:33 lo 0.00 0.00 0.00 0.00 10:35:33 virbr0 0.00 0.00 0.00 0.00 10:35:33 wlp5s0 0.00 0.00 0.00 0.00 10:35:33 virbr0-nic 0.00 0.00 0.00 0.00 10:35:33 enp6s0 1033.50 608.50 993.34 116.88 [...] $ sar -n DEV --iface=virbr0,enp6s0 Linux 4.4.14-200.fc22.x86_64 (home) 05/12/18 _x86_64_ (8 CPU) 10:35:29 IFACE rxpck/s txpck/s rxkB/s txkB/s [...] 10:35:31 virbr0 0.00 0.00 0.00 0.00 10:35:31 enp6s0 49.00 41.00 29.17 6.47 10:35:33 virbr0 0.00 0.00 0.00 0.00 10:35:33 enp6s0 1033.50 608.50 993.34 116.88 [...] Signed-off-by: Sebastien GODARD --- pr_stats.c | 19 +++++++++++- sa.h | 16 ++++++++++ sa_common.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sar.c | 19 +++++++++++- 4 files changed, 138 insertions(+), 2 deletions(-) diff --git a/pr_stats.c b/pr_stats.c index 40b3da8..a0f106d 100644 --- a/pr_stats.c +++ b/pr_stats.c @@ -41,7 +41,8 @@ extern unsigned int dm_major; extern int dis; extern char timestamp[][TIMESTAMP_LEN]; extern unsigned long avg_count; - +extern struct sa_dlist *st_dev_list; +extern int dlist_idx; /* *************************************************************************** @@ -1153,6 +1154,14 @@ __print_funct_t print_net_dev_stats(struct activity *a, int prev, int curr, if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sndp, sndc, STATS_NET_DEV_SIZE2CMP)) continue; + if (dlist_idx) { + /* A list of devices has been entered on the command line */ + if (!search_sa_dlist(st_dev_list, dlist_idx, sndc->interface, + A_NET_DEV)) + /* Device not found */ + continue; + } + printf("%-11s", timestamp[curr]); if (!DISPLAY_HUMAN_READ(flags)) { @@ -1226,6 +1235,14 @@ __print_funct_t print_net_edev_stats(struct activity *a, int prev, int curr, if (DISPLAY_ZERO_OMIT(flags) && !memcmp(snedp, snedc, STATS_NET_EDEV_SIZE2CMP)) continue; + if (dlist_idx) { + /* A list of devices has been entered on the command line */ + if (!search_sa_dlist(st_dev_list, dlist_idx, snedc->interface, + A_NET_DEV)) + /* Device not found */ + continue; + } + printf("%-11s", timestamp[curr]); if (!DISPLAY_HUMAN_READ(flags)) { diff --git a/sa.h b/sa.h index dbb48e6..ca15751 100644 --- a/sa.h +++ b/sa.h @@ -1097,6 +1097,16 @@ struct tstamp { int use; }; +/* List of devices entered on the command line */ +struct sa_dlist { + /* Device type */ + int dev_id __attribute__ ((aligned (4))); + /* Device name */ + char dev_name[MAX_NAME_LEN]; +}; + +#define SA_DLIST_SIZE (sizeof(struct sa_dlist)) + /* *************************************************************************** @@ -1264,6 +1274,8 @@ void get_itv_value (struct record_header *, struct record_header *, unsigned long long *); int next_slice (unsigned long long, unsigned long long, int, long); +void parse_sa_devices + (int, char *[], struct sa_dlist **, int *, int *, int, int); int parse_sar_opt (char * [], int *, struct activity * [], unsigned int *, int); int parse_sar_I_opt @@ -1305,6 +1317,10 @@ int sa_get_record_timestamp_struct (unsigned int, struct record_header *, struct tm *, struct tm *); int sa_open_read_magic (int *, char *, struct file_magic *, int, int *, int); +void salloc_sa_dlist + (struct sa_dlist **, int); +int search_sa_dlist + (struct sa_dlist *, int, char *, int); void select_all_activities (struct activity * []); void select_default_activity diff --git a/sa_common.c b/sa_common.c index ea659e4..434fd12 100644 --- a/sa_common.c +++ b/sa_common.c @@ -123,6 +123,55 @@ int get_activity_nr(struct activity *act[], unsigned int option, int count_outpu return n; } +/* + *************************************************************************** + * Allocate structures for devices entered on the command line. + * + * IN: + * @list_len Number of arguments on the command line. + * + * OUT: + * @st_dev_list Address of allocated structures. + *************************************************************************** + */ +void salloc_sa_dlist(struct sa_dlist **st_dev_list, int list_len) +{ + if ((*st_dev_list = (struct sa_dlist *) malloc(SA_DLIST_SIZE * list_len)) == NULL) { + perror("malloc"); + exit(4); + } + memset(*st_dev_list, 0, SA_DLIST_SIZE * list_len); +} + +/* + *************************************************************************** + * Look for device in list. + * + * IN: + * @st_dev_list Structure where devices are saved. + * @dlist_idx Number of devices in the list. + * @d_name Device name to look for. + * @d_id Device type. + * + * RETURNS: + * 1 if device found in list, 0 otherwise. + *************************************************************************** + */ +int search_sa_dlist(struct sa_dlist *st_dev_list, int dlist_idx, char *d_name, int d_id) +{ + int i; + struct sa_dlist *st_dev_list_i; + + for (i = 0; i < dlist_idx; i++) { + st_dev_list_i = st_dev_list + i; + if ((st_dev_list_i->dev_id == d_id) && + !strcmp(st_dev_list_i->dev_name, d_name)) + return 1; + } + + return 0; +} + /* *************************************************************************** * Look for the most recent of saDD and saYYYYMMDD to decide which one to @@ -2379,6 +2428,43 @@ int parse_sa_P_opt(char *argv[], int *opt, unsigned int *flags, struct activity return 1; } +/* + *************************************************************************** + * Parse devices entered on the command line. + * + * IN: + * @argc Number of arguments in the list. + * @argv Arguments list. + * @st_dev_list Structure where devices will be saved. + * @dlist_idx Number of devices previously saved in the list. + * @opt Index in list of arguments. + * @d_id Type of device. + * @pos Position is string where is located the first device. + * + * OUT: + * @st_dev_list Structure where devices have been saved. + * @dlist_idx Total number of devices saved in the list. + * @opt Index on next argument. + *************************************************************************** + */ +void parse_sa_devices(int argc, char *argv[], struct sa_dlist **st_dev_list, + int *dlist_idx, int *opt, int d_id, int pos) +{ + char *t; + struct sa_dlist *st_dev_list_i; + + if (*st_dev_list == NULL) { + /* Allocate device list */ + salloc_sa_dlist(st_dev_list, argc - 1 + count_csvalues(argc, argv)); + } + for (t = strtok(argv[*opt] + pos, ","); t; t = strtok(NULL, ",")) { + st_dev_list_i = *st_dev_list + (*dlist_idx)++; + st_dev_list_i->dev_id = d_id; + strncpy(st_dev_list_i->dev_name, t, MAX_NAME_LEN - 1); + } + (*opt)++; +} + /* *************************************************************************** * Compute network interface utilization. diff --git a/sar.c b/sar.c index 6bd9396..85082ee 100644 --- a/sar.c +++ b/sar.c @@ -76,6 +76,10 @@ struct record_header record_hdr[3]; */ unsigned int id_seq[NR_ACT]; +/* Devices entered on the command line */ +struct sa_dlist *st_dev_list = NULL; +int dlist_idx = 0; + struct tm rectime; /* Contain the date specified by -s and -e options */ @@ -118,9 +122,10 @@ void usage(char *progname) "[ -A ] [ -B ] [ -b ] [ -C ] [ -D ] [ -d ] [ -F [ MOUNT ] ] [ -H ] [ -h ]\n" "[ -p ] [ -q ] [ -r [ ALL ] ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -V ]\n" "[ -v ] [ -W ] [ -w ] [ -y ] [ -z ]\n" - "[ --dec={ 0 | 1 | 2 } ] [ --help ] [ --human ] [ --sadc ]\n" "[ -I { | SUM | ALL } ] [ -P { | ALL } ]\n" "[ -m { [,...] | ALL } ] [ -n { [,...] | ALL } ]\n" + "[ --dec={ 0 | 1 | 2 } ] [ --iface= ]\n" + "[ --help ] [ --human ] [ --sadc ]\n" "[ -j { ID | LABEL | PATH | UUID | ... } ]\n" "[ -f [ ] | -o [ ] | -[0-9]+ ]\n" "[ -i ] [ -s [ ] ] [ -e [ ] ]\n")); @@ -1271,6 +1276,12 @@ int main(int argc, char **argv) which_sadc(); } + else if (!strncmp(argv[opt], "--iface=", 8)) { + /* Parse devices entered on the command line */ + parse_sa_devices(argc, argv, &st_dev_list, + &dlist_idx, &opt, A_NET_DEV, 8); + } + else if (!strcmp(argv[opt], "--help")) { /* Display help message */ display_help(argv[0]); @@ -1501,6 +1512,9 @@ int main(int argc, char **argv) /* Free stuctures and activity bitmaps */ free_bitmaps(act); free_structures(act); + if (st_dev_list) { + free(st_dev_list); + } return 0; } @@ -1625,6 +1639,9 @@ int main(int argc, char **argv) /* Free structures and activity bitmaps */ free_bitmaps(act); free_structures(act); + if (st_dev_list) { + free(st_dev_list); + } return 0; } -- 2.40.0