From patchwork Fri Oct 30 12:29:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Machata X-Patchwork-Id: 315980 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 82184C00A89 for ; Fri, 30 Oct 2020 12:32:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 192A8221FF for ; Fri, 30 Oct 2020 12:32:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=pmachata.org header.i=@pmachata.org header.b="QwqlzRKr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726642AbgJ3Mbt (ORCPT ); Fri, 30 Oct 2020 08:31:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44360 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726531AbgJ3MbM (ORCPT ); Fri, 30 Oct 2020 08:31:12 -0400 Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [IPv6:2001:67c:2050::465:101]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 13F3EC0613D2 for ; Fri, 30 Oct 2020 05:31:12 -0700 (PDT) Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:105:465:1:2:0]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4CN1rG53D9zQky8; Fri, 30 Oct 2020 13:31:10 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pmachata.org; s=MBO0001; t=1604061068; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L8gPvARuOucKpeeGtwIx19zoR5UzyAayT53YkNHfC9Y=; b=QwqlzRKr9Sat0AMlQE8WH3dZH/nVdbDjbJ6iBYATXttGw4vyoKzL+c0Rn9XvSh+1NKKJIW +7Wc32eNLeULyrmkMmwOjQWS/ASWnMzQLQGCVgODgTZ5jwk4mClvrziy4AWFiYkBgF4519 OfRsfSDNGdS4wbJrxltOPr+mTkw8pkz1eKkCFVsmSpjEkg+XkRcc1Cha8QzqnIkQ2zbj7p +kvR35ytpwlQqGK4ejzK8iQ0wUyWmJC/m1f/gd2WvohzE3KzbiqxgZCpRyQEZlnR7r3GFs ZnJr1I67GMDx8T74pnBYPBIgxLS3SgPssA9UnOpCnjIEGoHK2Ct18IYNTfCKxQ== Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter01.heinlein-hosting.de (spamfilter01.heinlein-hosting.de [80.241.56.115]) (amavisd-new, port 10030) with ESMTP id zivff0W5rBLR; Fri, 30 Oct 2020 13:31:04 +0100 (CET) From: Petr Machata To: netdev@vger.kernel.org, dsahern@gmail.com, stephen@networkplumber.org Cc: john.fastabend@gmail.com, jiri@nvidia.com, idosch@nvidia.com, Jakub Kicinski , Roman Mashak , Petr Machata Subject: [PATCH iproute2-next v2 02/11] lib: Add parse_one_of(), parse_on_off() Date: Fri, 30 Oct 2020 13:29:49 +0100 Message-Id: <194ae677df465086d6cd1d7962c07d790e6d049d.1604059429.git.me@pmachata.org> In-Reply-To: References: MIME-Version: 1.0 X-MBO-SPAM-Probability: * X-Rspamd-Score: 1.09 / 15.00 / 15.00 X-Rspamd-Queue-Id: A4B7B1707 X-Rspamd-UID: 236a96 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Take from the macsec code parse_one_of() and adapt so that it passes the primary result as the main return value, and error result through a pointer. That is the simplest way to make the code reusable across data types without introducing extra magic. Also from macsec take the specialization of parse_one_of() for parsing specifically the strings "off" and "on". Convert the macsec code to the new helpers. Signed-off-by: Petr Machata --- include/utils.h | 4 ++++ ip/ipmacsec.c | 52 +++++++++++-------------------------------------- lib/utils.c | 28 ++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/include/utils.h b/include/utils.h index 085b17b1f6e3..bd62cdcd7122 100644 --- a/include/utils.h +++ b/include/utils.h @@ -325,4 +325,8 @@ char *sprint_time64(__s64 time, char *buf); int do_batch(const char *name, bool force, int (*cmd)(int argc, char *argv[], void *user), void *user); +int parse_one_of(const char *msg, const char *realval, const char * const *list, + size_t len, int *p_err); +int parse_on_off(const char *msg, const char *realval, int *p_err); + #endif /* __UTILS_H__ */ diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c index 18289ecd6d9e..bf48e8b5d0b2 100644 --- a/ip/ipmacsec.c +++ b/ip/ipmacsec.c @@ -23,8 +23,6 @@ #include "ll_map.h" #include "libgenl.h" -static const char * const values_on_off[] = { "off", "on" }; - static const char * const validate_str[] = { [MACSEC_VALIDATE_DISABLED] = "disabled", [MACSEC_VALIDATE_CHECK] = "check", @@ -108,25 +106,6 @@ static void ipmacsec_usage(void) exit(-1); } -static int one_of(const char *msg, const char *realval, const char * const *list, - size_t len, int *index) -{ - int i; - - for (i = 0; i < len; i++) { - if (matches(realval, list[i]) == 0) { - *index = i; - return 0; - } - } - - fprintf(stderr, "Error: argument of \"%s\" must be one of ", msg); - for (i = 0; i < len; i++) - fprintf(stderr, "\"%s\", ", list[i]); - fprintf(stderr, "not \"%s\"\n", realval); - return -1; -} - static int get_an(__u8 *val, const char *arg) { int ret = get_u8(val, arg, 0); @@ -559,8 +538,7 @@ static int do_offload(enum cmd c, int argc, char **argv) if (argc == 0) ipmacsec_usage(); - ret = one_of("offload", *argv, offload_str, ARRAY_SIZE(offload_str), - (int *)&offload); + offload = parse_one_of("offload", *argv, offload_str, ARRAY_SIZE(offload_str), &ret); if (ret) ipmacsec_usage(); @@ -1334,8 +1312,7 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); int i; - ret = one_of("encrypt", *argv, values_on_off, - ARRAY_SIZE(values_on_off), &i); + i = parse_on_off("encrypt", *argv, &ret); if (ret != 0) return ret; addattr8(n, MACSEC_BUFLEN, IFLA_MACSEC_ENCRYPT, i); @@ -1343,8 +1320,7 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); int i; - ret = one_of("send_sci", *argv, values_on_off, - ARRAY_SIZE(values_on_off), &i); + i = parse_on_off("send_sci", *argv, &ret); if (ret != 0) return ret; send_sci = i; @@ -1354,8 +1330,7 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); int i; - ret = one_of("end_station", *argv, values_on_off, - ARRAY_SIZE(values_on_off), &i); + i = parse_on_off("end_station", *argv, &ret); if (ret != 0) return ret; es = i; @@ -1364,8 +1339,7 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); int i; - ret = one_of("scb", *argv, values_on_off, - ARRAY_SIZE(values_on_off), &i); + i = parse_on_off("scb", *argv, &ret); if (ret != 0) return ret; scb = i; @@ -1374,8 +1348,7 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); int i; - ret = one_of("protect", *argv, values_on_off, - ARRAY_SIZE(values_on_off), &i); + i = parse_on_off("protect", *argv, &ret); if (ret != 0) return ret; addattr8(n, MACSEC_BUFLEN, IFLA_MACSEC_PROTECT, i); @@ -1383,8 +1356,7 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); int i; - ret = one_of("replay", *argv, values_on_off, - ARRAY_SIZE(values_on_off), &i); + i = parse_on_off("replay", *argv, &ret); if (ret != 0) return ret; replay_protect = !!i; @@ -1395,9 +1367,8 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, invarg("expected replay window size", *argv); } else if (strcmp(*argv, "validate") == 0) { NEXT_ARG(); - ret = one_of("validate", *argv, - validate_str, ARRAY_SIZE(validate_str), - (int *)&validate); + validate = parse_one_of("validate", *argv, validate_str, + ARRAY_SIZE(validate_str), &ret); if (ret != 0) return ret; addattr8(n, MACSEC_BUFLEN, @@ -1411,9 +1382,8 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, invarg("expected an { 0..3 }", *argv); } else if (strcmp(*argv, "offload") == 0) { NEXT_ARG(); - ret = one_of("offload", *argv, - offload_str, ARRAY_SIZE(offload_str), - (int *)&offload); + offload = parse_one_of("offload", *argv, offload_str, + ARRAY_SIZE(offload_str), &ret); if (ret != 0) return ret; addattr8(n, MACSEC_BUFLEN, diff --git a/lib/utils.c b/lib/utils.c index 9815e328c9e0..930877ae0f0d 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1735,3 +1735,31 @@ int do_batch(const char *name, bool force, return ret; } + +int parse_one_of(const char *msg, const char *realval, const char * const *list, + size_t len, int *p_err) +{ + int i; + + for (i = 0; i < len; i++) { + if (list[i] && matches(realval, list[i]) == 0) { + *p_err = 0; + return i; + } + } + + fprintf(stderr, "Error: argument of \"%s\" must be one of ", msg); + for (i = 0; i < len; i++) + if (list[i]) + fprintf(stderr, "\"%s\", ", list[i]); + fprintf(stderr, "not \"%s\"\n", realval); + *p_err = -EINVAL; + return 0; +} + +int parse_on_off(const char *msg, const char *realval, int *p_err) +{ + static const char * const values_on_off[] = { "off", "on" }; + + return parse_one_of(msg, realval, values_on_off, ARRAY_SIZE(values_on_off), p_err); +} From patchwork Fri Oct 30 12:29:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Machata X-Patchwork-Id: 315981 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20A01C00A89 for ; Fri, 30 Oct 2020 12:31:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B4D9B221FF for ; Fri, 30 Oct 2020 12:31:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=pmachata.org header.i=@pmachata.org header.b="GQaHfAa9" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726531AbgJ3Mbu (ORCPT ); Fri, 30 Oct 2020 08:31:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44352 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726325AbgJ3MbL (ORCPT ); Fri, 30 Oct 2020 08:31:11 -0400 Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [IPv6:2001:67c:2050::465:101]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4AF29C0613D4 for ; Fri, 30 Oct 2020 05:31:11 -0700 (PDT) Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4CN1rF0LhLzQl8x; Fri, 30 Oct 2020 13:31:09 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pmachata.org; s=MBO0001; t=1604061067; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lTWKdB9jKvPLlGcL64b7TayarsnysHuzTi2oE2fPlwI=; b=GQaHfAa9BH/V8obvaobK/cg6ESlyy5l+VZVUl2a5wvM2gRftLqLLd5vUOanrBYfzoiDu48 LMR/0t9dg4PrZuGW6cyzFieFTQ1vq6I0wzWE8Ll2N0z6/e2+iYfiwKO2iyJ4wbFVxXzroz b0KgLFyNxjWrucXvVsCxYe6BCfAmlzqHzGbVKskqLnbw3/vcT1HOYMYD+dT2ckXH56CKxg TAjkzSZijM3Cf/874DwWj8UIieC+KVkIln3aIi8gFMiN29sY5cM2e42NgbnVujL+sFcNHN K6vgVM6jsy4ln3cR+r5whP4hVFQh3ljUScsMKXkLkZvjqeQ9fpkeD7POLLwkAw== Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter03.heinlein-hosting.de (spamfilter03.heinlein-hosting.de [80.241.56.117]) (amavisd-new, port 10030) with ESMTP id aZOoE6h2C3Zs; Fri, 30 Oct 2020 13:31:05 +0100 (CET) From: Petr Machata To: netdev@vger.kernel.org, dsahern@gmail.com, stephen@networkplumber.org Cc: john.fastabend@gmail.com, jiri@nvidia.com, idosch@nvidia.com, Jakub Kicinski , Roman Mashak , Petr Machata Subject: [PATCH iproute2-next v2 03/11] lib: utils: Add print_on_off_bool() Date: Fri, 30 Oct 2020 13:29:50 +0100 Message-Id: <5ed9e2e7cdf9326e8f7ec80f33f0f11eafc3a425.1604059429.git.me@pmachata.org> In-Reply-To: References: MIME-Version: 1.0 X-MBO-SPAM-Probability: * X-Rspamd-Score: 1.06 / 15.00 / 15.00 X-Rspamd-Queue-Id: 07756171C X-Rspamd-UID: d16a04 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The value of a number of booleans is shown as "on" and "off" in the plain output, and as an actual boolean in JSON mode. Add a function that does that. Signed-off-by: Petr Machata --- include/utils.h | 1 + lib/utils.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/utils.h b/include/utils.h index bd62cdcd7122..e3cdb098834a 100644 --- a/include/utils.h +++ b/include/utils.h @@ -328,5 +328,6 @@ int do_batch(const char *name, bool force, int parse_one_of(const char *msg, const char *realval, const char * const *list, size_t len, int *p_err); int parse_on_off(const char *msg, const char *realval, int *p_err); +void print_on_off_bool(FILE *fp, const char *flag, bool val); #endif /* __UTILS_H__ */ diff --git a/lib/utils.c b/lib/utils.c index 930877ae0f0d..8deec86ecbcd 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1763,3 +1763,11 @@ int parse_on_off(const char *msg, const char *realval, int *p_err) return parse_one_of(msg, realval, values_on_off, ARRAY_SIZE(values_on_off), p_err); } + +void print_on_off_bool(FILE *fp, const char *flag, bool val) +{ + if (is_json_context()) + print_bool(PRINT_JSON, flag, NULL, val); + else + fprintf(fp, "%s %s ", flag, val ? "on" : "off"); +} From patchwork Fri Oct 30 12:29:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Machata X-Patchwork-Id: 315982 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 239E9C4363A for ; Fri, 30 Oct 2020 12:31:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B5FE2221FF for ; Fri, 30 Oct 2020 12:31:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=pmachata.org header.i=@pmachata.org header.b="y4GuetPr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726576AbgJ3Mbk (ORCPT ); Fri, 30 Oct 2020 08:31:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44366 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726549AbgJ3MbN (ORCPT ); Fri, 30 Oct 2020 08:31:13 -0400 Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [IPv6:2001:67c:2050::465:101]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 44A27C0613D2 for ; Fri, 30 Oct 2020 05:31:13 -0700 (PDT) Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4CN1rH38SHzQl90; Fri, 30 Oct 2020 13:31:11 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pmachata.org; s=MBO0001; t=1604061069; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HQljg/nd8YNyMVPl1dJEdxLDy2LuGivGEot1LFvtSGU=; b=y4GuetPr+Iky875rrDIRPkh38RE+VF/KkcHy2SwO/S2j7BEbYNA/cly9x/Uaour0FQ4NGU T+cn3sjLU0l/i0MAC/Z4bvv5D1EJhetIruLTPNZubp0mtaSNjkrdEgxKf16d1LPPleKRm7 202SvKzTW7VmSWssYReAwXt2it+OkEnP77xOVjjD88NdfCZT9yPH0X+YyZY7MTs/0xev++ y/0PuSMnMWOU0V6j3jtcw0KtVMgjpk8dIflFksXHWyg+BxbzIntR04i83pA56AnoDJNCWC dQpmu3z3uG9YN0Af5/J8Aqbcds3WjxfiuaQSqv4EWm/NbDN1w2CCKuEkaEodvQ== Received: from smtp2.mailbox.org ([80.241.60.241]) by hefe.heinlein-support.de (hefe.heinlein-support.de [91.198.250.172]) (amavisd-new, port 10030) with ESMTP id jycAUSIFAdav; Fri, 30 Oct 2020 13:31:07 +0100 (CET) From: Petr Machata To: netdev@vger.kernel.org, dsahern@gmail.com, stephen@networkplumber.org Cc: john.fastabend@gmail.com, jiri@nvidia.com, idosch@nvidia.com, Jakub Kicinski , Roman Mashak , Petr Machata Subject: [PATCH iproute2-next v2 05/11] lib: Extract from devlink/mnlg a helper, mnlu_msg_prepare() Date: Fri, 30 Oct 2020 13:29:52 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-MBO-SPAM-Probability: * X-Rspamd-Score: 1.10 / 15.00 / 15.00 X-Rspamd-Queue-Id: 56FE01728 X-Rspamd-UID: b07bd9 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Allocation of a new netlink message with the two usual headers is reusable with other netlink netlink message types. Extract it into a helper, mnlu_msg_prepare(). Take the second header as an argument, instead of passing in parameters to initialize it, and copy it in. Signed-off-by: Petr Machata --- devlink/mnlg.c | 18 ++++++------------ include/mnl_utils.h | 2 ++ lib/mnl_utils.c | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/devlink/mnlg.c b/devlink/mnlg.c index 9817bbad5e7d..4995b7af06a3 100644 --- a/devlink/mnlg.c +++ b/devlink/mnlg.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -36,19 +35,14 @@ static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd, uint16_t flags, uint32_t id, uint8_t version) { + struct genlmsghdr genl = { + .cmd = cmd, + .version = version, + }; struct nlmsghdr *nlh; - struct genlmsghdr *genl; - - nlh = mnl_nlmsg_put_header(nlg->buf); - nlh->nlmsg_type = id; - nlh->nlmsg_flags = flags; - nlg->seq = time(NULL); - nlh->nlmsg_seq = nlg->seq; - - genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); - genl->cmd = cmd; - genl->version = version; + nlh = mnlu_msg_prepare(nlg->buf, id, flags, &genl, sizeof(genl)); + nlg->seq = nlh->nlmsg_seq; return nlh; } diff --git a/include/mnl_utils.h b/include/mnl_utils.h index 10a064afdfe8..86ce30f49a94 100644 --- a/include/mnl_utils.h +++ b/include/mnl_utils.h @@ -3,5 +3,7 @@ #define __MNL_UTILS_H__ 1 struct mnl_socket *mnlu_socket_open(int bus); +struct nlmsghdr *mnlu_msg_prepare(void *buf, uint32_t nlmsg_type, uint16_t flags, + void *extra_header, size_t extra_header_size); #endif /* __MNL_UTILS_H__ */ diff --git a/lib/mnl_utils.c b/lib/mnl_utils.c index 2426912aa511..61e8060ecbca 100644 --- a/lib/mnl_utils.c +++ b/lib/mnl_utils.c @@ -3,6 +3,8 @@ * mnl_utils.c Helpers for working with libmnl. */ +#include +#include #include #include "mnl_utils.h" @@ -28,3 +30,20 @@ err_bind: mnl_socket_close(nl); return NULL; } + +struct nlmsghdr *mnlu_msg_prepare(void *buf, uint32_t nlmsg_type, uint16_t flags, + void *extra_header, size_t extra_header_size) +{ + struct nlmsghdr *nlh; + void *eh; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = nlmsg_type; + nlh->nlmsg_flags = flags; + nlh->nlmsg_seq = time(NULL); + + eh = mnl_nlmsg_put_extra_header(nlh, extra_header_size); + memcpy(eh, extra_header, extra_header_size); + + return nlh; +} From patchwork Fri Oct 30 12:29:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Machata X-Patchwork-Id: 315985 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB74FC4363A for ; Fri, 30 Oct 2020 12:31:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 845CB2087E for ; Fri, 30 Oct 2020 12:31:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=pmachata.org header.i=@pmachata.org header.b="FLTsRAta" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726606AbgJ3MbV (ORCPT ); Fri, 30 Oct 2020 08:31:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44380 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726555AbgJ3MbQ (ORCPT ); Fri, 30 Oct 2020 08:31:16 -0400 Received: from mout-p-103.mailbox.org (mout-p-103.mailbox.org [IPv6:2001:67c:2050::465:103]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6935C0613D2 for ; Fri, 30 Oct 2020 05:31:15 -0700 (PDT) Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-103.mailbox.org (Postfix) with ESMTPS id 4CN1rK5QvRzQkJg; Fri, 30 Oct 2020 13:31:13 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pmachata.org; s=MBO0001; t=1604061071; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BszT7JLDxFOvofg7/1xMCcph79s1fIPk1iSklTLrGvI=; b=FLTsRAtayvcYfsDC3hbQiJe+buB1PWPz+OOhkOWB5dvEmAPUCtxyNQCwaCJp/+ZgkvHTg+ fIt/xOtNcSwMUG1YdxXve7EPZvePRlx/et/bZlcirczYnWbvHnY0vHda+Jia07B7GDdFE8 bVoxK3Mz1b+1LrEuzXq8Qa8LYwct9GcBfYGC7r9gXyHN9vTZfwL4vGiwcd0exfKHVLlFya rUZAgGo2ls8yqKbKHgh1MPXltyFaNu9rcwiHCklZcxfTXtQaYxiqi0d5ubapZo3M0hkSOz hvjpf7K6n1o/N44H6l2KS+cq/BvjLYkcviVqP0dYC/gg+u10rYQVUumerc851g== Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter02.heinlein-hosting.de (spamfilter02.heinlein-hosting.de [80.241.56.116]) (amavisd-new, port 10030) with ESMTP id zLOaPs6oujom; Fri, 30 Oct 2020 13:31:11 +0100 (CET) From: Petr Machata To: netdev@vger.kernel.org, dsahern@gmail.com, stephen@networkplumber.org Cc: john.fastabend@gmail.com, jiri@nvidia.com, idosch@nvidia.com, Jakub Kicinski , Roman Mashak , Petr Machata Subject: [PATCH iproute2-next v2 08/11] lib: parse_mapping: Update argc, argv on error Date: Fri, 30 Oct 2020 13:29:55 +0100 Message-Id: <4eaa2d34e2876a1901f4be565e21b482b9d55205.1604059429.git.me@pmachata.org> In-Reply-To: References: MIME-Version: 1.0 X-MBO-SPAM-Probability: ** X-Rspamd-Score: 1.64 / 15.00 / 15.00 X-Rspamd-Queue-Id: B1485171D X-Rspamd-UID: 7b12ae Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Currently argc and argv are not updated unless parsing of all of the mapping was successful. However in that case, "ip link" will point at the wrong argument when complaining: # ip link add name eth0.100 link eth0 type vlan id 100 egress 1:1 2:foo Error: argument "1" is wrong: invalid egress-qos-map Update argc and argv even in the case of parsing error, so that the right element is indicated. Signed-off-by: Petr Machata --- lib/utils.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index aba7cc0960cd..089bbde715da 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1778,6 +1778,7 @@ int parse_mapping(int *argcp, char ***argvp, { int argc = *argcp; char **argv = *argvp; + int ret = 0; while (argc > 0) { char *colon = strchr(*argv, ':'); @@ -1787,15 +1788,19 @@ int parse_mapping(int *argcp, char ***argvp, break; *colon = '\0'; - if (get_u32(&key, *argv, 0)) - return 1; - if (mapping_cb(key, colon + 1, mapping_cb_data)) - return 1; + if (get_u32(&key, *argv, 0)) { + ret = 1; + break; + } + if (mapping_cb(key, colon + 1, mapping_cb_data)) { + ret = 1; + break; + } argc--, argv++; } *argcp = argc; *argvp = argv; - return 0; + return ret; } From patchwork Fri Oct 30 12:29:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Machata X-Patchwork-Id: 315984 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4D54C4363A for ; Fri, 30 Oct 2020 12:31:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 22612221FF for ; Fri, 30 Oct 2020 12:31:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=pmachata.org header.i=@pmachata.org header.b="068hic9Q" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726592AbgJ3MbU (ORCPT ); Fri, 30 Oct 2020 08:31:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726557AbgJ3MbR (ORCPT ); Fri, 30 Oct 2020 08:31:17 -0400 Received: from mout-p-103.mailbox.org (mout-p-103.mailbox.org [IPv6:2001:67c:2050::465:103]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 21C7CC0613D2 for ; Fri, 30 Oct 2020 05:31:17 -0700 (PDT) Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-103.mailbox.org (Postfix) with ESMTPS id 4CN1rM1hbVzQkLK; Fri, 30 Oct 2020 13:31:15 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pmachata.org; s=MBO0001; t=1604061073; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6eCmMsC7TqxsBhNRrnZ8Cb0HXn6LSNmhzQNeYBA8EeM=; b=068hic9QGaH9w74Ehs2GZtbvzlBsxf53Q09jLcSHw1U3nJ+28GUw1CIsQKfw4AZz+0rGSL C/HdLCjZ3sl/wewJ+w1Qq5EX4D6ir4GBoslWBREax0Pk1JLnq0I4nbRpKswXcmdM+VCsce 8Df4sq9F0He4bjw+qWibfzm5/IDLW3Bcu1HzDBg4dofZlHUStCfEA/YIlPZvMyUBnDx3xY Jv9u8oTOEMNQ0HkW4yOCVxoB7c5R1AbuMQUjfeEUiMDcOwHAJSxTb+ILBqKgU76Sr6ksBE yUwpzfiW1c11pdzf9SUSgCKY8JM7LFCyOzaSbVzINWglYotyikkXWjPqhLyxJA== Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter01.heinlein-hosting.de (spamfilter01.heinlein-hosting.de [80.241.56.115]) (amavisd-new, port 10030) with ESMTP id CxLL_Q36-byU; Fri, 30 Oct 2020 13:31:12 +0100 (CET) From: Petr Machata To: netdev@vger.kernel.org, dsahern@gmail.com, stephen@networkplumber.org Cc: john.fastabend@gmail.com, jiri@nvidia.com, idosch@nvidia.com, Jakub Kicinski , Roman Mashak , Petr Machata Subject: [PATCH iproute2-next v2 09/11] lib: parse_mapping: Recognize a keyword "all" Date: Fri, 30 Oct 2020 13:29:56 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-MBO-SPAM-Probability: ** X-Rspamd-Score: 1.51 / 15.00 / 15.00 X-Rspamd-Queue-Id: 3E0541707 X-Rspamd-UID: cf5443 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The DCB tool will have to provide an interface to a number of fixed-size arrays. Unlike the egress- and ingress-qos-map, it makes good sense to have an interface to set all members to the same value. For example to set strict priority on all TCs besides select few, or to reset allocated bandwidth to all zeroes, again besides several explicitly-given ones. To support this usage, extend the parse_mapping() with a boolean that determines whether this special use is supported. If "all" is given and recognized, mapping_cb is called with the key of -1. Have iplink_vlan pass false for allow_all. Signed-off-by: Petr Machata --- include/utils.h | 2 +- ip/iplink_vlan.c | 2 +- lib/utils.c | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/utils.h b/include/utils.h index 1c72221ae92c..8ec1b7ab0d8d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -330,7 +330,7 @@ int parse_one_of(const char *msg, const char *realval, const char * const *list, int parse_on_off(const char *msg, const char *realval, int *p_err); void print_on_off_bool(FILE *fp, const char *flag, bool val); -int parse_mapping(int *argcp, char ***argvp, +int parse_mapping(int *argcp, char ***argvp, bool allow_all, int (*mapping_cb)(__u32 key, char *value, void *data), void *mapping_cb_data); diff --git a/ip/iplink_vlan.c b/ip/iplink_vlan.c index dadc349db16c..1426f2afca23 100644 --- a/ip/iplink_vlan.c +++ b/ip/iplink_vlan.c @@ -69,7 +69,7 @@ static int vlan_parse_qos_map(int *argcp, char ***argvp, struct nlmsghdr *n, tail = addattr_nest(n, 1024, attrtype); - if (parse_mapping(argcp, argvp, &parse_qos_mapping, n)) + if (parse_mapping(argcp, argvp, false, &parse_qos_mapping, n)) return 1; addattr_nest_end(n, tail); diff --git a/lib/utils.c b/lib/utils.c index 089bbde715da..3b3b42b15013 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1772,7 +1772,7 @@ void print_on_off_bool(FILE *fp, const char *flag, bool val) fprintf(fp, "%s %s ", flag, val ? "on" : "off"); } -int parse_mapping(int *argcp, char ***argvp, +int parse_mapping(int *argcp, char ***argvp, bool allow_all, int (*mapping_cb)(__u32 key, char *value, void *data), void *mapping_cb_data) { @@ -1788,7 +1788,9 @@ int parse_mapping(int *argcp, char ***argvp, break; *colon = '\0'; - if (get_u32(&key, *argv, 0)) { + if (allow_all && matches(*argv, "all") == 0) { + key = (__u32) -1; + } else if (get_u32(&key, *argv, 0)) { ret = 1; break; } From patchwork Fri Oct 30 12:29:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Machata X-Patchwork-Id: 315983 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72A5DC4741F for ; Fri, 30 Oct 2020 12:31:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4FADF221FF for ; Fri, 30 Oct 2020 12:31:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=pmachata.org header.i=@pmachata.org header.b="rqvkpVsg" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726597AbgJ3Mbd (ORCPT ); Fri, 30 Oct 2020 08:31:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44396 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726565AbgJ3MbU (ORCPT ); Fri, 30 Oct 2020 08:31:20 -0400 Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [IPv6:2001:67c:2050::465:202]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11CD5C0613D4 for ; Fri, 30 Oct 2020 05:31:19 -0700 (PDT) Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:105:465:1:2:0]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-202.mailbox.org (Postfix) with ESMTPS id 4CN1rP4zYszQlRP; Fri, 30 Oct 2020 13:31:17 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pmachata.org; s=MBO0001; t=1604061075; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DRQyeD9g+DCB+nb0t5FfMdTD0YY3Uy3DDRtpgm9SnQw=; b=rqvkpVsgkFm529iLoqwV6Z0pwE6oSV9GVgJM6Le8yeqU1R+1CEDOpCBI9e54yzUozt1Rzl BdjWKS+cy80JUklC0LyE55Hxk/iCU6gIpoIzUFmVLhGOPkFu4RurD2R19bbfpuHrCY5eUC H6OcAqXSTRX3GzMHKH6HMFKE0aNHiXtY1gbOpk0g0E3fxVhkof9gYPfLB3thg11YSZ0xfh OCtf4NiWYj+gli9WSLMFh0VStfsZUg8KUQwqOAAkx0EKOhyrz36bHLOGOmyInDfNyhYiBz Wu4RyxwzzLq0bLvlulcan8ApnJMK8R3rnJH0f6pUgICm1tFn0k96szFqSwvvog== Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter06.heinlein-hosting.de (spamfilter06.heinlein-hosting.de [80.241.56.125]) (amavisd-new, port 10030) with ESMTP id 0mfwgxe4ZlDq; Fri, 30 Oct 2020 13:31:14 +0100 (CET) From: Petr Machata To: netdev@vger.kernel.org, dsahern@gmail.com, stephen@networkplumber.org Cc: john.fastabend@gmail.com, jiri@nvidia.com, idosch@nvidia.com, Jakub Kicinski , Roman Mashak , Petr Machata Subject: [PATCH iproute2-next v2 11/11] dcb: Add a subtool for the DCB ETS object Date: Fri, 30 Oct 2020 13:29:58 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-MBO-SPAM-Probability: * X-Rspamd-Score: 0.05 / 15.00 / 15.00 X-Rspamd-Queue-Id: A2E89171C X-Rspamd-UID: 5c89c2 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org ETS, for "Enhanced Transmission Selection", is a set of configurations that permit configuration of mapping of priorities to traffic classes, traffic selection algorithm to use per traffic class, bandwidth allocation, etc. Add a dcb subtool to allow showing and tweaking of individual ETS configuration options. For example: # dcb ets show dev eni1np1 willing on ets_cap 8 cbs off tc-bw 0:0 1:0 2:0 3:0 4:100 5:0 6:0 7:0 pg-bw 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0 tc-tsa 0:strict 1:strict 2:strict 3:strict 4:ets 5:strict 6:strict 7:strict prio-tc 0:1 1:3 2:5 3:0 4:0 5:0 6:0 7:0 reco-tc-bw 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0 reco-tc-tsa 0:strict 1:strict 2:strict 3:strict 4:strict 5:strict 6:strict 7:strict reco-prio-tc 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0 Signed-off-by: Petr Machata --- dcb/Makefile | 2 +- dcb/dcb.c | 4 +- dcb/dcb.h | 4 + dcb/dcb_ets.c | 430 +++++++++++++++++++++++++++++++++++++++++++++ man/man8/dcb-ets.8 | 185 +++++++++++++++++++ man/man8/dcb.8 | 11 ++ 6 files changed, 634 insertions(+), 2 deletions(-) create mode 100644 dcb/dcb_ets.c create mode 100644 man/man8/dcb-ets.8 diff --git a/dcb/Makefile b/dcb/Makefile index 9966c8f0bfa4..895817163562 100644 --- a/dcb/Makefile +++ b/dcb/Makefile @@ -5,7 +5,7 @@ TARGETS := ifeq ($(HAVE_MNL),y) -DCBOBJ = dcb.o +DCBOBJ = dcb.o dcb_ets.o TARGETS += dcb endif diff --git a/dcb/dcb.c b/dcb/dcb.c index 26c1f91e815a..a776aa542f93 100644 --- a/dcb/dcb.c +++ b/dcb/dcb.c @@ -286,7 +286,7 @@ static void dcb_help(void) fprintf(stderr, "Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n" " dcb [ -f[orce] ] -b[atch] filename -N[etns] netnsname\n" - "where OBJECT :=\n" + "where OBJECT := ets\n" " OPTIONS := { -V[ersion] | -j[son] | -p[retty] | -v[erbose] }\n"); } @@ -295,6 +295,8 @@ static int dcb_cmd(struct dcb *dcb, int argc, char **argv) if (!argc || matches(*argv, "help") == 0) { dcb_help(); return 0; + } else if (matches(*argv, "ets") == 0) { + return dcb_cmd_ets(dcb, argc - 1, argv + 1); } fprintf(stderr, "Object \"%s\" is unknown\n", *argv); diff --git a/dcb/dcb.h b/dcb/dcb.h index 1d31a0f94652..9b46e09178be 100644 --- a/dcb/dcb.h +++ b/dcb/dcb.h @@ -32,4 +32,8 @@ void dcb_print_array_num(FILE *fp, const __u8 *array, size_t size); void dcb_print_array_kw(FILE *fp, const __u8 *array, size_t array_size, const char *const kw[], size_t kw_size); +/* dcb_ets.c */ + +int dcb_cmd_ets(struct dcb *dcb, int argc, char **argv); + #endif /* __DCB_H__ */ diff --git a/dcb/dcb_ets.c b/dcb/dcb_ets.c new file mode 100644 index 000000000000..1af8dce8100d --- /dev/null +++ b/dcb/dcb_ets.c @@ -0,0 +1,430 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include + +#include "dcb.h" +#include "utils.h" + +static void dcb_ets_help_set(void) +{ + fprintf(stderr, + "Usage: dcb ets set dev STRING\n" + " [ willing { on | off } ]\n" + " [ { tc-tsa | reco-tc-tsa } TSA-MAP ]\n" + " [ { pg-bw | tc-bw | reco-tc-bw } BW-MAP ]\n" + " [ { prio-tc | reco-prio-tc } PRIO-MAP ]\n" + "\n" + " where TSA-MAP := [ TSA-MAP ] TSA-MAPPING\n" + " TSA-MAPPING := { all | TC }:{ strict | cbs | ets | vendor }\n" + " BW-MAP := [ BW-MAP ] BW-MAPPING\n" + " BW-MAPPING := { all | TC }:INTEGER\n" + " PRIO-MAP := [ PRIO-MAP ] PRIO-MAPPING\n" + " PRIO-MAPPING := { all | PRIO }:TC\n" + " TC := { 0 .. 7 }\n" + " PRIO := { 0 .. 7 }\n" + "\n" + ); +} + +static void dcb_ets_help_show(void) +{ + fprintf(stderr, + "Usage: dcb ets show dev STRING\n" + " [ willing | ets-cap | cbs | tc-tsa | reco-tc-tsa |\n" + " pg-bw | tc-bw | reco-tc-bw | prio-tc |\n" + " reco-prio-tc ]\n" + "\n" + ); +} + +static void dcb_ets_help(void) +{ + fprintf(stderr, + "Usage: dcb ets help\n" + "\n" + ); + dcb_ets_help_show(); + dcb_ets_help_set(); +} + +static const char *const tsa_names[] = { + [IEEE_8021QAZ_TSA_STRICT] = "strict", + [IEEE_8021QAZ_TSA_CB_SHAPER] = "cbs", + [IEEE_8021QAZ_TSA_ETS] = "ets", + [IEEE_8021QAZ_TSA_VENDOR] = "vendor", +}; + +static int dcb_ets_parse_mapping_tc_tsa(__u32 key, char *value, void *data) +{ + __u8 tsa; + int ret; + + tsa = parse_one_of("TSA", value, tsa_names, ARRAY_SIZE(tsa_names), &ret); + if (ret) + return ret; + + return dcb_parse_mapping(key, tsa, -1, data, "TC", "TSA"); +} + +static int dcb_ets_parse_mapping_tc_int(__u32 key, char *value, __u8 max_value, __u8 *array, + const char *what_key, const char *what_value) +{ + __u8 int_value; + + if (get_u8(&int_value, value, 0)) + return -EINVAL; + + return dcb_parse_mapping(key, int_value, max_value, array, what_key, what_value); +} + +static int dcb_ets_parse_mapping_tc_bw(__u32 key, char *value, void *data) +{ + return dcb_ets_parse_mapping_tc_int(key, value, 100, data, "TC", "BW"); +} + +static int dcb_ets_parse_mapping_prio_tc(unsigned int key, char *value, void *data) +{ + return dcb_ets_parse_mapping_tc_int(key, value, IEEE_8021QAZ_MAX_TCS, data, "PRIO", "TC"); +} + +static void dcb_print_array_tsa(FILE *fp, const __u8 *array, size_t size) +{ + dcb_print_array_kw(fp, array, size, tsa_names, ARRAY_SIZE(tsa_names)); +} + +static void dcb_ets_print_willing(FILE *fp, const struct ieee_ets *ets) +{ + print_on_off_bool(fp, "willing", ets->willing); +} + +static void dcb_ets_print_ets_cap(FILE *fp, const struct ieee_ets *ets) +{ + print_uint(PRINT_ANY, "ets_cap", "ets_cap %d ", ets->ets_cap); +} + +static void dcb_ets_print_cbs(FILE *fp, const struct ieee_ets *ets) +{ + print_on_off_bool(fp, "cbs", ets->cbs); +} + +static void dcb_ets_print_tc_bw(FILE *fp, const struct ieee_ets *ets) +{ + dcb_print_named_array(fp, "tc-bw", "tc_bw", + ets->tc_tx_bw, ARRAY_SIZE(ets->tc_tx_bw), + dcb_print_array_num); +} + +static void dcb_ets_print_pg_bw(FILE *fp, const struct ieee_ets *ets) +{ + dcb_print_named_array(fp, "pg-bw", "pg_bw", + ets->tc_rx_bw, ARRAY_SIZE(ets->tc_rx_bw), + dcb_print_array_num); +} + +static void dcb_ets_print_tc_tsa(FILE *fp, const struct ieee_ets *ets) +{ + dcb_print_named_array(fp, "tc-tsa", "tc_tsa", + ets->tc_tsa, ARRAY_SIZE(ets->tc_tsa), + dcb_print_array_tsa); +} + +static void dcb_ets_print_prio_tc(FILE *fp, const struct ieee_ets *ets) +{ + dcb_print_named_array(fp, "prio-tc", "prio_tc", + ets->prio_tc, ARRAY_SIZE(ets->prio_tc), + dcb_print_array_num); +} + +static void dcb_ets_print_reco_tc_bw(FILE *fp, const struct ieee_ets *ets) +{ + dcb_print_named_array(fp, "reco-tc-bw", "reco_tc_bw", + ets->tc_reco_bw, ARRAY_SIZE(ets->tc_reco_bw), + dcb_print_array_num); +} + +static void dcb_ets_print_reco_tc_tsa(FILE *fp, const struct ieee_ets *ets) +{ + dcb_print_named_array(fp, "reco-tc-tsa", "reco_tc_tsa", + ets->tc_reco_tsa, ARRAY_SIZE(ets->tc_reco_tsa), + dcb_print_array_tsa); +} + +static void dcb_ets_print_reco_prio_tc(FILE *fp, const struct ieee_ets *ets) +{ + dcb_print_named_array(fp, "reco-prio-tc", "reco_prio_tc", + ets->reco_prio_tc, ARRAY_SIZE(ets->reco_prio_tc), + dcb_print_array_num); +} + +static void dcb_ets_print(FILE *fp, const struct ieee_ets *ets) +{ + dcb_ets_print_willing(fp, ets); + dcb_ets_print_ets_cap(fp, ets); + dcb_ets_print_cbs(fp, ets); + print_nl(); + + dcb_ets_print_tc_bw(fp, ets); + print_nl(); + + dcb_ets_print_pg_bw(fp, ets); + print_nl(); + + dcb_ets_print_tc_tsa(fp, ets); + print_nl(); + + dcb_ets_print_prio_tc(fp, ets); + print_nl(); + + dcb_ets_print_reco_tc_bw(fp, ets); + print_nl(); + + dcb_ets_print_reco_tc_tsa(fp, ets); + print_nl(); + + dcb_ets_print_reco_prio_tc(fp, ets); + print_nl(); +} + +static int dcb_ets_get(struct dcb *dcb, const char *dev, struct ieee_ets *ets) +{ + return dcb_get_attribute(dcb, dev, DCB_ATTR_IEEE_ETS, ets, sizeof(*ets)); +} + +static int dcb_ets_validate_bw(const __u8 bw[], const __u8 tsa[], const char *what) +{ + bool has_ets = false; + unsigned int total = 0; + unsigned int tc; + + for (tc = 0; tc < IEEE_8021QAZ_MAX_TCS; tc++) { + if (tsa[tc] == IEEE_8021QAZ_TSA_ETS) { + has_ets = true; + break; + } + } + + /* TC bandwidth is only intended for ETS, but 802.1Q-2018 only requires + * that the sum be 100, and individual entries 0..100. It explicitly + * notes that non-ETS TCs can have non-0 TC bandwidth during + * reconfiguration. + */ + for (tc = 0; tc < IEEE_8021QAZ_MAX_TCS; tc++) { + if (bw[tc] > 100) { + fprintf(stderr, "%d%% for TC %d of %s is not a valid bandwidth percentage, expected 0..100%%\n", + bw[tc], tc, what); + return -EINVAL; + } + total += bw[tc]; + } + + /* This is what 802.1Q-2018 requires. */ + if (total == 100) + return 0; + + /* But this requirement does not make sense for all-strict + * configurations. Anything else than 0 does not make sense: either BW + * has not been reconfigured for the all-strict allocation yet, at which + * point we expect sum of 100. Or it has already been reconfigured, at + * which point accept 0. + */ + if (!has_ets && total == 0) + return 0; + + fprintf(stderr, "Bandwidth percentages in %s sum to %d%%, expected %d%%\n", + what, total, has_ets ? 100 : 0); + return -EINVAL; +} + +static int dcb_ets_set(struct dcb *dcb, const char *dev, const struct ieee_ets *ets) +{ + /* Do not validate pg-bw, which is not standard and has unclear + * meaning. + */ + if (dcb_ets_validate_bw(ets->tc_tx_bw, ets->tc_tsa, "tc-bw") || + dcb_ets_validate_bw(ets->tc_reco_bw, ets->tc_reco_tsa, "reco-tc-bw")) + return -EINVAL; + + return dcb_set_attribute(dcb, dev, DCB_ATTR_IEEE_ETS, ets, sizeof(*ets)); +} + +static int dcb_cmd_ets_set(struct dcb *dcb, const char *dev, int argc, char **argv) +{ + struct ieee_ets ets; + int ret; + + if (!argc) { + dcb_ets_help_set(); + return 0; + } + + ret = dcb_ets_get(dcb, dev, &ets); + if (ret) + return ret; + + do { + if (matches(*argv, "help") == 0) { + dcb_ets_help_set(); + return 0; + } else if (matches(*argv, "willing") == 0) { + NEXT_ARG(); + ets.willing = parse_on_off("willing", *argv, &ret); + if (ret) + return ret; + } else if (matches(*argv, "tc-tsa") == 0) { + NEXT_ARG(); + ret = parse_mapping(&argc, &argv, true, &dcb_ets_parse_mapping_tc_tsa, + ets.tc_tsa); + if (ret) { + fprintf(stderr, "Invalid tc-tsa mapping %s\n", *argv); + return ret; + } + continue; + } else if (matches(*argv, "reco-tc-tsa") == 0) { + NEXT_ARG(); + ret = parse_mapping(&argc, &argv, true, &dcb_ets_parse_mapping_tc_tsa, + ets.tc_reco_tsa); + if (ret) { + fprintf(stderr, "Invalid reco-tc-tsa mapping %s\n", *argv); + return ret; + } + continue; + } else if (matches(*argv, "tc-bw") == 0) { + NEXT_ARG(); + ret = parse_mapping(&argc, &argv, true, &dcb_ets_parse_mapping_tc_bw, + ets.tc_tx_bw); + if (ret) { + fprintf(stderr, "Invalid tc-bw mapping %s\n", *argv); + return ret; + } + continue; + } else if (matches(*argv, "pg-bw") == 0) { + NEXT_ARG(); + ret = parse_mapping(&argc, &argv, true, &dcb_ets_parse_mapping_tc_bw, + ets.tc_rx_bw); + if (ret) { + fprintf(stderr, "Invalid pg-bw mapping %s\n", *argv); + return ret; + } + continue; + } else if (matches(*argv, "reco-tc-bw") == 0) { + NEXT_ARG(); + ret = parse_mapping(&argc, &argv, true, &dcb_ets_parse_mapping_tc_bw, + ets.tc_reco_bw); + if (ret) { + fprintf(stderr, "Invalid reco-tc-bw mapping %s\n", *argv); + return ret; + } + continue; + } else if (matches(*argv, "prio-tc") == 0) { + NEXT_ARG(); + ret = parse_mapping(&argc, &argv, true, &dcb_ets_parse_mapping_prio_tc, + ets.prio_tc); + if (ret) { + fprintf(stderr, "Invalid prio-tc mapping %s\n", *argv); + return ret; + } + continue; + } else if (matches(*argv, "reco-prio-tc") == 0) { + NEXT_ARG(); + ret = parse_mapping(&argc, &argv, true, &dcb_ets_parse_mapping_prio_tc, + ets.reco_prio_tc); + if (ret) { + fprintf(stderr, "Invalid reco-prio-tc mapping %s\n", *argv); + return ret; + } + continue; + } else { + fprintf(stderr, "What is \"%s\"?\n", *argv); + dcb_ets_help_set(); + return -EINVAL; + } + + NEXT_ARG_FWD(); + } while (argc > 0); + + return dcb_ets_set(dcb, dev, &ets); +} + +static int dcb_cmd_ets_show(struct dcb *dcb, const char *dev, int argc, char **argv) +{ + struct ieee_ets ets; + int ret; + + ret = dcb_ets_get(dcb, dev, &ets); + if (ret) + return ret; + + open_json_object(NULL); + + if (!argc) { + dcb_ets_print(stdout, &ets); + goto out; + } + + do { + if (matches(*argv, "help") == 0) { + dcb_ets_help(); + return 0; + } else if (matches(*argv, "willing") == 0) { + dcb_ets_print_willing(stdout, &ets); + print_nl(); + } else if (matches(*argv, "ets-cap") == 0) { + dcb_ets_print_ets_cap(stdout, &ets); + print_nl(); + } else if (matches(*argv, "cbs") == 0) { + dcb_ets_print_cbs(stdout, &ets); + print_nl(); + } else if (matches(*argv, "tc-tsa") == 0) { + dcb_ets_print_tc_tsa(stdout, &ets); + print_nl(); + } else if (matches(*argv, "reco-tc-tsa") == 0) { + dcb_ets_print_reco_tc_tsa(stdout, &ets); + print_nl(); + } else if (matches(*argv, "tc-bw") == 0) { + dcb_ets_print_tc_bw(stdout, &ets); + print_nl(); + } else if (matches(*argv, "pg-bw") == 0) { + dcb_ets_print_pg_bw(stdout, &ets); + print_nl(); + } else if (matches(*argv, "reco-tc-bw") == 0) { + dcb_ets_print_reco_tc_bw(stdout, &ets); + print_nl(); + } else if (matches(*argv, "prio-tc") == 0) { + dcb_ets_print_prio_tc(stdout, &ets); + print_nl(); + } else if (matches(*argv, "reco-prio-tc") == 0) { + dcb_ets_print_reco_prio_tc(stdout, &ets); + print_nl(); + } else { + fprintf(stderr, "What is \"%s\"?\n", *argv); + dcb_ets_help(); + return -EINVAL; + } + + NEXT_ARG_FWD(); + } while (argc > 0); + +out: + close_json_object(); + return 0; +} + +int dcb_cmd_ets(struct dcb *dcb, int argc, char **argv) +{ + if (!argc || matches(*argv, "help") == 0) { + dcb_ets_help(); + return 0; + } else if (matches(*argv, "show") == 0) { + NEXT_ARG_FWD(); + return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_ets_show, dcb_ets_help_show); + } else if (matches(*argv, "set") == 0) { + NEXT_ARG_FWD(); + return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_ets_set, dcb_ets_help_set); + } else { + fprintf(stderr, "What is \"%s\"?\n", *argv); + dcb_ets_help(); + return -EINVAL; + } +} diff --git a/man/man8/dcb-ets.8 b/man/man8/dcb-ets.8 new file mode 100644 index 000000000000..5286199f180f --- /dev/null +++ b/man/man8/dcb-ets.8 @@ -0,0 +1,185 @@ +.TH DCB-ETS 8 "19 October 2020" "iproute2" "Linux" +.SH NAME +dcb-ets \- show / manipulate ETS (Enhanced Transmission Selection) settings of +the DCB (Data Center Bridging) subsystem +.SH SYNOPSIS +.sp +.ad l +.in +8 + +.ti -8 +.B dcb +.RI "[ " OPTIONS " ] " +.B ets +.RI "{ " COMMAND " | " help " }" +.sp + +.ti -8 +.B dcb ets show dev +.RI DEV +.B "[ {" willing "|" ets-cap "|" cbs "|" tc-tsa "|" reco-tc-tsa "|" +.B pg-bw "|" tc-bw "|" reco-tc-bw "|" prio-tc "|" +.B reco-prio-tc "} ]" + +.ti -8 +.B dcb ets set dev +.RI DEV +.B "[" willing "{" on "|" off "} ]" +.B "[ {" tc-tsa "|" reco-tc-tsa "}" \fITSA-MAP\fB "]" +.B "[ {" pg-bw "|" tc-bw "|" reco-tc-bw "}" \fIBW-MAP\fB "]" +.B "[ {" prio-tc "|" reco-prio-tc "}" \fIPRIO-MAP\fB "]" + +.ti -8 +.IR TSA-MAP " := [ " TSA-MAP " ] " TSA-MAPPING + +.ti -8 +.IR TSA-MAPPING " := { " TC " | " \fBall " }" \fB: "{ " \fBstrict\fR " | " +.IR \fBcbs\fR " | " \fBets\fR " | " \fBvendor\fR " }" + +.ti -8 +.IR BW-MAP " := [ " BW-MAP " ] " BW-MAPPING + +.ti -8 +.IR BW-MAPPING " := { " TC " | " \fBall " }" \fB:\fIINTEGER\fR + +.ti -8 +.IR PRIO-MAP " := [ " PRIO-MAP " ] " PRIO-MAPPING + +.ti -8 +.IR PRIO-MAPPING " := { " PRIO " | " \fBall " }" \fB:\fITC\fR + +.ti -8 +.IR TC " := { " \fB0\fR " .. " \fB7\fR " }" + +.ti -8 +.IR PRIO " := { " \fB0\fR " .. " \fB7\fR " }" + + +.SH DESCRIPTION + +.B dcb ets +is used to configure Enhanced Transmission Selection attributes through Linux +DCB (Data Center Bridging) interface. ETS permits configuration of mapping of +priorities to traffic classes, traffic selection algorithm to use per traffic +class, bandwidth allocation, etc. + +Two DCB TLVs are related to the ETS feature: a configuration and recommendation +values. Recommendation values are named with a prefix +.B reco-, +while the configuration ones have plain names. + +.SH PARAMETERS + +For read-write parameters, the following describes only the write direction, +i.e. as used with the \fBset\fR command. For the \fBshow\fR command, the +parameter name is to be used as a simple keyword without further arguments. This +instructs the tool to show the value of a given parameter. When no parameters +are given, the tool shows the complete ETS configuration. + +.TP +.B ets-cap +A read-only property that shows the number of supported ETS traffic classes. + +.TP +.B cbs +A read-only property that is enabled if the driver and the hardware support the +CBS Transmission Selection Algorithm. + +.TP +.B willing \fR{ \fBon\fR | \fBoff\fR } +Whether local host should accept configuration from peer TLVs. + +.TP +.B prio-tc \fITC-MAP +.TQ +.B reco-prio-tc \fITC-MAP +\fITC-MAP\fR uses the array parameter syntax, see dcb(8) for details. Keys are +priorities, values are traffic classes. For each priority sets a TC where +traffic with that priority is directed to. + +.TP +.B tc-tsa \fITSA-MAP +.TQ +.B reco-tc-tsa \fITSA-MAP +\fITC-MAP\fR uses the array parameter syntax, see dcb(8) for details. Keys are +TCs, values are Transmission Selection Algorithm (TSA) keywords described below. +For each TC sets an algorithm used for deciding how traffic queued up at this TC +is scheduled for transmission. Supported TSAs are: + +.B strict +- for strict priority, where traffic in higher-numbered TCs always takes +precedence over traffic in lower-numbered TCs. +.br +.B ets +- for Enhanced Traffic Selection, where available bandwidth is distributed among +the ETS-enabled TCs according to the weights set by +.B tc-bw +and +.B reco-tc-bw\fR, +respectively. +.br +.B cbs +- for Credit Based Shaper, where traffic is scheduled in a strict manner up to +the limit set by a shaper. +.br +.B vendor +- for vendor-specific traffic selection algorithm. + +.TP +.B tc-bw \fIBW-MAP +.TQ +.B reco-tc-bw \fIBW-MAP +\fIBW-MAP\fR uses the array parameter syntax, see dcb(8) for details. Keys are +TCs, values are integers representing percent of available bandwidth given to +the traffic class in question. The value should be 0 for TCs whose TSA is not +\fBets\fR, and the sum of all values shall be 100. As an exception to the +standard wording, a configuration with no ETS TCs is permitted to sum up to 0 +instead. +.br + +.TP +.B pg-bw \fIBW-MAP +The precise meaning of \fBpg-bw\fR is not standardized, but the assumption seems +to be that the same scheduling process as on the transmit side is applicable on +receive side as well, and configures receive bandwidth allocation for \fBets\fR +ingress traffic classes (priority groups). + +.SH EXAMPLE & USAGE + +Configure ETS priomap in a one-to-one fashion: + +.P +# dcb ets set dev eth0 prio-tc 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 + +Set TSA and transmit bandwidth configuration: + +.P +# dcb ets set dev eth0 tc-tsa all:strict 0:ets 1:ets 2:ets \\ +.br + tc-bw all:0 0:33 1:33 2:34 + +Show what was set: + +.P +# dcb ets show dev eth0 prio-tc tc-tsa tc-bw +.br +prio-tc 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 +.br +tc-tsa 0:ets 1:ets 2:ets 3:strict 4:strict 5:strict 6:strict 7:strict +.br +tc-bw 0:33 1:33 2:34 3:0 4:0 5:0 6:0 7:0 + +.SH EXIT STATUS +Exit status is 0 if command was successful or a positive integer upon failure. + +.SH SEE ALSO +.BR dcb (8) + +.SH REPORTING BUGS +Report any bugs to the Network Developers mailing list +.B +where the development and maintenance is primarily done. +You do not have to be subscribed to the list to send a message there. + +.SH AUTHOR +Petr Machata diff --git a/man/man8/dcb.8 b/man/man8/dcb.8 index 25ddf204d60e..ec116f6ce265 100644 --- a/man/man8/dcb.8 +++ b/man/man8/dcb.8 @@ -6,6 +6,13 @@ dcb \- show / manipulate DCB (Data Center Bridging) settings .ad l .in +8 +.ti -8 +.B dcb +.RI "[ " OPTIONS " ] " +.B ets +.RI "{ " COMMAND " | " help " }" +.sp + .ti -8 .B dcb .RB "[ " -force " ] " @@ -46,6 +53,10 @@ When combined with -j generate a pretty JSON output. .SH OBJECTS +.TP +.B ets +- Configuration of ETS (Enhanced Transmission Selection) + .SH COMMANDS A \fICOMMAND\fR specifies the action to perform on the object. The set of