From 8d0e0af2a097f46aa5d8b9a1a4da3af970fe28ef Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Jul 2019 13:07:19 +0900 Subject: [PATCH 1/8] networkctl: merge multiple table_add_cell() by using table_add_many() --- src/network/networkctl.c | 304 ++++++++++++++------------------------- 1 file changed, 106 insertions(+), 198 deletions(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 5f74f7b5cc8..33572cac1ad 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -360,27 +360,16 @@ static int list_links(int argc, char *argv[], void *userdata) { t = link_get_type_string(links[i].iftype, d); - r = table_add_cell(table, NULL, TABLE_INT, &links[i].ifindex); - if (r < 0) - return r; - r = table_add_many(table, + TABLE_INT, links[i].ifindex, TABLE_STRING, links[i].name, - TABLE_STRING, strna(t)); + TABLE_STRING, strna(t), + TABLE_STRING, strna(operational_state), + TABLE_SET_COLOR, on_color_operational, + TABLE_STRING, strna(setup_state), + TABLE_SET_COLOR, on_color_setup); if (r < 0) return r; - - r = table_add_cell(table, &cell, TABLE_STRING, strna(operational_state)); - if (r < 0) - return r; - - (void) table_set_color(table, cell, on_color_operational); - - r = table_add_cell(table, &cell, TABLE_STRING, strna(setup_state)); - if (r < 0) - return r; - - (void) table_set_color(table, cell, on_color_setup); } r = table_print(table, NULL); @@ -551,11 +540,9 @@ static int dump_gateways( for (i = 0; i < n; i++) { _cleanup_free_ char *gateway = NULL, *description = NULL, *with_description = NULL; - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_STRING, i == 0 ? "Gateway:" : ""); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, i == 0 ? "Gateway:" : ""); if (r < 0) return r; @@ -609,11 +596,9 @@ static int dump_addresses( for (i = 0; i < n; i++) { _cleanup_free_ char *pretty = NULL; - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_STRING, i == 0 ? "Address:" : ""); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, i == 0 ? "Address:" : ""); if (r < 0) return r; @@ -707,7 +692,7 @@ static int dump_address_labels(sd_netlink *rtnl) { if (r < 0) return r; - r = table_add_cell_stringf(table, &cell, "%s/%u", pretty, prefixlen); + r = table_add_cell_stringf(table, NULL, "%s/%u", pretty, prefixlen); if (r < 0) return r; } @@ -793,7 +778,6 @@ static int dump_lldp_neighbors(Table *table, const char *prefix, int ifindex) { for (;;) { const char *system_name = NULL, *port_id = NULL, *port_description = NULL; _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - _cleanup_free_ char *str = NULL; r = next_lldp_neighbor(f, &n); if (r < 0) @@ -801,11 +785,9 @@ static int dump_lldp_neighbors(Table *table, const char *prefix, int ifindex) { if (r == 0) break; - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_STRING, c == 0 ? prefix : ""); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, c == 0 ? prefix : ""); if (r < 0) return r; @@ -813,14 +795,12 @@ static int dump_lldp_neighbors(Table *table, const char *prefix, int ifindex) { (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); (void) sd_lldp_neighbor_get_port_description(n, &port_description); - if (asprintf(&str, "%s on port %s%s%s%s", - strna(system_name), strna(port_id), - isempty(port_description) ? "" : " (", - port_description, - isempty(port_description) ? "" : ")") < 0) - return -ENOMEM; - - r = table_add_cell(table, NULL, TABLE_STRING, str); + r = table_add_cell_stringf(table, NULL, + "%s on port %s%s%s%s", + strna(system_name), strna(port_id), + isempty(port_description) ? "" : " (", + port_description, + isempty(port_description) ? "" : ")"); if (r < 0) return r; @@ -840,15 +820,10 @@ static int dump_ifindexes(Table *table, const char *prefix, const int *ifindexes return 0; for (c = 0; ifindexes[c] > 0; c++) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_STRING, c == 0 ? prefix : ""); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_IFINDEX, ifindexes + c); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, c == 0 ? prefix : "", + TABLE_IFINDEX, ifindexes[c]); if (r < 0) return r; } @@ -864,15 +839,10 @@ static int dump_list(Table *table, const char *prefix, char **l) { return 0; STRV_FOREACH(i, l) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_STRING, i == l ? prefix : ""); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_STRING, *i); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, i == l ? prefix : "", + TABLE_STRING, *i); if (r < 0) return r; } @@ -881,13 +851,13 @@ static int dump_list(Table *table, const char *prefix, char **l) { } #define DUMP_STATS_ONE(name, val_name) \ - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); \ + r = table_add_many(table, \ + TABLE_EMPTY, \ + TABLE_STRING, name ":"); \ if (r < 0) \ return r; \ - r = table_add_cell(table, NULL, TABLE_STRING, name ":"); \ - if (r < 0) \ - return r; \ - r = table_add_cell(table, NULL, info->has_stats64 ? TABLE_UINT64 : TABLE_UINT32, \ + r = table_add_cell(table, NULL, \ + info->has_stats64 ? TABLE_UINT64 : TABLE_UINT32, \ info->has_stats64 ? (void*) &info->stats64.val_name : (void*) &info->stats.val_name); \ if (r < 0) \ return r; @@ -984,53 +954,30 @@ static int link_status_one( table_set_header(table, false); - r = table_add_cell(table, &cell, TABLE_STRING, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE)); + r = table_add_many(table, + TABLE_STRING, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), + TABLE_SET_COLOR, on_color_operational); if (r < 0) return r; - (void) table_set_color(table, cell, on_color_operational); r = table_add_cell_stringf(table, &cell, "%i: %s", info->ifindex, info->name); if (r < 0) return r; (void) table_set_align_percent(table, cell, 0); - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, &cell, TABLE_STRING, "Link File:"); - if (r < 0) - return r; - (void) table_set_align_percent(table, cell, 100); - r = table_add_cell(table, NULL, TABLE_STRING, strna(link)); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Network File:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, strna(network)); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Type:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, strna(t)); - if (r < 0) - return r; - - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "State:"); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_EMPTY, + TABLE_STRING, "Link File:", + TABLE_SET_ALIGN_PERCENT, 100, + TABLE_STRING, strna(link), + TABLE_EMPTY, + TABLE_STRING, "Network File:", + TABLE_STRING, strna(network), + TABLE_EMPTY, + TABLE_STRING, "Type:", + TABLE_STRING, strna(t), + TABLE_EMPTY, + TABLE_STRING, "State:"); if (r < 0) return r; r = table_add_cell_stringf(table, NULL, "%s%s%s (%s%s%s)", @@ -1040,46 +987,34 @@ static int link_status_one( return r; if (path) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Path:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, path); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Path:", + TABLE_STRING, path); if (r < 0) return r; } if (driver) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Driver:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, driver); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Driver:", + TABLE_STRING, driver); if (r < 0) return r; } if (vendor) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Vendor:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, vendor); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Vendor:", + TABLE_STRING, vendor); if (r < 0) return r; } if (model) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Model:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, model); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Model:", + TABLE_STRING, model); if (r < 0) return r; } @@ -1090,10 +1025,9 @@ static int link_status_one( (void) ieee_oui(hwdb, &info->mac_address, &description); - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "HW Address:"); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "HW Address:"); if (r < 0) return r; r = table_add_cell_stringf(table, NULL, "%s%s%s%s", @@ -1111,10 +1045,9 @@ static int link_status_one( xsprintf(min_str, "%" PRIu32, info->min_mtu); xsprintf(max_str, "%" PRIu32, info->max_mtu); - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "MTU:"); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "MTU:"); if (r < 0) return r; r = table_add_cell_stringf(table, NULL, "%" PRIu32 "%s%s%s%s%s%s%s", @@ -1133,13 +1066,11 @@ static int link_status_one( if (info->has_bitrates) { char tx[FORMAT_BYTES_MAX], rx[FORMAT_BYTES_MAX]; - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Bit Rate (Tx/Rx):"); if (r < 0) return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Bit Rate (Tx/Rx):"); - if (r < 0) - return r; - r = table_add_cell_stringf(table, NULL, "%sbps/%sbps", format_bytes_full(tx, sizeof tx, info->tx_bitrate, 0), format_bytes_full(rx, sizeof rx, info->rx_bitrate, 0)); @@ -1148,10 +1079,9 @@ static int link_status_one( } if (info->has_tx_queues || info->has_rx_queues) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Queue Length (Tx/Rx):"); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Queue Length (Tx/Rx):"); if (r < 0) return r; r = table_add_cell_stringf(table, NULL, "%" PRIu32 "/%" PRIu32, info->tx_queues, info->rx_queues); @@ -1164,49 +1094,37 @@ static int link_status_one( const char *port = port_to_string(info->port); if (IN_SET(info->autonegotiation, AUTONEG_DISABLE, AUTONEG_ENABLE)) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Auto negotiation:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_BOOLEAN, &info->autonegotiation); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Auto negotiation:", + TABLE_BOOLEAN, info->autonegotiation == AUTONEG_ENABLE); if (r < 0) return r; } if (info->speed > 0) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Speed:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_BPS, &info->speed); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Speed:", + TABLE_BPS, info->speed); if (r < 0) return r; } if (duplex) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Duplex:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, duplex); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Duplex:", + TABLE_STRING, duplex); if (r < 0) return r; } if (port) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Port:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, port); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Port:", + TABLE_STRING, port); if (r < 0) return r; } @@ -1239,13 +1157,10 @@ static int link_status_one( (void) sd_network_link_get_timezone(info->ifindex, &tz); if (tz) { - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Time Zone:"); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, tz); + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Time Zone:", + TABLE_STRING, tz); if (r < 0) return r; } @@ -1287,19 +1202,12 @@ static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) { table_set_header(table, false); - r = table_add_cell(table, &cell, TABLE_STRING, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE)); - if (r < 0) - return r; - (void) table_set_color(table, cell, on_color_operational); - - r = table_add_cell(table, NULL, TABLE_STRING, "State:"); - if (r < 0) - return r; - - r = table_add_cell(table, &cell, TABLE_STRING, strna(operational_state)); - if (r < 0) - return r; - (void) table_set_color(table, cell, on_color_operational); + r = table_add_many(table, + TABLE_STRING, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), + TABLE_SET_COLOR, on_color_operational, + TABLE_STRING, "State:", + TABLE_STRING, strna(operational_state), + TABLE_SET_COLOR, on_color_operational); r = dump_addresses(rtnl, table, 0); if (r < 0) From a7a257cdda6ac94dc26b58460b648c8d206c82ee Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Jul 2019 13:43:28 +0900 Subject: [PATCH 2/8] table: add TABLE_IN_ADDR and TABLE_IN6_ADDR --- src/shared/format-table.c | 43 +++++++++++++++++++++++++++++++++++++++ src/shared/format-table.h | 2 ++ 2 files changed, 45 insertions(+) diff --git a/src/shared/format-table.c b/src/shared/format-table.c index aede59bf346..6de7da0df0c 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -9,6 +9,7 @@ #include "format-table.h" #include "format-util.h" #include "gunicode.h" +#include "in-addr-util.h" #include "memory-util.h" #include "pager.h" #include "parse-util.h" @@ -84,6 +85,7 @@ typedef struct TableData { uint64_t uint64; int percent; /* we use 'int' as datatype for percent values in order to match the result of parse_percent() */ int ifindex; + union in_addr_union address; /* … add more here as we start supporting more cell data types … */ }; } TableData; @@ -252,6 +254,12 @@ static size_t table_data_size(TableDataType type, const void *data) { case TABLE_IFINDEX: return sizeof(int); + case TABLE_IN_ADDR: + return sizeof(struct in_addr); + + case TABLE_IN6_ADDR: + return sizeof(struct in6_addr); + default: assert_not_reached("Uh? Unexpected cell type"); } @@ -705,6 +713,7 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) { int percent; int ifindex; bool b; + union in_addr_union address; } buffer; switch (type) { @@ -777,6 +786,16 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) { data = &buffer.ifindex; break; + case TABLE_IN_ADDR: + buffer.address = *va_arg(ap, union in_addr_union *); + data = &buffer.address.in; + break; + + case TABLE_IN6_ADDR: + buffer.address = *va_arg(ap, union in_addr_union *); + data = &buffer.address.in6; + break; + case TABLE_SET_MINIMUM_WIDTH: { size_t w = va_arg(ap, size_t); @@ -976,6 +995,12 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t case TABLE_IFINDEX: return CMP(a->ifindex, b->ifindex); + case TABLE_IN_ADDR: + return CMP(a->address.in.s_addr, b->address.in.s_addr); + + case TABLE_IN6_ADDR: + return memcmp(&a->address.in6, &b->address.in6, FAMILY_ADDRESS_SIZE(AF_INET6)); + default: ; } @@ -1218,6 +1243,18 @@ static const char *table_data_format(TableData *d) { break; } + case TABLE_IN_ADDR: + case TABLE_IN6_ADDR: { + _cleanup_free_ char *p = NULL; + + if (in_addr_to_string(d->type == TABLE_IN_ADDR ? AF_INET : AF_INET6, + &d->address, &p) < 0) + return NULL; + + d->formatted = TAKE_PTR(p); + break; + } + default: assert_not_reached("Unexpected type?"); } @@ -1749,6 +1786,12 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) { case TABLE_IFINDEX: return json_variant_new_integer(ret, d->ifindex); + case TABLE_IN_ADDR: + return json_variant_new_array_bytes(ret, &d->address, FAMILY_ADDRESS_SIZE(AF_INET)); + + case TABLE_IN6_ADDR: + return json_variant_new_array_bytes(ret, &d->address, FAMILY_ADDRESS_SIZE(AF_INET6)); + default: return -EINVAL; } diff --git a/src/shared/format-table.h b/src/shared/format-table.h index 452f1706c0c..d402e95e0f1 100644 --- a/src/shared/format-table.h +++ b/src/shared/format-table.h @@ -27,6 +27,8 @@ typedef enum TableDataType { TABLE_UINT64, TABLE_PERCENT, TABLE_IFINDEX, + TABLE_IN_ADDR, /* Takes a union in_addr_union (or a struct in_addr) */ + TABLE_IN6_ADDR, /* Takes a union in_addr_union (or a struct in6_addr) */ _TABLE_DATA_TYPE_MAX, /* The following are not really data types, but commands for table_add_cell_many() to make changes to From e74294c30aca770c08938aa34ab073e13d569c39 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Jul 2019 14:14:02 +0900 Subject: [PATCH 3/8] table: add TABLE_UINT8 or friends --- src/shared/format-table.c | 124 ++++++++++++++++++++++++++++++++++++++ src/shared/format-table.h | 4 ++ 2 files changed, 128 insertions(+) diff --git a/src/shared/format-table.c b/src/shared/format-table.c index 6de7da0df0c..9813f4ba886 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -78,9 +78,13 @@ typedef struct TableData { uint64_t size; char string[0]; int int_val; + int8_t int8; + int16_t int16; int32_t int32; int64_t int64; unsigned uint_val; + uint8_t uint8; + uint16_t uint16; uint32_t uint32; uint64_t uint64; int percent; /* we use 'int' as datatype for percent values in order to match the result of parse_percent() */ @@ -248,6 +252,14 @@ static size_t table_data_size(TableDataType type, const void *data) { case TABLE_UINT32: return sizeof(uint32_t); + case TABLE_INT16: + case TABLE_UINT16: + return sizeof(uint16_t); + + case TABLE_INT8: + case TABLE_UINT8: + return sizeof(uint8_t); + case TABLE_INT: case TABLE_UINT: case TABLE_PERCENT: @@ -705,9 +717,13 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) { uint64_t size; usec_t usec; int int_val; + int8_t int8; + int16_t int16; int32_t int32; int64_t int64; unsigned uint_val; + uint8_t uint8; + uint16_t uint16; uint32_t uint32; uint64_t uint64; int percent; @@ -751,6 +767,24 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) { data = &buffer.int_val; break; + case TABLE_INT8: { + int x = va_arg(ap, int); + assert(x >= INT8_MIN && x <= INT8_MAX); + + buffer.int8 = x; + data = &buffer.int8; + break; + } + + case TABLE_INT16: { + int x = va_arg(ap, int); + assert(x >= INT16_MIN && x <= INT16_MAX); + + buffer.int16 = x; + data = &buffer.int16; + break; + } + case TABLE_INT32: buffer.int32 = va_arg(ap, int32_t); data = &buffer.int32; @@ -766,6 +800,24 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) { data = &buffer.uint_val; break; + case TABLE_UINT8: { + unsigned x = va_arg(ap, unsigned); + assert(x <= UINT8_MAX); + + buffer.uint8 = x; + data = &buffer.uint8; + break; + } + + case TABLE_UINT16: { + unsigned x = va_arg(ap, unsigned); + assert(x <= UINT16_MAX); + + buffer.uint16 = x; + data = &buffer.uint16; + break; + } + case TABLE_UINT32: buffer.uint32 = va_arg(ap, uint32_t); data = &buffer.uint32; @@ -974,6 +1026,12 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t case TABLE_INT: return CMP(a->int_val, b->int_val); + case TABLE_INT8: + return CMP(a->int8, b->int8); + + case TABLE_INT16: + return CMP(a->int16, b->int16); + case TABLE_INT32: return CMP(a->int32, b->int32); @@ -983,6 +1041,12 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t case TABLE_UINT: return CMP(a->uint_val, b->uint_val); + case TABLE_UINT8: + return CMP(a->uint8, b->uint8); + + case TABLE_UINT16: + return CMP(a->uint16, b->uint16); + case TABLE_UINT32: return CMP(a->uint32, b->uint32); @@ -1154,6 +1218,30 @@ static const char *table_data_format(TableData *d) { break; } + case TABLE_INT8: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->int8) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIi8, d->int8); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_INT16: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->int16) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIi16, d->int16); + d->formatted = TAKE_PTR(p); + break; + } + case TABLE_INT32: { _cleanup_free_ char *p; @@ -1190,6 +1278,30 @@ static const char *table_data_format(TableData *d) { break; } + case TABLE_UINT8: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->uint8) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIu8, d->uint8); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_UINT16: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->uint16) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIu16, d->uint16); + d->formatted = TAKE_PTR(p); + break; + } + case TABLE_UINT32: { _cleanup_free_ char *p; @@ -1765,6 +1877,12 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) { case TABLE_INT: return json_variant_new_integer(ret, d->int_val); + case TABLE_INT8: + return json_variant_new_integer(ret, d->int8); + + case TABLE_INT16: + return json_variant_new_integer(ret, d->int16); + case TABLE_INT32: return json_variant_new_integer(ret, d->int32); @@ -1774,6 +1892,12 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) { case TABLE_UINT: return json_variant_new_unsigned(ret, d->uint_val); + case TABLE_UINT8: + return json_variant_new_unsigned(ret, d->uint8); + + case TABLE_UINT16: + return json_variant_new_unsigned(ret, d->uint16); + case TABLE_UINT32: return json_variant_new_unsigned(ret, d->uint32); diff --git a/src/shared/format-table.h b/src/shared/format-table.h index d402e95e0f1..c6df8bf70cb 100644 --- a/src/shared/format-table.h +++ b/src/shared/format-table.h @@ -20,9 +20,13 @@ typedef enum TableDataType { TABLE_SIZE, TABLE_BPS, TABLE_INT, + TABLE_INT8, + TABLE_INT16, TABLE_INT32, TABLE_INT64, TABLE_UINT, + TABLE_UINT8, + TABLE_UINT16, TABLE_UINT32, TABLE_UINT64, TABLE_PERCENT, From 57894dc98977dbe33734d5b7319bd7a89ce809d1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 29 Jul 2019 23:30:32 +0900 Subject: [PATCH 4/8] table: add missing NULL initialization --- src/shared/format-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/format-table.c b/src/shared/format-table.c index 9813f4ba886..44937e1c913 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -1339,7 +1339,7 @@ static const char *table_data_format(TableData *d) { } case TABLE_IFINDEX: { - _cleanup_free_ char *p; + _cleanup_free_ char *p = NULL; char name[IF_NAMESIZE + 1]; if (format_ifname(d->ifindex, name)) { From 77372afbe06d60c8700c5466824396c72e312cb1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 29 Jul 2019 23:47:04 +0900 Subject: [PATCH 5/8] time-util: introduce jiffies_to_usec() --- src/basic/time-util.c | 16 +++++++++++++--- src/basic/time-util.h | 3 ++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 434159f41ce..e13361463be 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -1414,8 +1414,8 @@ struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) { return utc ? gmtime_r(t, tm) : localtime_r(t, tm); } -unsigned long usec_to_jiffies(usec_t u) { - static thread_local unsigned long hz = 0; +static uint32_t sysconf_clock_ticks_cached(void) { + static thread_local uint32_t hz = 0; long r; if (hz == 0) { @@ -1425,7 +1425,17 @@ unsigned long usec_to_jiffies(usec_t u) { hz = r; } - return DIV_ROUND_UP(u , USEC_PER_SEC / hz); + return hz; +} + +uint32_t usec_to_jiffies(usec_t u) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(u, USEC_PER_SEC / hz); +} + +usec_t jiffies_to_usec(uint32_t j) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(j * USEC_PER_SEC, hz); } usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) { diff --git a/src/basic/time-util.h b/src/basic/time-util.h index e3a529d9709..4c371257e33 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -136,7 +136,8 @@ int get_timezone(char **timezone); time_t mktime_or_timegm(struct tm *tm, bool utc); struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc); -unsigned long usec_to_jiffies(usec_t usec); +uint32_t usec_to_jiffies(usec_t usec); +usec_t jiffies_to_usec(uint32_t jiffies); bool in_utc_timezone(void); From c82d1bf2b32471b57c7b569a370b5be0c05cc3a6 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 25 Jul 2019 22:39:34 +0530 Subject: [PATCH 6/8] networkctl: Add support to display bridge properties --- src/network/networkctl.c | 82 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 33572cac1ad..a1531ae8d2a 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -47,6 +47,9 @@ #include "terminal-util.h" #include "verbs.h" +/* Kernel defines MODULE_NAME_LEN as 64 - sizeof(unsigned long). So, 64 is enough. */ +#define NETDEV_KIND_MAX 64 + static PagerFlags arg_pager_flags = 0; static bool arg_legend = true; static bool arg_all = false; @@ -106,6 +109,7 @@ static void setup_state_to_color(const char *state, const char **on, const char typedef struct LinkInfo { char name[IFNAMSIZ+1]; + char netdev_kind[NETDEV_KIND_MAX]; int ifindex; unsigned short iftype; struct ether_addr mac_address; @@ -123,6 +127,15 @@ typedef struct LinkInfo { uint64_t tx_bitrate; uint64_t rx_bitrate; + /* bridge info */ + uint32_t forward_delay; + uint32_t hello_time; + uint32_t max_age; + uint32_t ageing_time; + uint32_t stp_state; + uint16_t priority; + uint8_t mcast_igmp_version; + /* ethtool info */ int autonegotiation; size_t speed; @@ -142,10 +155,47 @@ static int link_info_compare(const LinkInfo *a, const LinkInfo *b) { return CMP(a->ifindex, b->ifindex); } +static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { + const char *received_kind; + int r; + + assert(m); + assert(info); + + r = sd_netlink_message_enter_container(m, IFLA_LINKINFO); + if (r < 0) + return r; + + r = sd_netlink_message_read_string(m, IFLA_INFO_KIND, &received_kind); + if (r < 0) + return r; + + r = sd_netlink_message_enter_container(m, IFLA_INFO_DATA); + if (r < 0) + return r; + + if (streq(received_kind, "bridge")) { + (void) sd_netlink_message_read_u32(m, IFLA_BR_FORWARD_DELAY, &info->forward_delay); + (void) sd_netlink_message_read_u32(m, IFLA_BR_HELLO_TIME, &info->hello_time); + (void) sd_netlink_message_read_u32(m, IFLA_BR_MAX_AGE, &info->max_age); + (void) sd_netlink_message_read_u32(m, IFLA_BR_AGEING_TIME, &info->ageing_time); + (void) sd_netlink_message_read_u32(m, IFLA_BR_STP_STATE, &info->stp_state); + (void) sd_netlink_message_read_u16(m, IFLA_BR_PRIORITY, &info->priority); + (void) sd_netlink_message_read_u8(m, IFLA_BR_MCAST_IGMP_VERSION, &info->mcast_igmp_version); + } + + strncpy(info->netdev_kind, received_kind, IFNAMSIZ); + + (void) sd_netlink_message_exit_container(m); + (void) sd_netlink_message_exit_container(m); + + return 0; +} + static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) { const char *name; - uint16_t type; int ifindex, r; + uint16_t type; assert(m); assert(info); @@ -202,6 +252,9 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) { else if (sd_netlink_message_read(m, IFLA_STATS, sizeof info->stats, &info->stats) >= 0) info->has_stats = true; + /* fill kind info */ + (void) decode_netdev(m, info); + return 1; } @@ -1063,6 +1116,33 @@ static int link_status_one( return r; } + if (streq_ptr(info->netdev_kind, "bridge")) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Forward Delay:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->forward_delay), + TABLE_EMPTY, + TABLE_STRING, "Hello Time:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->hello_time), + TABLE_EMPTY, + TABLE_STRING, "Max Age:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->max_age), + TABLE_EMPTY, + TABLE_STRING, "Ageing Time:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->ageing_time), + TABLE_EMPTY, + TABLE_STRING, "Priority:", + TABLE_UINT16, info->priority, + TABLE_EMPTY, + TABLE_STRING, "STP:", + TABLE_BOOLEAN, info->stp_state > 0, + TABLE_EMPTY, + TABLE_STRING, "Multicast IGMP Version:", + TABLE_UINT8, info->mcast_igmp_version); + if (r < 0) + return r; + } + if (info->has_bitrates) { char tx[FORMAT_BYTES_MAX], rx[FORMAT_BYTES_MAX]; From b24281aaca9641ecc8c7bf7f0faba803c38749e7 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 25 Jul 2019 22:39:34 +0530 Subject: [PATCH 7/8] networkctl : Add support to display vxlan properties --- src/network/networkctl.c | 89 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index a1531ae8d2a..03b916d4129 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -107,6 +107,20 @@ static void setup_state_to_color(const char *state, const char **on, const char *on = *off = ""; } +typedef struct VxLanInfo { + uint32_t vni; + uint32_t link; + + int local_family; + int group_family; + + union in_addr_union local; + union in_addr_union group; + + uint16_t dest_port; + +} VxLanInfo; + typedef struct LinkInfo { char name[IFNAMSIZ+1]; char netdev_kind[NETDEV_KIND_MAX]; @@ -136,6 +150,9 @@ typedef struct LinkInfo { uint16_t priority; uint8_t mcast_igmp_version; + /* vxlan info */ + VxLanInfo vxlan_info; + /* ethtool info */ int autonegotiation; size_t speed; @@ -182,6 +199,30 @@ static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { (void) sd_netlink_message_read_u32(m, IFLA_BR_STP_STATE, &info->stp_state); (void) sd_netlink_message_read_u16(m, IFLA_BR_PRIORITY, &info->priority); (void) sd_netlink_message_read_u8(m, IFLA_BR_MCAST_IGMP_VERSION, &info->mcast_igmp_version); + + } else if (streq(received_kind, "vxlan")) { + (void) sd_netlink_message_read_u32(m, IFLA_VXLAN_ID, &info->vxlan_info.vni); + + r = sd_netlink_message_read_in_addr(m, IFLA_VXLAN_GROUP, &info->vxlan_info.group.in); + if (r >= 0) + info->vxlan_info.group_family = AF_INET; + else { + r = sd_netlink_message_read_in6_addr(m, IFLA_VXLAN_GROUP6, &info->vxlan_info.group.in6); + if (r >= 0) + info->vxlan_info.group_family = AF_INET6; + } + + r = sd_netlink_message_read_in_addr(m, IFLA_VXLAN_LOCAL, &info->vxlan_info.local.in); + if (r >= 0) + info->vxlan_info.local_family = AF_INET; + else { + r = sd_netlink_message_read_in6_addr(m, IFLA_VXLAN_LOCAL6, &info->vxlan_info.local.in6); + if (r >= 0) + info->vxlan_info.local_family = AF_INET6; + } + + (void) sd_netlink_message_read_u32(m, IFLA_VXLAN_LINK, &info->vxlan_info.link); + (void) sd_netlink_message_read_u16(m, IFLA_VXLAN_PORT, &info->vxlan_info.dest_port); } strncpy(info->netdev_kind, received_kind, IFNAMSIZ); @@ -1141,6 +1182,54 @@ static int link_status_one( TABLE_UINT8, info->mcast_igmp_version); if (r < 0) return r; + + } else if (streq_ptr(info->netdev_kind, "vxlan")) { + if (info->vxlan_info.vni > 0) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "VNI:", + TABLE_UINT32, info->vxlan_info.vni); + if (r < 0) + return r; + } + + if (IN_SET(info->vxlan_info.group_family, AF_INET, AF_INET6)) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Group:", + info->vxlan_info.group_family == AF_INET ? TABLE_IN_ADDR : TABLE_IN6_ADDR, + &info->vxlan_info.group); + if (r < 0) + return r; + } + + if (IN_SET(info->vxlan_info.local_family, AF_INET, AF_INET6)) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Local:", + info->vxlan_info.local_family == AF_INET ? TABLE_IN_ADDR : TABLE_IN6_ADDR, + &info->vxlan_info.local); + if (r < 0) + return r; + } + + if (info->vxlan_info.dest_port > 0) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Destination Port:", + TABLE_UINT16, be16toh(info->vxlan_info.dest_port)); + if (r < 0) + return r; + } + + if (info->vxlan_info.link > 0) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Underlying Device:", + TABLE_IFINDEX, info->vxlan_info.link); + if (r < 0) + return r; + } } if (info->has_bitrates) { From 36bc2ffbc1626e7eb10d52ff728d4dd00561a97d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Jul 2019 15:23:39 +0900 Subject: [PATCH 8/8] test-network: add tests for new entries in "networkctl status" --- test/test-network/systemd-networkd-tests.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 49a04f313a8..76313cf0265 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -705,6 +705,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state'))) self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version'))) + output = check_output(*networkctl_cmd, 'status', 'bridge99') + print(output) + self.assertRegex(output, 'Priority: 9') + self.assertRegex(output, 'STP: yes') + self.assertRegex(output, 'Multicast IGMP Version: 3') + def test_bond(self): copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev') start_networkd() @@ -1266,6 +1272,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent') self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent') + output = check_output(*networkctl_cmd, 'status', 'vxlan99') + print(output) + self.assertRegex(output, 'VNI: 999') + self.assertRegex(output, 'Destination Port: 5555') + self.assertRegex(output, 'Underlying Device: test1') + def test_macsec(self): copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key', 'macsec.network', '12-dummy.netdev')