diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-07-29 19:32:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-29 19:32:14 +0200 |
commit | 0f7dfea171951e32960ec2539b7315e69325cbf5 (patch) | |
tree | b881397ad546469b3d762c8a8debc5762e660eb6 | |
parent | 5afb1f275e1d1abddd36c48e2139cee54ba96097 (diff) | |
parent | 36bc2ffbc1626e7eb10d52ff728d4dd00561a97d (diff) | |
download | systemd-0f7dfea171951e32960ec2539b7315e69325cbf5.tar.gz |
Merge pull request #13201 from yuwata/networkctl-merge-table_add_cell
networkctl cleanups and improvements
-rw-r--r-- | src/basic/time-util.c | 16 | ||||
-rw-r--r-- | src/basic/time-util.h | 3 | ||||
-rw-r--r-- | src/network/networkctl.c | 475 | ||||
-rw-r--r-- | src/shared/format-table.c | 169 | ||||
-rw-r--r-- | src/shared/format-table.h | 6 | ||||
-rwxr-xr-x | test/test-network/systemd-networkd-tests.py | 12 |
6 files changed, 477 insertions, 204 deletions
diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 434159f41c..e13361463b 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 e3a529d970..4c371257e3 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); diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 5f74f7b5cc..03b916d412 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; @@ -104,8 +107,23 @@ 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]; int ifindex; unsigned short iftype; struct ether_addr mac_address; @@ -123,6 +141,18 @@ 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; + + /* vxlan info */ + VxLanInfo vxlan_info; + /* ethtool info */ int autonegotiation; size_t speed; @@ -142,10 +172,71 @@ 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); + + } 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); + + (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 +293,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; } @@ -360,27 +454,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)); - 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)); + 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; - - (void) table_set_color(table, cell, on_color_setup); } r = table_print(table, NULL); @@ -551,11 +634,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 +690,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 +786,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 +872,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 +879,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 +889,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 +914,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 +933,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 +945,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 +1048,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 +1081,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 +1119,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 +1139,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", @@ -1130,16 +1157,89 @@ 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; + + } 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) { char tx[FORMAT_BYTES_MAX], rx[FORMAT_BYTES_MAX]; - r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); - if (r < 0) - return r; - r = table_add_cell(table, NULL, TABLE_STRING, "Bit Rate (Tx/Rx):"); + r = table_add_many(table, + TABLE_EMPTY, + 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 +1248,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 +1263,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 +1326,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 +1371,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) diff --git a/src/shared/format-table.c b/src/shared/format-table.c index aede59bf34..44937e1c91 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" @@ -77,13 +78,18 @@ 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() */ int ifindex; + union in_addr_union address; /* … add more here as we start supporting more cell data types … */ }; } TableData; @@ -246,12 +252,26 @@ 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: 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"); } @@ -697,14 +717,19 @@ 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; int ifindex; bool b; + union in_addr_union address; } buffer; switch (type) { @@ -742,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; @@ -757,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; @@ -777,6 +838,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); @@ -955,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); @@ -964,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); @@ -976,6 +1059,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: ; } @@ -1129,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; @@ -1165,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; @@ -1202,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)) { @@ -1218,6 +1355,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?"); } @@ -1728,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); @@ -1737,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); @@ -1749,6 +1910,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 452f1706c0..c6df8bf70c 100644 --- a/src/shared/format-table.h +++ b/src/shared/format-table.h @@ -20,13 +20,19 @@ 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, 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 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 49a04f313a..76313cf026 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') |