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:
commit
a0279563d7
@ -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>
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user