]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkctl: extend "networkctl list" and "networctl lldp" to optionally take interfac...
authorLennart Poettering <lennart@poettering.net>
Fri, 19 Feb 2016 17:57:11 +0000 (18:57 +0100)
committerLennart Poettering <lennart@poettering.net>
Sun, 21 Feb 2016 19:40:57 +0000 (20:40 +0100)
This way, the output may be reduced to only show data about the specified
interfaces.

man/networkctl.xml
src/network/networkctl.c

index c688714b307ca653dc03964b60ae7b729ac4b08b..24e1de6986c5a65f4383764be5d3b8f60a58d6e6 100644 (file)
       <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>
index 9838e7a5a675a33de41e594af618a02f951a0920..d19bf131cdab7400c8c0ffc88d6be9153f58a4eb 100644 (file)
@@ -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_and_sort_links(sd_netlink_message *m, LinkInfo **ret) {
-        _cleanup_free_ LinkInfo *links = NULL;
-        size_t size = 0, c = 0;
-        sd_netlink_message *i;
-        int r;
+static int decode_link_one(sd_netlink_message *m, LinkInfo *info) {
+        const char *name;
+        unsigned short iftype;
+        uint16_t type;
+        int ifindex, r;
 
-        for (i = m; i; i = sd_netlink_message_next(i)) {
-                const char *name;
-                unsigned short iftype;
-                uint16_t type;
-                int ifindex;
+        assert(m);
+        assert(info);
 
-                r = sd_netlink_message_get_type(i, &type);
-                if (r < 0)
-                        return r;
+        r = sd_netlink_message_get_type(m, &type);
+        if (r < 0)
+                return r;
 
-                if (type != RTM_NEWLINK)
-                        continue;
+        if (type != RTM_NEWLINK)
+                return 0;
 
-                r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
-                if (r < 0)
-                        return r;
+        r = sd_rtnl_message_link_get_ifindex(m, &ifindex);
+        if (r < 0)
+                return r;
 
-                r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
-                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(i, &iftype);
-                if (r < 0)
-                        return r;
+        r = sd_rtnl_message_link_get_type(m, &iftype);
+        if (r < 0)
+                return r;
 
-                if (!GREEDY_REALLOC(links, size, c+1))
+        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 allocated = 0, c = 0;
+        sd_netlink_message *i;
+        int r;
+
+        for (i = m; i; i = sd_netlink_message_next(i)) {
+                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 },
                 {}
         };