]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/iplink.c
libnetlink: add size argument to rtnl_talk
[mirror_iproute2.git] / ip / iplink.c
index 5dd606062d9c2673288804a668b5dec5685dba90..a4a498055d463518028e1e1435b86c828e9ca853 100644 (file)
@@ -32,6 +32,7 @@
 #include "rt_names.h"
 #include "utils.h"
 #include "ip_common.h"
+#include "namespace.h"
 
 #define IPLINK_IOCTL_COMPAT    1
 #ifndef LIBDIR
@@ -52,9 +53,9 @@ void iplink_usage(void)
                fprintf(stderr, "                   [ numtxqueues QUEUE_COUNT ]\n");
                fprintf(stderr, "                   [ numrxqueues QUEUE_COUNT ]\n");
                fprintf(stderr, "                   type TYPE [ ARGS ]\n");
-               fprintf(stderr, "       ip link delete DEV type TYPE [ ARGS ]\n");
+               fprintf(stderr, "       ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n");
                fprintf(stderr, "\n");
-               fprintf(stderr, "       ip link set { dev DEVICE | group DEVGROUP } [ { up | down } ]\n");
+               fprintf(stderr, "       ip link set { DEVICE | dev DEVICE | group DEVGROUP } [ { up | down } ]\n");
        } else
                fprintf(stderr, "Usage: ip link set DEVICE [ { up | down } ]\n");
 
@@ -71,6 +72,7 @@ void iplink_usage(void)
        fprintf(stderr, "                         [ mtu MTU ]\n");
        fprintf(stderr, "                         [ netns PID ]\n");
        fprintf(stderr, "                         [ netns NAME ]\n");
+       fprintf(stderr, "                         [ link-netnsid ID ]\n");
        fprintf(stderr, "                         [ alias NAME ]\n");
        fprintf(stderr, "                         [ vf NUM [ mac LLADDR ]\n");
        fprintf(stderr, "                                  [ vlan VLANID [ qos VLAN-QOS ] ]\n");
@@ -78,18 +80,20 @@ void iplink_usage(void)
        fprintf(stderr, "                                  [ rate TXRATE ] ] \n");
 
        fprintf(stderr, "                                  [ spoofchk { on | off} ] ] \n");
+       fprintf(stderr, "                                  [ query_rss { on | off} ] ] \n");
        fprintf(stderr, "                                  [ state { auto | enable | disable} ] ]\n");
        fprintf(stderr, "                         [ master DEVICE ]\n");
        fprintf(stderr, "                         [ nomaster ]\n");
        fprintf(stderr, "                         [ addrgenmode { eui64 | none } ]\n");
-       fprintf(stderr, "       ip link show [ DEVICE | group GROUP ] [up]\n");
+       fprintf(stderr, "       ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n");
 
        if (iplink_have_newlink()) {
+               fprintf(stderr, "       ip link help [ TYPE ]\n");
                fprintf(stderr, "\n");
                fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
                fprintf(stderr, "          bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n");
                fprintf(stderr, "          gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n");
-               fprintf(stderr, "          bond_slave }\n");
+               fprintf(stderr, "          bond_slave | ipvlan }\n");
        }
        exit(-1);
 }
@@ -328,6 +332,18 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
                        ivs.vf = vf;
                        addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs));
 
+               } else if (matches(*argv, "query_rss") == 0) {
+                       struct ifla_vf_rss_query_en ivs;
+                       NEXT_ARG();
+                       if (matches(*argv, "on") == 0)
+                               ivs.setting = 1;
+                       else if (matches(*argv, "off") == 0)
+                               ivs.setting = 0;
+                       else
+                               invarg("Invalid \"query_rss\" value\n", *argv);
+                       ivs.vf = vf;
+                       addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(ivs));
+
                } else if (matches(*argv, "state") == 0) {
                        struct ifla_vf_link_state ivl;
                        NEXT_ARG();
@@ -384,6 +400,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
        int numtxqueues = -1;
        int numrxqueues = -1;
        int dev_index = 0;
+       int link_netnsid = -1;
 
        *group = -1;
        ret = argc;
@@ -439,7 +456,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
                        NEXT_ARG();
                        if (netns != -1)
                                duparg("netns", *argv);
-                       if ((netns = get_netns_fd(*argv)) >= 0)
+                       if ((netns = netns_get_fd(*argv)) >= 0)
                                addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
                        else if (get_integer(&netns, *argv, 0) == 0)
                                addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
@@ -586,6 +603,14 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
                        addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode);
                        addattr_nest_end(&req->n, afs6);
                        addattr_nest_end(&req->n, afs);
+               } else if (matches(*argv, "link-netnsid") == 0) {
+                       NEXT_ARG();
+                       if (link_netnsid != -1)
+                               duparg("link-netnsid", *argv);
+                       if (get_integer(&link_netnsid, *argv, 0))
+                               invarg("Invalid \"link-netnsid\" value\n", *argv);
+                       addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
+                                 link_netnsid);
                } else {
                        if (strcmp(*argv, "dev") == 0) {
                                NEXT_ARG();
@@ -649,7 +674,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 
                        req.i.ifi_index = 0;
                        addattr32(&req.n, sizeof(req), IFLA_GROUP, group);
-                       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+                       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                                exit(2);
                        return 0;
                }
@@ -705,11 +730,11 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
        }
 
        if (type) {
-               struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
+               struct rtattr *linkinfo;
                char slavebuf[128], *ulinep = strchr(type, '_');
                int iflatype;
 
-               addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
+               linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
                addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
                         strlen(type));
 
@@ -727,14 +752,13 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
                        iflatype = IFLA_INFO_DATA;
                }
                if (lu && argc) {
-                       struct rtattr * data = NLMSG_TAIL(&req.n);
-                       addattr_l(&req.n, sizeof(req), iflatype, NULL, 0);
+                       struct rtattr *data = addattr_nest(&req.n, sizeof(req), iflatype);
 
                        if (lu->parse_opt &&
                            lu->parse_opt(lu, argc, argv, &req.n))
                                return -1;
 
-                       data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
+                       addattr_nest_end(&req.n, data);
                } else if (argc) {
                        if (matches(*argv, "help") == 0)
                                usage();
@@ -742,14 +766,14 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
                                        "Try \"ip link help\".\n", *argv);
                        return -1;
                }
-               linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
+               addattr_nest_end(&req.n, linkinfo);
        } else if (flags & NLM_F_CREATE) {
                fprintf(stderr, "Not enough information: \"type\" argument "
                                "is required\n");
                return -1;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
                exit(2);
 
        return 0;
@@ -759,7 +783,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
 {
        int len;
        struct iplink_req req;
-       char answer[16384];
+       struct {
+               struct nlmsghdr n;
+               char buf[16384];
+       } answer;
 
        memset(&req, 0, sizeof(req));
 
@@ -779,10 +806,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
        }
        addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, (struct nlmsghdr *)answer) < 0)
+       if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
                return -2;
 
-       print_linkinfo(NULL, (struct nlmsghdr *)answer, stdout);
+       print_linkinfo(NULL, &answer.n, stdout);
 
        return 0;
 }
@@ -1137,6 +1164,23 @@ static int do_set(int argc, char **argv)
 }
 #endif /* IPLINK_IOCTL_COMPAT */
 
+static void do_help(int argc, char **argv)
+{
+       struct link_util *lu = NULL;
+
+       if (argc <= 0) {
+               usage();
+               return ;
+       }
+
+       lu = get_link_kind(*argv);
+
+       if (lu && lu->print_help)
+               lu->print_help(lu, argc-1, argv+1, stdout);
+       else
+               usage();
+}
+
 int do_iplink(int argc, char **argv)
 {
        if (argc > 0) {
@@ -1166,8 +1210,10 @@ int do_iplink(int argc, char **argv)
                    matches(*argv, "lst") == 0 ||
                    matches(*argv, "list") == 0)
                        return ipaddr_list_link(argc-1, argv+1);
-               if (matches(*argv, "help") == 0)
-                       usage();
+               if (matches(*argv, "help") == 0) {
+                       do_help(argc-1, argv+1);
+                       return 0;
+               }
        } else
                return ipaddr_list_link(0, NULL);