Merge branch 'master' into net-next
diff --git a/include/utils.h b/include/utils.h
index 27562a1..82f1aa7 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -248,5 +248,6 @@
bool show_label);
char *int_to_str(int val, char *buf);
+int get_guid(__u64 *guid, const char *arg);
#endif /* __UTILS_H__ */
diff --git a/ip/iplink.c b/ip/iplink.c
index f2a2e13..365240e 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -317,7 +317,8 @@
len, halen);
return -1;
}
- addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm));
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC,
+ &ivm, sizeof(ivm));
} else if (matches(*argv, "vlan") == 0) {
struct ifla_vf_vlan ivv;
@@ -338,7 +339,8 @@
PREV_ARG();
}
}
- addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv));
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN,
+ &ivv, sizeof(ivv));
} else if (matches(*argv, "rate") == 0) {
struct ifla_vf_tx_rate ivt;
@@ -378,7 +380,8 @@
else
return on_off("spoofchk", *argv);
ivs.vf = vf;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs));
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK,
+ &ivs, sizeof(ivs));
} else if (matches(*argv, "query_rss") == 0) {
struct ifla_vf_rss_query_en ivs;
@@ -391,7 +394,8 @@
else
return on_off("query_rss", *argv);
ivs.vf = vf;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(ivs));
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN,
+ &ivs, sizeof(ivs));
} else if (matches(*argv, "trust") == 0) {
struct ifla_vf_trust ivt;
@@ -404,7 +408,8 @@
else
invarg("Invalid \"trust\" value\n", *argv);
ivt.vf = vf;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_TRUST, &ivt, sizeof(ivt));
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_TRUST,
+ &ivt, sizeof(ivt));
} else if (matches(*argv, "state") == 0) {
struct ifla_vf_link_state ivl;
@@ -419,7 +424,30 @@
else
invarg("Invalid \"state\" value\n", *argv);
ivl.vf = vf;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl));
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE,
+ &ivl, sizeof(ivl));
+ } else if (matches(*argv, "node_guid") == 0) {
+ struct ifla_vf_guid ivg;
+
+ NEXT_ARG();
+ ivg.vf = vf;
+ if (get_guid(&ivg.guid, *argv)) {
+ invarg("Invalid GUID format\n", *argv);
+ return -1;
+ }
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_IB_NODE_GUID,
+ &ivg, sizeof(ivg));
+ } else if (matches(*argv, "port_guid") == 0) {
+ struct ifla_vf_guid ivg;
+
+ NEXT_ARG();
+ ivg.vf = vf;
+ if (get_guid(&ivg.guid, *argv)) {
+ invarg("Invalid GUID format\n", *argv);
+ return -1;
+ }
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_IB_PORT_GUID,
+ &ivg, sizeof(ivg));
} else {
/* rewind arg */
PREV_ARG();
@@ -523,9 +551,11 @@
duparg("netns", *argv);
netns = netns_get_fd(*argv);
if (netns >= 0)
- addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
+ addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD,
+ &netns, 4);
else if (get_integer(&netns, *argv, 0) == 0)
- addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
+ addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID,
+ &netns, 4);
else
invarg("Invalid \"netns\" value\n", *argv);
} else if (strcmp(*argv, "multicast") == 0) {
@@ -689,7 +719,8 @@
invarg("Invalid address generation mode\n", *argv);
afs = addattr_nest(&req->n, sizeof(*req), IFLA_AF_SPEC);
afs6 = addattr_nest(&req->n, sizeof(*req), AF_INET6);
- addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode);
+ addattr8(&req->n, sizeof(*req),
+ IFLA_INET6_ADDR_GEN_MODE, mode);
addattr_nest_end(&req->n, afs6);
addattr_nest_end(&req->n, afs);
} else if (matches(*argv, "link-netnsid") == 0) {
@@ -728,10 +759,11 @@
if (dev_index && addr_len) {
int halen = nl_get_ll_addr_len(dev_index);
+
if (halen >= 0 && halen != addr_len) {
fprintf(stderr,
- "Invalid address length %d - must be %d bytes\n",
- addr_len, halen);
+ "Invalid address length %d - must be %d bytes\n",
+ addr_len, halen);
return -1;
}
}
@@ -759,7 +791,8 @@
req.n.nlmsg_type = cmd;
req.i.ifi_family = preferred_family;
- ret = iplink_parse(argc, argv, &req, &name, &type, &link, &dev, &group, &index);
+ ret = iplink_parse(argc, argv,
+ &req, &name, &type, &link, &dev, &group, &index);
if (ret < 0)
return ret;
@@ -772,8 +805,8 @@
&group, sizeof(group));
else {
if (argc) {
- fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"ip link "
- "help\".\n", *argv);
+ fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
+ *argv);
return -1;
}
if (flags & NLM_F_CREATE) {
@@ -830,7 +863,8 @@
if (name) {
len = strlen(name) + 1;
if (len == 1)
- invarg("\"\" is not a valid device identifier\n", "name");
+ invarg("\"\" is not a valid device identifier\n",
+ "name");
if (len > IFNAMSIZ)
invarg("\"name\" too long\n", name);
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len);
@@ -859,7 +893,8 @@
iflatype = IFLA_INFO_DATA;
}
if (lu && argc) {
- struct rtattr *data = addattr_nest(&req.n, sizeof(req), iflatype);
+ struct rtattr *data = addattr_nest(&req.n,
+ sizeof(req), iflatype);
if (lu->parse_opt &&
lu->parse_opt(lu, argc, argv, &req.n))
@@ -1090,7 +1125,8 @@
if (alen < 0)
return -1;
if (alen != halen) {
- fprintf(stderr, "Wrong address (%s) length: expected %d bytes\n", lla, halen);
+ fprintf(stderr, "Wrong address (%s) length: expected %d bytes\n",
+ lla, halen);
return -1;
}
return 0;
@@ -1230,7 +1266,8 @@
}
if (!dev) {
- fprintf(stderr, "Not enough of information: \"dev\" argument is required.\n");
+ fprintf(stderr,
+ "Not enough of information: \"dev\" argument is required.\n");
exit(-1);
}
diff --git a/ip/iproute.c b/ip/iproute.c
index 24f6b01..c564fa6 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1810,12 +1810,42 @@
return 0;
}
+static int rtattr_cmp(const struct rtattr *rta1, const struct rtattr *rta2)
+{
+ if (!rta1 || !rta2 || rta1->rta_len != rta2->rta_len)
+ return 1;
+
+ return memcmp(RTA_DATA(rta1), RTA_DATA(rta2), RTA_PAYLOAD(rta1));
+}
+
static int restore_handler(const struct sockaddr_nl *nl,
struct rtnl_ctrl_data *ctrl,
struct nlmsghdr *n, void *arg)
{
- int ret;
+ struct rtmsg *r = NLMSG_DATA(n);
+ struct rtattr *tb[RTA_MAX+1];
+ int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
+ int ret, prio = *(int *)arg;
+ parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
+
+ /* Restore routes in correct order:
+ * 0. ones for local addresses,
+ * 1. ones for local networks,
+ * 2. others (remote networks/hosts).
+ */
+ if (!prio && !tb[RTA_GATEWAY] && (!tb[RTA_PREFSRC] ||
+ !rtattr_cmp(tb[RTA_PREFSRC], tb[RTA_DST])))
+ goto restore;
+ else if (prio == 1 && !tb[RTA_GATEWAY] &&
+ rtattr_cmp(tb[RTA_PREFSRC], tb[RTA_DST]))
+ goto restore;
+ else if (prio == 2 && tb[RTA_GATEWAY])
+ goto restore;
+
+ return 0;
+
+restore:
n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
ll_init_map(&rth);
@@ -1848,10 +1878,23 @@
static int iproute_restore(void)
{
+ int pos, prio;
+
if (route_dump_check_magic())
exit(-1);
- exit(rtnl_from_file(stdin, &restore_handler, NULL));
+ pos = ftell(stdin);
+ for (prio = 0; prio < 3; prio++) {
+ int err;
+
+ err = rtnl_from_file(stdin, &restore_handler, &prio);
+ if (err)
+ exit(err);
+
+ fseek(stdin, pos, SEEK_SET);
+ }
+
+ exit(0);
}
static int show_handler(const struct sockaddr_nl *nl,
diff --git a/lib/utils.c b/lib/utils.c
index 7dceeb5..9660474 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1121,3 +1121,38 @@
sprintf(buf, "%d", val);
return buf;
}
+
+int get_guid(__u64 *guid, const char *arg)
+{
+ unsigned long int tmp;
+ char *endptr;
+ int i;
+
+#define GUID_STR_LEN 23
+ /* Verify strict format: format string must be
+ * xx:xx:xx:xx:xx:xx:xx:xx where xx can be an arbitrary
+ * hex digit
+ */
+
+ if (strlen(arg) != GUID_STR_LEN)
+ return -1;
+
+ /* make sure columns are in place */
+ for (i = 0; i < 7; i++)
+ if (arg[2 + i * 3] != ':')
+ return -1;
+
+ *guid = 0;
+ for (i = 0; i < 8; i++) {
+ tmp = strtoul(arg + i * 3, &endptr, 16);
+ if (endptr != arg + i * 3 + 2)
+ return -1;
+
+ if (tmp > 255)
+ return -1;
+
+ *guid |= tmp << (56 - 8 * i);
+ }
+
+ return 0;
+}
diff --git a/man/man8/Makefile b/man/man8/Makefile
index 929826e..9badbed 100644
--- a/man/man8/Makefile
+++ b/man/man8/Makefile
@@ -16,7 +16,8 @@
tc-basic.8 tc-cgroup.8 tc-flow.8 tc-flower.8 tc-fw.8 tc-route.8 \
tc-tcindex.8 tc-u32.8 \
tc-connmark.8 tc-csum.8 tc-mirred.8 tc-nat.8 tc-pedit.8 tc-police.8 \
- tc-simple.8 tc-skbedit.8 tc-vlan.8 tc-xt.8
+ tc-simple.8 tc-skbedit.8 tc-vlan.8 tc-xt.8 \
+ devlink.8 devlink-dev.8 devlink-monitor.8 devlink-port.8 devlink-sb.8
all: $(TARGETS)
diff --git a/man/man8/devlink.8 b/man/man8/devlink.8
index df00f4f..cf0563b 100644
--- a/man/man8/devlink.8
+++ b/man/man8/devlink.8
@@ -76,6 +76,7 @@
.BR devlink-dev (8),
.BR devlink-port (8),
.BR devlink-monitor (8),
+.BR devlink-sb (8),
.br
.SH REPORTING BUGS
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index ad18f75..95fef02 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -146,7 +146,11 @@
.br
.RB "[ " state " { " auto " | " enable " | " disable " } ]"
.br
-.RB "[ " trust " { " on " | " off " } ] ]"
+.RB "[ " trust " { " on " | " off " } ]"
+.br
+.RB "[ " node_guid " eui64 ]"
+.br
+.RB "[ " port_guid " eui64 ] ]"
.br
.in -9
.RB "[ " master
@@ -1196,6 +1200,12 @@
.BI trust " on|off"
- trust the specified VF user. This enables that VF user can set a specific feature
which may impact security and/or performance. (e.g. VF multicast promiscuous mode)
+.sp
+.BI node_guid " eui64"
+- configure node GUID for the VF.
+.sp
+.BI port_guid " eui64"
+- configure port GUID for the VF.
.in -8
.TP