From: Stephen Hemminger Date: Wed, 28 Apr 2021 02:39:39 +0000 (-0700) Subject: Merge git://git.kernel.org/pub/scm/network/iproute2/iproute2-next X-Git-Tag: v5.13.0~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2363bc99f9745b1aa16645136ec6a9c443d4687e;p=thirdparty%2Fiproute2.git Merge git://git.kernel.org/pub/scm/network/iproute2/iproute2-next Required manual fix of devlink/devlink.c Signed-off-by: Stephen Hemminger --- 2363bc99f9745b1aa16645136ec6a9c443d4687e diff --cc devlink/devlink.c index faa87b3de,16eca4f9e..0b5548fbe --- a/devlink/devlink.c +++ b/devlink/devlink.c @@@ -965,13 -917,7 +917,13 @@@ static int strtobool(const char *str, b static int __dl_argv_handle(char *str, char **p_bus_name, char **p_dev_name) { - str_split_by_char(str, p_bus_name, p_dev_name, '/'); + int err; + - err = strslashrsplit(str, p_bus_name, p_dev_name); ++ err = str_split_by_char(str, p_bus_name, p_dev_name, '/'); + if (err) { + pr_err("Devlink identification (\"bus_name/dev_name\") \"%s\" is invalid\n", str); + return err; + } return 0; } diff --cc ip/ipnexthop.c index f0658a9cb,e88feaf6a..9478aa529 --- a/ip/ipnexthop.c +++ b/ip/ipnexthop.c @@@ -275,11 -408,54 +408,55 @@@ int print_nexthop(struct nlmsghdr *n, v return 0; } + int print_nexthop_bucket(struct nlmsghdr *n, void *arg) + { + struct nhmsg *nhm = NLMSG_DATA(n); + struct rtattr *tb[NHA_MAX+1]; + FILE *fp = (FILE *)arg; + int len; + + if (n->nlmsg_type != RTM_DELNEXTHOPBUCKET && + n->nlmsg_type != RTM_NEWNEXTHOPBUCKET) { + fprintf(stderr, "Not a nexthop bucket: %08x %08x %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + return -1; + } + + len = n->nlmsg_len - NLMSG_SPACE(sizeof(*nhm)); + if (len < 0) { + close_json_object(); + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + + parse_rtattr_flags(tb, NHA_MAX, RTM_NHA(nhm), len, NLA_F_NESTED); + + open_json_object(NULL); + + if (n->nlmsg_type == RTM_DELNEXTHOP) + print_bool(PRINT_ANY, "deleted", "Deleted ", true); + + if (tb[NHA_ID]) + print_uint(PRINT_ANY, "id", "id %u ", + rta_getattr_u32(tb[NHA_ID])); + + if (tb[NHA_RES_BUCKET]) + print_nh_res_bucket(fp, tb[NHA_RES_BUCKET]); + + print_rt_flags(fp, nhm->nh_flags); + + print_string(PRINT_FP, NULL, "%s", "\n"); + close_json_object(); + fflush(fp); + + return 0; + } + static int add_nh_group_attr(struct nlmsghdr *n, int maxlen, char *argv) { - struct nexthop_grp *grps; + struct nexthop_grp *grps = NULL; int count = 0, i; + int err = -1; char *sep, *wsep; if (*argv != '\0') @@@ -325,12 -501,113 +502,116 @@@ argv = sep + 1; } - return addattr_l(n, maxlen, NHA_GROUP, grps, count * sizeof(*grps)); + err = addattr_l(n, maxlen, NHA_GROUP, grps, count * sizeof(*grps)); +out: + free(grps); + return err; } + static int read_nh_group_type(const char *name) + { + if (strcmp(name, "mpath") == 0) + return NEXTHOP_GRP_TYPE_MPATH; + else if (strcmp(name, "resilient") == 0) + return NEXTHOP_GRP_TYPE_RES; + + return __NEXTHOP_GRP_TYPE_MAX; + } + + static void parse_nh_group_type_res(struct nlmsghdr *n, int maxlen, int *argcp, + char ***argvp) + { + char **argv = *argvp; + struct rtattr *nest; + int argc = *argcp; + + if (!NEXT_ARG_OK()) + return; + + nest = addattr_nest(n, maxlen, NHA_RES_GROUP); + nest->rta_type |= NLA_F_NESTED; + + NEXT_ARG_FWD(); + while (argc > 0) { + if (strcmp(*argv, "buckets") == 0) { + __u16 buckets; + + NEXT_ARG(); + if (get_u16(&buckets, *argv, 0)) + invarg("invalid buckets value", *argv); + + addattr16(n, maxlen, NHA_RES_GROUP_BUCKETS, buckets); + } else if (strcmp(*argv, "idle_timer") == 0) { + __u32 idle_timer; + + NEXT_ARG(); + if (get_unsigned(&idle_timer, *argv, 0) || + idle_timer >= ~0UL / 100) + invarg("invalid idle timer value", *argv); + + addattr32(n, maxlen, NHA_RES_GROUP_IDLE_TIMER, + idle_timer * 100); + } else if (strcmp(*argv, "unbalanced_timer") == 0) { + __u32 unbalanced_timer; + + NEXT_ARG(); + if (get_unsigned(&unbalanced_timer, *argv, 0) || + unbalanced_timer >= ~0UL / 100) + invarg("invalid unbalanced timer value", *argv); + + addattr32(n, maxlen, NHA_RES_GROUP_UNBALANCED_TIMER, + unbalanced_timer * 100); + } else { + break; + } + argc--; argv++; + } + + /* argv is currently the first unparsed argument, but ipnh_modify() + * will move to the next, so step back. + */ + *argcp = argc + 1; + *argvp = argv - 1; + + addattr_nest_end(n, nest); + } + + static void parse_nh_group_type(struct nlmsghdr *n, int maxlen, int *argcp, + char ***argvp) + { + char **argv = *argvp; + int argc = *argcp; + __u16 type; + + NEXT_ARG(); + type = read_nh_group_type(*argv); + if (type > NEXTHOP_GRP_TYPE_MAX) + invarg("\"type\" value is invalid\n", *argv); + + switch (type) { + case NEXTHOP_GRP_TYPE_MPATH: + /* No additional arguments */ + break; + case NEXTHOP_GRP_TYPE_RES: + parse_nh_group_type_res(n, maxlen, &argc, &argv); + break; + } + + *argcp = argc; + *argvp = argv; + + addattr16(n, maxlen, NHA_GROUP_TYPE, type); + } + + static int ipnh_parse_id(const char *argv) + { + __u32 id; + + if (get_unsigned(&id, argv, 0)) + invarg("invalid id value", argv); + return id; + } + static int ipnh_modify(int cmd, unsigned int flags, int argc, char **argv) { struct {