]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/ipaddress.c
Merge branch 'master' into iproute2-next
[mirror_iproute2.git] / ip / ipaddress.c
index d01d7030b4420257dea1f05665578c0946d200d8..c0c1fbbe4c74d10a8fadfedfac08333fe93b9db5 100644 (file)
@@ -49,9 +49,9 @@ static void usage(void) __attribute__((noreturn));
 
 static void usage(void)
 {
-       if (do_link) {
+       if (do_link)
                iplink_usage();
-       }
+
        fprintf(stderr, "Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]\n");
        fprintf(stderr, "                                                      [ CONFFLAG-LIST ]\n");
        fprintf(stderr, "       ip address del IFADDR dev IFNAME [mngtmpaddr]\n");
@@ -63,7 +63,7 @@ static void usage(void)
        fprintf(stderr, "       ip address {showdump|restore}\n");
        fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
        fprintf(stderr, "          [ broadcast ADDR ] [ anycast ADDR ]\n");
-       fprintf(stderr, "          [ label IFNAME ] [ scope SCOPE-ID ]\n");
+       fprintf(stderr, "          [ label IFNAME ] [ scope SCOPE-ID ] [ metric METRIC ]\n");
        fprintf(stderr, "SCOPE-ID := [ host | link | global | NUMBER ]\n");
        fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
        fprintf(stderr, "FLAG  := [ permanent | dynamic | secondary | primary |\n");
@@ -77,7 +77,7 @@ static void usage(void)
        fprintf(stderr, "          bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | lowpan |\n");
        fprintf(stderr, "          gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan | vti |\n");
        fprintf(stderr, "          nlmon | can | bond_slave | ipvlan | geneve | bridge_slave |\n");
-       fprintf(stderr, "          hsr | macsec | netdevsim\n");
+       fprintf(stderr, "          hsr | macsec | netdevsim }\n");
 
        exit(-1);
 }
@@ -240,7 +240,7 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
                const char *kind
                        = rta_getattr_str(linkinfo[IFLA_INFO_KIND]);
 
-               print_string(PRINT_FP, NULL, "%s", _SL_);
+               print_nl();
                print_string(PRINT_ANY, "info_kind", "    %s ", kind);
 
                lu = get_link_kind(kind);
@@ -269,7 +269,7 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
                const char *slave_kind
                        = rta_getattr_str(linkinfo[IFLA_INFO_SLAVE_KIND]);
 
-               print_string(PRINT_FP, NULL, "%s", _SL_);
+               print_nl();
                print_string(PRINT_ANY,
                             "info_slave_kind",
                             "    %s_slave ",
@@ -416,10 +416,10 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
        }
 
        if (vf_tx_rate->rate)
-               print_int(PRINT_ANY,
-                         "tx_rate",
-                         ", tx rate %d (Mbps)",
-                         vf_tx_rate->rate);
+               print_uint(PRINT_ANY,
+                          "tx_rate",
+                          ", tx rate %u (Mbps)",
+                          vf_tx_rate->rate);
 
        if (vf[IFLA_VF_RATE]) {
                struct ifla_vf_rate *vf_rate = RTA_DATA(vf[IFLA_VF_RATE]);
@@ -428,14 +428,14 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
 
                if (is_json_context()) {
                        open_json_object("rate");
-                       print_int(PRINT_JSON, "max_tx", NULL, max_tx);
-                       print_int(PRINT_ANY, "min_tx", NULL, min_tx);
+                       print_uint(PRINT_JSON, "max_tx", NULL, max_tx);
+                       print_uint(PRINT_ANY, "min_tx", NULL, min_tx);
                        close_json_object();
                } else {
                        if (max_tx)
-                               fprintf(fp, ", max_tx_rate %dMbps", max_tx);
+                               fprintf(fp, ", max_tx_rate %uMbps", max_tx);
                        if (min_tx)
-                               fprintf(fp, ", min_tx_rate %dMbps", min_tx);
+                               fprintf(fp, ", min_tx_rate %uMbps", min_tx);
                }
        }
 
@@ -554,42 +554,58 @@ static void print_vf_stats64(FILE *fp, struct rtattr *vfstats)
 
                /* RX stats */
                open_json_object("rx");
-               print_uint(PRINT_JSON, "bytes", NULL,
+               print_u64(PRINT_JSON, "bytes", NULL,
                           rta_getattr_u64(vf[IFLA_VF_STATS_RX_BYTES]));
-               print_uint(PRINT_JSON, "packets", NULL,
+               print_u64(PRINT_JSON, "packets", NULL,
                           rta_getattr_u64(vf[IFLA_VF_STATS_RX_PACKETS]));
-               print_uint(PRINT_JSON, "multicast", NULL,
+               print_u64(PRINT_JSON, "multicast", NULL,
                           rta_getattr_u64(vf[IFLA_VF_STATS_MULTICAST]));
-               print_uint(PRINT_JSON, "broadcast", NULL,
+               print_u64(PRINT_JSON, "broadcast", NULL,
                           rta_getattr_u64(vf[IFLA_VF_STATS_BROADCAST]));
+               if (vf[IFLA_VF_STATS_RX_DROPPED])
+                       print_u64(PRINT_JSON, "dropped", NULL,
+                                 rta_getattr_u64(vf[IFLA_VF_STATS_RX_DROPPED]));
                close_json_object();
 
                /* TX stats */
                open_json_object("tx");
-               print_uint(PRINT_JSON, "tx_bytes", NULL,
+               print_u64(PRINT_JSON, "tx_bytes", NULL,
                           rta_getattr_u64(vf[IFLA_VF_STATS_TX_BYTES]));
-               print_uint(PRINT_JSON, "tx_packets", NULL,
+               print_u64(PRINT_JSON, "tx_packets", NULL,
                           rta_getattr_u64(vf[IFLA_VF_STATS_TX_PACKETS]));
+               if (vf[IFLA_VF_STATS_TX_DROPPED])
+                       print_u64(PRINT_JSON, "dropped", NULL,
+                                 rta_getattr_u64(vf[IFLA_VF_STATS_TX_DROPPED]));
                close_json_object();
                close_json_object();
        } else {
                /* RX stats */
                fprintf(fp, "%s", _SL_);
-               fprintf(fp, "    RX: bytes  packets  mcast   bcast %s", _SL_);
+               fprintf(fp, "    RX: bytes  packets  mcast   bcast ");
+               if (vf[IFLA_VF_STATS_RX_DROPPED])
+                       fprintf(fp, "  dropped ");
+               fprintf(fp, "%s", _SL_);
                fprintf(fp, "    ");
 
                print_num(fp, 10, rta_getattr_u64(vf[IFLA_VF_STATS_RX_BYTES]));
                print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_RX_PACKETS]));
                print_num(fp, 7, rta_getattr_u64(vf[IFLA_VF_STATS_MULTICAST]));
                print_num(fp, 7, rta_getattr_u64(vf[IFLA_VF_STATS_BROADCAST]));
+               if (vf[IFLA_VF_STATS_RX_DROPPED])
+                       print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_RX_DROPPED]));
 
                /* TX stats */
                fprintf(fp, "%s", _SL_);
-               fprintf(fp, "    TX: bytes  packets %s", _SL_);
+               fprintf(fp, "    TX: bytes  packets ");
+               if (vf[IFLA_VF_STATS_TX_DROPPED])
+                       fprintf(fp, "  dropped ");
+               fprintf(fp, "%s", _SL_);
                fprintf(fp, "    ");
 
                print_num(fp, 10, rta_getattr_u64(vf[IFLA_VF_STATS_TX_BYTES]));
                print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_TX_PACKETS]));
+               if (vf[IFLA_VF_STATS_TX_DROPPED])
+                       print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_TX_DROPPED]));
        }
 }
 
@@ -608,69 +624,69 @@ static void __print_link_stats(FILE *fp, struct rtattr *tb[])
 
                /* RX stats */
                open_json_object("rx");
-               print_uint(PRINT_JSON, "bytes", NULL, s->rx_bytes);
-               print_uint(PRINT_JSON, "packets", NULL, s->rx_packets);
-               print_uint(PRINT_JSON, "errors", NULL, s->rx_errors);
-               print_uint(PRINT_JSON, "dropped", NULL, s->rx_dropped);
-               print_uint(PRINT_JSON, "over_errors", NULL, s->rx_over_errors);
-               print_uint(PRINT_JSON, "multicast", NULL, s->multicast);
+               print_u64(PRINT_JSON, "bytes", NULL, s->rx_bytes);
+               print_u64(PRINT_JSON, "packets", NULL, s->rx_packets);
+               print_u64(PRINT_JSON, "errors", NULL, s->rx_errors);
+               print_u64(PRINT_JSON, "dropped", NULL, s->rx_dropped);
+               print_u64(PRINT_JSON, "over_errors", NULL, s->rx_over_errors);
+               print_u64(PRINT_JSON, "multicast", NULL, s->multicast);
                if (s->rx_compressed)
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "compressed", NULL, s->rx_compressed);
 
                /* RX error stats */
                if (show_stats > 1) {
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "length_errors",
                                   NULL, s->rx_length_errors);
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "crc_errors",
                                   NULL, s->rx_crc_errors);
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "frame_errors",
                                   NULL, s->rx_frame_errors);
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "fifo_errors",
                                   NULL, s->rx_fifo_errors);
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "missed_errors",
                                   NULL, s->rx_missed_errors);
                        if (s->rx_nohandler)
-                               print_uint(PRINT_JSON,
+                               print_u64(PRINT_JSON,
                                           "nohandler", NULL, s->rx_nohandler);
                }
                close_json_object();
 
                /* TX stats */
                open_json_object("tx");
-               print_uint(PRINT_JSON, "bytes", NULL, s->tx_bytes);
-               print_uint(PRINT_JSON, "packets", NULL, s->tx_packets);
-               print_uint(PRINT_JSON, "errors", NULL, s->tx_errors);
-               print_uint(PRINT_JSON, "dropped", NULL, s->tx_dropped);
-               print_uint(PRINT_JSON,
+               print_u64(PRINT_JSON, "bytes", NULL, s->tx_bytes);
+               print_u64(PRINT_JSON, "packets", NULL, s->tx_packets);
+               print_u64(PRINT_JSON, "errors", NULL, s->tx_errors);
+               print_u64(PRINT_JSON, "dropped", NULL, s->tx_dropped);
+               print_u64(PRINT_JSON,
                           "carrier_errors",
                           NULL, s->tx_carrier_errors);
-               print_uint(PRINT_JSON, "collisions", NULL, s->collisions);
+               print_u64(PRINT_JSON, "collisions", NULL, s->collisions);
                if (s->tx_compressed)
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "compressed", NULL, s->tx_compressed);
 
                /* TX error stats */
                if (show_stats > 1) {
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "aborted_errors",
                                   NULL, s->tx_aborted_errors);
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "fifo_errors",
                                   NULL, s->tx_fifo_errors);
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "window_errors",
                                   NULL, s->tx_window_errors);
-                       print_uint(PRINT_JSON,
+                       print_u64(PRINT_JSON,
                                   "heartbeat_errors",
                                   NULL, s->tx_heartbeat_errors);
                        if (carrier_changes)
-                               print_uint(PRINT_JSON, "carrier_changes", NULL,
+                               print_u64(PRINT_JSON, "carrier_changes", NULL,
                                           rta_getattr_u32(carrier_changes));
                }
 
@@ -749,7 +765,7 @@ static void print_link_stats(FILE *fp, struct nlmsghdr *n)
        parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi),
                     n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
        __print_link_stats(fp, tb);
-       fprintf(fp, "%s", _SL_);
+       print_nl();
 }
 
 static int print_linkinfo_brief(FILE *fp, const char *name,
@@ -837,10 +853,8 @@ int print_linkinfo(const struct sockaddr_nl *who,
        if (!name)
                return -1;
 
-       if (filter.label &&
-           (!filter.family || filter.family == AF_PACKET) &&
-           fnmatch(filter.label, name, 0))
-               return -1;
+       if (filter.label)
+               return 0;
 
        if (tb[IFLA_GROUP]) {
                int group = rta_getattr_u32(tb[IFLA_GROUP]);
@@ -915,7 +929,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
                print_link_event(fp, rta_getattr_u32(tb[IFLA_EVENT]));
 
        if (!filter.family || filter.family == AF_PACKET || show_details) {
-               print_string(PRINT_FP, NULL, "%s", _SL_);
+               print_nl();
                print_string(PRINT_ANY,
                             "link_type",
                             "    link/%s ",
@@ -955,15 +969,36 @@ int print_linkinfo(const struct sockaddr_nl *who,
                if (is_json_context()) {
                        print_int(PRINT_JSON, "link_netnsid", NULL, id);
                } else {
-                       if (id >= 0)
-                               print_int(PRINT_FP, NULL,
-                                         " link-netnsid %d", id);
-                       else
+                       if (id >= 0) {
+                               char *name = get_name_from_nsid(id);
+
+                               if (name)
+                                       print_string(PRINT_FP, NULL,
+                                                    " link-netns %s", name);
+                               else
+                                       print_int(PRINT_FP, NULL,
+                                                 " link-netnsid %d", id);
+                       } else
                                print_string(PRINT_FP, NULL,
                                             " link-netnsid %s", "unknown");
                }
        }
 
+       if (tb[IFLA_NEW_NETNSID]) {
+               int id = rta_getattr_u32(tb[IFLA_NEW_NETNSID]);
+               char *name = get_name_from_nsid(id);
+
+               if (name)
+                       print_string(PRINT_FP, NULL, " new-netns %s", name);
+               else
+                       print_int(PRINT_FP, NULL, " new-netnsid %d", id);
+       }
+       if (tb[IFLA_NEW_IFINDEX]) {
+               int id = rta_getattr_u32(tb[IFLA_NEW_IFINDEX]);
+
+               print_int(PRINT_FP, NULL, " new-ifindex %d", id);
+       }
+
        if (tb[IFLA_PROTO_DOWN]) {
                if (rta_getattr_u8(tb[IFLA_PROTO_DOWN]))
                        print_bool(PRINT_ANY,
@@ -977,6 +1012,16 @@ int print_linkinfo(const struct sockaddr_nl *who,
                                   " promiscuity %u ",
                                   rta_getattr_u32(tb[IFLA_PROMISCUITY]));
 
+               if (tb[IFLA_MIN_MTU])
+                       print_uint(PRINT_ANY,
+                                  "min_mtu", "minmtu %u ",
+                                  rta_getattr_u32(tb[IFLA_MIN_MTU]));
+
+               if (tb[IFLA_MAX_MTU])
+                       print_uint(PRINT_ANY,
+                                  "max_mtu", "maxmtu %u ",
+                                  rta_getattr_u32(tb[IFLA_MAX_MTU]));
+
                if (tb[IFLA_LINKINFO])
                        print_linktype(fp, tb[IFLA_LINKINFO]);
 
@@ -1045,7 +1090,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
                xdp_dump(fp, tb[IFLA_XDP], true, true);
 
        if (do_link && show_stats) {
-               print_string(PRINT_FP, NULL, "%s", _SL_);
+               print_nl();
                __print_link_stats(fp, tb);
        }
 
@@ -1328,6 +1373,10 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
                                                           rta_tb[IFA_ADDRESS]));
                }
                print_int(PRINT_ANY, "prefixlen", "/%d ", ifa->ifa_prefixlen);
+
+               if (rta_tb[IFA_RT_PRIORITY])
+                       print_uint(PRINT_ANY, "metric", "metric %u ",
+                                  rta_getattr_u32(rta_tb[IFA_RT_PRIORITY]));
        }
 
        if (brief)
@@ -1369,7 +1418,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
        if (rta_tb[IFA_CACHEINFO]) {
                struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
 
-               print_string(PRINT_FP, NULL, "%s", _SL_);
+               print_nl();
                print_string(PRINT_FP, NULL, "       valid_lft ", NULL);
 
                if (ci->ifa_valid == INFINITY_LIFE_TIME) {
@@ -1649,7 +1698,7 @@ static int ipaddr_flush(void)
        filter.flushe = sizeof(flushb);
 
        while ((max_flush_loops == 0) || (round < max_flush_loops)) {
-               if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
+               if (rtnl_addrdump_req(&rth, filter.family) < 0) {
                        perror("Cannot send dump request");
                        exit(1);
                }
@@ -1729,7 +1778,7 @@ static int iplink_filter_req(struct nlmsghdr *nlh, int reqlen)
 int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
                     struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
 {
-       if (rtnl_wilddump_req_filter_fn(&rth, preferred_family, RTM_GETLINK,
+       if (rtnl_linkdump_req_filter_fn(&rth, preferred_family,
                                        filter_fn) < 0) {
                perror("Cannot send dump request");
                return 1;
@@ -1741,7 +1790,7 @@ int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
        }
 
        if (ainfo) {
-               if (rtnl_wilddump_request(&rth, family, RTM_GETADDR) < 0) {
+               if (rtnl_addrdump_req(&rth, family) < 0) {
                        perror("Cannot send dump request");
                        return 1;
                }
@@ -1866,7 +1915,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
                if (ipadd_save_prep())
                        exit(1);
 
-               if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETADDR) < 0) {
+               if (rtnl_addrdump_req(&rth, preferred_family) < 0) {
                        perror("Cannot send dump request");
                        exit(1);
                }
@@ -1897,7 +1946,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
                        exit(1);
                }
                delete_json_obj();
-               exit(0);
+               goto out;
        }
 
        if (filter.family != AF_PACKET) {
@@ -1967,16 +2016,22 @@ ipaddr_loop_each_vf(struct rtattr *tb[], int vfnum, int *min, int *max)
        exit(1);
 }
 
-void ipaddr_get_vf_rate(int vfnum, int *min, int *max, int idx)
+void ipaddr_get_vf_rate(int vfnum, int *min, int *max, const char *dev)
 {
        struct nlmsg_chain linfo = { NULL, NULL};
        struct rtattr *tb[IFLA_MAX+1];
        struct ifinfomsg *ifi;
        struct nlmsg_list *l;
        struct nlmsghdr *n;
-       int len;
+       int idx, len;
 
-       if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) {
+       idx = ll_name_to_index(dev);
+       if (idx == 0) {
+               fprintf(stderr, "Device %s does not exist\n", dev);
+               exit(1);
+       }
+
+       if (rtnl_linkdump_req(&rth, AF_UNSPEC) < 0) {
                perror("Cannot send dump request");
                exit(1);
        }
@@ -2034,6 +2089,16 @@ static bool ipaddr_is_multicast(inet_prefix *a)
                return false;
 }
 
+static bool is_valid_label(const char *dev, const char *label)
+{
+       size_t len = strlen(dev);
+
+       if (strncmp(label, dev, len) != 0)
+               return false;
+
+       return label[len] == '\0' || label[len] == ':';
+}
+
 static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 {
        struct {
@@ -2119,6 +2184,15 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
                        NEXT_ARG();
                        l = *argv;
                        addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1);
+               } else if (matches(*argv, "metric") == 0 ||
+                          matches(*argv, "priority") == 0 ||
+                          matches(*argv, "preference") == 0) {
+                       __u32 metric;
+
+                       NEXT_ARG();
+                       if (get_u32(&metric, *argv, 0))
+                               invarg("\"metric\" value is invalid\n", *argv);
+                       addattr32(&req.n, sizeof(req), IFA_RT_PRIORITY, metric);
                } else if (matches(*argv, "valid_lft") == 0) {
                        if (valid_lftp)
                                duparg("valid_lft", *argv);
@@ -2168,8 +2242,10 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
                fprintf(stderr, "Not enough information: \"dev\" argument is required.\n");
                return -1;
        }
-       if (l && matches(d, l) != 0) {
-               fprintf(stderr, "\"dev\" (%s) must match \"label\" (%s).\n", d, l);
+       if (l && !is_valid_label(d, l)) {
+               fprintf(stderr,
+                       "\"label\" (%s) must match \"dev\" (%s) or be prefixed by \"dev\" with a colon.\n",
+                       l, d);
                return -1;
        }
 
@@ -2211,10 +2287,9 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
        if (!scoped && cmd != RTM_DELADDR)
                req.ifa.ifa_scope = default_scope(&lcl);
 
-       if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
-               fprintf(stderr, "Cannot find device \"%s\"\n", d);
-               return -1;
-       }
+       req.ifa.ifa_index = ll_name_to_index(d);
+       if (!req.ifa.ifa_index)
+               return nodev(d);
 
        if (valid_lftp || preferred_lftp) {
                struct ifa_cacheinfo cinfo = {};