diff --git a/include/utils.h b/include/utils.h index 27562a1c..82f1aa7d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -248,5 +248,6 @@ int do_each_netns(int (*func)(char *nsname, void *arg), void *arg, 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 f2a2e13c..365240e6 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -317,7 +317,8 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, 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 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, 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 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, 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 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, 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 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, 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 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, 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 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, 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 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, 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 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, 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 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) 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 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) &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 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) 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 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) 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 @@ static int parse_address(const char *dev, int hatype, int halen, 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 @@ static int do_set(int argc, char **argv) } 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 24f6b010..c564fa6d 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -1810,12 +1810,42 @@ static int iproute_get(int argc, char **argv) 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 route_dump_check_magic(void) 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 7dceeb58..96604746 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1121,3 +1121,38 @@ char *int_to_str(int val, char *buf) 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 929826ec..9badbed7 100644 --- a/man/man8/Makefile +++ b/man/man8/Makefile @@ -16,7 +16,8 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 rtpr.8 ss. 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 df00f4fa..cf0563b9 100644 --- a/man/man8/devlink.8 +++ b/man/man8/devlink.8 @@ -76,6 +76,7 @@ Exit status is 0 if command was successful or a positive integer upon failure. .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 ad18f755..95fef02c 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -146,7 +146,11 @@ ip-link \- network device configuration .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 @@ sent by the VF. .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