#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
+#include "namespace.h"
#define IPLINK_IOCTL_COMPAT 1
#ifndef LIBDIR
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");
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");
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);
}
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();
int numtxqueues = -1;
int numrxqueues = -1;
int dev_index = 0;
+ int link_netnsid = -1;
*group = -1;
ret = argc;
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);
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();
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;
}
}
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));
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();
"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;
{
int len;
struct iplink_req req;
- char answer[16384];
+ struct {
+ struct nlmsghdr n;
+ char buf[16384];
+ } answer;
memset(&req, 0, sizeof(req));
}
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;
}
}
#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) {
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);