From patchwork Fri Jun 7 22:38:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112326 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="JKdfM46T"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHVj0km3z9sDB for ; Sat, 8 Jun 2019 08:38:21 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731765AbfFGWiU (ORCPT ); Fri, 7 Jun 2019 18:38:20 -0400 Received: from mail.kernel.org ([198.145.29.99]:48596 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730846AbfFGWiT (ORCPT ); Fri, 7 Jun 2019 18:38:19 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id CAA2720868; Fri, 7 Jun 2019 22:38:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947098; bh=xM5DNrsmEG9g5p6X7sFE3f4jmCS9m0E85wnQOdos27o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JKdfM46TRvrV7NbChfCjBo57GkOTg7sQi0V2zGO4x7HrXHShjxleXdcR4+VLec5T0 bhOTOCxQ/D0N4lb3JrGdS9GEeMScSEP9klkrDlyit9QXt92eM+kDMjfIKY0rMZRRW2 i3WRqsE3X5KqwsGETdrI2n0tdWCkBjDOMu/TspGo= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 01/10] libnetlink: Set NLA_F_NESTED in rta_nest Date: Fri, 7 Jun 2019 15:38:07 -0700 Message-Id: <20190607223816.27512-2-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Kernel now requires NLA_F_NESTED to be set on new nested attributes. Set NLA_F_NESTED in rta_nest. Signed-off-by: David Ahern --- lib/libnetlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 0d48a3d43cf0..6ae51a9dba14 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -1336,6 +1336,7 @@ struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type) struct rtattr *nest = RTA_TAIL(rta); rta_addattr_l(rta, maxlen, type, NULL, 0); + nest->rta_type |= NLA_F_NESTED; return nest; } From patchwork Fri Jun 7 22:38:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112336 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="RMYaOsVc"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHW82M4dz9s9y for ; Sat, 8 Jun 2019 08:38:44 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731837AbfFGWin (ORCPT ); Fri, 7 Jun 2019 18:38:43 -0400 Received: from mail.kernel.org ([198.145.29.99]:48602 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731521AbfFGWiT (ORCPT ); Fri, 7 Jun 2019 18:38:19 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 0A5AD2089E; Fri, 7 Jun 2019 22:38:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947099; bh=wh63PGozm3piZl4WOI2F2hGTXJdzE6fSQuzQ+CdKI5E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RMYaOsVcjDcwlvl8kh/47nOR+8pGt0O3pFRqgK5DNCgjEr3tHWTfmvWZ3mIdjuCvV xgx21xf81pxiSIc6gTP471+MAYWNlxVoRidm3VMFLwZCdAHtHBQdRwiN847PQ53Ztn dF2pRZryx5XEtAERcSclbV4OtFNYX3C/WzDhRPkI= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 02/10] lwtunnel: Pass encap and encap_type attributes to lwt_parse_encap Date: Fri, 7 Jun 2019 15:38:08 -0700 Message-Id: <20190607223816.27512-3-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern lwt_parse_encap currently assumes the encap attribute is RTA_ENCAP and the type is RTA_ENCAP_TYPE. Change lwt_parse_encap to take these as input arguments for reuse by nexthop code which has the attributes as NHA_ENCAP and NHA_ENCAP_TYPE. Signed-off-by: David Ahern --- ip/ip_common.h | 3 ++- ip/iproute.c | 6 ++++-- ip/iproute_lwtunnel.c | 7 ++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ip/ip_common.h b/ip/ip_common.h index b4aa34a70c92..df279e4f7b9a 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -134,7 +134,8 @@ int bond_parse_xstats(struct link_util *lu, int argc, char **argv); int bond_print_xstats(struct nlmsghdr *n, void *arg); /* iproute_lwtunnel.c */ -int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp); +int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp, + int encap_attr, int encap_type_attr); void lwt_print_encap(FILE *fp, struct rtattr *encap_type, struct rtattr *encap); /* iplink_xdp.c */ diff --git a/ip/iproute.c b/ip/iproute.c index 2b3dcc5dbd53..440b1fc8b413 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -997,7 +997,8 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, } else if (strcmp(*argv, "encap") == 0) { int old_len = rta->rta_len; - if (lwt_parse_encap(rta, len, &argc, &argv)) + if (lwt_parse_encap(rta, len, &argc, &argv, + RTA_ENCAP, RTA_ENCAP_TYPE)) return -1; rtnh->rtnh_len += rta->rta_len - old_len; } else if (strcmp(*argv, "as") == 0) { @@ -1416,7 +1417,8 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) rta->rta_type = RTA_ENCAP; rta->rta_len = RTA_LENGTH(0); - lwt_parse_encap(rta, sizeof(buf), &argc, &argv); + lwt_parse_encap(rta, sizeof(buf), &argc, &argv, + RTA_ENCAP, RTA_ENCAP_TYPE); if (rta->rta_len > RTA_LENGTH(0)) addraw_l(&req.n, 1024 diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index 03217b8f08f8..60f34a32a6e5 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -1111,7 +1111,8 @@ static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp, return 0; } -int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) +int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp, + int encap_attr, int encap_type_attr) { struct rtattr *nest; int argc = *argcp; @@ -1131,7 +1132,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) exit(-1); } - nest = rta_nest(rta, len, RTA_ENCAP); + nest = rta_nest(rta, len, encap_attr); switch (type) { case LWTUNNEL_ENCAP_MPLS: ret = parse_encap_mpls(rta, len, &argc, &argv); @@ -1164,7 +1165,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) rta_nest_end(rta, nest); - ret = rta_addattr16(rta, len, RTA_ENCAP_TYPE, type); + ret = rta_addattr16(rta, len, encap_type_attr, type); *argcp = argc; *argvp = argv; From patchwork Fri Jun 7 22:38:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112331 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="uHszTUxI"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHVw1rQdz9s9y for ; Sat, 8 Jun 2019 08:38:32 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731786AbfFGWiW (ORCPT ); Fri, 7 Jun 2019 18:38:22 -0400 Received: from mail.kernel.org ([198.145.29.99]:48612 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731749AbfFGWiT (ORCPT ); Fri, 7 Jun 2019 18:38:19 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 3DB952146F; Fri, 7 Jun 2019 22:38:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947099; bh=n8IBK3dCAN27MQYAkoLRDxbNXvETLAbr5HekssFqeRQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uHszTUxI4KZYnWs7soAfXacPosn+IvU07F3g3oNOMgiSrWaN7DUfQ4W6bh6eibw4y emheRzsPMJfbMFAM9uYUsPsVncpircp1wQhzPVY6g1LF08pp/TX5qB5SWcZRWH1uoO VqlaetRq18AM2mTyVhph5gnt9sVc7X3HPKIth/50= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 03/10] libnetlink: Add helper to add a group via setsockopt Date: Fri, 7 Jun 2019 15:38:09 -0700 Message-Id: <20190607223816.27512-4-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern groups > 31 have to be joined using the setsockopt. Since the nexthop group is 32, add a helper to allow 'ip monitor' to listen for nexthop messages. Signed-off-by: David Ahern --- include/libnetlink.h | 3 ++- lib/libnetlink.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/libnetlink.h b/include/libnetlink.h index 503b3ec11bb6..599b2c592f68 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -45,7 +45,8 @@ int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions) int rtnl_open_byproto(struct rtnl_handle *rth, unsigned int subscriptions, int protocol) __attribute__((warn_unused_result)); - +int rtnl_add_nl_group(struct rtnl_handle *rth, unsigned int group) + __attribute__((warn_unused_result)); void rtnl_close(struct rtnl_handle *rth); void rtnl_set_strict_dump(struct rtnl_handle *rth); diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 6ae51a9dba14..eb85bbdf01ee 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -173,6 +173,12 @@ void rtnl_set_strict_dump(struct rtnl_handle *rth) rth->flags |= RTNL_HANDLE_F_STRICT_CHK; } +int rtnl_add_nl_group(struct rtnl_handle *rth, unsigned int group) +{ + return setsockopt(rth->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, + &group, sizeof(group)); +} + void rtnl_close(struct rtnl_handle *rth) { if (rth->fd >= 0) { From patchwork Fri Jun 7 22:38:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112327 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="ZeDjve2V"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHVl6S2mz9s9y for ; Sat, 8 Jun 2019 08:38:23 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731792AbfFGWiX (ORCPT ); Fri, 7 Jun 2019 18:38:23 -0400 Received: from mail.kernel.org ([198.145.29.99]:48622 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731751AbfFGWiT (ORCPT ); Fri, 7 Jun 2019 18:38:19 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 73A1620840; Fri, 7 Jun 2019 22:38:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947099; bh=UIstGdJB++uCNT+ZZwRcDYZ7xxWQ4yA79qmUZ+sEvoM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZeDjve2VLC9o3L7iRCS5UNoC8ylI5tb0m43iRvA+A+RVwbXEB2/NvUhUu4baTipvH 4kmxJXUsEPu+D8v7KdWnTqx7ceYo9f5DfpXMB9iN0qJ9SXi3TuLZ/d8gevwGHcDVtQ 0eRu7EtgYtaRWwYMA3TkReC4pTGkuPwohDac0qEA= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 04/10] uapi: Import nexthop object API Date: Fri, 7 Jun 2019 15:38:10 -0700 Message-Id: <20190607223816.27512-5-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Add nexthop.h from kernel with the uapi for nexthop objects. Signed-off-by: David Ahern --- include/uapi/linux/nexthop.h | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 include/uapi/linux/nexthop.h diff --git a/include/uapi/linux/nexthop.h b/include/uapi/linux/nexthop.h new file mode 100644 index 000000000000..b56c5b895476 --- /dev/null +++ b/include/uapi/linux/nexthop.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_NEXTHOP_H +#define _LINUX_NEXTHOP_H + +#include + +struct nhmsg { + unsigned char nh_family; + unsigned char nh_scope; /* return only */ + unsigned char nh_protocol; /* Routing protocol that installed nh */ + unsigned char resvd; + unsigned int nh_flags; /* RTNH_F flags */ +}; + +/* entry in a nexthop group */ +struct nexthop_grp { + __u32 id; /* nexthop id - must exist */ + __u8 weight; /* weight of this nexthop */ + __u8 resvd1; + __u16 resvd2; +}; + +enum { + NEXTHOP_GRP_TYPE_MPATH, /* default type if not specified */ + __NEXTHOP_GRP_TYPE_MAX, +}; + +#define NEXTHOP_GRP_TYPE_MAX (__NEXTHOP_GRP_TYPE_MAX - 1) + +enum { + NHA_UNSPEC, + NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */ + + NHA_GROUP, /* array of nexthop_grp */ + NHA_GROUP_TYPE, /* u16 one of NEXTHOP_GRP_TYPE */ + /* if NHA_GROUP attribute is added, no other attributes can be set */ + + NHA_BLACKHOLE, /* flag; nexthop used to blackhole packets */ + /* if NHA_BLACKHOLE is added, OIF, GATEWAY, ENCAP can not be set */ + + NHA_OIF, /* u32; nexthop device */ + NHA_GATEWAY, /* be32 (IPv4) or in6_addr (IPv6) gw address */ + NHA_ENCAP_TYPE, /* u16; lwt encap type */ + NHA_ENCAP, /* lwt encap data */ + + /* NHA_OIF can be appended to dump request to return only + * nexthops using given device + */ + NHA_GROUPS, /* flag; only return nexthop groups in dump */ + NHA_MASTER, /* u32; only return nexthops with given master dev */ + + __NHA_MAX, +}; + +#define NHA_MAX (__NHA_MAX - 1) +#endif From patchwork Fri Jun 7 22:38:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112335 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="NbN7FLrJ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHW56m42z9s9y for ; Sat, 8 Jun 2019 08:38:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731835AbfFGWil (ORCPT ); Fri, 7 Jun 2019 18:38:41 -0400 Received: from mail.kernel.org ([198.145.29.99]:48632 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731755AbfFGWiU (ORCPT ); Fri, 7 Jun 2019 18:38:20 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A6E0C20868; Fri, 7 Jun 2019 22:38:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947099; bh=hefFaO5llMPR2l4B0U1XpbdcfUiRpqZKAfXbnOf7l4E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NbN7FLrJL8KHNOZhwlM8l7gcTa282x8ox90hMUH72T3dROX0W3cEjjG1JBsyx5M47 XielpsM2hB0895HiT4KqLdmOUR4oM9j2EF70UR1K5NyAZ/LJKqss1O1Y3Je3A3/Kej QpjLYzJ5kSEdUHfrFVOFgY6aGLvlTFwDagUNAlxM= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 05/10] libnetlink: Add helper to create nexthop dump request Date: Fri, 7 Jun 2019 15:38:11 -0700 Message-Id: <20190607223816.27512-6-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Add rtnl_nexthopdump_req to initiate a dump request of nexthop objects. Signed-off-by: David Ahern --- include/libnetlink.h | 4 ++++ lib/libnetlink.c | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/libnetlink.h b/include/libnetlink.h index 599b2c592f68..1ddba8dcd220 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -93,6 +93,10 @@ int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int rtnl_dump_request_n(struct rtnl_handle *rth, struct nlmsghdr *n) __attribute__((warn_unused_result)); +int rtnl_nexthopdump_req(struct rtnl_handle *rth, int family, + req_filter_fn_t filter_fn) + __attribute__((warn_unused_result)); + struct rtnl_ctrl_data { int nsid; }; diff --git a/lib/libnetlink.c b/lib/libnetlink.c index eb85bbdf01ee..af2a3bbfd29b 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "libnetlink.h" @@ -252,6 +253,32 @@ int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions) return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); } +int rtnl_nexthopdump_req(struct rtnl_handle *rth, int family, + req_filter_fn_t filter_fn) +{ + struct { + struct nlmsghdr nlh; + struct nhmsg nhm; + char buf[128]; + } req = { + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)), + .nlh.nlmsg_type = RTM_GETNEXTHOP, + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, + .nlh.nlmsg_seq = rth->dump = ++rth->seq, + .nhm.nh_family = family, + }; + + if (filter_fn) { + int err; + + err = filter_fn(&req.nlh, sizeof(req)); + if (err) + return err; + } + + return send(rth->fd, &req, sizeof(req), 0); +} + int rtnl_addrdump_req(struct rtnl_handle *rth, int family, req_filter_fn_t filter_fn) { From patchwork Fri Jun 7 22:38:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112330 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="LGFf/FjZ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHVr4DjGz9s9y for ; Sat, 8 Jun 2019 08:38:28 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731797AbfFGWiX (ORCPT ); Fri, 7 Jun 2019 18:38:23 -0400 Received: from mail.kernel.org ([198.145.29.99]:48612 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731757AbfFGWiU (ORCPT ); Fri, 7 Jun 2019 18:38:20 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DA76121473; Fri, 7 Jun 2019 22:38:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947100; bh=OG0wc8/oYDzywD85XBqx7O/FRwq7vk/0t/+gQ7NluxY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LGFf/FjZ1oONNu0csQNeAyGlmLzYXGWrx7SY2LwhjIr9wAt+qdHBKWxgE6Z5jsVDm n6jMr0V/UI0IKYzC26pPMqxxzQLRzF/+456hFgrK28k+fKLaGk4PUTLb/cSW739l2S cM571TqyVquiTFo1qHIyRtxhI2omAV9rChjxFGzI= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 06/10] ip route: Export print_rt_flags, print_rta_if and print_rta_gateway Date: Fri, 7 Jun 2019 15:38:12 -0700 Message-Id: <20190607223816.27512-7-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Export print_rt_flags and print_rta_if for use by the nexthop command. Change print_rta_gateway to take the family versus rtmsg struct and export for use by the nexthop command. Signed-off-by: David Ahern --- ip/ip_common.h | 5 ++++- ip/iproute.c | 17 ++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ip/ip_common.h b/ip/ip_common.h index df279e4f7b9a..3e8183e2c48c 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -156,5 +156,8 @@ int name_is_vrf(const char *name); #endif void print_num(FILE *fp, unsigned int width, uint64_t count); - +void print_rt_flags(FILE *fp, unsigned int flags); +void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix); +void print_rta_gateway(FILE *fp, unsigned char family, + const struct rtattr *rta); #endif /* _IP_COMMON_H_ */ diff --git a/ip/iproute.c b/ip/iproute.c index 440b1fc8b413..1c443265d479 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -349,7 +349,7 @@ static void print_rtax_features(FILE *fp, unsigned int features) "features", "%#llx ", of); } -static void print_rt_flags(FILE *fp, unsigned int flags) +void print_rt_flags(FILE *fp, unsigned int flags) { open_json_array(PRINT_JSON, is_json_context() ? "flags" : ""); @@ -394,8 +394,7 @@ static void print_rt_pref(FILE *fp, unsigned int pref) } } -static void print_rta_if(FILE *fp, const struct rtattr *rta, - const char *prefix) +void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix) { const char *ifname = ll_index_to_name(rta_getattr_u32(rta)); @@ -532,17 +531,16 @@ static void print_rta_newdst(FILE *fp, const struct rtmsg *r, } } -static void print_rta_gateway(FILE *fp, const struct rtmsg *r, - const struct rtattr *rta) +void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta) { - const char *gateway = format_host_rta(r->rtm_family, rta); + const char *gateway = format_host_rta(family, rta); if (is_json_context()) print_string(PRINT_JSON, "gateway", NULL, gateway); else { fprintf(fp, "via "); print_color_string(PRINT_FP, - ifa_family_color(r->rtm_family), + ifa_family_color(family), NULL, "%s ", gateway); } } @@ -679,7 +677,8 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r, if (tb[RTA_NEWDST]) print_rta_newdst(fp, r, tb[RTA_NEWDST]); if (tb[RTA_GATEWAY]) - print_rta_gateway(fp, r, tb[RTA_GATEWAY]); + print_rta_gateway(fp, r->rtm_family, + tb[RTA_GATEWAY]); if (tb[RTA_VIA]) print_rta_via(fp, tb[RTA_VIA]); if (tb[RTA_FLOW]) @@ -822,7 +821,7 @@ int print_route(struct nlmsghdr *n, void *arg) } if (tb[RTA_GATEWAY] && filter.rvia.bitlen != host_len) - print_rta_gateway(fp, r, tb[RTA_GATEWAY]); + print_rta_gateway(fp, r->rtm_family, tb[RTA_GATEWAY]); if (tb[RTA_VIA]) print_rta_via(fp, tb[RTA_VIA]); From patchwork Fri Jun 7 22:38:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112328 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="X1/74rqz"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHVn2644z9s9y for ; Sat, 8 Jun 2019 08:38:25 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731805AbfFGWiY (ORCPT ); Fri, 7 Jun 2019 18:38:24 -0400 Received: from mail.kernel.org ([198.145.29.99]:48622 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730849AbfFGWiV (ORCPT ); Fri, 7 Jun 2019 18:38:21 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 1A36E2146F; Fri, 7 Jun 2019 22:38:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947100; bh=iECCdojkXt3QTtIvglbKZf1xj//mSxZSqsU5afvAPfY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=X1/74rqzWyUZeCCe+RE7u9mgPXzzQUXepq19RB8FatMnHsGlaQvf+me4dP1h2ZDBK z4mn9mgukVrX7DbB3qMxSgeaKgSoxoW/uomgcTl9AP6hNUaDF+Aww3zCZykILZE6A8 yxgiC/Fp9CE2mymQG7Y9cRB0USd+Pq7V1LKA3XYQ= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 07/10] Add support for nexthop objects Date: Fri, 7 Jun 2019 15:38:13 -0700 Message-Id: <20190607223816.27512-8-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Add nexthop subcommand to ip. Implement basic commands for creating, deleting and dumping nexthop objects. Syntax follows 'nexthop' syntax from existing 'ip route' command. Examples: 1. Single path $ ip nexthop add id 1 via 10.99.1.2 dev veth1 $ ip nexthop ls id 1 via 10.99.1.2 src 10.99.1.1 dev veth1 scope link 2. ECMP $ ip nexthop add id 2 via 10.99.3.2 dev veth3 $ ip nexthop add id 1001 group 1/2 --> creates a nexthop group with 2 component nexthops: id 1 and id 2 both the same weight $ ip nexthop ls id 1 via 10.99.1.2 src 10.99.1.1 dev veth1 scope link id 2 via 10.99.3.2 src 10.99.3.1 dev veth3 scope link id 1001 group 1/2 3. Weighted multipath $ ip nexthop add id 1002 group 1,10/2,20 --> creates a nexthop group with 2 component nexthops: id 1 with a weight of 10 and id 2 with a weight of 20 $ ip nexthop ls id 1 via 10.99.1.2 src 10.99.1.1 dev veth1 scope link id 2 via 10.99.3.2 src 10.99.3.1 dev veth3 scope link id 1001 group 1/2 id 1002 group 1,10/2,20 Signed-off-by: David Ahern --- ip/Makefile | 3 +- ip/ip.c | 3 +- ip/ip_common.h | 2 + ip/ipnexthop.c | 558 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 ip/ipnexthop.c diff --git a/ip/Makefile b/ip/Makefile index 7ce6e91a528c..5ab78d7d3b84 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -10,7 +10,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ - ipvrf.o iplink_xstats.o ipseg6.o iplink_netdevsim.o iplink_rmnet.o + ipvrf.o iplink_xstats.o ipseg6.o iplink_netdevsim.o iplink_rmnet.o \ + ipnexthop.o RTMONOBJ=rtmon.o diff --git a/ip/ip.c b/ip/ip.c index b71ae816e24d..b46fd8dd056c 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -50,7 +50,7 @@ static void usage(void) "where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n" " tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n" " netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n" - " vrf | sr }\n" + " vrf | sr | nexthop }\n" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" " -h[uman-readable] | -iec | -j[son] | -p[retty] |\n" " -f[amily] { inet | inet6 | mpls | bridge | link } |\n" @@ -100,6 +100,7 @@ static const struct cmd { { "netconf", do_ipnetconf }, { "vrf", do_ipvrf}, { "sr", do_seg6 }, + { "nexthop", do_ipnh }, { "help", do_help }, { 0 } }; diff --git a/ip/ip_common.h b/ip/ip_common.h index 3e8183e2c48c..cd916ec87c26 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -47,6 +47,7 @@ int print_prefix(struct nlmsghdr *n, void *arg); int print_rule(struct nlmsghdr *n, void *arg); int print_netconf(struct rtnl_ctrl_data *ctrl, struct nlmsghdr *n, void *arg); +int print_nexthop(struct nlmsghdr *n, void *arg); void netns_map_init(void); void netns_nsid_socket_init(void); int print_nsid(struct nlmsghdr *n, void *arg); @@ -80,6 +81,7 @@ int do_ipvrf(int argc, char **argv); void vrf_reset(void); int netns_identify_pid(const char *pidstr, char *name, int len); int do_seg6(int argc, char **argv); +int do_ipnh(int argc, char **argv); int iplink_get(char *name, __u32 filt_mask); int iplink_ifla_xstats(int argc, char **argv); diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c new file mode 100644 index 000000000000..97f09e74d01b --- /dev/null +++ b/ip/ipnexthop.c @@ -0,0 +1,558 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ip nexthop + * + * Copyright (c) 2017-19 David Ahern + */ + +#include +#include +#include +#include +#include + +#include "utils.h" +#include "ip_common.h" + +static struct { + unsigned int flushed; + unsigned int groups; + unsigned int ifindex; + unsigned int master; +} filter; + +enum { + IPNH_LIST, + IPNH_FLUSH, +}; + +#define RTM_NHA(h) ((struct rtattr *)(((char *)(h)) + \ + NLMSG_ALIGN(sizeof(struct nhmsg)))) + +static void usage(void) __attribute__((noreturn)); + +static void usage(void) +{ + fprintf(stderr, + "Usage: ip nexthop { list | flush } SELECTOR\n" + " ip nexthop { add | replace } id ID NH [ protocol ID ]\n" + " ip nexthop { get| del } id ID\n" + "SELECTOR := [ id ID ] [ dev DEV ] [ vrf NAME ] [ master DEV ]\n" + " [ groups ]\n" + "NH := { blackhole | [ via ADDRESS ] [ dev DEV ] [ onlink ]\n" + " [ encap ENCAPTYPE ENCAPHDR ] | group GROUP ] }\n" + "GROUP := [ id[,weight]>//... ]\n" + "ENCAPTYPE := [ mpls ]\n" + "ENCAPHDR := [ MPLSLABEL ]\n"); + exit(-1); +} + +static int nh_dump_filter(struct nlmsghdr *nlh, int reqlen) +{ + int err; + + if (filter.ifindex) { + err = addattr32(nlh, reqlen, NHA_OIF, filter.ifindex); + if (err) + return err; + } + + if (filter.groups) { + addattr_l(nlh, reqlen, NHA_GROUPS, NULL, 0); + if (err) + return err; + } + + if (filter.master) { + addattr32(nlh, reqlen, NHA_MASTER, filter.master); + if (err) + return err; + } + + return 0; +} + +static struct rtnl_handle rth_del = { .fd = -1 }; + +static int delete_nexthop(__u32 id) +{ + struct { + struct nlmsghdr n; + struct nhmsg nhm; + char buf[64]; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = RTM_DELNEXTHOP, + .nhm.nh_family = AF_UNSPEC, + }; + + req.n.nlmsg_seq = ++rth_del.seq; + + addattr32(&req.n, sizeof(req), NHA_ID, id); + + if (rtnl_talk(&rth_del, &req.n, NULL) < 0) + return -1; + return 0; +} + +static int flush_nexthop(struct nlmsghdr *nlh, void *arg) +{ + struct nhmsg *nhm = NLMSG_DATA(nlh); + struct rtattr *tb[NHA_MAX+1]; + __u32 id = 0; + int len; + + len = nlh->nlmsg_len - NLMSG_SPACE(sizeof(*nhm)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + + parse_rtattr(tb, NHA_MAX, RTM_NHA(nhm), len); + if (tb[NHA_ID]) + id = rta_getattr_u32(tb[NHA_ID]); + + if (id && !delete_nexthop(id)) + filter.flushed++; + + return 0; +} + +static int ipnh_flush(unsigned int all) +{ + int rc = -2; + + if (all) { + filter.groups = 1; + filter.ifindex = 0; + filter.master = 0; + } + + if (rtnl_open(&rth_del, 0) < 0) { + fprintf(stderr, "Cannot open rtnetlink\n"); + return EXIT_FAILURE; + } +again: + if (rtnl_nexthopdump_req(&rth, preferred_family, nh_dump_filter) < 0) { + perror("Cannot send dump request"); + goto out; + } + + if (rtnl_dump_filter(&rth, flush_nexthop, stdout) < 0) { + fprintf(stderr, "Dump terminated. Failed to flush nexthops\n"); + goto out; + } + + /* if deleting all, then remove groups first */ + if (all && filter.groups) { + filter.groups = 0; + goto again; + } + + rc = 0; +out: + rtnl_close(&rth_del); + if (!filter.flushed) + printf("Nothing to flush\n"); + else + printf("Flushed %d nexthops\n", filter.flushed); + + return rc; +} + +static void print_nh_group(FILE *fp, const struct rtattr *grps_attr) +{ + struct nexthop_grp *nhg = RTA_DATA(grps_attr); + int num = RTA_PAYLOAD(grps_attr) / sizeof(*nhg); + int i; + + if (!num || num * sizeof(*nhg) != RTA_PAYLOAD(grps_attr)) { + fprintf(fp, ""); + return; + } + + open_json_array(PRINT_JSON, "group"); + print_string(PRINT_FP, NULL, "%s", "group "); + for (i = 0; i < num; ++i) { + open_json_object(NULL); + + if (i) + print_string(PRINT_FP, NULL, "%s", "/"); + + print_uint(PRINT_ANY, "id", "%u", nhg[i].id); + if (nhg[i].weight) + print_uint(PRINT_ANY, "weight", ",%u", nhg[i].weight + 1); + + close_json_object(); + } + close_json_array(PRINT_JSON, NULL); +} + +int print_nexthop(struct nlmsghdr *n, void *arg) +{ + struct nhmsg *nhm = NLMSG_DATA(n); + struct rtattr *tb[NHA_MAX+1]; + FILE *fp = (FILE *)arg; + int len; + + SPRINT_BUF(b1); + + if (n->nlmsg_type != RTM_DELNEXTHOP && + n->nlmsg_type != RTM_NEWNEXTHOP) { + fprintf(stderr, "Not a nexthop: %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(tb, NHA_MAX, RTM_NHA(nhm), len); + + open_json_object(NULL); + + if (n->nlmsg_type == RTM_DELROUTE) + 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_GROUP]) + print_nh_group(fp, tb[NHA_GROUP]); + + if (tb[NHA_ENCAP]) + lwt_print_encap(fp, tb[NHA_ENCAP_TYPE], tb[NHA_ENCAP]); + + if (tb[NHA_GATEWAY]) + print_rta_gateway(fp, nhm->nh_family, tb[NHA_GATEWAY]); + + if (tb[NHA_OIF]) + print_rta_if(fp, tb[NHA_OIF], "dev"); + + if (nhm->nh_scope != RT_SCOPE_UNIVERSE || show_details > 0) { + print_string(PRINT_ANY, "scope", "scope %s ", + rtnl_rtscope_n2a(nhm->nh_scope, b1, sizeof(b1))); + } + + if (tb[NHA_BLACKHOLE]) + print_null(PRINT_ANY, "blackhole", "blackhole", NULL); + + if (nhm->nh_protocol != RTPROT_UNSPEC || show_details > 0) { + print_string(PRINT_ANY, "protocol", "proto %s ", + rtnl_rtprot_n2a(nhm->nh_protocol, b1, sizeof(b1))); + } + + if (tb[NHA_OIF]) + 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; + int count = 0, i; + char *sep, *wsep; + + if (*argv != '\0') + count = 1; + + /* separator is '/' */ + sep = strchr(argv, '/'); + while (sep) { + count++; + sep = strchr(sep + 1, '/'); + } + + if (count == 0) + return -1; + + grps = calloc(count, sizeof(*grps)); + if (!grps) + return -1; + + for (i = 0; i < count; ++i) { + sep = strchr(argv, '/'); + if (sep) + *sep = '\0'; + + wsep = strchr(argv, ','); + if (wsep) + *wsep = '\0'; + + if (get_unsigned(&grps[i].id, argv, 0)) + return -1; + if (wsep) { + unsigned int w; + + wsep++; + if (get_unsigned(&w, wsep, 0) || w == 0 || w > 256) + invarg("\"weight\" is invalid\n", wsep); + grps[i].weight = w - 1; + } + + if (!sep) + break; + + argv = sep + 1; + } + + return addattr_l(n, maxlen, NHA_GROUP, grps, count * sizeof(*grps)); +} + +static int ipnh_modify(int cmd, unsigned int flags, int argc, char **argv) +{ + struct { + struct nlmsghdr n; + struct nhmsg nhm; + char buf[1024]; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)), + .n.nlmsg_flags = NLM_F_REQUEST | flags, + .n.nlmsg_type = cmd, + .nhm.nh_family = preferred_family, + }; + __u32 nh_flags = 0; + + while (argc > 0) { + if (!strcmp(*argv, "id")) { + __u32 id; + + NEXT_ARG(); + if (get_unsigned(&id, *argv, 0)) + invarg("invalid id value", *argv); + addattr32(&req.n, sizeof(req), NHA_ID, id); + } else if (!strcmp(*argv, "dev")) { + int ifindex; + + NEXT_ARG(); + ifindex = ll_name_to_index(*argv); + if (!ifindex) + invarg("Device does not exist\n", *argv); + addattr32(&req.n, sizeof(req), NHA_OIF, ifindex); + if (req.nhm.nh_family == AF_UNSPEC) + req.nhm.nh_family = AF_INET; + } else if (strcmp(*argv, "via") == 0) { + inet_prefix addr; + int family; + + NEXT_ARG(); + family = read_family(*argv); + if (family == AF_UNSPEC) + family = req.nhm.nh_family; + else + NEXT_ARG(); + get_addr(&addr, *argv, family); + if (req.nhm.nh_family == AF_UNSPEC) + req.nhm.nh_family = addr.family; + else if (req.nhm.nh_family != addr.family) + invarg("address family mismatch\n", *argv); + addattr_l(&req.n, sizeof(req), NHA_GATEWAY, + &addr.data, addr.bytelen); + } else if (strcmp(*argv, "encap") == 0) { + char buf[1024]; + struct rtattr *rta = (void *)buf; + + rta->rta_type = NHA_ENCAP; + rta->rta_len = RTA_LENGTH(0); + + lwt_parse_encap(rta, sizeof(buf), &argc, &argv, + NHA_ENCAP, NHA_ENCAP_TYPE); + + if (rta->rta_len > RTA_LENGTH(0)) { + addraw_l(&req.n, 1024, RTA_DATA(rta), + RTA_PAYLOAD(rta)); + } + } else if (!strcmp(*argv, "blackhole")) { + addattr_l(&req.n, sizeof(req), NHA_BLACKHOLE, NULL, 0); + if (req.nhm.nh_family == AF_UNSPEC) + req.nhm.nh_family = AF_INET; + } else if (!strcmp(*argv, "onlink")) { + nh_flags |= RTNH_F_ONLINK; + } else if (!strcmp(*argv, "group")) { + NEXT_ARG(); + + if (add_nh_group_attr(&req.n, sizeof(req), *argv)) + invarg("\"group\" value is invalid\n", *argv); + } else if (matches(*argv, "protocol") == 0) { + __u32 prot; + + NEXT_ARG(); + if (rtnl_rtprot_a2n(&prot, *argv)) + invarg("\"protocol\" value is invalid\n", *argv); + req.nhm.nh_protocol = prot; + } else if (strcmp(*argv, "help") == 0) { + usage(); + } else { + invarg("", *argv); + } + argc--; argv++; + } + + req.nhm.nh_flags = nh_flags; + + if (rtnl_talk(&rth, &req.n, NULL) < 0) + return -2; + + return 0; +} + +static int ipnh_get_id(__u32 id) +{ + struct { + struct nlmsghdr n; + struct nhmsg nhm; + char buf[1024]; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = RTM_GETNEXTHOP, + .nhm.nh_family = preferred_family, + }; + struct nlmsghdr *answer; + + addattr32(&req.n, sizeof(req), NHA_ID, id); + + if (rtnl_talk(&rth, &req.n, &answer) < 0) + return -2; + + new_json_obj(json); + + if (print_nexthop(answer, (void *)stdout) < 0) { + free(answer); + return -1; + } + + delete_json_obj(); + fflush(stdout); + + free(answer); + + return 0; +} + +static int ipnh_list_flush(int argc, char **argv, int action) +{ + unsigned int all = (argc == 0); + + while (argc > 0) { + if (!matches(*argv, "dev")) { + NEXT_ARG(); + filter.ifindex = ll_name_to_index(*argv); + if (!filter.ifindex) + invarg("Device does not exist\n", *argv); + } else if (!matches(*argv, "groups")) { + filter.groups = 1; + } else if (!matches(*argv, "master")) { + NEXT_ARG(); + filter.master = ll_name_to_index(*argv); + if (!filter.master) + invarg("Device does not exist\n", *argv); + } else if (matches(*argv, "vrf") == 0) { + NEXT_ARG(); + if (!name_is_vrf(*argv)) + invarg("Invalid VRF\n", *argv); + filter.master = ll_name_to_index(*argv); + if (!filter.master) + invarg("VRF does not exist\n", *argv); + } else if (!strcmp(*argv, "id")) { + __u32 id; + + NEXT_ARG(); + if (get_unsigned(&id, *argv, 0)) + invarg("invalid id value", *argv); + return ipnh_get_id(id); + } else if (matches(*argv, "help") == 0) { + usage(); + } else { + invarg("", *argv); + } + argc--; argv++; + } + + if (action == IPNH_FLUSH) + return ipnh_flush(all); + + if (rtnl_nexthopdump_req(&rth, preferred_family, nh_dump_filter) < 0) { + perror("Cannot send dump request"); + return -2; + } + + new_json_obj(json); + + if (rtnl_dump_filter(&rth, print_nexthop, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); + return -2; + } + + delete_json_obj(); + fflush(stdout); + + return 0; +} + +static int ipnh_get(int argc, char **argv) +{ + __u32 id = 0; + + while (argc > 0) { + if (!strcmp(*argv, "id")) { + NEXT_ARG(); + if (get_unsigned(&id, *argv, 0)) + invarg("invalid id value", *argv); + } else { + usage(); + } + argc--; argv++; + } + + if (!id) { + usage(); + return -1; + } + + return ipnh_get_id(id); +} + +int do_ipnh(int argc, char **argv) +{ + if (argc < 1) + return ipnh_list_flush(0, NULL, IPNH_LIST); + + if (!matches(*argv, "add")) + return ipnh_modify(RTM_NEWNEXTHOP, NLM_F_CREATE|NLM_F_EXCL, + argc-1, argv+1); + if (!matches(*argv, "replace")) + return ipnh_modify(RTM_NEWNEXTHOP, NLM_F_CREATE|NLM_F_REPLACE, + argc-1, argv+1); + if (!matches(*argv, "delete")) + return ipnh_modify(RTM_DELNEXTHOP, 0, argc-1, argv+1); + + if (!matches(*argv, "list") || + !matches(*argv, "show") || + !matches(*argv, "lst")) + return ipnh_list_flush(argc-1, argv+1, IPNH_LIST); + + if (!matches(*argv, "get")) + return ipnh_get(argc-1, argv+1); + + if (!matches(*argv, "flush")) + return ipnh_list_flush(argc-1, argv+1, IPNH_FLUSH); + + if (!matches(*argv, "help")) + usage(); + + fprintf(stderr, + "Command \"%s\" is unknown, try \"ip nexthop help\".\n", *argv); + exit(-1); +} From patchwork Fri Jun 7 22:38:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112333 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="Gjqzy877"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHW22Js9z9sCJ for ; Sat, 8 Jun 2019 08:38:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730083AbfFGWih (ORCPT ); Fri, 7 Jun 2019 18:38:37 -0400 Received: from mail.kernel.org ([198.145.29.99]:48660 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731766AbfFGWiV (ORCPT ); Fri, 7 Jun 2019 18:38:21 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 58B4D20840; Fri, 7 Jun 2019 22:38:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947100; bh=ceg+F7iwecba3xHBHBDynWI22NEJtvb64T5IIcZmzCg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Gjqzy877gpnmxb3uxxVwDxchOIqFvLz29Z8Fy5f0jP6ROAPQo5wDZMqEI/bMv0vz5 IxE23KwmENsP0IbWoUG4CbbySbmFvJ5vkfob+FEXNSB+9tifZ2UAjhyfAN9D2mK92i LBBK+zAplIru9Cl3cl2mS5pO5S5gKEIbOitAtL8g= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 08/10] ip: Add man page for nexthop command Date: Fri, 7 Jun 2019 15:38:14 -0700 Message-Id: <20190607223816.27512-9-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Document 'ip nexthop' options in a man page with a few examples. Signed-off-by: David Ahern --- man/man8/ip-nexthop.8 | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 man/man8/ip-nexthop.8 diff --git a/man/man8/ip-nexthop.8 b/man/man8/ip-nexthop.8 new file mode 100644 index 000000000000..da87ca3b58b7 --- /dev/null +++ b/man/man8/ip-nexthop.8 @@ -0,0 +1,196 @@ +.TH IP\-NEXTHOP 8 "30 May 2019" "iproute2" "Linux" +.SH "NAME" +ip-nexthop \- nexthop object management +.SH "SYNOPSIS" +.sp +.ad l +.in +8 +.ti -8 +.B ip +.RI "[ " ip-OPTIONS " ]" +.B nexthop +.RI " { " COMMAND " | " +.BR help " }" +.sp +.ti -8 + +.ti -8 +.BR "ip nexthop" " { " +.BR show " | " flush " } " +.I SELECTOR + +.ti -8 +.BR "ip nexthop" " { " add " | " replace " } id " +.I ID +.IR NH + +.ti -8 +.BR "ip nexthop" " { " get " | " del " } id " +.I ID + +.ti -8 +.IR SELECTOR " := " +.RB "[ " id +.IR ID " ] [ " +.B dev +.IR DEV " ] [ " +.B vrf +.IR NAME " ] [ " +.B master +.IR DEV " ] [ " +.BR groups " ] " + +.ti -8 +.IR NH " := { " +.BR blackhole " | [ " +.B via +.IR ADDRESS " ] [ " +.B dev +.IR DEV " ] [ " +.BR onlink " ] [ " +.B encap +.IR ENCAP " ] | " +.B group +.IR GROUP " } " + +.ti -8 +.IR ENCAP " := [ " +.IR ENCAP_MPLS " ] " + +.ti -8 +.IR ENCAP_MPLS " := " +.BR mpls " [ " +.IR LABEL " ] [" +.B ttl +.IR TTL " ]" + +.ti -8 +.IR GROUP " := " +.BR id "[," weight "[/...]" + +.SH DESCRIPTION +.B ip nexthop +is used to manipulate entries in the kernel's nexthop tables. +.TP +ip nexthop add id ID +add new nexthop entry +.TP +ip nexthop replace id ID +change the configuration of a nexthop or add new one +.RS +.TP +.BI via " [ FAMILY ] ADDRESS" +the address of the nexthop router, in the address family FAMILY. +Address family must match address family of nexthop instance. +.TP +.BI dev " NAME" +is the output device. +.TP +.B onlink +pretend that the nexthop is directly attached to this link, +even if it does not match any interface prefix. +.TP +.BI encap " ENCAPTYPE ENCAPHDR" +attach tunnel encapsulation attributes to this route. +.sp +.I ENCAPTYPE +is a string specifying the supported encapsulation type. Namely: + +.in +8 +.BI mpls +- encapsulation type MPLS +.sp +.in -8 +.I ENCAPHDR +is a set of encapsulation attributes specific to the +.I ENCAPTYPE. + +.in +8 +.B mpls +.in +2 +.I MPLSLABEL +- mpls label stack with labels separated by +.I "/" +.sp + +.B ttl +.I TTL +- TTL to use for MPLS header or 0 to inherit from IP header +.in -2 + +.TP +.BI group " GROUP" +create a nexthop group. Group specification is id with an optional +weight (id,weight) and a '/' as a separator between entries. +.TP +.B blackhole +create a blackhole nexthop +.RE + +.TP +ip nexthop delete id ID +delete nexthop with given id. +.RE + +.TP +ip nexthop show +show the contents of the nexthop table or the nexthops +selected by some criteria. +.RS +.TP +.BI dev " DEV " +show the nexthops using the given device. +.TP +.BI vrf " NAME " +show the nexthops using devices associated with the vrf name +.TP +.BI master " DEV " +show the nexthops using devices enslaved to given master device +.TP +.BI groups +show only nexthop groups +.RE +.TP +ip nexthop flush +flushes nexthops selected by some criteria. Criteria options are the same +as show. +.RE + +.TP +ip nexthop get id ID +get a single nexthop by id + +.SH EXAMPLES +.PP +ip nexthop ls +.RS 4 +Show all nexthop entries in the kernel. +.RE +.PP +ip nexthop add id 1 via 192.168.1.1 dev eth0 +.RS 4 +Adds an IPv4 nexthop with id 1 using the gateway 192.168.1.1 out device eth0. +.RE +.PP +ip nexthop add id 2 encap mpls 200/300 via 10.1.1.1 dev eth0 +.RS 4 +Adds an IPv4 nexthop with mpls encapsulation attributes attached to it. +.RE +.PP +ip nexthop add id 3 group 1/2 +.RS 4 +Adds a nexthop with id 3. The nexthop is a group using nexthops with ids +1 and 2 at equal weight. +.RE +.PP +ip nexthop add id 4 group 1,5/2,11 +.RS 4 +Adds a nexthop with id 4. The nexthop is a group using nexthops with ids +1 and 2 with nexthop 1 at weight 5 and nexthop 2 at weight 11. +.RE +.SH SEE ALSO +.br +.BR ip (8) + +.SH AUTHOR +Original Manpage by David Ahern From patchwork Fri Jun 7 22:38:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112329 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="iDdghy6i"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHVq0Wbgz9s9y for ; Sat, 8 Jun 2019 08:38:27 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731811AbfFGWiZ (ORCPT ); Fri, 7 Jun 2019 18:38:25 -0400 Received: from mail.kernel.org ([198.145.29.99]:48670 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731768AbfFGWiV (ORCPT ); Fri, 7 Jun 2019 18:38:21 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 8CA742089E; Fri, 7 Jun 2019 22:38:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947100; bh=kgQuroGDZGTjw1UO4m+5RNoHqkWJ4ZBzcuOnFKfkHEk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iDdghy6ijwwFWkiAdNfBfzs1pcDxrDb1Xry1tJXN8e0NFXSAJ1urp4j/7eZJmd5FI 8IUy3cvomKa8uRyJU8Ai5iTUfBz5rr8Zo6Nf1vH3i3fDIol9GfRTH60TIC78dc6SKP uR6yWdUwc6pZmTOG0dYv+B4GFXoikUlTAxJDOUu0= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 09/10] ip route: Add option to use nexthop objects Date: Fri, 7 Jun 2019 15:38:15 -0700 Message-Id: <20190607223816.27512-10-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Add nhid option for routes to use nexthop objects by id. Example: $ ip nexthop add id 1 via 10.99.1.2 dev veth1 $ ip route add 10.100.1.0/24 nhid 1 $ ip route ls ... 10.100.1.0/24 nhid 1 via 10.99.1.2 dev veth1 Signed-off-by: David Ahern --- ip/iproute.c | 14 ++++++++++++-- man/man8/ip-route.8.in | 13 ++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/ip/iproute.c b/ip/iproute.c index 1c443265d479..6b8142250349 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -80,7 +80,7 @@ static void usage(void) " [ table TABLE_ID ] [ proto RTPROTO ]\n" " [ scope SCOPE ] [ metric METRIC ]\n" " [ ttl-propagate { enabled | disabled } ]\n" - "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n" + "INFO_SPEC := { NH | nhid ID } OPTIONS FLAGS [ nexthop NH ]...\n" "NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n" " [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" "FAMILY := [ inet | inet6 | mpls | bridge | link ]\n" @@ -809,6 +809,10 @@ int print_route(struct nlmsghdr *n, void *arg) print_string(PRINT_ANY, "src", "from %s ", b1); } + if (tb[RTA_NH_ID]) + print_uint(PRINT_ANY, "nhid", "nhid %u ", + rta_getattr_u32(tb[RTA_NH_ID])); + if (tb[RTA_NEWDST]) print_rta_newdst(fp, r, tb[RTA_NEWDST]); @@ -1080,6 +1084,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) int table_ok = 0; int raw = 0; int type_ok = 0; + __u32 nhid = 0; if (cmd != RTM_DELROUTE) { req.r.rtm_protocol = RTPROT_BOOT; @@ -1358,6 +1363,11 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) } else if (strcmp(*argv, "nexthop") == 0) { nhs_ok = 1; break; + } else if (!strcmp(*argv, "nhid")) { + NEXT_ARG(); + if (get_u32(&nhid, *argv, 0)) + invarg("\"id\" value is invalid\n", *argv); + addattr32(&req.n, sizeof(req), RTA_NH_ID, nhid); } else if (matches(*argv, "protocol") == 0) { __u32 prot; @@ -1520,7 +1530,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) req.r.rtm_type == RTN_UNSPEC) { if (cmd == RTM_DELROUTE) req.r.rtm_scope = RT_SCOPE_NOWHERE; - else if (!gw_ok && !nhs_ok) + else if (!gw_ok && !nhs_ok && !nhid) req.r.rtm_scope = RT_SCOPE_LINK; } } diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in index b9ae6e30908d..a61b263e75e8 100644 --- a/man/man8/ip-route.8.in +++ b/man/man8/ip-route.8.in @@ -89,7 +89,9 @@ replace " } " .RB "{ " enabled " | " disabled " } ]" .ti -8 -.IR INFO_SPEC " := " "NH OPTIONS FLAGS" " [" +.IR INFO_SPEC " := { " NH " | " +.B nhid +.IR ID " } " "OPTIONS FLAGS" " [" .B nexthop .IR NH " ] ..." @@ -687,6 +689,10 @@ is a string specifying the route preference as defined in RFC4191 for Router .sp .TP +.BI nhid " ID" +use nexthop object with given id as nexthop specification. +.sp +.TP .BI encap " ENCAPTYPE ENCAPHDR" attach tunnel encapsulation attributes to this route. .sp @@ -1154,6 +1160,11 @@ ip -6 route add 2001:db8:1::/64 encap seg6 mode encap segs 2001:db8:42::1,2001:d .RS 4 Adds an IPv6 route with SRv6 encapsulation and two segments attached. .RE +.PP +ip route add 10.1.1.0/30 nhid 10 +.RS 4 +Adds an ipv4 route using nexthop object with id 10. +.RE .SH SEE ALSO .br .BR ip (8) From patchwork Fri Jun 7 22:38:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 1112334 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="WvrqqUxJ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45LHW26VyRz9sBb for ; Sat, 8 Jun 2019 08:38:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731834AbfFGWih (ORCPT ); Fri, 7 Jun 2019 18:38:37 -0400 Received: from mail.kernel.org ([198.145.29.99]:48676 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731772AbfFGWiV (ORCPT ); Fri, 7 Jun 2019 18:38:21 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C02D721479; Fri, 7 Jun 2019 22:38:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559947100; bh=y4GgxUE4lF8iag2yMAV9jIFARkru1PQ3cXDUPVGDn2A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WvrqqUxJSVs8fKFb2Dorbk/uydnl3SzTOloq8u3XLmu5nwvzWKx0JhSFAoDB1Mszk T0byvR/EKKe2ApFcOgfKvlwKH/v3iitEpY0Qb3BRzIYFoVP67SzCWtmYwWA/vu7wnj 5n+h6R+R1Nh1TXPRVrNj/JlmYkTQZrBpZ8K68B14= From: David Ahern To: stephen@networkplumber.org Cc: netdev@vger.kernel.org, David Ahern Subject: [PATCH v2 iproute-next 10/10] ipmonitor: Add nexthop option to monitor Date: Fri, 7 Jun 2019 15:38:16 -0700 Message-Id: <20190607223816.27512-11-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190607223816.27512-1-dsahern@kernel.org> References: <20190607223816.27512-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Add capability to ip-monitor to listen and dump nexthop messages. Since the nexthop group = 32 which exceeds the max groups bit field, 2 separate flags are needed - one that defaults on to indicate nexthop group is joined by default and a second that indicates a specific selection by the user (e.g, ip mon nexthop route). Signed-off-by: David Ahern Acked-by: Stephen Hemminger --- ip/ipmonitor.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c index 9ecc7fd2011a..685be52cfe64 100644 --- a/ip/ipmonitor.c +++ b/ip/ipmonitor.c @@ -84,6 +84,12 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl, } } + case RTM_NEWNEXTHOP: + case RTM_DELNEXTHOP: + print_headers(fp, "[NEXTHOP]", ctrl); + print_nexthop(n, arg); + return 0; + case RTM_NEWLINK: case RTM_DELLINK: ll_remember_index(n, NULL); @@ -161,6 +167,7 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl, int do_ipmonitor(int argc, char **argv) { + int lnexthop = 0, nh_set = 1; char *file = NULL; unsigned int groups = 0; int llink = 0; @@ -202,30 +209,42 @@ int do_ipmonitor(int argc, char **argv) } else if (matches(*argv, "link") == 0) { llink = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "address") == 0) { laddr = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "route") == 0) { lroute = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "mroute") == 0) { lmroute = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "prefix") == 0) { lprefix = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "neigh") == 0) { lneigh = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "netconf") == 0) { lnetconf = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "rule") == 0) { lrule = 1; groups = 0; + nh_set = 0; } else if (matches(*argv, "nsid") == 0) { lnsid = 1; groups = 0; + nh_set = 0; + } else if (matches(*argv, "nexthop") == 0) { + lnexthop = 1; + groups = 0; } else if (strcmp(*argv, "all") == 0) { prefix_banner = 1; } else if (matches(*argv, "all-nsid") == 0) { @@ -297,6 +316,9 @@ int do_ipmonitor(int argc, char **argv) if (lnsid) { groups |= nl_mgrp(RTNLGRP_NSID); } + if (nh_set) + lnexthop = 1; + if (file) { FILE *fp; int err; @@ -313,6 +335,12 @@ int do_ipmonitor(int argc, char **argv) if (rtnl_open(&rth, groups) < 0) exit(1); + + if (lnexthop && rtnl_add_nl_group(&rth, RTNLGRP_NEXTHOP) < 0) { + fprintf(stderr, "Failed to add nexthop group to list\n"); + exit(1); + } + if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0) exit(1);