4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
19 #include <sys/socket.h>
21 #include <linux/if_packet.h>
22 #include <linux/if_ether.h>
23 #include <linux/sockios.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
27 #include <sys/ioctl.h>
29 #include <linux/mpls.h>
33 #include "ip_common.h"
34 #include "namespace.h"
36 #define IPLINK_IOCTL_COMPAT 1
38 #define LIBDIR "/usr/lib"
42 #define GSO_MAX_SIZE 65536
45 #define GSO_MAX_SEGS 65535
49 static void usage(void) __attribute__((noreturn
));
50 static int iplink_have_newlink(void);
52 void iplink_usage(void)
54 if (iplink_have_newlink()) {
56 "Usage: ip link add [link DEV] [ name ] NAME\n"
57 " [ txqueuelen PACKETS ]\n"
58 " [ address LLADDR ]\n"
59 " [ broadcast LLADDR ]\n"
60 " [ mtu MTU ] [index IDX ]\n"
61 " [ numtxqueues QUEUE_COUNT ]\n"
62 " [ numrxqueues QUEUE_COUNT ]\n"
63 " type TYPE [ ARGS ]\n"
65 " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"
67 " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"
68 " [ { up | down } ]\n"
69 " [ type TYPE ARGS ]\n");
72 "Usage: ip link set DEVICE [ { up | down } ]\n");
75 " [ arp { on | off } ]\n"
76 " [ dynamic { on | off } ]\n"
77 " [ multicast { on | off } ]\n"
78 " [ allmulticast { on | off } ]\n"
79 " [ promisc { on | off } ]\n"
80 " [ trailers { on | off } ]\n"
81 " [ carrier { on | off } ]\n"
82 " [ txqueuelen PACKETS ]\n"
84 " [ address LLADDR ]\n"
85 " [ broadcast LLADDR ]\n"
87 " [ netns { PID | NAME } ]\n"
88 " [ link-netnsid ID ]\n"
90 " [ vf NUM [ mac LLADDR ]\n"
91 " [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]\n"
93 " [ max_tx_rate TXRATE ]\n"
94 " [ min_tx_rate TXRATE ]\n"
95 " [ spoofchk { on | off} ]\n"
96 " [ query_rss { on | off} ]\n"
97 " [ state { auto | enable | disable} ] ]\n"
98 " [ trust { on | off} ] ]\n"
99 " [ node_guid { eui64 } ]\n"
100 " [ port_guid { eui64 } ]\n"
102 " object FILE [ section NAME ] [ verbose ] |\n"
104 " [ master DEVICE ][ vrf NAME ]\n"
106 " [ addrgenmode { eui64 | none | stable_secret | random } ]\n"
107 " [ protodown { on | off } ]\n"
108 " [ gso_max_size BYTES ] | [ gso_max_segs PACKETS ]\n"
110 " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n");
112 fprintf(stderr
, "\n ip link xstats type TYPE [ ARGS ]\n");
113 fprintf(stderr
, "\n ip link afstats [ dev DEVICE ]\n");
115 if (iplink_have_newlink()) {
118 " ip link help [ TYPE ]\n"
120 "TYPE := { vlan | veth | vcan | vxcan | dummy | ifb | macvlan | macvtap |\n"
121 " bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
122 " gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n"
123 " vti | nlmon | team_slave | bond_slave | ipvlan | geneve |\n"
124 " bridge_slave | vrf | macsec | netdevsim }\n");
129 static void usage(void)
134 static int on_off(const char *msg
, const char *realval
)
137 "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
142 static void *BODY
; /* cached dlopen(NULL) handle */
143 static struct link_util
*linkutil_list
;
145 struct link_util
*get_link_kind(const char *id
)
151 for (l
= linkutil_list
; l
; l
= l
->next
)
152 if (strcmp(l
->id
, id
) == 0)
155 snprintf(buf
, sizeof(buf
), LIBDIR
"/ip/link_%s.so", id
);
156 dlh
= dlopen(buf
, RTLD_LAZY
);
158 /* look in current binary, only open once */
161 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
167 snprintf(buf
, sizeof(buf
), "%s_link_util", id
);
172 l
->next
= linkutil_list
;
177 static int get_link_mode(const char *mode
)
179 if (strcasecmp(mode
, "default") == 0)
180 return IF_LINK_MODE_DEFAULT
;
181 if (strcasecmp(mode
, "dormant") == 0)
182 return IF_LINK_MODE_DORMANT
;
186 static int get_addr_gen_mode(const char *mode
)
188 if (strcasecmp(mode
, "eui64") == 0)
189 return IN6_ADDR_GEN_MODE_EUI64
;
190 if (strcasecmp(mode
, "none") == 0)
191 return IN6_ADDR_GEN_MODE_NONE
;
192 if (strcasecmp(mode
, "stable_secret") == 0)
193 return IN6_ADDR_GEN_MODE_STABLE_PRIVACY
;
194 if (strcasecmp(mode
, "random") == 0)
195 return IN6_ADDR_GEN_MODE_RANDOM
;
199 #if IPLINK_IOCTL_COMPAT
200 static int have_rtnl_newlink
= -1;
202 static int accept_msg(const struct sockaddr_nl
*who
,
203 struct rtnl_ctrl_data
*ctrl
,
204 struct nlmsghdr
*n
, void *arg
)
206 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(n
);
208 if (n
->nlmsg_type
== NLMSG_ERROR
&&
209 (err
->error
== -EOPNOTSUPP
|| err
->error
== -EINVAL
))
210 have_rtnl_newlink
= 0;
212 have_rtnl_newlink
= 1;
216 static int iplink_have_newlink(void)
223 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
224 .n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
,
225 .n
.nlmsg_type
= RTM_NEWLINK
,
226 .i
.ifi_family
= AF_UNSPEC
,
229 if (have_rtnl_newlink
< 0) {
230 if (rtnl_send(&rth
, &req
.n
, req
.n
.nlmsg_len
) < 0) {
231 perror("request send failed");
234 rtnl_listen(&rth
, accept_msg
, NULL
);
236 return have_rtnl_newlink
;
238 #else /* IPLINK_IOCTL_COMPAT */
239 static int iplink_have_newlink(void)
243 #endif /* ! IPLINK_IOCTL_COMPAT */
245 static int nl_get_ll_addr_len(unsigned int dev_index
)
248 struct iplink_req req
= {
250 .nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
251 .nlmsg_type
= RTM_GETLINK
,
252 .nlmsg_flags
= NLM_F_REQUEST
255 .ifi_family
= preferred_family
,
256 .ifi_index
= dev_index
,
259 struct nlmsghdr
*answer
;
260 struct rtattr
*tb
[IFLA_MAX
+1];
262 if (rtnl_talk(&rth
, &req
.n
, &answer
) < 0)
265 len
= answer
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ifinfomsg
));
271 parse_rtattr_flags(tb
, IFLA_MAX
, IFLA_RTA(NLMSG_DATA(answer
)),
273 if (!tb
[IFLA_ADDRESS
]) {
278 len
= RTA_PAYLOAD(tb
[IFLA_ADDRESS
]);
283 static void iplink_parse_vf_vlan_info(int vf
, int *argcp
, char ***argvp
,
284 struct ifla_vf_vlan_info
*ivvip
)
287 char **argv
= *argvp
;
291 if (get_unsigned(&vci
, *argv
, 0) || vci
> 4095)
292 invarg("Invalid \"vlan\" value\n", *argv
);
297 ivvip
->vlan_proto
= htons(ETH_P_8021Q
);
300 if (matches(*argv
, "qos") == 0) {
302 if (get_unsigned(&ivvip
->qos
, *argv
, 0))
303 invarg("Invalid \"qos\" value\n", *argv
);
311 if (matches(*argv
, "proto") == 0) {
313 if (ll_proto_a2n(&ivvip
->vlan_proto
, *argv
))
314 invarg("protocol is invalid\n", *argv
);
315 if (ivvip
->vlan_proto
!= htons(ETH_P_8021AD
) &&
316 ivvip
->vlan_proto
!= htons(ETH_P_8021Q
)) {
319 char msg
[64 + sizeof(b1
) + sizeof(b2
)];
322 "Invalid \"vlan protocol\" value - supported %s, %s\n",
323 ll_proto_n2a(htons(ETH_P_8021Q
),
325 ll_proto_n2a(htons(ETH_P_8021AD
),
339 static int iplink_parse_vf(int vf
, int *argcp
, char ***argvp
,
340 struct iplink_req
*req
, int dev_index
)
342 char new_rate_api
= 0, count
= 0, override_legacy_rate
= 0;
343 struct ifla_vf_rate tivt
;
344 int len
, argc
= *argcp
;
345 char **argv
= *argvp
;
346 struct rtattr
*vfinfo
;
348 tivt
.min_tx_rate
= -1;
349 tivt
.max_tx_rate
= -1;
351 vfinfo
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_VF_INFO
);
353 while (NEXT_ARG_OK()) {
356 if (!matches(*argv
, "max_tx_rate")) {
359 /* override legacy rate */
360 override_legacy_rate
= 1;
361 } else if (!matches(*argv
, "min_tx_rate")) {
372 while (NEXT_ARG_OK()) {
374 if (matches(*argv
, "mac") == 0) {
375 struct ifla_vf_mac ivm
= { 0 };
376 int halen
= nl_get_ll_addr_len(dev_index
);
380 len
= ll_addr_a2n((char *)ivm
.mac
, 32, *argv
);
383 if (halen
> 0 && len
!= halen
) {
385 "Invalid address length %d - must be %d bytes\n",
389 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_MAC
,
391 } else if (matches(*argv
, "vlan") == 0) {
392 struct ifla_vf_vlan_info ivvi
;
394 iplink_parse_vf_vlan_info(vf
, &argc
, &argv
, &ivvi
);
395 /* support the old interface in case of older kernel*/
396 if (ivvi
.vlan_proto
== htons(ETH_P_8021Q
)) {
397 struct ifla_vf_vlan ivv
;
400 ivv
.vlan
= ivvi
.vlan
;
402 addattr_l(&req
->n
, sizeof(*req
),
403 IFLA_VF_VLAN
, &ivv
, sizeof(ivv
));
405 struct rtattr
*vfvlanlist
;
407 vfvlanlist
= addattr_nest(&req
->n
, sizeof(*req
),
409 addattr_l(&req
->n
, sizeof(*req
),
410 IFLA_VF_VLAN_INFO
, &ivvi
,
413 while (NEXT_ARG_OK()) {
415 if (matches(*argv
, "vlan") != 0) {
419 iplink_parse_vf_vlan_info(vf
, &argc
,
421 addattr_l(&req
->n
, sizeof(*req
),
422 IFLA_VF_VLAN_INFO
, &ivvi
,
425 addattr_nest_end(&req
->n
, vfvlanlist
);
427 } else if (matches(*argv
, "rate") == 0) {
428 struct ifla_vf_tx_rate ivt
;
431 if (get_unsigned(&ivt
.rate
, *argv
, 0))
432 invarg("Invalid \"rate\" value\n", *argv
);
436 addattr_l(&req
->n
, sizeof(*req
),
437 IFLA_VF_TX_RATE
, &ivt
, sizeof(ivt
));
438 else if (!override_legacy_rate
)
439 tivt
.max_tx_rate
= ivt
.rate
;
441 } else if (matches(*argv
, "max_tx_rate") == 0) {
443 if (get_unsigned(&tivt
.max_tx_rate
, *argv
, 0))
444 invarg("Invalid \"max tx rate\" value\n",
448 } else if (matches(*argv
, "min_tx_rate") == 0) {
450 if (get_unsigned(&tivt
.min_tx_rate
, *argv
, 0))
451 invarg("Invalid \"min tx rate\" value\n",
455 } else if (matches(*argv
, "spoofchk") == 0) {
456 struct ifla_vf_spoofchk ivs
;
459 if (matches(*argv
, "on") == 0)
461 else if (matches(*argv
, "off") == 0)
464 return on_off("spoofchk", *argv
);
466 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_SPOOFCHK
,
469 } else if (matches(*argv
, "query_rss") == 0) {
470 struct ifla_vf_rss_query_en ivs
;
473 if (matches(*argv
, "on") == 0)
475 else if (matches(*argv
, "off") == 0)
478 return on_off("query_rss", *argv
);
480 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RSS_QUERY_EN
,
483 } else if (matches(*argv
, "trust") == 0) {
484 struct ifla_vf_trust ivt
;
487 if (matches(*argv
, "on") == 0)
489 else if (matches(*argv
, "off") == 0)
492 invarg("Invalid \"trust\" value\n", *argv
);
494 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_TRUST
,
497 } else if (matches(*argv
, "state") == 0) {
498 struct ifla_vf_link_state ivl
;
501 if (matches(*argv
, "auto") == 0)
502 ivl
.link_state
= IFLA_VF_LINK_STATE_AUTO
;
503 else if (matches(*argv
, "enable") == 0)
504 ivl
.link_state
= IFLA_VF_LINK_STATE_ENABLE
;
505 else if (matches(*argv
, "disable") == 0)
506 ivl
.link_state
= IFLA_VF_LINK_STATE_DISABLE
;
508 invarg("Invalid \"state\" value\n", *argv
);
510 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_LINK_STATE
,
512 } else if (matches(*argv
, "node_guid") == 0) {
513 struct ifla_vf_guid ivg
;
517 if (get_guid(&ivg
.guid
, *argv
)) {
518 invarg("Invalid GUID format\n", *argv
);
521 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_NODE_GUID
,
523 } else if (matches(*argv
, "port_guid") == 0) {
524 struct ifla_vf_guid ivg
;
528 if (get_guid(&ivg
.guid
, *argv
)) {
529 invarg("Invalid GUID format\n", *argv
);
532 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_PORT_GUID
,
544 if (tivt
.min_tx_rate
== -1 || tivt
.max_tx_rate
== -1) {
545 ipaddr_get_vf_rate(tivt
.vf
, &tmin
, &tmax
, dev_index
);
546 if (tivt
.min_tx_rate
== -1)
547 tivt
.min_tx_rate
= tmin
;
548 if (tivt
.max_tx_rate
== -1)
549 tivt
.max_tx_rate
= tmax
;
552 if (tivt
.max_tx_rate
&& tivt
.min_tx_rate
> tivt
.max_tx_rate
) {
554 "Invalid min_tx_rate %d - must be <= max_tx_rate %d\n",
555 tivt
.min_tx_rate
, tivt
.max_tx_rate
);
559 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RATE
, &tivt
,
564 incomplete_command();
566 addattr_nest_end(&req
->n
, vfinfo
);
573 int iplink_parse(int argc
, char **argv
, struct iplink_req
*req
, char **type
)
584 int numtxqueues
= -1;
585 int numrxqueues
= -1;
587 int link_netnsid
= -1;
595 if (strcmp(*argv
, "up") == 0) {
596 req
->i
.ifi_change
|= IFF_UP
;
597 req
->i
.ifi_flags
|= IFF_UP
;
598 } else if (strcmp(*argv
, "down") == 0) {
599 req
->i
.ifi_change
|= IFF_UP
;
600 req
->i
.ifi_flags
&= ~IFF_UP
;
601 } else if (strcmp(*argv
, "name") == 0) {
604 duparg("name", *argv
);
605 if (check_ifname(*argv
))
606 invarg("\"name\" not a valid ifname", *argv
);
610 dev_index
= ll_name_to_index(dev
);
612 } else if (strcmp(*argv
, "index") == 0) {
615 duparg("index", *argv
);
618 invarg("Invalid \"index\" value", *argv
);
619 } else if (matches(*argv
, "link") == 0) {
622 } else if (matches(*argv
, "address") == 0) {
624 addr_len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
627 addattr_l(&req
->n
, sizeof(*req
),
628 IFLA_ADDRESS
, abuf
, addr_len
);
629 } else if (matches(*argv
, "broadcast") == 0 ||
630 strcmp(*argv
, "brd") == 0) {
632 len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
635 addattr_l(&req
->n
, sizeof(*req
),
636 IFLA_BROADCAST
, abuf
, len
);
637 } else if (matches(*argv
, "txqueuelen") == 0 ||
638 strcmp(*argv
, "qlen") == 0 ||
639 matches(*argv
, "txqlen") == 0) {
642 duparg("txqueuelen", *argv
);
643 if (get_integer(&qlen
, *argv
, 0))
644 invarg("Invalid \"txqueuelen\" value\n", *argv
);
645 addattr_l(&req
->n
, sizeof(*req
),
646 IFLA_TXQLEN
, &qlen
, 4);
647 } else if (strcmp(*argv
, "mtu") == 0) {
650 duparg("mtu", *argv
);
651 if (get_integer(&mtu
, *argv
, 0))
652 invarg("Invalid \"mtu\" value\n", *argv
);
653 addattr_l(&req
->n
, sizeof(*req
), IFLA_MTU
, &mtu
, 4);
654 } else if (strcmp(*argv
, "xdpgeneric") == 0 ||
655 strcmp(*argv
, "xdpdrv") == 0 ||
656 strcmp(*argv
, "xdpoffload") == 0 ||
657 strcmp(*argv
, "xdp") == 0) {
658 bool generic
= strcmp(*argv
, "xdpgeneric") == 0;
659 bool drv
= strcmp(*argv
, "xdpdrv") == 0;
660 bool offload
= strcmp(*argv
, "xdpoffload") == 0;
663 if (xdp_parse(&argc
, &argv
, req
, dev_index
,
664 generic
, drv
, offload
))
667 if (offload
&& name
== dev
)
669 } else if (strcmp(*argv
, "netns") == 0) {
672 duparg("netns", *argv
);
673 netns
= netns_get_fd(*argv
);
675 addattr_l(&req
->n
, sizeof(*req
), IFLA_NET_NS_FD
,
677 else if (get_integer(&netns
, *argv
, 0) == 0)
678 addattr_l(&req
->n
, sizeof(*req
),
679 IFLA_NET_NS_PID
, &netns
, 4);
681 invarg("Invalid \"netns\" value\n", *argv
);
682 } else if (strcmp(*argv
, "multicast") == 0) {
684 req
->i
.ifi_change
|= IFF_MULTICAST
;
686 if (strcmp(*argv
, "on") == 0)
687 req
->i
.ifi_flags
|= IFF_MULTICAST
;
688 else if (strcmp(*argv
, "off") == 0)
689 req
->i
.ifi_flags
&= ~IFF_MULTICAST
;
691 return on_off("multicast", *argv
);
692 } else if (strcmp(*argv
, "allmulticast") == 0) {
694 req
->i
.ifi_change
|= IFF_ALLMULTI
;
696 if (strcmp(*argv
, "on") == 0)
697 req
->i
.ifi_flags
|= IFF_ALLMULTI
;
698 else if (strcmp(*argv
, "off") == 0)
699 req
->i
.ifi_flags
&= ~IFF_ALLMULTI
;
701 return on_off("allmulticast", *argv
);
702 } else if (strcmp(*argv
, "promisc") == 0) {
704 req
->i
.ifi_change
|= IFF_PROMISC
;
706 if (strcmp(*argv
, "on") == 0)
707 req
->i
.ifi_flags
|= IFF_PROMISC
;
708 else if (strcmp(*argv
, "off") == 0)
709 req
->i
.ifi_flags
&= ~IFF_PROMISC
;
711 return on_off("promisc", *argv
);
712 } else if (strcmp(*argv
, "trailers") == 0) {
714 req
->i
.ifi_change
|= IFF_NOTRAILERS
;
716 if (strcmp(*argv
, "off") == 0)
717 req
->i
.ifi_flags
|= IFF_NOTRAILERS
;
718 else if (strcmp(*argv
, "on") == 0)
719 req
->i
.ifi_flags
&= ~IFF_NOTRAILERS
;
721 return on_off("trailers", *argv
);
722 } else if (strcmp(*argv
, "arp") == 0) {
724 req
->i
.ifi_change
|= IFF_NOARP
;
726 if (strcmp(*argv
, "on") == 0)
727 req
->i
.ifi_flags
&= ~IFF_NOARP
;
728 else if (strcmp(*argv
, "off") == 0)
729 req
->i
.ifi_flags
|= IFF_NOARP
;
731 return on_off("arp", *argv
);
732 } else if (strcmp(*argv
, "carrier") == 0) {
736 if (strcmp(*argv
, "on") == 0)
738 else if (strcmp(*argv
, "off") == 0)
741 return on_off("carrier", *argv
);
743 addattr8(&req
->n
, sizeof(*req
), IFLA_CARRIER
, carrier
);
744 } else if (strcmp(*argv
, "vf") == 0) {
745 struct rtattr
*vflist
;
748 if (get_integer(&vf
, *argv
, 0))
749 invarg("Invalid \"vf\" value\n", *argv
);
751 vflist
= addattr_nest(&req
->n
, sizeof(*req
),
756 len
= iplink_parse_vf(vf
, &argc
, &argv
, req
, dev_index
);
759 addattr_nest_end(&req
->n
, vflist
);
763 } else if (matches(*argv
, "master") == 0) {
767 ifindex
= ll_name_to_index(*argv
);
769 invarg("Device does not exist\n", *argv
);
770 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
772 } else if (strcmp(*argv
, "vrf") == 0) {
776 ifindex
= ll_name_to_index(*argv
);
778 invarg("Not a valid VRF name\n", *argv
);
779 if (!name_is_vrf(*argv
))
780 invarg("Not a valid VRF name\n", *argv
);
781 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
782 &ifindex
, sizeof(ifindex
));
783 } else if (matches(*argv
, "nomaster") == 0) {
786 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
788 } else if (matches(*argv
, "dynamic") == 0) {
790 req
->i
.ifi_change
|= IFF_DYNAMIC
;
792 if (strcmp(*argv
, "on") == 0)
793 req
->i
.ifi_flags
|= IFF_DYNAMIC
;
794 else if (strcmp(*argv
, "off") == 0)
795 req
->i
.ifi_flags
&= ~IFF_DYNAMIC
;
797 return on_off("dynamic", *argv
);
798 } else if (matches(*argv
, "type") == 0) {
803 } else if (matches(*argv
, "alias") == 0) {
807 invarg("alias too long\n", *argv
);
808 addattr_l(&req
->n
, sizeof(*req
), IFLA_IFALIAS
,
810 } else if (strcmp(*argv
, "group") == 0) {
813 duparg("group", *argv
);
814 if (rtnl_group_a2n(&group
, *argv
))
815 invarg("Invalid \"group\" value\n", *argv
);
816 addattr32(&req
->n
, sizeof(*req
), IFLA_GROUP
, group
);
817 } else if (strcmp(*argv
, "mode") == 0) {
821 mode
= get_link_mode(*argv
);
823 invarg("Invalid link mode\n", *argv
);
824 addattr8(&req
->n
, sizeof(*req
), IFLA_LINKMODE
, mode
);
825 } else if (strcmp(*argv
, "state") == 0) {
829 state
= get_operstate(*argv
);
831 invarg("Invalid operstate\n", *argv
);
833 addattr8(&req
->n
, sizeof(*req
), IFLA_OPERSTATE
, state
);
834 } else if (matches(*argv
, "numtxqueues") == 0) {
836 if (numtxqueues
!= -1)
837 duparg("numtxqueues", *argv
);
838 if (get_integer(&numtxqueues
, *argv
, 0))
839 invarg("Invalid \"numtxqueues\" value\n",
841 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_TX_QUEUES
,
843 } else if (matches(*argv
, "numrxqueues") == 0) {
845 if (numrxqueues
!= -1)
846 duparg("numrxqueues", *argv
);
847 if (get_integer(&numrxqueues
, *argv
, 0))
848 invarg("Invalid \"numrxqueues\" value\n",
850 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_RX_QUEUES
,
852 } else if (matches(*argv
, "addrgenmode") == 0) {
853 struct rtattr
*afs
, *afs6
;
857 mode
= get_addr_gen_mode(*argv
);
859 invarg("Invalid address generation mode\n",
861 afs
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_AF_SPEC
);
862 afs6
= addattr_nest(&req
->n
, sizeof(*req
), AF_INET6
);
863 addattr8(&req
->n
, sizeof(*req
),
864 IFLA_INET6_ADDR_GEN_MODE
, mode
);
865 addattr_nest_end(&req
->n
, afs6
);
866 addattr_nest_end(&req
->n
, afs
);
867 } else if (matches(*argv
, "link-netnsid") == 0) {
869 if (link_netnsid
!= -1)
870 duparg("link-netnsid", *argv
);
871 if (get_integer(&link_netnsid
, *argv
, 0))
872 invarg("Invalid \"link-netnsid\" value\n",
874 addattr32(&req
->n
, sizeof(*req
), IFLA_LINK_NETNSID
,
876 } else if (strcmp(*argv
, "protodown") == 0) {
877 unsigned int proto_down
;
880 if (strcmp(*argv
, "on") == 0)
882 else if (strcmp(*argv
, "off") == 0)
885 return on_off("protodown", *argv
);
886 addattr8(&req
->n
, sizeof(*req
), IFLA_PROTO_DOWN
,
888 } else if (strcmp(*argv
, "gso_max_size") == 0) {
889 unsigned int max_size
;
892 if (get_unsigned(&max_size
, *argv
, 0) ||
893 max_size
> GSO_MAX_SIZE
)
894 invarg("Invalid \"gso_max_size\" value\n",
896 addattr32(&req
->n
, sizeof(*req
),
897 IFLA_GSO_MAX_SIZE
, max_size
);
898 } else if (strcmp(*argv
, "gso_max_segs") == 0) {
899 unsigned int max_segs
;
902 if (get_unsigned(&max_segs
, *argv
, 0) ||
903 max_segs
> GSO_MAX_SEGS
)
904 invarg("Invalid \"gso_max_segs\" value\n",
906 addattr32(&req
->n
, sizeof(*req
),
907 IFLA_GSO_MAX_SEGS
, max_segs
);
909 if (matches(*argv
, "help") == 0)
912 if (strcmp(*argv
, "dev") == 0)
915 duparg2("dev", *argv
);
916 if (check_ifname(*argv
))
917 invarg("\"dev\" not a valid ifname", *argv
);
919 dev_index
= ll_name_to_index(dev
);
926 /* Allow "ip link add dev" and "ip link add name" */
931 else if (!strcmp(name
, dev
))
934 if (dev_index
&& addr_len
) {
935 int halen
= nl_get_ll_addr_len(dev_index
);
937 if (halen
>= 0 && halen
!= addr_len
) {
939 "Invalid address length %d - must be %d bytes\n",
945 if (!(req
->n
.nlmsg_flags
& NLM_F_CREATE
) && index
) {
947 "index can be used only when creating devices.\n");
955 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
959 if (req
->n
.nlmsg_flags
& NLM_F_CREATE
) {
961 "group cannot be used when creating devices.\n");
970 if (!(req
->n
.nlmsg_flags
& NLM_F_CREATE
)) {
973 "Not enough information: \"dev\" argument is required.\n");
977 req
->i
.ifi_index
= ll_name_to_index(dev
);
978 if (!req
->i
.ifi_index
)
981 /* Not renaming to the same name */
987 "both \"name\" and \"dev\" cannot be used when creating devices.\n");
994 ifindex
= ll_name_to_index(link
);
997 addattr32(&req
->n
, sizeof(*req
), IFLA_LINK
, ifindex
);
1000 req
->i
.ifi_index
= index
;
1004 addattr_l(&req
->n
, sizeof(*req
),
1005 IFLA_IFNAME
, name
, strlen(name
) + 1);
1011 static int iplink_modify(int cmd
, unsigned int flags
, int argc
, char **argv
)
1014 struct iplink_req req
= {
1015 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
1016 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
1017 .n
.nlmsg_type
= cmd
,
1018 .i
.ifi_family
= preferred_family
,
1022 ret
= iplink_parse(argc
, argv
, &req
, &type
);
1027 struct link_util
*lu
;
1028 struct rtattr
*linkinfo
;
1029 char *ulinep
= strchr(type
, '_');
1032 linkinfo
= addattr_nest(&req
.n
, sizeof(req
), IFLA_LINKINFO
);
1033 addattr_l(&req
.n
, sizeof(req
), IFLA_INFO_KIND
, type
,
1036 lu
= get_link_kind(type
);
1037 if (ulinep
&& !strcmp(ulinep
, "_slave"))
1038 iflatype
= IFLA_INFO_SLAVE_DATA
;
1040 iflatype
= IFLA_INFO_DATA
;
1046 struct rtattr
*data
;
1048 data
= addattr_nest(&req
.n
, sizeof(req
), iflatype
);
1050 if (lu
->parse_opt
&&
1051 lu
->parse_opt(lu
, argc
, argv
, &req
.n
))
1054 addattr_nest_end(&req
.n
, data
);
1056 if (matches(*argv
, "help") == 0)
1059 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
1063 addattr_nest_end(&req
.n
, linkinfo
);
1064 } else if (flags
& NLM_F_CREATE
) {
1066 "Not enough information: \"type\" argument is required\n");
1070 if (rtnl_talk(&rth
, &req
.n
, NULL
) < 0)
1076 int iplink_get(unsigned int flags
, char *name
, __u32 filt_mask
)
1078 struct iplink_req req
= {
1079 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
1080 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
1081 .n
.nlmsg_type
= RTM_GETLINK
,
1082 .i
.ifi_family
= preferred_family
,
1084 struct nlmsghdr
*answer
;
1087 addattr_l(&req
.n
, sizeof(req
),
1088 IFLA_IFNAME
, name
, strlen(name
) + 1);
1090 addattr32(&req
.n
, sizeof(req
), IFLA_EXT_MASK
, filt_mask
);
1092 if (rtnl_talk(&rth
, &req
.n
, &answer
) < 0)
1095 open_json_object(NULL
);
1096 print_linkinfo(NULL
, answer
, stdout
);
1097 close_json_object();
1103 #if IPLINK_IOCTL_COMPAT
1104 static int get_ctl_fd(void)
1109 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
1113 fd
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
1116 fd
= socket(PF_INET6
, SOCK_DGRAM
, 0);
1120 perror("Cannot create control socket");
1124 static int do_chflags(const char *dev
, __u32 flags
, __u32 mask
)
1130 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1134 err
= ioctl(fd
, SIOCGIFFLAGS
, &ifr
);
1136 perror("SIOCGIFFLAGS");
1140 if ((ifr
.ifr_flags
^flags
)&mask
) {
1141 ifr
.ifr_flags
&= ~mask
;
1142 ifr
.ifr_flags
|= mask
&flags
;
1143 err
= ioctl(fd
, SIOCSIFFLAGS
, &ifr
);
1145 perror("SIOCSIFFLAGS");
1151 static int do_changename(const char *dev
, const char *newdev
)
1157 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1158 strncpy(ifr
.ifr_newname
, newdev
, IFNAMSIZ
);
1162 err
= ioctl(fd
, SIOCSIFNAME
, &ifr
);
1164 perror("SIOCSIFNAME");
1172 static int set_qlen(const char *dev
, int qlen
)
1174 struct ifreq ifr
= { .ifr_qlen
= qlen
};
1181 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1182 if (ioctl(s
, SIOCSIFTXQLEN
, &ifr
) < 0) {
1183 perror("SIOCSIFXQLEN");
1192 static int set_mtu(const char *dev
, int mtu
)
1194 struct ifreq ifr
= { .ifr_mtu
= mtu
};
1201 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1202 if (ioctl(s
, SIOCSIFMTU
, &ifr
) < 0) {
1203 perror("SIOCSIFMTU");
1212 static int get_address(const char *dev
, int *htype
)
1214 struct ifreq ifr
= {};
1215 struct sockaddr_ll me
= {
1216 .sll_family
= AF_PACKET
,
1217 .sll_protocol
= htons(ETH_P_LOOP
),
1222 s
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
1224 perror("socket(PF_PACKET)");
1228 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1229 if (ioctl(s
, SIOCGIFINDEX
, &ifr
) < 0) {
1230 perror("SIOCGIFINDEX");
1235 me
.sll_ifindex
= ifr
.ifr_ifindex
;
1236 if (bind(s
, (struct sockaddr
*)&me
, sizeof(me
)) == -1) {
1243 if (getsockname(s
, (struct sockaddr
*)&me
, &alen
) == -1) {
1244 perror("getsockname");
1249 *htype
= me
.sll_hatype
;
1250 return me
.sll_halen
;
1253 static int parse_address(const char *dev
, int hatype
, int halen
,
1254 char *lla
, struct ifreq
*ifr
)
1258 memset(ifr
, 0, sizeof(*ifr
));
1259 strncpy(ifr
->ifr_name
, dev
, IFNAMSIZ
);
1260 ifr
->ifr_hwaddr
.sa_family
= hatype
;
1261 alen
= ll_addr_a2n(ifr
->ifr_hwaddr
.sa_data
, 14, lla
);
1264 if (alen
!= halen
) {
1266 "Wrong address (%s) length: expected %d bytes\n",
1273 static int set_address(struct ifreq
*ifr
, int brd
)
1280 if (ioctl(s
, brd
?SIOCSIFHWBROADCAST
:SIOCSIFHWADDR
, ifr
) < 0) {
1281 perror(brd
?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
1289 static int do_set(int argc
, char **argv
)
1296 char *newaddr
= NULL
;
1297 char *newbrd
= NULL
;
1298 struct ifreq ifr0
, ifr1
;
1299 char *newname
= NULL
;
1303 if (strcmp(*argv
, "up") == 0) {
1306 } else if (strcmp(*argv
, "down") == 0) {
1309 } else if (strcmp(*argv
, "name") == 0) {
1311 if (check_ifname(*argv
))
1312 invarg("\"name\" not a valid ifname", *argv
);
1314 } else if (matches(*argv
, "address") == 0) {
1317 } else if (matches(*argv
, "broadcast") == 0 ||
1318 strcmp(*argv
, "brd") == 0) {
1321 } else if (matches(*argv
, "txqueuelen") == 0 ||
1322 strcmp(*argv
, "qlen") == 0 ||
1323 matches(*argv
, "txqlen") == 0) {
1326 duparg("txqueuelen", *argv
);
1327 if (get_integer(&qlen
, *argv
, 0))
1328 invarg("Invalid \"txqueuelen\" value\n", *argv
);
1329 } else if (strcmp(*argv
, "mtu") == 0) {
1332 duparg("mtu", *argv
);
1333 if (get_integer(&mtu
, *argv
, 0))
1334 invarg("Invalid \"mtu\" value\n", *argv
);
1335 } else if (strcmp(*argv
, "multicast") == 0) {
1337 mask
|= IFF_MULTICAST
;
1339 if (strcmp(*argv
, "on") == 0)
1340 flags
|= IFF_MULTICAST
;
1341 else if (strcmp(*argv
, "off") == 0)
1342 flags
&= ~IFF_MULTICAST
;
1344 return on_off("multicast", *argv
);
1345 } else if (strcmp(*argv
, "allmulticast") == 0) {
1347 mask
|= IFF_ALLMULTI
;
1349 if (strcmp(*argv
, "on") == 0)
1350 flags
|= IFF_ALLMULTI
;
1351 else if (strcmp(*argv
, "off") == 0)
1352 flags
&= ~IFF_ALLMULTI
;
1354 return on_off("allmulticast", *argv
);
1355 } else if (strcmp(*argv
, "promisc") == 0) {
1357 mask
|= IFF_PROMISC
;
1359 if (strcmp(*argv
, "on") == 0)
1360 flags
|= IFF_PROMISC
;
1361 else if (strcmp(*argv
, "off") == 0)
1362 flags
&= ~IFF_PROMISC
;
1364 return on_off("promisc", *argv
);
1365 } else if (strcmp(*argv
, "trailers") == 0) {
1367 mask
|= IFF_NOTRAILERS
;
1369 if (strcmp(*argv
, "off") == 0)
1370 flags
|= IFF_NOTRAILERS
;
1371 else if (strcmp(*argv
, "on") == 0)
1372 flags
&= ~IFF_NOTRAILERS
;
1374 return on_off("trailers", *argv
);
1375 } else if (strcmp(*argv
, "arp") == 0) {
1379 if (strcmp(*argv
, "on") == 0)
1380 flags
&= ~IFF_NOARP
;
1381 else if (strcmp(*argv
, "off") == 0)
1384 return on_off("arp", *argv
);
1385 } else if (matches(*argv
, "dynamic") == 0) {
1387 mask
|= IFF_DYNAMIC
;
1389 if (strcmp(*argv
, "on") == 0)
1390 flags
|= IFF_DYNAMIC
;
1391 else if (strcmp(*argv
, "off") == 0)
1392 flags
&= ~IFF_DYNAMIC
;
1394 return on_off("dynamic", *argv
);
1396 if (strcmp(*argv
, "dev") == 0)
1398 else if (matches(*argv
, "help") == 0)
1402 duparg2("dev", *argv
);
1403 if (check_ifname(*argv
))
1404 invarg("\"dev\" not a valid ifname", *argv
);
1412 "Not enough of information: \"dev\" argument is required.\n");
1416 if (newaddr
|| newbrd
) {
1417 halen
= get_address(dev
, &htype
);
1421 if (parse_address(dev
, htype
, halen
,
1422 newaddr
, &ifr0
) < 0)
1426 if (parse_address(dev
, htype
, halen
,
1432 if (newname
&& strcmp(dev
, newname
)) {
1433 if (do_changename(dev
, newname
) < 0)
1438 if (set_qlen(dev
, qlen
) < 0)
1442 if (set_mtu(dev
, mtu
) < 0)
1445 if (newaddr
|| newbrd
) {
1447 if (set_address(&ifr1
, 1) < 0)
1451 if (set_address(&ifr0
, 0) < 0)
1456 return do_chflags(dev
, flags
, mask
);
1459 #endif /* IPLINK_IOCTL_COMPAT */
1461 static void print_mpls_stats(FILE *fp
, struct rtattr
*attr
)
1463 struct rtattr
*mrtb
[MPLS_STATS_MAX
+1];
1464 struct mpls_link_stats
*stats
;
1466 parse_rtattr(mrtb
, MPLS_STATS_MAX
, RTA_DATA(attr
),
1468 if (!mrtb
[MPLS_STATS_LINK
])
1471 stats
= RTA_DATA(mrtb
[MPLS_STATS_LINK
]);
1473 fprintf(fp
, " mpls:\n");
1474 fprintf(fp
, " RX: bytes packets errors dropped noroute\n");
1476 print_num(fp
, 10, stats
->rx_bytes
);
1477 print_num(fp
, 8, stats
->rx_packets
);
1478 print_num(fp
, 7, stats
->rx_errors
);
1479 print_num(fp
, 8, stats
->rx_dropped
);
1480 print_num(fp
, 7, stats
->rx_noroute
);
1482 fprintf(fp
, " TX: bytes packets errors dropped\n");
1484 print_num(fp
, 10, stats
->tx_bytes
);
1485 print_num(fp
, 8, stats
->tx_packets
);
1486 print_num(fp
, 7, stats
->tx_errors
);
1487 print_num(fp
, 7, stats
->tx_dropped
);
1491 static void print_af_stats_attr(FILE *fp
, int ifindex
, struct rtattr
*attr
)
1493 bool if_printed
= false;
1497 rem
= RTA_PAYLOAD(attr
);
1498 for (i
= RTA_DATA(attr
); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
)) {
1499 if (preferred_family
!= AF_UNSPEC
&&
1500 i
->rta_type
!= preferred_family
)
1504 fprintf(fp
, "%u: %s\n", ifindex
,
1505 ll_index_to_name(ifindex
));
1509 switch (i
->rta_type
) {
1511 print_mpls_stats(fp
, i
);
1514 fprintf(fp
, " unknown af(%d)\n", i
->rta_type
);
1520 struct af_stats_ctx
{
1525 static int print_af_stats(const struct sockaddr_nl
*who
,
1529 struct if_stats_msg
*ifsm
= NLMSG_DATA(n
);
1530 struct rtattr
*tb
[IFLA_STATS_MAX
+1];
1531 int len
= n
->nlmsg_len
;
1532 struct af_stats_ctx
*ctx
= arg
;
1535 len
-= NLMSG_LENGTH(sizeof(*ifsm
));
1537 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
1541 if (ctx
->ifindex
&& ifsm
->ifindex
!= ctx
->ifindex
)
1544 parse_rtattr(tb
, IFLA_STATS_MAX
, IFLA_STATS_RTA(ifsm
), len
);
1546 if (tb
[IFLA_STATS_AF_SPEC
])
1547 print_af_stats_attr(fp
, ifsm
->ifindex
, tb
[IFLA_STATS_AF_SPEC
]);
1553 static int iplink_afstats(int argc
, char **argv
)
1555 __u32 filt_mask
= IFLA_STATS_FILTER_BIT(IFLA_STATS_AF_SPEC
);
1556 const char *filter_dev
= NULL
;
1557 struct af_stats_ctx ctx
= {
1563 if (strcmp(*argv
, "dev") == 0) {
1566 duparg2("dev", *argv
);
1568 } else if (matches(*argv
, "help") == 0) {
1572 "Command \"%s\" is unknown, try \"ip link help\".\n",
1581 ctx
.ifindex
= ll_name_to_index(filter_dev
);
1582 if (ctx
.ifindex
<= 0) {
1584 "Device \"%s\" does not exist.\n",
1590 if (rtnl_wilddump_stats_req_filter(&rth
, AF_UNSPEC
,
1593 perror("Cannont send dump request");
1597 if (rtnl_dump_filter(&rth
, print_af_stats
, &ctx
) < 0) {
1598 fprintf(stderr
, "Dump terminated\n");
1605 static void do_help(int argc
, char **argv
)
1607 struct link_util
*lu
= NULL
;
1614 lu
= get_link_kind(*argv
);
1615 if (lu
&& lu
->print_help
)
1616 lu
->print_help(lu
, argc
-1, argv
+1, stdout
);
1621 int do_iplink(int argc
, char **argv
)
1624 return ipaddr_list_link(0, NULL
);
1626 if (iplink_have_newlink()) {
1627 if (matches(*argv
, "add") == 0)
1628 return iplink_modify(RTM_NEWLINK
,
1629 NLM_F_CREATE
|NLM_F_EXCL
,
1631 if (matches(*argv
, "set") == 0 ||
1632 matches(*argv
, "change") == 0)
1633 return iplink_modify(RTM_NEWLINK
, 0,
1635 if (matches(*argv
, "replace") == 0)
1636 return iplink_modify(RTM_NEWLINK
,
1637 NLM_F_CREATE
|NLM_F_REPLACE
,
1639 if (matches(*argv
, "delete") == 0)
1640 return iplink_modify(RTM_DELLINK
, 0,
1643 #if IPLINK_IOCTL_COMPAT
1644 if (matches(*argv
, "set") == 0)
1645 return do_set(argc
-1, argv
+1);
1649 if (matches(*argv
, "show") == 0 ||
1650 matches(*argv
, "lst") == 0 ||
1651 matches(*argv
, "list") == 0)
1652 return ipaddr_list_link(argc
-1, argv
+1);
1654 if (matches(*argv
, "xstats") == 0)
1655 return iplink_ifla_xstats(argc
-1, argv
+1);
1657 if (matches(*argv
, "afstats") == 0) {
1658 iplink_afstats(argc
-1, argv
+1);
1662 if (matches(*argv
, "help") == 0) {
1663 do_help(argc
-1, argv
+1);
1667 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip link help\".\n",