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>
<term>
<command>list</command>
<optional><replaceable>LINK</replaceable></optional>
<optional><replaceable>PATTERN</replaceable></optional>
</term>
<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:
<programlisting>IDX LINK TYPE OPERATIONAL SETUP
@ -180,13 +182,13 @@
<varlistentry>
<term>
<command>status</command>
<optional><replaceable>LINK</replaceable></optional>
<optional><replaceable>PATTERN</replaceable></optional>
</term>
<listitem>
<para>Show information about the specified links: type,
state, kernel module driver, hardware and IP address,
configured DNS servers, etc.</para>
<para>Show information about the specified links: type, state, kernel module driver, hardware and
IP address, configured DNS servers, etc. If one ore more <replaceable>PATTERN</replaceable>s are
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
<option>--all</option>.</para>
@ -208,13 +210,14 @@
<varlistentry>
<term>
<command>lldp</command>
<optional><replaceable>LINK</replaceable></optional>
<optional><replaceable>PATTERN</replaceable></optional>
</term>
<listitem>
<para>Show discovered LLDP (Link Layer Discovery Protocol) neighbors. If one or more link names are specified
only neighbors on those interfaces are shown. 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
<para>Show discovered LLDP (Link Layer Discovery Protocol) neighbors. If one or more
<replaceable>PATTERN</replaceable>s are specified only neighbors on those interfaces are shown.
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
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);
}
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;
uint16_t type;
int r;
int ifindex, r;
assert(m);
assert(info);
@ -122,7 +122,7 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info) {
if (type != RTM_NEWLINK)
return 0;
r = sd_rtnl_message_link_get_ifindex(m, &info->ifindex);
r = sd_rtnl_message_link_get_ifindex(m, &ifindex);
if (r < 0)
return r;
@ -130,11 +130,21 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info) {
if (r < 0)
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);
if (r < 0)
return r;
strscpy(info->name, sizeof info->name, name);
info->ifindex = ifindex;
info->has_mac_address =
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;
}
static int acquire_link_info_strv(sd_netlink *rtnl, char **l, 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) {
static int acquire_link_info(sd_netlink *rtnl, char **patterns, LinkInfo **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_free_ LinkInfo *links = NULL;
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))
return -ENOMEM;
r = decode_link(i, links + c);
r = decode_link(i, links + c, patterns);
if (r < 0)
return r;
if (r > 0)
@ -243,10 +206,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (argc > 1)
c = acquire_link_info_strv(rtnl, argv + 1, &links);
else
c = acquire_link_info_all(rtnl, &links);
c = acquire_link_info(rtnl, argc > 1 ? argv + 1 : NULL, &links);
if (c < 0)
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");
if (arg_all)
c = acquire_link_info_all(rtnl, &links);
c = acquire_link_info(rtnl, NULL, &links);
else if (argc <= 1)
return system_status(rtnl, hwdb);
else
c = acquire_link_info_strv(rtnl, argv + 1, &links);
c = acquire_link_info(rtnl, argv + 1, &links);
if (c < 0)
return c;
@ -965,10 +925,7 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (argc > 1)
c = acquire_link_info_strv(rtnl, argv + 1, &links);
else
c = acquire_link_info_all(rtnl, &links);
c = acquire_link_info(rtnl, argc > 1 ? argv + 1 : NULL, &links);
if (c < 0)
return c;
@ -1078,9 +1035,9 @@ static int help(void) {
" --no-legend Do not show the headers and footers\n"
" -a --all Show status for all links\n\n"
"Commands:\n"
" list [LINK...] List links\n"
" status [LINK...] Show link status\n"
" lldp [LINK...] Show LLDP neighbors\n"
" list [PATTERN...] List links\n"
" status [PATTERN...] Show link status\n"
" lldp [PATTERN...] Show LLDP neighbors\n"
" label Show current address label entries in the kernel\n"
"\nSee the %s for details.\n"
, program_invocation_short_name

View File

@ -276,6 +276,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
print(output)
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):
self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
self.start_networkd()