mirror of
https://github.com/systemd/systemd.git
synced 2024-11-24 02:33:36 +08:00
networkctl: extend "networkctl list" and "networctl lldp" to optionally take interface names
This way, the output may be reduced to only show data about the specified interfaces.
This commit is contained in:
parent
7d367b45f6
commit
e997c4b09d
@ -102,12 +102,14 @@
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>list</command>
|
||||
<optional><replaceable>LINK...</replaceable></optional>
|
||||
</term>
|
||||
|
||||
<listitem>
|
||||
<para>Show a list of existing links and their
|
||||
status. Produces output similar to <programlisting>
|
||||
IDX LINK TYPE OPERATIONAL SETUP
|
||||
<para>Show a list of existing links and their status. If no further arguments are specified shows all links,
|
||||
otherwise just the specified links. Produces output similar to:
|
||||
|
||||
<programlisting>IDX LINK TYPE OPERATIONAL SETUP
|
||||
1 lo loopback carrier unmanaged
|
||||
2 eth0 ether routable configured
|
||||
3 virbr0 ether no-carrier unmanaged
|
||||
@ -128,10 +130,10 @@ IDX LINK TYPE OPERATIONAL SETUP
|
||||
state, kernel module driver, hardware and IP address,
|
||||
configured DNS servers, etc.</para>
|
||||
|
||||
<para>When no links are specified, routable links are
|
||||
shown. Also see the option <option>--all</option>.</para>
|
||||
<para>When no links are specified, an overall network status is shown. Also see the option
|
||||
<option>--all</option>.</para>
|
||||
|
||||
<para>Produces output similar to
|
||||
<para>Produces output similar to:
|
||||
<programlisting>
|
||||
● State: routable
|
||||
Address: 10.193.76.5 on eth0
|
||||
@ -148,11 +150,26 @@ IDX LINK TYPE OPERATIONAL SETUP
|
||||
<varlistentry>
|
||||
<term>
|
||||
<command>lldp</command>
|
||||
<optional><replaceable>LINK...</replaceable></optional>
|
||||
</term>
|
||||
|
||||
<listitem>
|
||||
<para>Show LLDP (Link Layer Discovery Protocol)
|
||||
status.</para>
|
||||
<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 on the specific interface, see
|
||||
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
details.</para>
|
||||
|
||||
<para>Produces output similar to:
|
||||
<programlisting>LINK CHASSIS ID SYSTEM NAME CAPS PORT ID PORT DESCRIPTION
|
||||
enp0s25 00:e0:4c:00:00:00 GS1900 ..b........ 2 Port #2
|
||||
|
||||
Capability Flags:
|
||||
o - Other; p - Repeater; b - Bridge; w - WLAN Access Point; r - Router;
|
||||
t - Telephone; d - DOCSIS cable device; a - Station; c - Customer VLAN;
|
||||
s - Service VLAN, m - Two-port MAC Relay (TPMR)
|
||||
|
||||
1 neighbors listed.</programlisting></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
@ -73,7 +73,7 @@ static int link_get_type_string(unsigned short iftype, sd_device *d, char **ret)
|
||||
* to show a more useful type string for
|
||||
* them */
|
||||
|
||||
(void)sd_device_get_devtype(d, &devtype);
|
||||
(void) sd_device_get_devtype(d, &devtype);
|
||||
|
||||
if (streq_ptr(devtype, "wlan"))
|
||||
id = "wlan";
|
||||
@ -107,7 +107,7 @@ static int link_get_type_string(unsigned short iftype, sd_device *d, char **ret)
|
||||
}
|
||||
|
||||
typedef struct LinkInfo {
|
||||
const char *name;
|
||||
char name[IFNAMSIZ+1];
|
||||
int ifindex;
|
||||
unsigned short iftype;
|
||||
} LinkInfo;
|
||||
@ -118,44 +118,56 @@ static int link_info_compare(const void *a, const void *b) {
|
||||
return x->ifindex - y->ifindex;
|
||||
}
|
||||
|
||||
static int decode_link_one(sd_netlink_message *m, LinkInfo *info) {
|
||||
const char *name;
|
||||
unsigned short iftype;
|
||||
uint16_t type;
|
||||
int ifindex, r;
|
||||
|
||||
assert(m);
|
||||
assert(info);
|
||||
|
||||
r = sd_netlink_message_get_type(m, &type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type != RTM_NEWLINK)
|
||||
return 0;
|
||||
|
||||
r = sd_rtnl_message_link_get_ifindex(m, &ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_string(m, IFLA_IFNAME, &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_rtnl_message_link_get_type(m, &iftype);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
strncpy(info->name, name, sizeof(info->name));
|
||||
info->ifindex = ifindex;
|
||||
info->iftype = iftype;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int decode_and_sort_links(sd_netlink_message *m, LinkInfo **ret) {
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
size_t size = 0, c = 0;
|
||||
size_t allocated = 0, c = 0;
|
||||
sd_netlink_message *i;
|
||||
int r;
|
||||
|
||||
for (i = m; i; i = sd_netlink_message_next(i)) {
|
||||
const char *name;
|
||||
unsigned short iftype;
|
||||
uint16_t type;
|
||||
int ifindex;
|
||||
|
||||
r = sd_netlink_message_get_type(i, &type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type != RTM_NEWLINK)
|
||||
continue;
|
||||
|
||||
r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_rtnl_message_link_get_type(i, &iftype);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!GREEDY_REALLOC(links, size, c+1))
|
||||
if (!GREEDY_REALLOC(links, allocated, c+1))
|
||||
return -ENOMEM;
|
||||
|
||||
links[c].name = name;
|
||||
links[c].ifindex = ifindex;
|
||||
links[c].iftype = iftype;
|
||||
c++;
|
||||
r = decode_link_one(i, links + c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
c++;
|
||||
}
|
||||
|
||||
qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
|
||||
@ -197,7 +209,59 @@ static void setup_state_to_color(const char *state, const char **on, const char
|
||||
*on = *off = "";
|
||||
}
|
||||
|
||||
static int acquire_link_info(LinkInfo **ret) {
|
||||
static int acquire_link_info_strv(char **l, LinkInfo **ret) {
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
char **i;
|
||||
size_t c = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
links = new(LinkInfo, strv_length(l));
|
||||
if (!links)
|
||||
return log_oom();
|
||||
|
||||
r = sd_netlink_open(&rtnl);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to netlink: %m");
|
||||
|
||||
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_one(reply, links + c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
c++;
|
||||
}
|
||||
|
||||
qsort_safe(links, c, sizeof(LinkInfo), link_info_compare);
|
||||
|
||||
*ret = links;
|
||||
links = NULL;
|
||||
|
||||
return (int) c;
|
||||
}
|
||||
|
||||
static int acquire_link_info_all(LinkInfo **ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
|
||||
@ -232,7 +296,10 @@ static int list_links(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
int c, i;
|
||||
|
||||
c = acquire_link_info(&links);
|
||||
if (argc > 1)
|
||||
c = acquire_link_info_strv(argv + 1, &links);
|
||||
else
|
||||
c = acquire_link_info_all(&links);
|
||||
if (c < 0)
|
||||
return c;
|
||||
|
||||
@ -553,7 +620,6 @@ static int link_status_one(
|
||||
|
||||
r = sd_netlink_message_append_string(req, IFLA_IFNAME, name);
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return rtnl_log_create_error(r);
|
||||
|
||||
@ -793,7 +859,10 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_free_ LinkInfo *links = NULL;
|
||||
int i, r, c, j;
|
||||
|
||||
c = acquire_link_info(&links);
|
||||
if (argc > 1)
|
||||
c = acquire_link_info_strv(argv + 1, &links);
|
||||
else
|
||||
c = acquire_link_info_all(&links);
|
||||
if (c < 0)
|
||||
return c;
|
||||
|
||||
@ -874,11 +943,11 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
if (arg_legend)
|
||||
printf("\nCapabilities:\n"
|
||||
printf("\nCapability Flags:\n"
|
||||
"o - Other; p - Repeater; b - Bridge; w - WLAN Access Point; r - Router;\n"
|
||||
"t - Telephone; d - DOCSIS cable device; a - Station; c - Customer VLAN;\n"
|
||||
"s - Service VLAN, m - Two-port MAC Relay (TPMR)\n\n"
|
||||
"Total entries displayed: %i\n", j);
|
||||
"%i neighbors listed.\n", j);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -892,9 +961,9 @@ static void help(void) {
|
||||
" --no-legend Do not show the headers and footers\n"
|
||||
" -a --all Show status for all links\n\n"
|
||||
"Commands:\n"
|
||||
" list List links\n"
|
||||
" list [LINK...] List links\n"
|
||||
" status [LINK...] Show link status\n"
|
||||
" lldp Show lldp neighbors\n"
|
||||
" lldp [LINK...] Show lldp neighbors\n"
|
||||
, program_invocation_short_name);
|
||||
}
|
||||
|
||||
@ -956,9 +1025,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
static int networkctl_main(int argc, char *argv[]) {
|
||||
const Verb verbs[] = {
|
||||
{ "list", VERB_ANY, 1, VERB_DEFAULT, list_links },
|
||||
{ "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
|
||||
{ "status", VERB_ANY, VERB_ANY, 0, link_status },
|
||||
{ "lldp", VERB_ANY, 1, 0, link_lldp_status },
|
||||
{ "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
|
||||
{}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user