|
|
a4b897 |
commit 9764c8d5063de9d76326f028fce66f6e4e49bb5a
|
|
|
a4b897 |
Author: Pavel Šimerda <psimerda@redhat.com>
|
|
|
a4b897 |
Date: Thu May 28 12:17:39 2015 +0200
|
|
|
a4b897 |
|
|
|
a4b897 |
backport selected ip-link/ip-address features and documentation
|
|
|
a4b897 |
|
|
|
a4b897 |
diff --git a/ip/ip.c b/ip/ip.c
|
|
|
a4b897 |
index 86f8b45..7f2c206 100644
|
|
|
a4b897 |
--- a/ip/ip.c
|
|
|
a4b897 |
+++ b/ip/ip.c
|
|
|
a4b897 |
@@ -22,8 +22,11 @@
|
|
|
a4b897 |
#include "SNAPSHOT.h"
|
|
|
a4b897 |
#include "utils.h"
|
|
|
a4b897 |
#include "ip_common.h"
|
|
|
a4b897 |
+#include "namespace.h"
|
|
|
a4b897 |
|
|
|
a4b897 |
int preferred_family = AF_UNSPEC;
|
|
|
a4b897 |
+int human_readable = 0;
|
|
|
a4b897 |
+int use_iec = 0;
|
|
|
a4b897 |
int show_stats = 0;
|
|
|
a4b897 |
int show_details = 0;
|
|
|
a4b897 |
int resolve_hosts = 0;
|
|
|
a4b897 |
@@ -33,6 +36,7 @@ char * _SL_ = NULL;
|
|
|
a4b897 |
int force = 0;
|
|
|
a4b897 |
int max_flush_loops = 10;
|
|
|
a4b897 |
int batch_mode = 0;
|
|
|
a4b897 |
+bool do_all = false;
|
|
|
a4b897 |
|
|
|
a4b897 |
struct rtnl_handle rth = { .fd = -1 };
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -47,11 +51,12 @@ static void usage(void)
|
|
|
a4b897 |
" tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\n"
|
|
|
a4b897 |
" netns | l2tp | tcp_metrics | token }\n"
|
|
|
a4b897 |
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
|
|
|
a4b897 |
+" -h[uman-readable] | -iec |\n"
|
|
|
a4b897 |
" -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
|
|
|
a4b897 |
" -4 | -6 | -I | -D | -B | -0 |\n"
|
|
|
a4b897 |
" -l[oops] { maximum-addr-flush-attempts } |\n"
|
|
|
a4b897 |
" -o[neline] | -t[imestamp] | -b[atch] [filename] |\n"
|
|
|
a4b897 |
-" -rc[vbuf] [size]}\n");
|
|
|
a4b897 |
+" -rc[vbuf] [size] | -n[etns] name | -a[ll] }\n");
|
|
|
a4b897 |
exit(-1);
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -65,7 +70,7 @@ static const struct cmd {
|
|
|
a4b897 |
const char *cmd;
|
|
|
a4b897 |
int (*func)(int argc, char **argv);
|
|
|
a4b897 |
} cmds[] = {
|
|
|
a4b897 |
- { "address", do_ipaddr },
|
|
|
a4b897 |
+ { "address", do_ipaddr },
|
|
|
a4b897 |
{ "addrlabel", do_ipaddrlabel },
|
|
|
a4b897 |
{ "maddress", do_multiaddr },
|
|
|
a4b897 |
{ "route", do_iproute },
|
|
|
a4b897 |
@@ -212,6 +217,11 @@ int main(int argc, char **argv)
|
|
|
a4b897 |
preferred_family = AF_DECnet;
|
|
|
a4b897 |
} else if (strcmp(opt, "-B") == 0) {
|
|
|
a4b897 |
preferred_family = AF_BRIDGE;
|
|
|
a4b897 |
+ } else if (matches(opt, "-human") == 0 ||
|
|
|
a4b897 |
+ matches(opt, "-human-readable") == 0) {
|
|
|
a4b897 |
+ ++human_readable;
|
|
|
a4b897 |
+ } else if (matches(opt, "-iec") == 0) {
|
|
|
a4b897 |
+ ++use_iec;
|
|
|
a4b897 |
} else if (matches(opt, "-stats") == 0 ||
|
|
|
a4b897 |
matches(opt, "-statistics") == 0) {
|
|
|
a4b897 |
++show_stats;
|
|
|
a4b897 |
@@ -253,6 +263,12 @@ int main(int argc, char **argv)
|
|
|
a4b897 |
rcvbuf = size;
|
|
|
a4b897 |
} else if (matches(opt, "-help") == 0) {
|
|
|
a4b897 |
usage();
|
|
|
a4b897 |
+ } else if (matches(opt, "-netns") == 0) {
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ if (netns_switch(argv[1]))
|
|
|
a4b897 |
+ exit(-1);
|
|
|
a4b897 |
+ } else if (matches(opt, "-all") == 0) {
|
|
|
a4b897 |
+ do_all = true;
|
|
|
a4b897 |
} else {
|
|
|
a4b897 |
fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
|
|
|
a4b897 |
exit(-1);
|
|
|
a4b897 |
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
|
|
|
a4b897 |
index 5b9a438..c99a078 100644
|
|
|
a4b897 |
--- a/ip/ipaddress.c
|
|
|
a4b897 |
+++ b/ip/ipaddress.c
|
|
|
a4b897 |
@@ -28,6 +28,7 @@
|
|
|
a4b897 |
#include <linux/netdevice.h>
|
|
|
a4b897 |
#include <linux/if_arp.h>
|
|
|
a4b897 |
#include <linux/sockios.h>
|
|
|
a4b897 |
+#include <linux/net_namespace.h>
|
|
|
a4b897 |
|
|
|
a4b897 |
#include "rt_names.h"
|
|
|
a4b897 |
#include "utils.h"
|
|
|
a4b897 |
@@ -69,7 +70,7 @@ static void usage(void)
|
|
|
a4b897 |
}
|
|
|
a4b897 |
fprintf(stderr, "Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ CONFFLAG-LIST ]\n");
|
|
|
a4b897 |
- fprintf(stderr, " ip addr del IFADDR dev STRING\n");
|
|
|
a4b897 |
+ fprintf(stderr, " ip addr del IFADDR dev STRING [mngtmpaddr]\n");
|
|
|
a4b897 |
fprintf(stderr, " ip addr {show|save|flush} [ dev STRING ] [ scope SCOPE-ID ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label PATTERN ] [up]\n");
|
|
|
a4b897 |
fprintf(stderr, " ip addr {showdump|restore}\n");
|
|
|
a4b897 |
@@ -82,7 +83,7 @@ static void usage(void)
|
|
|
a4b897 |
fprintf(stderr, " tentative | deprecated | dadfailed | temporary |\n");
|
|
|
a4b897 |
fprintf(stderr, " CONFFLAG-LIST ]\n");
|
|
|
a4b897 |
fprintf(stderr, "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n");
|
|
|
a4b897 |
- fprintf(stderr, "CONFFLAG := [ home | nodad ]\n");
|
|
|
a4b897 |
+ fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute ]\n");
|
|
|
a4b897 |
fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n");
|
|
|
a4b897 |
fprintf(stderr, "LFT := forever | SECONDS\n");
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -223,12 +224,36 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
|
|
|
a4b897 |
}
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
+static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ struct rtattr *inet6_attr;
|
|
|
a4b897 |
+ struct rtattr *tb[IFLA_INET6_MAX + 1];
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ inet6_attr = parse_rtattr_one_nested(AF_INET6, af_spec_attr);
|
|
|
a4b897 |
+ if (!inet6_attr)
|
|
|
a4b897 |
+ return;
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
|
|
|
a4b897 |
+ switch (rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE])) {
|
|
|
a4b897 |
+ case IN6_ADDR_GEN_MODE_EUI64:
|
|
|
a4b897 |
+ fprintf(fp, "addrgenmode eui64 ");
|
|
|
a4b897 |
+ break;
|
|
|
a4b897 |
+ case IN6_ADDR_GEN_MODE_NONE:
|
|
|
a4b897 |
+ fprintf(fp, "addrgenmode none ");
|
|
|
a4b897 |
+ break;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
|
|
a4b897 |
{
|
|
|
a4b897 |
struct ifla_vf_mac *vf_mac;
|
|
|
a4b897 |
struct ifla_vf_vlan *vf_vlan;
|
|
|
a4b897 |
struct ifla_vf_tx_rate *vf_tx_rate;
|
|
|
a4b897 |
struct ifla_vf_spoofchk *vf_spoofchk;
|
|
|
a4b897 |
+ struct ifla_vf_link_state *vf_linkstate;
|
|
|
a4b897 |
struct rtattr *vf[IFLA_VF_MAX+1];
|
|
|
a4b897 |
struct rtattr *tmp;
|
|
|
a4b897 |
SPRINT_BUF(b1);
|
|
|
a4b897 |
@@ -255,6 +280,20 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
|
|
a4b897 |
else
|
|
|
a4b897 |
vf_spoofchk = RTA_DATA(vf[IFLA_VF_SPOOFCHK]);
|
|
|
a4b897 |
|
|
|
a4b897 |
+ if (vf_spoofchk) {
|
|
|
a4b897 |
+ /* Check if the link state vf info type is supported by
|
|
|
a4b897 |
+ * this kernel.
|
|
|
a4b897 |
+ */
|
|
|
a4b897 |
+ tmp = (struct rtattr *)((char *)vf[IFLA_VF_SPOOFCHK] +
|
|
|
a4b897 |
+ vf[IFLA_VF_SPOOFCHK]->rta_len);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (tmp->rta_type != IFLA_VF_LINK_STATE)
|
|
|
a4b897 |
+ vf_linkstate = NULL;
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ vf_linkstate = RTA_DATA(vf[IFLA_VF_LINK_STATE]);
|
|
|
a4b897 |
+ } else
|
|
|
a4b897 |
+ vf_linkstate = NULL;
|
|
|
a4b897 |
+
|
|
|
a4b897 |
fprintf(fp, "\n vf %d MAC %s", vf_mac->vf,
|
|
|
a4b897 |
ll_addr_n2a((unsigned char *)&vf_mac->mac,
|
|
|
a4b897 |
ETH_ALEN, 0, b1, sizeof(b1)));
|
|
|
a4b897 |
@@ -270,99 +309,203 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
|
|
a4b897 |
else
|
|
|
a4b897 |
fprintf(fp, ", spoof checking off");
|
|
|
a4b897 |
}
|
|
|
a4b897 |
+ if (vf_linkstate) {
|
|
|
a4b897 |
+ if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_AUTO)
|
|
|
a4b897 |
+ fprintf(fp, ", link-state auto");
|
|
|
a4b897 |
+ else if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_ENABLE)
|
|
|
a4b897 |
+ fprintf(fp, ", link-state enable");
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ fprintf(fp, ", link-state disable");
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
-static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s) {
|
|
|
a4b897 |
- fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+static void print_num(FILE *fp, unsigned width, uint64_t count)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ const char *prefix = "kMGTPE";
|
|
|
a4b897 |
+ const unsigned int base = use_iec ? 1024 : 1000;
|
|
|
a4b897 |
+ uint64_t powi = 1;
|
|
|
a4b897 |
+ uint16_t powj = 1;
|
|
|
a4b897 |
+ uint8_t precision = 2;
|
|
|
a4b897 |
+ char buf[64];
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (!human_readable || count < base) {
|
|
|
a4b897 |
+ fprintf(fp, "%-*"PRIu64" ", width, count);
|
|
|
a4b897 |
+ return;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* increase value by a factor of 1000/1024 and print
|
|
|
a4b897 |
+ * if result is something a human can read */
|
|
|
a4b897 |
+ for(;;) {
|
|
|
a4b897 |
+ powi *= base;
|
|
|
a4b897 |
+ if (count / base < powi)
|
|
|
a4b897 |
+ break;
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (!prefix[1])
|
|
|
a4b897 |
+ break;
|
|
|
a4b897 |
+ ++prefix;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* try to guess a good number of digits for precision */
|
|
|
a4b897 |
+ for (; precision > 0; precision--) {
|
|
|
a4b897 |
+ powj *= 10;
|
|
|
a4b897 |
+ if (count / powi < powj)
|
|
|
a4b897 |
+ break;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ snprintf(buf, sizeof(buf), "%.*f%c%s", precision,
|
|
|
a4b897 |
+ (double) count / powi, *prefix, use_iec ? "i" : "");
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, "%-*s ", width, buf);
|
|
|
a4b897 |
+}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
|
|
|
a4b897 |
+ const struct rtattr *carrier_changes)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ /* RX stats */
|
|
|
a4b897 |
fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
|
|
|
a4b897 |
s->rx_compressed ? "compressed" : "", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
|
|
|
a4b897 |
- (uint64_t)s->rx_bytes,
|
|
|
a4b897 |
- (uint64_t)s->rx_packets,
|
|
|
a4b897 |
- (uint64_t)s->rx_errors,
|
|
|
a4b897 |
- (uint64_t)s->rx_dropped,
|
|
|
a4b897 |
- (uint64_t)s->rx_over_errors,
|
|
|
a4b897 |
- (uint64_t)s->multicast);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 10, s->rx_bytes);
|
|
|
a4b897 |
+ print_num(fp, 8, s->rx_packets);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_dropped);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_over_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->multicast);
|
|
|
a4b897 |
if (s->rx_compressed)
|
|
|
a4b897 |
- fprintf(fp, " %-7"PRIu64"",
|
|
|
a4b897 |
- (uint64_t)s->rx_compressed);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_compressed);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* RX error stats */
|
|
|
a4b897 |
if (show_stats > 1) {
|
|
|
a4b897 |
fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
|
|
|
a4b897 |
- (uint64_t)s->rx_length_errors,
|
|
|
a4b897 |
- (uint64_t)s->rx_crc_errors,
|
|
|
a4b897 |
- (uint64_t)s->rx_frame_errors,
|
|
|
a4b897 |
- (uint64_t)s->rx_fifo_errors,
|
|
|
a4b897 |
- (uint64_t)s->rx_missed_errors);
|
|
|
a4b897 |
+ fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 8, s->rx_length_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_crc_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_frame_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_fifo_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_missed_errors);
|
|
|
a4b897 |
}
|
|
|
a4b897 |
fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* TX stats */
|
|
|
a4b897 |
fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
|
|
|
a4b897 |
- (uint64_t)s->tx_compressed ? "compressed" : "", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
|
|
|
a4b897 |
- (uint64_t)s->tx_bytes,
|
|
|
a4b897 |
- (uint64_t)s->tx_packets,
|
|
|
a4b897 |
- (uint64_t)s->tx_errors,
|
|
|
a4b897 |
- (uint64_t)s->tx_dropped,
|
|
|
a4b897 |
- (uint64_t)s->tx_carrier_errors,
|
|
|
a4b897 |
- (uint64_t)s->collisions);
|
|
|
a4b897 |
+ s->tx_compressed ? "compressed" : "", _SL_);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 10, s->tx_bytes);
|
|
|
a4b897 |
+ print_num(fp, 8, s->tx_packets);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_dropped);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_carrier_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->collisions);
|
|
|
a4b897 |
if (s->tx_compressed)
|
|
|
a4b897 |
- fprintf(fp, " %-7"PRIu64"",
|
|
|
a4b897 |
- (uint64_t)s->tx_compressed);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_compressed);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* TX error stats */
|
|
|
a4b897 |
if (show_stats > 1) {
|
|
|
a4b897 |
fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"",
|
|
|
a4b897 |
- (uint64_t)s->tx_aborted_errors,
|
|
|
a4b897 |
- (uint64_t)s->tx_fifo_errors,
|
|
|
a4b897 |
- (uint64_t)s->tx_window_errors,
|
|
|
a4b897 |
- (uint64_t)s->tx_heartbeat_errors);
|
|
|
a4b897 |
+ fprintf(fp, " TX errors: aborted fifo window heartbeat");
|
|
|
a4b897 |
+ if (carrier_changes)
|
|
|
a4b897 |
+ fprintf(fp, " transns");
|
|
|
a4b897 |
+ fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 8, s->tx_aborted_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_fifo_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_window_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_heartbeat_errors);
|
|
|
a4b897 |
+ if (carrier_changes)
|
|
|
a4b897 |
+ print_num(fp, 7, *(uint32_t*)RTA_DATA(carrier_changes));
|
|
|
a4b897 |
}
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
-static void print_link_stats(FILE *fp, const struct rtnl_link_stats *s)
|
|
|
a4b897 |
+static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
|
|
|
a4b897 |
+ const struct rtattr *carrier_changes)
|
|
|
a4b897 |
{
|
|
|
a4b897 |
- fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+ /* RX stats */
|
|
|
a4b897 |
fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
|
|
|
a4b897 |
s->rx_compressed ? "compressed" : "", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u",
|
|
|
a4b897 |
- s->rx_bytes, s->rx_packets, s->rx_errors,
|
|
|
a4b897 |
- s->rx_dropped, s->rx_over_errors,
|
|
|
a4b897 |
- s->multicast
|
|
|
a4b897 |
- );
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 10, s->rx_bytes);
|
|
|
a4b897 |
+ print_num(fp, 8, s->rx_packets);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_dropped);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_over_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->multicast);
|
|
|
a4b897 |
if (s->rx_compressed)
|
|
|
a4b897 |
- fprintf(fp, " %-7u", s->rx_compressed);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_compressed);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* RX error stats */
|
|
|
a4b897 |
if (show_stats > 1) {
|
|
|
a4b897 |
fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-7u %-7u %-7u %-7u %-7u",
|
|
|
a4b897 |
- s->rx_length_errors,
|
|
|
a4b897 |
- s->rx_crc_errors,
|
|
|
a4b897 |
- s->rx_frame_errors,
|
|
|
a4b897 |
- s->rx_fifo_errors,
|
|
|
a4b897 |
- s->rx_missed_errors
|
|
|
a4b897 |
- );
|
|
|
a4b897 |
+ fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_);
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 8, s->rx_length_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_crc_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_frame_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_fifo_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->rx_missed_errors);
|
|
|
a4b897 |
}
|
|
|
a4b897 |
fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* TX stats */
|
|
|
a4b897 |
fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
|
|
|
a4b897 |
s->tx_compressed ? "compressed" : "", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u",
|
|
|
a4b897 |
- s->tx_bytes, s->tx_packets, s->tx_errors,
|
|
|
a4b897 |
- s->tx_dropped, s->tx_carrier_errors, s->collisions);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 10, s->tx_bytes);
|
|
|
a4b897 |
+ print_num(fp, 8, s->tx_packets);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_dropped);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_carrier_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->collisions);
|
|
|
a4b897 |
if (s->tx_compressed)
|
|
|
a4b897 |
- fprintf(fp, " %-7u", s->tx_compressed);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_compressed);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ /* TX error stats */
|
|
|
a4b897 |
if (show_stats > 1) {
|
|
|
a4b897 |
fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_);
|
|
|
a4b897 |
- fprintf(fp, " %-7u %-7u %-7u %-7u",
|
|
|
a4b897 |
- s->tx_aborted_errors,
|
|
|
a4b897 |
- s->tx_fifo_errors,
|
|
|
a4b897 |
- s->tx_window_errors,
|
|
|
a4b897 |
- s->tx_heartbeat_errors
|
|
|
a4b897 |
- );
|
|
|
a4b897 |
+ fprintf(fp, " TX errors: aborted fifo window heartbeat");
|
|
|
a4b897 |
+ if (carrier_changes)
|
|
|
a4b897 |
+ fprintf(fp, " transns");
|
|
|
a4b897 |
+ fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ fprintf(fp, " ");
|
|
|
a4b897 |
+ print_num(fp, 8, s->tx_aborted_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_fifo_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_window_errors);
|
|
|
a4b897 |
+ print_num(fp, 7, s->tx_heartbeat_errors);
|
|
|
a4b897 |
+ if (carrier_changes)
|
|
|
a4b897 |
+ print_num(fp, 7, *(uint32_t*)RTA_DATA(carrier_changes));
|
|
|
a4b897 |
}
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
+static void __print_link_stats(FILE *fp, struct rtattr **tb)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ if (tb[IFLA_STATS64])
|
|
|
a4b897 |
+ print_link_stats64(fp, RTA_DATA(tb[IFLA_STATS64]),
|
|
|
a4b897 |
+ tb[IFLA_CARRIER_CHANGES]);
|
|
|
a4b897 |
+ else if (tb[IFLA_STATS])
|
|
|
a4b897 |
+ print_link_stats32(fp, RTA_DATA(tb[IFLA_STATS]),
|
|
|
a4b897 |
+ tb[IFLA_CARRIER_CHANGES]);
|
|
|
a4b897 |
+}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+static void print_link_stats(FILE *fp, struct nlmsghdr *n)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ struct ifinfomsg *ifi = NLMSG_DATA(n);
|
|
|
a4b897 |
+ struct rtattr * tb[IFLA_MAX+1];
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi),
|
|
|
a4b897 |
+ n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
|
|
|
a4b897 |
+ __print_link_stats(fp, tb);
|
|
|
a4b897 |
+ fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
int print_linkinfo(const struct sockaddr_nl *who,
|
|
|
a4b897 |
struct nlmsghdr *n, void *arg)
|
|
|
a4b897 |
{
|
|
|
a4b897 |
@@ -411,9 +554,13 @@ int print_linkinfo(const struct sockaddr_nl *who,
|
|
|
a4b897 |
if (iflink == 0)
|
|
|
a4b897 |
fprintf(fp, "@NONE: ");
|
|
|
a4b897 |
else {
|
|
|
a4b897 |
- fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
|
|
|
a4b897 |
- m_flag = ll_index_to_flags(iflink);
|
|
|
a4b897 |
- m_flag = !(m_flag & IFF_UP);
|
|
|
a4b897 |
+ if (tb[IFLA_LINK_NETNSID])
|
|
|
a4b897 |
+ fprintf(fp, "@if%d: ", iflink);
|
|
|
a4b897 |
+ else {
|
|
|
a4b897 |
+ fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
|
|
|
a4b897 |
+ m_flag = ll_index_to_flags(iflink);
|
|
|
a4b897 |
+ m_flag = !(m_flag & IFF_UP);
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
}
|
|
|
a4b897 |
} else {
|
|
|
a4b897 |
fprintf(fp, ": ");
|
|
|
a4b897 |
@@ -461,26 +608,36 @@ int print_linkinfo(const struct sockaddr_nl *who,
|
|
|
a4b897 |
}
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
- if (do_link && tb[IFLA_PROMISCUITY] && show_details)
|
|
|
a4b897 |
+ if (tb[IFLA_LINK_NETNSID]) {
|
|
|
a4b897 |
+ int id = *(int*)RTA_DATA(tb[IFLA_LINK_NETNSID]);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (id >= 0)
|
|
|
a4b897 |
+ fprintf(fp, " link-netnsid %d", id);
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ fprintf(fp, " link-netnsid unknown");
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (tb[IFLA_PROMISCUITY] && show_details)
|
|
|
a4b897 |
fprintf(fp, " promiscuity %u ",
|
|
|
a4b897 |
*(int*)RTA_DATA(tb[IFLA_PROMISCUITY]));
|
|
|
a4b897 |
|
|
|
a4b897 |
- if (do_link && tb[IFLA_LINKINFO] && show_details)
|
|
|
a4b897 |
+ if (tb[IFLA_LINKINFO] && show_details)
|
|
|
a4b897 |
print_linktype(fp, tb[IFLA_LINKINFO]);
|
|
|
a4b897 |
|
|
|
a4b897 |
- if (do_link && tb[IFLA_IFALIAS]) {
|
|
|
a4b897 |
+ if (do_link && tb[IFLA_AF_SPEC] && show_details)
|
|
|
a4b897 |
+ print_af_spec(fp, tb[IFLA_AF_SPEC]);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if ((do_link || show_details) && tb[IFLA_IFALIAS]) {
|
|
|
a4b897 |
fprintf(fp, "%s alias %s", _SL_,
|
|
|
a4b897 |
rta_getattr_str(tb[IFLA_IFALIAS]));
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
if (do_link && show_stats) {
|
|
|
a4b897 |
- if (tb[IFLA_STATS64])
|
|
|
a4b897 |
- print_link_stats64(fp, RTA_DATA(tb[IFLA_STATS64]));
|
|
|
a4b897 |
- else if (tb[IFLA_STATS])
|
|
|
a4b897 |
- print_link_stats(fp, RTA_DATA(tb[IFLA_STATS]));
|
|
|
a4b897 |
+ fprintf(fp, "%s", _SL_);
|
|
|
a4b897 |
+ __print_link_stats(fp, tb);
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
- if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) {
|
|
|
a4b897 |
+ if ((do_link || show_details) && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) {
|
|
|
a4b897 |
struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST];
|
|
|
a4b897 |
int rem = RTA_PAYLOAD(vflist);
|
|
|
a4b897 |
for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
|
|
|
a4b897 |
@@ -489,7 +646,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
|
|
|
a4b897 |
|
|
|
a4b897 |
fprintf(fp, "\n");
|
|
|
a4b897 |
fflush(fp);
|
|
|
a4b897 |
- return 0;
|
|
|
a4b897 |
+ return 1;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
static int flush_update(void)
|
|
|
a4b897 |
@@ -512,10 +669,17 @@ static int set_lifetime(unsigned int *lifetime, char *argv)
|
|
|
a4b897 |
return 0;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
+static unsigned int get_ifa_flags(struct ifaddrmsg *ifa,
|
|
|
a4b897 |
+ struct rtattr *ifa_flags_attr)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ return ifa_flags_attr ? rta_getattr_u32(ifa_flags_attr) :
|
|
|
a4b897 |
+ ifa->ifa_flags;
|
|
|
a4b897 |
+}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
|
|
|
a4b897 |
void *arg)
|
|
|
a4b897 |
{
|
|
|
a4b897 |
- FILE *fp = (FILE*)arg;
|
|
|
a4b897 |
+ FILE *fp = arg;
|
|
|
a4b897 |
struct ifaddrmsg *ifa = NLMSG_DATA(n);
|
|
|
a4b897 |
int len = n->nlmsg_len;
|
|
|
a4b897 |
int deprecated = 0;
|
|
|
a4b897 |
@@ -536,7 +700,10 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
|
|
|
a4b897 |
if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
|
|
|
a4b897 |
return 0;
|
|
|
a4b897 |
|
|
|
a4b897 |
- parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
|
|
|
a4b897 |
+ parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa),
|
|
|
a4b897 |
+ n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]);
|
|
|
a4b897 |
|
|
|
a4b897 |
if (!rta_tb[IFA_LOCAL])
|
|
|
a4b897 |
rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
|
|
|
a4b897 |
@@ -547,7 +714,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
|
|
|
a4b897 |
return 0;
|
|
|
a4b897 |
if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
|
|
|
a4b897 |
return 0;
|
|
|
a4b897 |
- if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
|
|
|
a4b897 |
+ if ((filter.flags ^ ifa_flags) & filter.flagmask)
|
|
|
a4b897 |
return 0;
|
|
|
a4b897 |
if (filter.label) {
|
|
|
a4b897 |
SPRINT_BUF(b1);
|
|
|
a4b897 |
@@ -613,7 +780,8 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
|
|
|
a4b897 |
abuf, sizeof(abuf)));
|
|
|
a4b897 |
|
|
|
a4b897 |
if (rta_tb[IFA_ADDRESS] == NULL ||
|
|
|
a4b897 |
- memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) {
|
|
|
a4b897 |
+ memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]),
|
|
|
a4b897 |
+ ifa->ifa_family == AF_INET ? 4 : 16) == 0) {
|
|
|
a4b897 |
fprintf(fp, "/%d ", ifa->ifa_prefixlen);
|
|
|
a4b897 |
} else {
|
|
|
a4b897 |
fprintf(fp, " peer %s/%d ",
|
|
|
a4b897 |
@@ -640,36 +808,43 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
|
|
|
a4b897 |
abuf, sizeof(abuf)));
|
|
|
a4b897 |
}
|
|
|
a4b897 |
fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
|
|
|
a4b897 |
- ifa_flags = ifa->ifa_flags;
|
|
|
a4b897 |
- if (ifa->ifa_flags&IFA_F_SECONDARY) {
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_SECONDARY) {
|
|
|
a4b897 |
ifa_flags &= ~IFA_F_SECONDARY;
|
|
|
a4b897 |
if (ifa->ifa_family == AF_INET6)
|
|
|
a4b897 |
fprintf(fp, "temporary ");
|
|
|
a4b897 |
else
|
|
|
a4b897 |
fprintf(fp, "secondary ");
|
|
|
a4b897 |
}
|
|
|
a4b897 |
- if (ifa->ifa_flags&IFA_F_TENTATIVE) {
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_TENTATIVE) {
|
|
|
a4b897 |
ifa_flags &= ~IFA_F_TENTATIVE;
|
|
|
a4b897 |
fprintf(fp, "tentative ");
|
|
|
a4b897 |
}
|
|
|
a4b897 |
- if (ifa->ifa_flags&IFA_F_DEPRECATED) {
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_DEPRECATED) {
|
|
|
a4b897 |
ifa_flags &= ~IFA_F_DEPRECATED;
|
|
|
a4b897 |
deprecated = 1;
|
|
|
a4b897 |
fprintf(fp, "deprecated ");
|
|
|
a4b897 |
}
|
|
|
a4b897 |
- if (ifa->ifa_flags&IFA_F_HOMEADDRESS) {
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_HOMEADDRESS) {
|
|
|
a4b897 |
ifa_flags &= ~IFA_F_HOMEADDRESS;
|
|
|
a4b897 |
fprintf(fp, "home ");
|
|
|
a4b897 |
}
|
|
|
a4b897 |
- if (ifa->ifa_flags&IFA_F_NODAD) {
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_NODAD) {
|
|
|
a4b897 |
ifa_flags &= ~IFA_F_NODAD;
|
|
|
a4b897 |
fprintf(fp, "nodad ");
|
|
|
a4b897 |
}
|
|
|
a4b897 |
- if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_MANAGETEMPADDR) {
|
|
|
a4b897 |
+ ifa_flags &= ~IFA_F_MANAGETEMPADDR;
|
|
|
a4b897 |
+ fprintf(fp, "mngtmpaddr ");
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_NOPREFIXROUTE) {
|
|
|
a4b897 |
+ ifa_flags &= ~IFA_F_NOPREFIXROUTE;
|
|
|
a4b897 |
+ fprintf(fp, "noprefixroute ");
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ if (!(ifa_flags & IFA_F_PERMANENT)) {
|
|
|
a4b897 |
fprintf(fp, "dynamic ");
|
|
|
a4b897 |
} else
|
|
|
a4b897 |
ifa_flags &= ~IFA_F_PERMANENT;
|
|
|
a4b897 |
- if (ifa->ifa_flags&IFA_F_DADFAILED) {
|
|
|
a4b897 |
+ if (ifa_flags & IFA_F_DADFAILED) {
|
|
|
a4b897 |
ifa_flags &= ~IFA_F_DADFAILED;
|
|
|
a4b897 |
fprintf(fp, "dadfailed ");
|
|
|
a4b897 |
}
|
|
|
a4b897 |
@@ -896,6 +1071,8 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
|
|
|
a4b897 |
for (a = ainfo->head; a; a = a->next) {
|
|
|
a4b897 |
struct nlmsghdr *n = &a->h;
|
|
|
a4b897 |
struct ifaddrmsg *ifa = NLMSG_DATA(n);
|
|
|
a4b897 |
+ struct rtattr *tb[IFA_MAX + 1];
|
|
|
a4b897 |
+ unsigned int ifa_flags;
|
|
|
a4b897 |
|
|
|
a4b897 |
if (ifa->ifa_index != ifi->ifi_index)
|
|
|
a4b897 |
continue;
|
|
|
a4b897 |
@@ -904,11 +1081,13 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
|
|
|
a4b897 |
continue;
|
|
|
a4b897 |
if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
|
|
|
a4b897 |
continue;
|
|
|
a4b897 |
- if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
|
|
|
a4b897 |
+ ifa_flags = get_ifa_flags(ifa, tb[IFA_FLAGS]);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if ((filter.flags ^ ifa_flags) & filter.flagmask)
|
|
|
a4b897 |
continue;
|
|
|
a4b897 |
if (filter.pfx.family || filter.label) {
|
|
|
a4b897 |
- struct rtattr *tb[IFA_MAX+1];
|
|
|
a4b897 |
- parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
|
|
|
a4b897 |
if (!tb[IFA_LOCAL])
|
|
|
a4b897 |
tb[IFA_LOCAL] = tb[IFA_ADDRESS];
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -1084,6 +1263,12 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
|
|
|
a4b897 |
} else if (strcmp(*argv, "nodad") == 0) {
|
|
|
a4b897 |
filter.flags |= IFA_F_NODAD;
|
|
|
a4b897 |
filter.flagmask |= IFA_F_NODAD;
|
|
|
a4b897 |
+ } else if (strcmp(*argv, "mngtmpaddr") == 0) {
|
|
|
a4b897 |
+ filter.flags |= IFA_F_MANAGETEMPADDR;
|
|
|
a4b897 |
+ filter.flagmask |= IFA_F_MANAGETEMPADDR;
|
|
|
a4b897 |
+ } else if (strcmp(*argv, "noprefixroute") == 0) {
|
|
|
a4b897 |
+ filter.flags |= IFA_F_NOPREFIXROUTE;
|
|
|
a4b897 |
+ filter.flagmask |= IFA_F_NOPREFIXROUTE;
|
|
|
a4b897 |
} else if (strcmp(*argv, "dadfailed") == 0) {
|
|
|
a4b897 |
filter.flags |= IFA_F_DADFAILED;
|
|
|
a4b897 |
filter.flagmask |= IFA_F_DADFAILED;
|
|
|
a4b897 |
@@ -1163,11 +1348,15 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
for (l = linfo.head; l; l = l->next) {
|
|
|
a4b897 |
- if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
|
|
|
a4b897 |
+ int res = 0;
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (no_link || (res = print_linkinfo(NULL, &l->h, stdout)) >= 0) {
|
|
|
a4b897 |
struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
|
|
|
a4b897 |
if (filter.family != AF_PACKET)
|
|
|
a4b897 |
print_selected_addrinfo(ifi->ifi_index,
|
|
|
a4b897 |
ainfo.head, stdout);
|
|
|
a4b897 |
+ if (res > 0 && !do_link && show_stats)
|
|
|
a4b897 |
+ print_link_stats(stdout, &l->h);
|
|
|
a4b897 |
}
|
|
|
a4b897 |
}
|
|
|
a4b897 |
fflush(stdout);
|
|
|
a4b897 |
@@ -1222,6 +1411,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
|
|
|
a4b897 |
__u32 preferred_lft = INFINITY_LIFE_TIME;
|
|
|
a4b897 |
__u32 valid_lft = INFINITY_LIFE_TIME;
|
|
|
a4b897 |
struct ifa_cacheinfo cinfo;
|
|
|
a4b897 |
+ unsigned int ifa_flags = 0;
|
|
|
a4b897 |
|
|
|
a4b897 |
memset(&req, 0, sizeof(req));
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -1299,9 +1489,13 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
|
|
|
a4b897 |
if (set_lifetime(&preferred_lft, *argv))
|
|
|
a4b897 |
invarg("preferred_lft value", *argv);
|
|
|
a4b897 |
} else if (strcmp(*argv, "home") == 0) {
|
|
|
a4b897 |
- req.ifa.ifa_flags |= IFA_F_HOMEADDRESS;
|
|
|
a4b897 |
+ ifa_flags |= IFA_F_HOMEADDRESS;
|
|
|
a4b897 |
} else if (strcmp(*argv, "nodad") == 0) {
|
|
|
a4b897 |
- req.ifa.ifa_flags |= IFA_F_NODAD;
|
|
|
a4b897 |
+ ifa_flags |= IFA_F_NODAD;
|
|
|
a4b897 |
+ } else if (strcmp(*argv, "mngtmpaddr") == 0) {
|
|
|
a4b897 |
+ ifa_flags |= IFA_F_MANAGETEMPADDR;
|
|
|
a4b897 |
+ } else if (strcmp(*argv, "noprefixroute") == 0) {
|
|
|
a4b897 |
+ ifa_flags |= IFA_F_NOPREFIXROUTE;
|
|
|
a4b897 |
} else {
|
|
|
a4b897 |
if (strcmp(*argv, "local") == 0) {
|
|
|
a4b897 |
NEXT_ARG();
|
|
|
a4b897 |
@@ -1319,6 +1513,11 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
|
|
|
a4b897 |
}
|
|
|
a4b897 |
argc--; argv++;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
+ if (ifa_flags <= 0xff)
|
|
|
a4b897 |
+ req.ifa.ifa_flags = ifa_flags;
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ addattr32(&req.n, sizeof(req), IFA_FLAGS, ifa_flags);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
if (d == NULL) {
|
|
|
a4b897 |
fprintf(stderr, "Not enough information: \"dev\" argument is required.\n");
|
|
|
a4b897 |
return -1;
|
|
|
a4b897 |
diff --git a/ip/iplink.c b/ip/iplink.c
|
|
|
a4b897 |
index dc98019..e17d5df 100644
|
|
|
a4b897 |
--- a/ip/iplink.c
|
|
|
a4b897 |
+++ b/ip/iplink.c
|
|
|
a4b897 |
@@ -31,6 +31,7 @@
|
|
|
a4b897 |
#include "rt_names.h"
|
|
|
a4b897 |
#include "utils.h"
|
|
|
a4b897 |
#include "ip_common.h"
|
|
|
a4b897 |
+#include "namespace.h"
|
|
|
a4b897 |
|
|
|
a4b897 |
#define IPLINK_IOCTL_COMPAT 1
|
|
|
a4b897 |
#ifndef LIBDIR
|
|
|
a4b897 |
@@ -70,6 +71,7 @@ void iplink_usage(void)
|
|
|
a4b897 |
fprintf(stderr, " [ mtu MTU ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ netns PID ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ netns NAME ]\n");
|
|
|
a4b897 |
+ fprintf(stderr, " [ link-netnsid ID ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ alias NAME ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] ]\n");
|
|
|
a4b897 |
@@ -77,8 +79,11 @@ void iplink_usage(void)
|
|
|
a4b897 |
fprintf(stderr, " [ rate TXRATE ] ] \n");
|
|
|
a4b897 |
|
|
|
a4b897 |
fprintf(stderr, " [ spoofchk { on | off} ] ] \n");
|
|
|
a4b897 |
+ fprintf(stderr, " [ query_rss { on | off} ] ] \n");
|
|
|
a4b897 |
+ fprintf(stderr, " [ state { auto | enable | disable} ] ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ master DEVICE ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ nomaster ]\n");
|
|
|
a4b897 |
+ fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n");
|
|
|
a4b897 |
fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up]\n");
|
|
|
a4b897 |
|
|
|
a4b897 |
if (iplink_have_newlink()) {
|
|
|
a4b897 |
@@ -144,6 +149,15 @@ static int get_link_mode(const char *mode)
|
|
|
a4b897 |
return -1;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
+static int get_addr_gen_mode(const char *mode)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ if (strcasecmp(mode, "eui64") == 0)
|
|
|
a4b897 |
+ return IN6_ADDR_GEN_MODE_EUI64;
|
|
|
a4b897 |
+ if (strcasecmp(mode, "none") == 0)
|
|
|
a4b897 |
+ return IN6_ADDR_GEN_MODE_NONE;
|
|
|
a4b897 |
+ return -1;
|
|
|
a4b897 |
+}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
#if IPLINK_IOCTL_COMPAT
|
|
|
a4b897 |
static int have_rtnl_newlink = -1;
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -176,8 +190,13 @@ static int iplink_have_newlink(void)
|
|
|
a4b897 |
req.n.nlmsg_type = RTM_NEWLINK;
|
|
|
a4b897 |
req.i.ifi_family = AF_UNSPEC;
|
|
|
a4b897 |
|
|
|
a4b897 |
- rtnl_send(&rth, &req.n, req.n.nlmsg_len);
|
|
|
a4b897 |
- rtnl_listen(&rth, accept_msg, NULL);
|
|
|
a4b897 |
+ if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
|
|
|
a4b897 |
+ perror("Could not check for "
|
|
|
a4b897 |
+ "link configuration over netlink support");
|
|
|
a4b897 |
+ have_rtnl_newlink = 0;
|
|
|
a4b897 |
+ } else {
|
|
|
a4b897 |
+ rtnl_listen(&rth, accept_msg, NULL);
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
}
|
|
|
a4b897 |
return have_rtnl_newlink;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
@@ -254,7 +273,44 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
|
|
|
a4b897 |
invarg("Invalid \"spoofchk\" value\n", *argv);
|
|
|
a4b897 |
ivs.vf = vf;
|
|
|
a4b897 |
addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs));
|
|
|
a4b897 |
+ } else if (matches(*argv, "state") == 0) {
|
|
|
a4b897 |
+ struct ifla_vf_link_state ivl;
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ if (matches(*argv, "auto") == 0)
|
|
|
a4b897 |
+ ivl.link_state = IFLA_VF_LINK_STATE_AUTO;
|
|
|
a4b897 |
+ else if (matches(*argv, "enable") == 0)
|
|
|
a4b897 |
+ ivl.link_state = IFLA_VF_LINK_STATE_ENABLE;
|
|
|
a4b897 |
+ else if (matches(*argv, "disable") == 0)
|
|
|
a4b897 |
+ ivl.link_state = IFLA_VF_LINK_STATE_DISABLE;
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ invarg("Invalid \"state\" value\n", *argv);
|
|
|
a4b897 |
+ ivl.vf = vf;
|
|
|
a4b897 |
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl));
|
|
|
a4b897 |
+ } else if (matches(*argv, "query_rss") == 0) {
|
|
|
a4b897 |
+ struct ifla_vf_rss_query_en ivs;
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ if (matches(*argv, "on") == 0)
|
|
|
a4b897 |
+ ivs.setting = 1;
|
|
|
a4b897 |
+ else if (matches(*argv, "off") == 0)
|
|
|
a4b897 |
+ ivs.setting = 0;
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ invarg("Invalid \"query_rss\" value\n", *argv);
|
|
|
a4b897 |
+ ivs.vf = vf;
|
|
|
a4b897 |
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(ivs));
|
|
|
a4b897 |
|
|
|
a4b897 |
+ } else if (matches(*argv, "state") == 0) {
|
|
|
a4b897 |
+ struct ifla_vf_link_state ivl;
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ if (matches(*argv, "auto") == 0)
|
|
|
a4b897 |
+ ivl.link_state = IFLA_VF_LINK_STATE_AUTO;
|
|
|
a4b897 |
+ else if (matches(*argv, "enable") == 0)
|
|
|
a4b897 |
+ ivl.link_state = IFLA_VF_LINK_STATE_ENABLE;
|
|
|
a4b897 |
+ else if (matches(*argv, "disable") == 0)
|
|
|
a4b897 |
+ ivl.link_state = IFLA_VF_LINK_STATE_DISABLE;
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ invarg("Invalid \"state\" value\n", *argv);
|
|
|
a4b897 |
+ ivl.vf = vf;
|
|
|
a4b897 |
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl));
|
|
|
a4b897 |
} else {
|
|
|
a4b897 |
/* rewind arg */
|
|
|
a4b897 |
PREV_ARG();
|
|
|
a4b897 |
@@ -284,6 +340,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
|
|
|
a4b897 |
int vf = -1;
|
|
|
a4b897 |
int numtxqueues = -1;
|
|
|
a4b897 |
int numrxqueues = -1;
|
|
|
a4b897 |
+ int link_netnsid = -1;
|
|
|
a4b897 |
|
|
|
a4b897 |
*group = -1;
|
|
|
a4b897 |
ret = argc;
|
|
|
a4b897 |
@@ -334,7 +391,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
|
|
|
a4b897 |
NEXT_ARG();
|
|
|
a4b897 |
if (netns != -1)
|
|
|
a4b897 |
duparg("netns", *argv);
|
|
|
a4b897 |
- if ((netns = get_netns_fd(*argv)) >= 0)
|
|
|
a4b897 |
+ if ((netns = netns_get_fd(*argv)) >= 0)
|
|
|
a4b897 |
addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
|
|
|
a4b897 |
else if (get_integer(&netns, *argv, 0) == 0)
|
|
|
a4b897 |
addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
|
|
|
a4b897 |
@@ -466,6 +523,26 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
|
|
|
a4b897 |
invarg("Invalid \"numrxqueues\" value\n", *argv);
|
|
|
a4b897 |
addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
|
|
|
a4b897 |
&numrxqueues, 4);
|
|
|
a4b897 |
+ } else if (matches(*argv, "addrgenmode") == 0) {
|
|
|
a4b897 |
+ struct rtattr *afs, *afs6;
|
|
|
a4b897 |
+ int mode;
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ mode = get_addr_gen_mode(*argv);
|
|
|
a4b897 |
+ if (mode < 0)
|
|
|
a4b897 |
+ invarg("Invalid address generation mode\n", *argv);
|
|
|
a4b897 |
+ afs = addattr_nest(&req->n, sizeof(*req), IFLA_AF_SPEC);
|
|
|
a4b897 |
+ afs6 = addattr_nest(&req->n, sizeof(*req), AF_INET6);
|
|
|
a4b897 |
+ addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode);
|
|
|
a4b897 |
+ addattr_nest_end(&req->n, afs6);
|
|
|
a4b897 |
+ addattr_nest_end(&req->n, afs);
|
|
|
a4b897 |
+ } else if (matches(*argv, "link-netnsid") == 0) {
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ if (link_netnsid != -1)
|
|
|
a4b897 |
+ duparg("link-netnsid", *argv);
|
|
|
a4b897 |
+ if (get_integer(&link_netnsid, *argv, 0))
|
|
|
a4b897 |
+ invarg("Invalid \"link-netnsid\" value\n", *argv);
|
|
|
a4b897 |
+ addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
|
|
|
a4b897 |
+ link_netnsid);
|
|
|
a4b897 |
} else {
|
|
|
a4b897 |
if (strcmp(*argv, "dev") == 0) {
|
|
|
a4b897 |
NEXT_ARG();
|
|
|
a4b897 |
diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
|
|
|
a4b897 |
index 1025326..43b8abc 100644
|
|
|
a4b897 |
--- a/ip/iplink_vxlan.c
|
|
|
a4b897 |
+++ b/ip/iplink_vxlan.c
|
|
|
a4b897 |
@@ -23,11 +23,12 @@
|
|
|
a4b897 |
|
|
|
a4b897 |
static void explain(void)
|
|
|
a4b897 |
{
|
|
|
a4b897 |
- fprintf(stderr, "Usage: ... vxlan id VNI [ group ADDR ] [ local ADDR ]\n");
|
|
|
a4b897 |
+ fprintf(stderr, "Usage: ... vxlan id VNI [ { group | remote } ADDR ] [ local ADDR ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ dev PHYS_DEV ]\n");
|
|
|
a4b897 |
- fprintf(stderr, " [ port MIN MAX ] [ [no]learning ]\n");
|
|
|
a4b897 |
- fprintf(stderr, " [ [no]proxy ] [ [no]rsc ]\n");
|
|
|
a4b897 |
+ fprintf(stderr, " [ dstport PORT ] [ srcport MIN MAX ]\n");
|
|
|
a4b897 |
+ fprintf(stderr, " [ [no]learning ] [ [no]proxy ] [ [no]rsc ]\n");
|
|
|
a4b897 |
fprintf(stderr, " [ [no]l2miss ] [ [no]l3miss ]\n");
|
|
|
a4b897 |
+ fprintf(stderr, " [ gbp ]\n");
|
|
|
a4b897 |
fprintf(stderr, "\n");
|
|
|
a4b897 |
fprintf(stderr, "Where: VNI := 0-16777215\n");
|
|
|
a4b897 |
fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
|
|
|
a4b897 |
@@ -42,6 +43,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
int vni_set = 0;
|
|
|
a4b897 |
__u32 saddr = 0;
|
|
|
a4b897 |
__u32 gaddr = 0;
|
|
|
a4b897 |
+ __u32 daddr = 0;
|
|
|
a4b897 |
+ struct in6_addr saddr6 = IN6ADDR_ANY_INIT;
|
|
|
a4b897 |
+ struct in6_addr gaddr6 = IN6ADDR_ANY_INIT;
|
|
|
a4b897 |
+ struct in6_addr daddr6 = IN6ADDR_ANY_INIT;
|
|
|
a4b897 |
unsigned link = 0;
|
|
|
a4b897 |
__u8 tos = 0;
|
|
|
a4b897 |
__u8 ttl = 0;
|
|
|
a4b897 |
@@ -53,6 +58,12 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
__u8 noage = 0;
|
|
|
a4b897 |
__u32 age = 0;
|
|
|
a4b897 |
__u32 maxaddr = 0;
|
|
|
a4b897 |
+ __u16 dstport = 0;
|
|
|
a4b897 |
+ __u8 gbp = 0;
|
|
|
a4b897 |
+ __u8 udpcsum = 0;
|
|
|
a4b897 |
+ __u8 udp6zerocsumtx = 0;
|
|
|
a4b897 |
+ __u8 udp6zerocsumrx = 0;
|
|
|
a4b897 |
+ int dst_port_set = 0;
|
|
|
a4b897 |
struct ifla_vxlan_port_range range = { 0, 0 };
|
|
|
a4b897 |
|
|
|
a4b897 |
while (argc > 0) {
|
|
|
a4b897 |
@@ -65,15 +76,30 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
vni_set = 1;
|
|
|
a4b897 |
} else if (!matches(*argv, "group")) {
|
|
|
a4b897 |
NEXT_ARG();
|
|
|
a4b897 |
- gaddr = get_addr32(*argv);
|
|
|
a4b897 |
-
|
|
|
a4b897 |
- if (!IN_MULTICAST(ntohl(gaddr)))
|
|
|
a4b897 |
- invarg("invald group address", *argv);
|
|
|
a4b897 |
+ if (!inet_get_addr(*argv, &gaddr, &gaddr6)) {
|
|
|
a4b897 |
+ fprintf(stderr, "Invalid address \"%s\"\n", *argv);
|
|
|
a4b897 |
+ return -1;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ if (!IN6_IS_ADDR_MULTICAST(&gaddr6) && !IN_MULTICAST(ntohl(gaddr)))
|
|
|
a4b897 |
+ invarg("invalid group address", *argv);
|
|
|
a4b897 |
+ } else if (!matches(*argv, "remote")) {
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ if (!inet_get_addr(*argv, &daddr, &daddr6)) {
|
|
|
a4b897 |
+ fprintf(stderr, "Invalid address \"%s\"\n", *argv);
|
|
|
a4b897 |
+ return -1;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr)))
|
|
|
a4b897 |
+ invarg("invalid remote address", *argv);
|
|
|
a4b897 |
} else if (!matches(*argv, "local")) {
|
|
|
a4b897 |
NEXT_ARG();
|
|
|
a4b897 |
- if (strcmp(*argv, "any"))
|
|
|
a4b897 |
- saddr = get_addr32(*argv);
|
|
|
a4b897 |
- if (IN_MULTICAST(ntohl(saddr)))
|
|
|
a4b897 |
+ if (strcmp(*argv, "any")) {
|
|
|
a4b897 |
+ if (!inet_get_addr(*argv, &saddr, &saddr6)) {
|
|
|
a4b897 |
+ fprintf(stderr, "Invalid address \"%s\"\n", *argv);
|
|
|
a4b897 |
+ return -1;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6))
|
|
|
a4b897 |
invarg("invalid local address", *argv);
|
|
|
a4b897 |
} else if (!matches(*argv, "dev")) {
|
|
|
a4b897 |
NEXT_ARG();
|
|
|
a4b897 |
@@ -115,7 +141,8 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
maxaddr = 0;
|
|
|
a4b897 |
else if (get_u32(&maxaddr, *argv, 0))
|
|
|
a4b897 |
invarg("max addresses", *argv);
|
|
|
a4b897 |
- } else if (!matches(*argv, "port")) {
|
|
|
a4b897 |
+ } else if (!matches(*argv, "port") ||
|
|
|
a4b897 |
+ !matches(*argv, "srcport")) {
|
|
|
a4b897 |
__u16 minport, maxport;
|
|
|
a4b897 |
NEXT_ARG();
|
|
|
a4b897 |
if (get_u16(&minport, *argv, 0))
|
|
|
a4b897 |
@@ -125,6 +152,11 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
invarg("max port", *argv);
|
|
|
a4b897 |
range.low = htons(minport);
|
|
|
a4b897 |
range.high = htons(maxport);
|
|
|
a4b897 |
+ } else if (!matches(*argv, "dstport")){
|
|
|
a4b897 |
+ NEXT_ARG();
|
|
|
a4b897 |
+ if (get_u16(&dstport, *argv, 0))
|
|
|
a4b897 |
+ invarg("dst port", *argv);
|
|
|
a4b897 |
+ dst_port_set = 1;
|
|
|
a4b897 |
} else if (!matches(*argv, "nolearning")) {
|
|
|
a4b897 |
learning = 0;
|
|
|
a4b897 |
} else if (!matches(*argv, "learning")) {
|
|
|
a4b897 |
@@ -145,6 +177,20 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
l3miss = 0;
|
|
|
a4b897 |
} else if (!matches(*argv, "l3miss")) {
|
|
|
a4b897 |
l3miss = 1;
|
|
|
a4b897 |
+ } else if (!matches(*argv, "gbp")) {
|
|
|
a4b897 |
+ gbp = 1;
|
|
|
a4b897 |
+ } else if (!matches(*argv, "udpcsum")) {
|
|
|
a4b897 |
+ udpcsum = 1;
|
|
|
a4b897 |
+ } else if (!matches(*argv, "noudpcsum")) {
|
|
|
a4b897 |
+ udpcsum = 0;
|
|
|
a4b897 |
+ } else if (!matches(*argv, "udp6zerocsumtx")) {
|
|
|
a4b897 |
+ udp6zerocsumtx = 1;
|
|
|
a4b897 |
+ } else if (!matches(*argv, "noudp6zerocsumtx")) {
|
|
|
a4b897 |
+ udp6zerocsumtx = 0;
|
|
|
a4b897 |
+ } else if (!matches(*argv, "udp6zerocsumrx")) {
|
|
|
a4b897 |
+ udp6zerocsumrx = 1;
|
|
|
a4b897 |
+ } else if (!matches(*argv, "noudp6zerocsumrx")) {
|
|
|
a4b897 |
+ udp6zerocsumrx = 0;
|
|
|
a4b897 |
} else if (matches(*argv, "help") == 0) {
|
|
|
a4b897 |
explain();
|
|
|
a4b897 |
return -1;
|
|
|
a4b897 |
@@ -160,11 +206,35 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
fprintf(stderr, "vxlan: missing virtual network identifier\n");
|
|
|
a4b897 |
return -1;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (!dst_port_set) {
|
|
|
a4b897 |
+ fprintf(stderr, "vxlan: destination port not specified\n"
|
|
|
a4b897 |
+ "Will use Linux kernel default (non-standard value)\n");
|
|
|
a4b897 |
+ fprintf(stderr,
|
|
|
a4b897 |
+ "Use 'dstport 4789' to get the IANA assigned value\n"
|
|
|
a4b897 |
+ "Use 'dstport 0' to get default and quiet this message\n");
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ if ((gaddr && daddr) ||
|
|
|
a4b897 |
+ (memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) &&
|
|
|
a4b897 |
+ memcmp(&daddr6, &in6addr_any, sizeof(daddr6)))) {
|
|
|
a4b897 |
+ fprintf(stderr, "vxlan: both group and remote cannot be specified\n");
|
|
|
a4b897 |
+ return -1;
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
addattr32(n, 1024, IFLA_VXLAN_ID, vni);
|
|
|
a4b897 |
if (gaddr)
|
|
|
a4b897 |
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
|
|
|
a4b897 |
+ else if (daddr)
|
|
|
a4b897 |
+ addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4);
|
|
|
a4b897 |
+ if (memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) != 0)
|
|
|
a4b897 |
+ addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr));
|
|
|
a4b897 |
+ else if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0)
|
|
|
a4b897 |
+ addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr));
|
|
|
a4b897 |
+
|
|
|
a4b897 |
if (saddr)
|
|
|
a4b897 |
addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4);
|
|
|
a4b897 |
+ else if (memcmp(&saddr6, &in6addr_any, sizeof(saddr6)) != 0)
|
|
|
a4b897 |
+ addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6, sizeof(struct in6_addr));
|
|
|
a4b897 |
+
|
|
|
a4b897 |
if (link)
|
|
|
a4b897 |
addattr32(n, 1024, IFLA_VXLAN_LINK, link);
|
|
|
a4b897 |
addattr8(n, 1024, IFLA_VXLAN_TTL, ttl);
|
|
|
a4b897 |
@@ -174,6 +244,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
addattr8(n, 1024, IFLA_VXLAN_RSC, rsc);
|
|
|
a4b897 |
addattr8(n, 1024, IFLA_VXLAN_L2MISS, l2miss);
|
|
|
a4b897 |
addattr8(n, 1024, IFLA_VXLAN_L3MISS, l3miss);
|
|
|
a4b897 |
+ addattr8(n, 1024, IFLA_VXLAN_UDP_CSUM, udpcsum);
|
|
|
a4b897 |
+ addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, udp6zerocsumtx);
|
|
|
a4b897 |
+ addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, udp6zerocsumrx);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
if (noage)
|
|
|
a4b897 |
addattr32(n, 1024, IFLA_VXLAN_AGEING, 0);
|
|
|
a4b897 |
else if (age)
|
|
|
a4b897 |
@@ -184,6 +258,13 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|
|
a4b897 |
addattr_l(n, 1024, IFLA_VXLAN_PORT_RANGE,
|
|
|
a4b897 |
&range, sizeof(range));
|
|
|
a4b897 |
|
|
|
a4b897 |
+ if (dstport)
|
|
|
a4b897 |
+ addattr16(n, 1024, IFLA_VXLAN_PORT, htons(dstport));
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (gbp)
|
|
|
a4b897 |
+ addattr_l(n, 1024, IFLA_VXLAN_GBP, NULL, 0);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+
|
|
|
a4b897 |
return 0;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -208,9 +289,25 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|
|
a4b897 |
|
|
|
a4b897 |
if (tb[IFLA_VXLAN_GROUP]) {
|
|
|
a4b897 |
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_GROUP]);
|
|
|
a4b897 |
- if (addr)
|
|
|
a4b897 |
- fprintf(f, "group %s ",
|
|
|
a4b897 |
- format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
|
|
|
a4b897 |
+ if (addr) {
|
|
|
a4b897 |
+ if (IN_MULTICAST(ntohl(addr)))
|
|
|
a4b897 |
+ fprintf(f, "group %s ",
|
|
|
a4b897 |
+ format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ fprintf(f, "remote %s ",
|
|
|
a4b897 |
+ format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ } else if (tb[IFLA_VXLAN_GROUP6]) {
|
|
|
a4b897 |
+ struct in6_addr addr;
|
|
|
a4b897 |
+ memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_GROUP6]), sizeof(struct in6_addr));
|
|
|
a4b897 |
+ if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) {
|
|
|
a4b897 |
+ if (IN6_IS_ADDR_MULTICAST(&addr))
|
|
|
a4b897 |
+ fprintf(f, "group %s ",
|
|
|
a4b897 |
+ format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
|
|
|
a4b897 |
+ else
|
|
|
a4b897 |
+ fprintf(f, "remote %s ",
|
|
|
a4b897 |
+ format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
if (tb[IFLA_VXLAN_LOCAL]) {
|
|
|
a4b897 |
@@ -218,6 +315,12 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|
|
a4b897 |
if (addr)
|
|
|
a4b897 |
fprintf(f, "local %s ",
|
|
|
a4b897 |
format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
|
|
|
a4b897 |
+ } else if (tb[IFLA_VXLAN_LOCAL6]) {
|
|
|
a4b897 |
+ struct in6_addr addr;
|
|
|
a4b897 |
+ memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_LOCAL6]), sizeof(struct in6_addr));
|
|
|
a4b897 |
+ if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0)
|
|
|
a4b897 |
+ fprintf(f, "local %s ",
|
|
|
a4b897 |
+ format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
if (tb[IFLA_VXLAN_LINK] &&
|
|
|
a4b897 |
@@ -233,9 +336,13 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|
|
a4b897 |
if (tb[IFLA_VXLAN_PORT_RANGE]) {
|
|
|
a4b897 |
const struct ifla_vxlan_port_range *r
|
|
|
a4b897 |
= RTA_DATA(tb[IFLA_VXLAN_PORT_RANGE]);
|
|
|
a4b897 |
- fprintf(f, "port %u %u ", ntohs(r->low), ntohs(r->high));
|
|
|
a4b897 |
+ fprintf(f, "srcport %u %u ", ntohs(r->low), ntohs(r->high));
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
+ if (tb[IFLA_VXLAN_PORT])
|
|
|
a4b897 |
+ fprintf(f, "dstport %u ",
|
|
|
a4b897 |
+ ntohs(rta_getattr_u16(tb[IFLA_VXLAN_PORT])));
|
|
|
a4b897 |
+
|
|
|
a4b897 |
if (tb[IFLA_VXLAN_LEARNING] &&
|
|
|
a4b897 |
!rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]))
|
|
|
a4b897 |
fputs("nolearning ", f);
|
|
|
a4b897 |
@@ -277,6 +384,20 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|
|
a4b897 |
if (tb[IFLA_VXLAN_LIMIT] &&
|
|
|
a4b897 |
(maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT]) != 0))
|
|
|
a4b897 |
fprintf(f, "maxaddr %u ", maxaddr);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (tb[IFLA_VXLAN_UDP_CSUM] && rta_getattr_u8(tb[IFLA_VXLAN_UDP_CSUM]))
|
|
|
a4b897 |
+ fputs("udpcsum ", f);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] &&
|
|
|
a4b897 |
+ rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]))
|
|
|
a4b897 |
+ fputs("udp6zerocsumtx ", f);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] &&
|
|
|
a4b897 |
+ rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
|
|
|
a4b897 |
+ fputs("udp6zerocsumrx ", f);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+ if (tb[IFLA_VXLAN_GBP])
|
|
|
a4b897 |
+ fputs("gbp ", f);
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
struct link_util vxlan_link_util = {
|
|
|
a4b897 |
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
|
|
|
a4b897 |
index 9e2a795..baac6ae 100644
|
|
|
a4b897 |
--- a/lib/libnetlink.c
|
|
|
a4b897 |
+++ b/lib/libnetlink.c
|
|
|
a4b897 |
@@ -701,6 +701,18 @@ int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int l
|
|
|
a4b897 |
return i;
|
|
|
a4b897 |
}
|
|
|
a4b897 |
|
|
|
a4b897 |
+struct rtattr *parse_rtattr_one(int type, struct rtattr *rta, int len)
|
|
|
a4b897 |
+{
|
|
|
a4b897 |
+ while (RTA_OK(rta, len)) {
|
|
|
a4b897 |
+ if (rta->rta_type == type)
|
|
|
a4b897 |
+ return rta;
|
|
|
a4b897 |
+ rta = RTA_NEXT(rta, len);
|
|
|
a4b897 |
+ }
|
|
|
a4b897 |
+ if (len)
|
|
|
a4b897 |
+ fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
|
|
|
a4b897 |
+ return NULL;
|
|
|
a4b897 |
+}
|
|
|
a4b897 |
+
|
|
|
a4b897 |
int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta,
|
|
|
a4b897 |
int len)
|
|
|
a4b897 |
{
|
|
|
a4b897 |
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
|
|
|
a4b897 |
index 86e0bc9..a015b82 100644
|
|
|
a4b897 |
--- a/man/man8/ip-link.8.in
|
|
|
a4b897 |
+++ b/man/man8/ip-link.8.in
|
|
|
a4b897 |
@@ -16,6 +16,7 @@ ip-link \- network device configuration
|
|
|
a4b897 |
.ti -8
|
|
|
a4b897 |
.IR OPTIONS " := { "
|
|
|
a4b897 |
\fB\-V\fR[\fIersion\fR] |
|
|
|
a4b897 |
+\fB\-h\fR[\fIuman-readable\fR] |
|
|
|
a4b897 |
\fB\-s\fR[\fItatistics\fR] |
|
|
|
a4b897 |
\fB\-r\fR[\fIesolve\fR] |
|
|
|
a4b897 |
\fB\-f\fR[\fIamily\fR] {
|
|
|
a4b897 |
@@ -120,9 +121,11 @@ ip-link \- network device configuration
|
|
|
a4b897 |
] |
|
|
|
a4b897 |
.br
|
|
|
a4b897 |
.B master
|
|
|
a4b897 |
-.IR DEVICE
|
|
|
a4b897 |
+.IR DEVICE " |"
|
|
|
a4b897 |
.br
|
|
|
a4b897 |
-.B nomaster
|
|
|
a4b897 |
+.B nomaster " |"
|
|
|
a4b897 |
+.br
|
|
|
a4b897 |
+.B addrgenmode { eui64 | none }
|
|
|
a4b897 |
.BR " }"
|
|
|
a4b897 |
|
|
|
a4b897 |
|
|
|
a4b897 |
@@ -197,6 +200,65 @@ specifies the number of transmit queues for new device.
|
|
|
a4b897 |
specifies the number of receive queues for new device.
|
|
|
a4b897 |
|
|
|
a4b897 |
.TP
|
|
|
a4b897 |
+VLAN Type Support
|
|
|
a4b897 |
+For a link of type
|
|
|
a4b897 |
+.I VLAN
|
|
|
a4b897 |
+the following additional arguments are supported:
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BI "ip link add link " DEVICE
|
|
|
a4b897 |
+.BI name " NAME "
|
|
|
a4b897 |
+.BI type " vlan "
|
|
|
a4b897 |
+.R " [ "
|
|
|
a4b897 |
+.BI protocol " VLAN_PROTO "
|
|
|
a4b897 |
+.R " ] "
|
|
|
a4b897 |
+.BI id " VLANID "
|
|
|
a4b897 |
+.R " [ "
|
|
|
a4b897 |
+.BR reorder_hdr " { " on " | " off " } "
|
|
|
a4b897 |
+.R " ] "
|
|
|
a4b897 |
+.R " [ "
|
|
|
a4b897 |
+.BR gvrp " { " on " | " off " } "
|
|
|
a4b897 |
+.R " ] "
|
|
|
a4b897 |
+.R " [ "
|
|
|
a4b897 |
+.BR mvrp " { " on " | " off " } "
|
|
|
a4b897 |
+.R " ] "
|
|
|
a4b897 |
+.R " [ "
|
|
|
a4b897 |
+.BR loose_binding " { " on " | " off " } "
|
|
|
a4b897 |
+.R " ] "
|
|
|
a4b897 |
+.R " [ "
|
|
|
a4b897 |
+.BI ingress-qos-map " QOS-MAP "
|
|
|
a4b897 |
+.R " ] "
|
|
|
a4b897 |
+.R " [ "
|
|
|
a4b897 |
+.BI egress-qos-map " QOS-MAP "
|
|
|
a4b897 |
+.R " ] "
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.in +8
|
|
|
a4b897 |
+.sp
|
|
|
a4b897 |
+.BI protocol " VLAN_PROTO "
|
|
|
a4b897 |
+- either 802.1Q or 802.1ad.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BI id " VLANID "
|
|
|
a4b897 |
+- specifies the VID.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BR reorder_hdr " { " on " | " off " } "
|
|
|
a4b897 |
+- specifies whether ethernet headers are reordered or not.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BR gvrp " { " on " | " off " } "
|
|
|
a4b897 |
+- specifies whether this VLAN should be registered using GARP VLAN Registration Protocol.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BR mvrp " { " on " | " off " } "
|
|
|
a4b897 |
+- specifies whether this VLAN should be registered using Multiple VLAN Registration Protocol.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BR loose_binding " { " on " | " off " } "
|
|
|
a4b897 |
+- specifies whether the VLAN device state is bound to the physical device state.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BI ingress-qos-map " QOS-MAP "
|
|
|
a4b897 |
+- defines a mapping between priority code points on incoming frames. The format is FROM:TO with multiple mappings separated by spaces.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.BI egress-qos-map " QOS-MAP "
|
|
|
a4b897 |
+- the same as ingress-qos-map but for outgoing frames.
|
|
|
a4b897 |
+.in -8
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
VXLAN Type Support
|
|
|
a4b897 |
For a link of type
|
|
|
a4b897 |
.I VXLAN
|
|
|
a4b897 |
@@ -206,8 +268,8 @@ the following additional arguments are supported:
|
|
|
a4b897 |
.BI type " vxlan " id " ID
|
|
|
a4b897 |
.R " [ "
|
|
|
a4b897 |
.BI dev " PHYS_DEV "
|
|
|
a4b897 |
-.R " ] [ "
|
|
|
a4b897 |
-.BI group " IPADDR "
|
|
|
a4b897 |
+.RB " ] [ { " group " | " remote " } "
|
|
|
a4b897 |
+.I IPADDR
|
|
|
a4b897 |
.R " ] [ "
|
|
|
a4b897 |
.BI local " IPADDR "
|
|
|
a4b897 |
.R " ] [ "
|
|
|
a4b897 |
@@ -226,6 +288,8 @@ the following additional arguments are supported:
|
|
|
a4b897 |
.I "[no]l2miss "
|
|
|
a4b897 |
.R " ] [ "
|
|
|
a4b897 |
.I "[no]l3miss "
|
|
|
a4b897 |
+.R " ] [ "
|
|
|
a4b897 |
+.B gbp
|
|
|
a4b897 |
.R " ]"
|
|
|
a4b897 |
|
|
|
a4b897 |
.in +8
|
|
|
a4b897 |
@@ -240,6 +304,17 @@ Identifier) to use.
|
|
|
a4b897 |
.sp
|
|
|
a4b897 |
.BI group " IPADDR"
|
|
|
a4b897 |
- specifies the multicast IP address to join.
|
|
|
a4b897 |
+This parameter cannot be specified with the
|
|
|
a4b897 |
+.B remote
|
|
|
a4b897 |
+parameter.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.sp
|
|
|
a4b897 |
+.BI remote " IPADDR"
|
|
|
a4b897 |
+- specifies the unicast destination IP address to use in outgoing packets
|
|
|
a4b897 |
+when the destination link layer address is not known in the VXLAN device
|
|
|
a4b897 |
+forwarding database. This parameter cannot be specified with the
|
|
|
a4b897 |
+.B group
|
|
|
a4b897 |
+parameter.
|
|
|
a4b897 |
|
|
|
a4b897 |
.sp
|
|
|
a4b897 |
.BI local " IPADDR"
|
|
|
a4b897 |
@@ -279,6 +354,49 @@ are entered into the VXLAN device forwarding database.
|
|
|
a4b897 |
.I [no]l3miss
|
|
|
a4b897 |
- specifies if netlink IP ADDR miss notifications are generated.
|
|
|
a4b897 |
|
|
|
a4b897 |
+.sp
|
|
|
a4b897 |
+.B gbp
|
|
|
a4b897 |
+- enables the Group Policy extension (VXLAN-GBP).
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.in +4
|
|
|
a4b897 |
+Allows to transport group policy context across VXLAN network peers.
|
|
|
a4b897 |
+If enabled, includes the mark of a packet in the VXLAN header for outgoing
|
|
|
a4b897 |
+packets and fills the packet mark based on the information found in the
|
|
|
a4b897 |
+VXLAN header for incomming packets.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+Format of upper 16 bits of packet mark (flags);
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.in +2
|
|
|
a4b897 |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
a4b897 |
+.br
|
|
|
a4b897 |
+|-|-|-|-|-|-|-|-|-|D|-|-|A|-|-|-|
|
|
|
a4b897 |
+.br
|
|
|
a4b897 |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.B D :=
|
|
|
a4b897 |
+Don't Learn bit. When set, this bit indicates that the egress
|
|
|
a4b897 |
+VTEP MUST NOT learn the source address of the encapsulated frame.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.B A :=
|
|
|
a4b897 |
+Indicates that the group policy has already been applied to
|
|
|
a4b897 |
+this packet. Policies MUST NOT be applied by devices when the A bit is set.
|
|
|
a4b897 |
+.in -2
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+Format of lower 16 bits of packet mark (policy ID):
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.in +2
|
|
|
a4b897 |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
a4b897 |
+.br
|
|
|
a4b897 |
+| Group Policy ID |
|
|
|
a4b897 |
+.br
|
|
|
a4b897 |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
a4b897 |
+.in -2
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+Example:
|
|
|
a4b897 |
+ iptables -A OUTPUT [...] -j MARK --set-mark 0x800FF
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.in -4
|
|
|
a4b897 |
+
|
|
|
a4b897 |
.in -8
|
|
|
a4b897 |
|
|
|
a4b897 |
.SS ip link delete - delete virtual link
|
|
|
a4b897 |
@@ -366,14 +484,29 @@ the interface is
|
|
|
a4b897 |
.IR "POINTOPOINT" .
|
|
|
a4b897 |
|
|
|
a4b897 |
.TP
|
|
|
a4b897 |
-.BI netns " PID"
|
|
|
a4b897 |
-move the device to the network namespace associated with the process
|
|
|
a4b897 |
-.IR "PID".
|
|
|
a4b897 |
-
|
|
|
a4b897 |
-.TP
|
|
|
a4b897 |
-.BI netns " NETNSNAME"
|
|
|
a4b897 |
+.BI netns " NETNSNAME " \fR| " PID"
|
|
|
a4b897 |
move the device to the network namespace associated with name
|
|
|
a4b897 |
-.IR "NETNSNAME".
|
|
|
a4b897 |
+.IR "NETNSNAME " or
|
|
|
a4b897 |
+.RI process " PID".
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+Some devices are not allowed to change network namespace: loopback, bridge,
|
|
|
a4b897 |
+ppp, wireless. These are network namespace local devices. In such case
|
|
|
a4b897 |
+.B ip
|
|
|
a4b897 |
+tool will return "Invalid argument" error. It is possible to find out if device is local
|
|
|
a4b897 |
+to a single network namespace by checking
|
|
|
a4b897 |
+.B netns-local
|
|
|
a4b897 |
+flag in the output of the
|
|
|
a4b897 |
+.BR ethtool ":"
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.in +8
|
|
|
a4b897 |
+.B ethtool -k
|
|
|
a4b897 |
+.I DEVICE
|
|
|
a4b897 |
+.in -8
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+To change network namespace for wireless devices the
|
|
|
a4b897 |
+.B iw
|
|
|
a4b897 |
+tool can be used. But it allows to change network namespace only for physical devices and by process
|
|
|
a4b897 |
+.IR PID .
|
|
|
a4b897 |
|
|
|
a4b897 |
.TP
|
|
|
a4b897 |
.BI alias " NAME"
|
|
|
a4b897 |
@@ -442,6 +575,10 @@ set master device of the device (enslave device).
|
|
|
a4b897 |
.BI nomaster
|
|
|
a4b897 |
unset master device of the device (release device).
|
|
|
a4b897 |
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
+.BR "addrgenmode eui64 " or " addrgenmode none"
|
|
|
a4b897 |
+allow to ipv6 set address generation mode
|
|
|
a4b897 |
+
|
|
|
a4b897 |
.PP
|
|
|
a4b897 |
.B Warning:
|
|
|
a4b897 |
If multiple parameter changes are requested,
|
|
|
a4b897 |
@@ -471,6 +608,27 @@ specifies what group of devices to show.
|
|
|
a4b897 |
.B up
|
|
|
a4b897 |
only display running interfaces.
|
|
|
a4b897 |
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
+The show command has additional formatting options:
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.RS
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
+.BR "\-s" , " \-stats", " \-statistics"
|
|
|
a4b897 |
+output more statistics about packet usage.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
+.BR "\-d", " \-details"
|
|
|
a4b897 |
+output more detailed information.
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
+.BR "\-h", " \-human", " \-human-readble"
|
|
|
a4b897 |
+output statistics with human readable values number followed by suffix
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
+.BR "\-iec"
|
|
|
a4b897 |
+print human readable rates in IEC units (ie. 1K = 1024).
|
|
|
a4b897 |
+.RE
|
|
|
a4b897 |
+
|
|
|
a4b897 |
.SH "EXAMPLES"
|
|
|
a4b897 |
.PP
|
|
|
a4b897 |
ip link show
|
|
|
a4b897 |
@@ -495,7 +653,8 @@ Removes vlan device.
|
|
|
a4b897 |
|
|
|
a4b897 |
.SH SEE ALSO
|
|
|
a4b897 |
.br
|
|
|
a4b897 |
-.BR ip (8)
|
|
|
a4b897 |
+.BR ip (8),
|
|
|
a4b897 |
+.BR ip-netns (8)
|
|
|
a4b897 |
|
|
|
a4b897 |
.SH AUTHOR
|
|
|
a4b897 |
Original Manpage by Michail Litvak <mci@owl.openwall.com>
|
|
|
a4b897 |
diff --git a/man/man8/ip.8 b/man/man8/ip.8
|
|
|
a4b897 |
index 9065b3a..0713756 100644
|
|
|
a4b897 |
--- a/man/man8/ip.8
|
|
|
a4b897 |
+++ b/man/man8/ip.8
|
|
|
a4b897 |
@@ -31,7 +31,8 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
|
|
|
a4b897 |
\fB\-r\fR[\fIesolve\fR] |
|
|
|
a4b897 |
\fB\-f\fR[\fIamily\fR] {
|
|
|
a4b897 |
.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | "
|
|
|
a4b897 |
-\fB\-o\fR[\fIneline\fR] }
|
|
|
a4b897 |
+\fB\-o\fR[\fIneline\fR] |
|
|
|
a4b897 |
+\fB\-n\fR[\fIetns\fR] name }
|
|
|
a4b897 |
|
|
|
a4b897 |
|
|
|
a4b897 |
.SH OPTIONS
|
|
|
a4b897 |
@@ -130,6 +131,26 @@ the output.
|
|
|
a4b897 |
use the system's name resolver to print DNS names instead of
|
|
|
a4b897 |
host addresses.
|
|
|
a4b897 |
|
|
|
a4b897 |
+.TP
|
|
|
a4b897 |
+.BR "\-n" , " \-net" , " \-netns " <NETNS>
|
|
|
a4b897 |
+switches
|
|
|
a4b897 |
+.B ip
|
|
|
a4b897 |
+to the specified network namespace
|
|
|
a4b897 |
+.IR NETNS .
|
|
|
a4b897 |
+Actually it just simplifies executing of:
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.B ip netns exec
|
|
|
a4b897 |
+.IR NETNS
|
|
|
a4b897 |
+.B ip
|
|
|
a4b897 |
+.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
|
|
a4b897 |
+.BR help " }"
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+to
|
|
|
a4b897 |
+
|
|
|
a4b897 |
+.B ip
|
|
|
a4b897 |
+.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
|
|
a4b897 |
+.BR help " }"
|
|
|
a4b897 |
+
|
|
|
a4b897 |
.SH IP - COMMAND SYNTAX
|
|
|
a4b897 |
|
|
|
a4b897 |
.SS
|