1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-30 01:47:42 +03:00

Merge pull request #11719 from yuwata/networkctl-wildcards

networkctl: accept wildcards to specify links
This commit is contained in:
Lennart Poettering 2019-02-15 11:44:24 +01:00 committed by GitHub
commit a0279563d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 75 deletions

View File

@ -78,11 +78,13 @@
<varlistentry> <varlistentry>
<term> <term>
<command>list</command> <command>list</command>
<optional><replaceable>LINK</replaceable></optional> <optional><replaceable>PATTERN</replaceable></optional>
</term> </term>
<listitem> <listitem>
<para>Show a list of existing links and their status. If no further arguments are specified shows all links, <para>Show a list of existing links and their status. If one ore more
<replaceable>PATTERN</replaceable>s are specified, only links matching one of them are shown.
If no further arguments are specified shows all links,
otherwise just the specified links. Produces output similar to: otherwise just the specified links. Produces output similar to:
<programlisting>IDX LINK TYPE OPERATIONAL SETUP <programlisting>IDX LINK TYPE OPERATIONAL SETUP
@ -180,13 +182,13 @@
<varlistentry> <varlistentry>
<term> <term>
<command>status</command> <command>status</command>
<optional><replaceable>LINK</replaceable></optional> <optional><replaceable>PATTERN</replaceable></optional>
</term> </term>
<listitem> <listitem>
<para>Show information about the specified links: type, <para>Show information about the specified links: type, state, kernel module driver, hardware and
state, kernel module driver, hardware and IP address, IP address, configured DNS servers, etc. If one ore more <replaceable>PATTERN</replaceable>s are
configured DNS servers, etc.</para> specified, only links matching one of them are shown.</para>
<para>When no links are specified, an overall network status is shown. Also see the option <para>When no links are specified, an overall network status is shown. Also see the option
<option>--all</option>.</para> <option>--all</option>.</para>
@ -208,13 +210,14 @@
<varlistentry> <varlistentry>
<term> <term>
<command>lldp</command> <command>lldp</command>
<optional><replaceable>LINK</replaceable></optional> <optional><replaceable>PATTERN</replaceable></optional>
</term> </term>
<listitem> <listitem>
<para>Show discovered LLDP (Link Layer Discovery Protocol) neighbors. If one or more link names are specified <para>Show discovered LLDP (Link Layer Discovery Protocol) neighbors. If one or more
only neighbors on those interfaces are shown. Otherwise shows discovered neighbors on all interfaces. Note <replaceable>PATTERN</replaceable>s are specified only neighbors on those interfaces are shown.
that for this feature to work, <varname>LLDP=</varname> must be turned on for the specific interface, see Otherwise shows discovered neighbors on all interfaces. Note that for this feature to work,
<varname>LLDP=</varname> must be turned on for the specific interface, see
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> for <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para> details.</para>

View File

@ -107,10 +107,10 @@ static int link_info_compare(const LinkInfo *a, const LinkInfo *b) {
return CMP(a->ifindex, b->ifindex); return CMP(a->ifindex, b->ifindex);
} }
static int decode_link(sd_netlink_message *m, LinkInfo *info) { static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) {
const char *name; const char *name;
uint16_t type; uint16_t type;
int r; int ifindex, r;
assert(m); assert(m);
assert(info); assert(info);
@ -122,7 +122,7 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info) {
if (type != RTM_NEWLINK) if (type != RTM_NEWLINK)
return 0; return 0;
r = sd_rtnl_message_link_get_ifindex(m, &info->ifindex); r = sd_rtnl_message_link_get_ifindex(m, &ifindex);
if (r < 0) if (r < 0)
return r; return r;
@ -130,11 +130,21 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info) {
if (r < 0) if (r < 0)
return r; return r;
if (patterns) {
char str[DECIMAL_STR_MAX(int)];
xsprintf(str, "%i", ifindex);
if (!strv_fnmatch(patterns, str, 0) && !strv_fnmatch(patterns, name, 0))
return 0;
}
r = sd_rtnl_message_link_get_type(m, &info->iftype); r = sd_rtnl_message_link_get_type(m, &info->iftype);
if (r < 0) if (r < 0)
return r; return r;
strscpy(info->name, sizeof info->name, name); strscpy(info->name, sizeof info->name, name);
info->ifindex = ifindex;
info->has_mac_address = info->has_mac_address =
sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 && sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 &&
@ -147,54 +157,7 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info) {
return 1; return 1;
} }
static int acquire_link_info_strv(sd_netlink *rtnl, char **l, LinkInfo **ret) { static int acquire_link_info(sd_netlink *rtnl, char **patterns, LinkInfo **ret) {
_cleanup_free_ LinkInfo *links = NULL;
char **i;
size_t c = 0;
int r;
assert(rtnl);
assert(ret);
links = new(LinkInfo, strv_length(l));
if (!links)
return log_oom();
STRV_FOREACH(i, l) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
int ifindex;
if (parse_ifindex(*i, &ifindex) >= 0)
r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
else {
r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0);
if (r < 0)
return rtnl_log_create_error(r);
r = sd_netlink_message_append_string(req, IFLA_IFNAME, *i);
}
if (r < 0)
return rtnl_log_create_error(r);
r = sd_netlink_call(rtnl, req, 0, &reply);
if (r < 0)
return log_error_errno(r, "Failed to request link: %m");
r = decode_link(reply, links + c);
if (r < 0)
return r;
if (r > 0)
c++;
}
typesafe_qsort(links, c, link_info_compare);
*ret = TAKE_PTR(links);
return (int) c;
}
static int acquire_link_info_all(sd_netlink *rtnl, LinkInfo **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_free_ LinkInfo *links = NULL; _cleanup_free_ LinkInfo *links = NULL;
size_t allocated = 0, c = 0; size_t allocated = 0, c = 0;
@ -220,7 +183,7 @@ static int acquire_link_info_all(sd_netlink *rtnl, LinkInfo **ret) {
if (!GREEDY_REALLOC(links, allocated, c+1)) if (!GREEDY_REALLOC(links, allocated, c+1))
return -ENOMEM; return -ENOMEM;
r = decode_link(i, links + c); r = decode_link(i, links + c, patterns);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r > 0)
@ -243,10 +206,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m"); return log_error_errno(r, "Failed to connect to netlink: %m");
if (argc > 1) c = acquire_link_info(rtnl, argc > 1 ? argv + 1 : NULL, &links);
c = acquire_link_info_strv(rtnl, argv + 1, &links);
else
c = acquire_link_info_all(rtnl, &links);
if (c < 0) if (c < 0)
return c; return c;
@ -887,11 +847,11 @@ static int link_status(int argc, char *argv[], void *userdata) {
log_debug_errno(r, "Failed to open hardware database: %m"); log_debug_errno(r, "Failed to open hardware database: %m");
if (arg_all) if (arg_all)
c = acquire_link_info_all(rtnl, &links); c = acquire_link_info(rtnl, NULL, &links);
else if (argc <= 1) else if (argc <= 1)
return system_status(rtnl, hwdb); return system_status(rtnl, hwdb);
else else
c = acquire_link_info_strv(rtnl, argv + 1, &links); c = acquire_link_info(rtnl, argv + 1, &links);
if (c < 0) if (c < 0)
return c; return c;
@ -965,10 +925,7 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m"); return log_error_errno(r, "Failed to connect to netlink: %m");
if (argc > 1) c = acquire_link_info(rtnl, argc > 1 ? argv + 1 : NULL, &links);
c = acquire_link_info_strv(rtnl, argv + 1, &links);
else
c = acquire_link_info_all(rtnl, &links);
if (c < 0) if (c < 0)
return c; return c;
@ -1078,9 +1035,9 @@ static int help(void) {
" --no-legend Do not show the headers and footers\n" " --no-legend Do not show the headers and footers\n"
" -a --all Show status for all links\n\n" " -a --all Show status for all links\n\n"
"Commands:\n" "Commands:\n"
" list [LINK...] List links\n" " list [PATTERN...] List links\n"
" status [LINK...] Show link status\n" " status [PATTERN...] Show link status\n"
" lldp [LINK...] Show LLDP neighbors\n" " lldp [PATTERN...] Show LLDP neighbors\n"
" label Show current address label entries in the kernel\n" " label Show current address label entries in the kernel\n"
"\nSee the %s for details.\n" "\nSee the %s for details.\n"
, program_invocation_short_name , program_invocation_short_name

View File

@ -276,6 +276,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output) print(output)
self.assertRegex(output, '00:50:56:c0:00:28') self.assertRegex(output, '00:50:56:c0:00:28')
output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
self.assertRegex(output, '1 lo ')
self.assertRegex(output, 'dropin-test')
output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
self.assertNotRegex(output, '1 lo ')
self.assertRegex(output, 'dropin-test')
output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
self.assertNotRegex(output, '1 lo ')
self.assertRegex(output, 'dropin-test')
def test_bridge(self): def test_bridge(self):
self.copy_unit_to_networkd_unit_path('25-bridge.netdev') self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
self.start_networkd() self.start_networkd()