From patchwork Tue Jan 14 17:56:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222966 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=KOyrYoPD; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyqw2j8Tz9sR0 for ; Wed, 15 Jan 2020 04:58:36 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728779AbgANR6e (ORCPT ); Tue, 14 Jan 2020 12:58:34 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:42582 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726053AbgANR6c (ORCPT ); Tue, 14 Jan 2020 12:58:32 -0500 Received: by mail-lj1-f193.google.com with SMTP id y4so15387728ljj.9 for ; Tue, 14 Jan 2020 09:58:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=M7dGQIqTzWEMkio4akH4cg6mHCfmnNJAqzweWg3IPew=; b=KOyrYoPDKO/L6xfHagAIPLVBllOIvBf02OrQ4SsgBrEjWAf7oiimfkex4sixNWEiBV +6nt2FT4ON+JFNG6S/hfsbMQyP9M4qIzxecg0KgnJn0H4YELqwLf9ErKC7a8gETYz79I o2BJAH0YfjbeerHgdfsH8XybtDzGes0Rrkx/4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=M7dGQIqTzWEMkio4akH4cg6mHCfmnNJAqzweWg3IPew=; b=ofE2uqTjgAcQUmTSN2W8qPf73zep7rt11P1mN0zOmv5VKwGN49aDViNOTkn8pjPOEI OCDsjNrRo6ZIQ0iGZKA0gAt+EpCW372gv91KW+sYmWpVeVAIaOsVeGk2ywSdPUqYEoI0 awGHP323n5SGgVXXmOv79ewBLxgKkTgP3HKPSBYH2RM/1Xl65YGavBk/i8/0qFjDbbjP 3jz5vxtUNNj4A7xiksnMnMoYa/KPk5WOA+gJ/ITUlRdGVDczBsvbB1AtX8Yr813bdA0I r6R4kVwIvOyQKAMjc6v/KpGwBGWvZIB+TZ2okjv4CcdyxCuKTj+7BddOAJtadNxb+ftr Zqug== X-Gm-Message-State: APjAAAWGDM3P4nJhgYbPeF/dMTWAEo0gKC2zbLibg+3/NT8AHOjUccUF 9KeffQXKpaI2iAFzlz0fpTO4Kj2lz00= X-Google-Smtp-Source: APXvYqxcLZRY3/TOPTNVim2eGLUxFCGINorQpID+jv3qnjDdBIE71omVW0RrCPu8IIaG8Ak9h0xU1g== X-Received: by 2002:a05:651c:1b0:: with SMTP id c16mr15378691ljn.236.1579024710559; Tue, 14 Jan 2020 09:58:30 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:29 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 1/8] net: bridge: vlan: add helpers to check for vlan id/range validity Date: Tue, 14 Jan 2020 19:56:07 +0200 Message-Id: <20200114175614.17543-2-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add helpers to check if a vlan id or range are valid. The range helper must be called when range start or end are detected. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_netlink.c | 13 +++---------- net/bridge/br_private.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 60136575aea4..14100e8653e6 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -568,17 +568,13 @@ static int br_process_vlan_info(struct net_bridge *br, bool *changed, struct netlink_ext_ack *extack) { - if (!vinfo_curr->vid || vinfo_curr->vid >= VLAN_VID_MASK) + if (!br_vlan_valid_id(vinfo_curr->vid)) return -EINVAL; if (vinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { - /* check if we are already processing a range */ - if (*vinfo_last) + if (!br_vlan_valid_range(vinfo_curr, *vinfo_last)) return -EINVAL; *vinfo_last = vinfo_curr; - /* don't allow range of pvids */ - if ((*vinfo_last)->flags & BRIDGE_VLAN_INFO_PVID) - return -EINVAL; return 0; } @@ -586,10 +582,7 @@ static int br_process_vlan_info(struct net_bridge *br, struct bridge_vlan_info tmp_vinfo; int v, err; - if (!(vinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_END)) - return -EINVAL; - - if (vinfo_curr->vid <= (*vinfo_last)->vid) + if (!br_vlan_valid_range(vinfo_curr, *vinfo_last)) return -EINVAL; memcpy(&tmp_vinfo, *vinfo_last, diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f540f3bdf294..dbc0089e2c1a 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -507,6 +507,37 @@ static inline bool nbp_state_should_learn(const struct net_bridge_port *p) return p->state == BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING; } +static inline bool br_vlan_valid_id(u16 vid) +{ + return vid > 0 && vid < VLAN_VID_MASK; +} + +static inline bool br_vlan_valid_range(const struct bridge_vlan_info *cur, + const struct bridge_vlan_info *last) +{ + /* pvid flag is not allowed in ranges */ + if (cur->flags & BRIDGE_VLAN_INFO_PVID) + return false; + + /* check for required range flags */ + if (!(cur->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | + BRIDGE_VLAN_INFO_RANGE_END))) + return false; + + /* when cur is the range end, check if: + * - it has range start flag + * - range ids are invalid (end is equal to or before start) + */ + if (last) { + if (cur->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) + return false; + else if (cur->vid <= last->vid) + return false; + } + + return true; +} + static inline int br_opt_get(const struct net_bridge *br, enum net_bridge_opts opt) { From patchwork Tue Jan 14 17:56:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222967 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=L1I1cGq/; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyqx0mQcz9sR1 for ; Wed, 15 Jan 2020 04:58:37 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728803AbgANR6g (ORCPT ); Tue, 14 Jan 2020 12:58:36 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:37761 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728773AbgANR6e (ORCPT ); Tue, 14 Jan 2020 12:58:34 -0500 Received: by mail-lj1-f193.google.com with SMTP id o13so15391087ljg.4 for ; Tue, 14 Jan 2020 09:58:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=OEK3+d3CKz1mIylcZTyAVylsHfHcJSc3xiPKTSlMW5U=; b=L1I1cGq/VpF7rqeu4/9JOaVMNqaD7c6cok3OLJOPl574ZH9zu4R3FyH+Ma0EExTcEw wLgcDPu17VJMrRImy3c5TAxGreQuchKtD9lgYnhTJw3ZWLtYXv3B5hkPWcyK6f8PgTKl eW6lKELnIuzYn3DSD4a4sKoVnWhzghrHj36Bs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=OEK3+d3CKz1mIylcZTyAVylsHfHcJSc3xiPKTSlMW5U=; b=bJIE7mpuoQFTwSU2rrd2RJckyDg3JjV0WRQ5dfujGJa6D23uZI72XBSo/Cl3y42Qw2 c0bYvj20qt6v/5ewisPqrmppw7VTSs7tY2QcVrfdZQi64nu28iO/m5Ml5eIuu2XEYoak VoiqEJpHBEAoER1AEQCL5Y/YBMwkdCel8SKxm1YqaV3GwiIQXYTyfctJd3Gd/dGIdu4i nya9aS+A3t/SR4LXvFDcqO6BZ3LaYfhVUnTOqlUVTb6UKuBgeJTLA7S4zh2VLf4S+acP ccwl2QLLKJa4yVgqGwpTLugom1322RBnsvAZFqbZFHqNB3f69D3l8E6DlqwlXHbFCRST 7YdA== X-Gm-Message-State: APjAAAVnSwjUE8rq6s4q3uyUsxDWaI9W+vkqFErHLbKJCn1Pe9BbLLJz 2nBZ0u9qTUwEbiTNv1OKXgAUvC3lzQE= X-Google-Smtp-Source: APXvYqwH+MWStQtul4RUIFL2GpYqrcOYO/6bPGvcbwmhPfsrD+4LrI95SGLCtOyK6qObwuUi/kkD7Q== X-Received: by 2002:a2e:461a:: with SMTP id t26mr15043100lja.204.1579024712249; Tue, 14 Jan 2020 09:58:32 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:31 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 2/8] net: bridge: netlink: add extack error messages when processing vlans Date: Tue, 14 Jan 2020 19:56:08 +0200 Message-Id: <20200114175614.17543-3-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add extack messages on vlan processing errors. We need to move the flags missing check after the "last" check since we may have "last" set but lack a range end flag in the next entry. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_netlink.c | 6 +++--- net/bridge/br_private.h | 38 +++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 14100e8653e6..40942cece51a 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -568,11 +568,11 @@ static int br_process_vlan_info(struct net_bridge *br, bool *changed, struct netlink_ext_ack *extack) { - if (!br_vlan_valid_id(vinfo_curr->vid)) + if (!br_vlan_valid_id(vinfo_curr->vid, extack)) return -EINVAL; if (vinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { - if (!br_vlan_valid_range(vinfo_curr, *vinfo_last)) + if (!br_vlan_valid_range(vinfo_curr, *vinfo_last, extack)) return -EINVAL; *vinfo_last = vinfo_curr; return 0; @@ -582,7 +582,7 @@ static int br_process_vlan_info(struct net_bridge *br, struct bridge_vlan_info tmp_vinfo; int v, err; - if (!br_vlan_valid_range(vinfo_curr, *vinfo_last)) + if (!br_vlan_valid_range(vinfo_curr, *vinfo_last, extack)) return -EINVAL; memcpy(&tmp_vinfo, *vinfo_last, diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index dbc0089e2c1a..a7dddc5d7790 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -507,32 +507,48 @@ static inline bool nbp_state_should_learn(const struct net_bridge_port *p) return p->state == BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING; } -static inline bool br_vlan_valid_id(u16 vid) +static inline bool br_vlan_valid_id(u16 vid, struct netlink_ext_ack *extack) { - return vid > 0 && vid < VLAN_VID_MASK; + bool ret = vid > 0 && vid < VLAN_VID_MASK; + + if (!ret) + NL_SET_ERR_MSG_MOD(extack, "Vlan id is invalid"); + + return ret; } static inline bool br_vlan_valid_range(const struct bridge_vlan_info *cur, - const struct bridge_vlan_info *last) + const struct bridge_vlan_info *last, + struct netlink_ext_ack *extack) { /* pvid flag is not allowed in ranges */ - if (cur->flags & BRIDGE_VLAN_INFO_PVID) - return false; - - /* check for required range flags */ - if (!(cur->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | - BRIDGE_VLAN_INFO_RANGE_END))) + if (cur->flags & BRIDGE_VLAN_INFO_PVID) { + NL_SET_ERR_MSG_MOD(extack, "Pvid isn't allowed in a range"); return false; + } /* when cur is the range end, check if: * - it has range start flag * - range ids are invalid (end is equal to or before start) */ if (last) { - if (cur->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) + if (cur->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { + NL_SET_ERR_MSG_MOD(extack, "Found a new vlan range start while processing one"); return false; - else if (cur->vid <= last->vid) + } else if (!(cur->flags & BRIDGE_VLAN_INFO_RANGE_END)) { + NL_SET_ERR_MSG_MOD(extack, "Vlan range end flag is missing"); return false; + } else if (cur->vid <= last->vid) { + NL_SET_ERR_MSG_MOD(extack, "End vlan id is less than or equal to start vlan id"); + return false; + } + } + + /* check for required range flags */ + if (!(cur->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | + BRIDGE_VLAN_INFO_RANGE_END))) { + NL_SET_ERR_MSG_MOD(extack, "Both vlan range flags are missing"); + return false; } return true; From patchwork Tue Jan 14 17:56:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222969 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=EHqdpGNs; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyr12JPwz9sR0 for ; Wed, 15 Jan 2020 04:58:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728864AbgANR6k (ORCPT ); Tue, 14 Jan 2020 12:58:40 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:34640 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726053AbgANR6g (ORCPT ); Tue, 14 Jan 2020 12:58:36 -0500 Received: by mail-lj1-f193.google.com with SMTP id z22so15420229ljg.1 for ; Tue, 14 Jan 2020 09:58:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VgjmK8wyUDR97bSwB5wlCT5//+1zzhSgncPfQ/07YPs=; b=EHqdpGNsFZ7ObJf1aQWsbmNPtLtTUVAujPEuA6igEdonPJW9E2Vc+C8kCZpEqe9Oc7 2viQ3gj0ZMAOG6D6c48e/RpEi7EI6cFDl5CQ0MN3i3iN8BdaaokycnwqNg4Px5d2hXEQ Ay9+TmZtqJ3OdHnJ74SRMdmJkD2QtBWiVQr7M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VgjmK8wyUDR97bSwB5wlCT5//+1zzhSgncPfQ/07YPs=; b=T5gL9tCr0NmJqg+18AypAqRi4ACEHZdl5L5PWJ4MLiZpI4Os1H+Q5Tg3JwJ5QgkXgF tIeZ0On2mhc4g6j9igu081e4YurmxAY/RkzdO7/mQDsGKsnd5uuv+cMiZ5E2HNbcl5fR 9W4XpaGiT/ck0RHIAUGasW50I+awU0//uIHF4hzK79bQMxpgNNO6teou0S6xopke1UAh rM2KjgL1yaKm+ez7ACiuTlX5w1BvDPjuoNhEPQ5WneY41lN/tvEKqge8amtx7V4u2mLY gu92i2hQkbT490p4cCLsAC4zmhD70lnvKLjuhEuVRE0iUUFLEL1VeEWbwRS4l4Ablhwc gTWw== X-Gm-Message-State: APjAAAWiNa/i3JX1e+QzV+zbZn/AfnhCQkca/1f+vnWDye1w0z0FwU9k Vz8Y4K/n6iGXuykYnzaNgDZutCGFUzE= X-Google-Smtp-Source: APXvYqyE4hY9vjq6BIIrkCCTHPYDWo8OPdNCjsuTQhu3Cxe6Als6T4PKVSNdhapw36jqXAglNTvBdA== X-Received: by 2002:a2e:8188:: with SMTP id e8mr13816621ljg.57.1579024713754; Tue, 14 Jan 2020 09:58:33 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:33 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 3/8] net: bridge: vlan: add rtm definitions and dump support Date: Tue, 14 Jan 2020 19:56:09 +0200 Message-Id: <20200114175614.17543-4-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds vlan rtm definitions: - NEWVLAN: to be used for creating vlans, setting options and notifications - DELVLAN: to be used for deleting vlans - GETVLAN: used for dumping vlan information Dumping vlans which can span multiple messages is added now with basic information (vid and flags). We use nlmsg_parse() to validate the header length in order to be able to extend the message with filtering attributes later. Signed-off-by: Nikolay Aleksandrov --- v2: use nlmsg_parse() for stricter validation include/uapi/linux/if_bridge.h | 28 +++++++ include/uapi/linux/rtnetlink.h | 7 ++ net/bridge/br_netlink.c | 2 + net/bridge/br_private.h | 14 ++++ net/bridge/br_vlan.c | 148 +++++++++++++++++++++++++++++++++ security/selinux/nlmsgtab.c | 5 +- 6 files changed, 203 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 4a58e3d7de46..4da04f77d9ee 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -165,6 +165,34 @@ struct bridge_stp_xstats { __u64 tx_tcn; }; +/* Bridge vlan RTM header */ +struct br_vlan_msg { + __u8 family; + __u8 reserved1; + __u16 reserved2; + __u32 ifindex; +}; + +/* Bridge vlan RTM attributes + * [BRIDGE_VLANDB_ENTRY] = { + * [BRIDGE_VLANDB_ENTRY_INFO] + * ... + * } + */ +enum { + BRIDGE_VLANDB_UNSPEC, + BRIDGE_VLANDB_ENTRY, + __BRIDGE_VLANDB_MAX, +}; +#define BRIDGE_VLANDB_MAX (__BRIDGE_VLANDB_MAX - 1) + +enum { + BRIDGE_VLANDB_ENTRY_UNSPEC, + BRIDGE_VLANDB_ENTRY_INFO, + __BRIDGE_VLANDB_ENTRY_MAX, +}; +#define BRIDGE_VLANDB_ENTRY_MAX (__BRIDGE_VLANDB_ENTRY_MAX - 1) + /* Bridge multicast database attributes * [MDBA_MDB] = { * [MDBA_MDB_ENTRY] = { diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 1418a8362bb7..e06e3e09a1b4 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -171,6 +171,13 @@ enum { RTM_GETLINKPROP, #define RTM_GETLINKPROP RTM_GETLINKPROP + RTM_NEWVLAN = 112, +#define RTM_NEWNVLAN RTM_NEWVLAN + RTM_DELVLAN, +#define RTM_DELVLAN RTM_DELVLAN + RTM_GETVLAN, +#define RTM_GETVLAN RTM_GETVLAN + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 40942cece51a..75a7ecf95d7f 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1657,6 +1657,7 @@ int __init br_netlink_init(void) int err; br_mdb_init(); + br_vlan_rtnl_init(); rtnl_af_register(&br_af_ops); err = rtnl_link_register(&br_link_ops); @@ -1674,6 +1675,7 @@ int __init br_netlink_init(void) void br_netlink_fini(void) { br_mdb_uninit(); + br_vlan_rtnl_uninit(); rtnl_af_unregister(&br_af_ops); rtnl_link_unregister(&br_link_ops); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a7dddc5d7790..1c00411ae938 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -958,6 +958,8 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v, void br_vlan_port_event(struct net_bridge_port *p, unsigned long event); int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr); +void br_vlan_rtnl_init(void); +void br_vlan_rtnl_uninit(void); static inline struct net_bridge_vlan_group *br_vlan_group( const struct net_bridge *br) @@ -1009,6 +1011,10 @@ static inline u16 br_get_pvid(const struct net_bridge_vlan_group *vg) return vg->pvid; } +static inline u16 br_vlan_flags(const struct net_bridge_vlan *v, u16 pvid) +{ + return v->vid == pvid ? v->flags | BRIDGE_VLAN_INFO_PVID : v->flags; +} #else static inline bool br_allowed_ingress(const struct net_bridge *br, struct net_bridge_vlan_group *vg, @@ -1152,6 +1158,14 @@ static inline int br_vlan_bridge_event(struct net_device *dev, { return 0; } + +static inline void br_vlan_rtnl_init(void) +{ +} + +static inline void br_vlan_rtnl_uninit(void) +{ +} #endif struct nf_br_ops { diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index bb98984cd27d..5f2ac4f244f5 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1505,3 +1505,151 @@ void br_vlan_port_event(struct net_bridge_port *p, unsigned long event) break; } } + +static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 flags) +{ + struct bridge_vlan_info info; + struct nlattr *nest; + + nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY); + if (!nest) + return false; + + memset(&info, 0, sizeof(info)); + info.vid = vid; + if (flags & BRIDGE_VLAN_INFO_UNTAGGED) + info.flags |= BRIDGE_VLAN_INFO_UNTAGGED; + if (flags & BRIDGE_VLAN_INFO_PVID) + info.flags |= BRIDGE_VLAN_INFO_PVID; + + if (nla_put(skb, BRIDGE_VLANDB_ENTRY_INFO, sizeof(info), &info)) + goto out_err; + + nla_nest_end(skb, nest); + + return true; + +out_err: + nla_nest_cancel(skb, nest); + return false; +} + +static int br_vlan_dump_dev(const struct net_device *dev, + struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct net_bridge_vlan_group *vg; + int idx = 0, s_idx = cb->args[1]; + struct nlmsghdr *nlh = NULL; + struct net_bridge_vlan *v; + struct net_bridge_port *p; + struct br_vlan_msg *bvm; + struct net_bridge *br; + int err = 0; + u16 pvid; + + if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) + return -EINVAL; + + if (netif_is_bridge_master(dev)) { + br = netdev_priv(dev); + vg = br_vlan_group_rcu(br); + p = NULL; + } else { + p = br_port_get_rcu(dev); + if (WARN_ON(!p)) + return -EINVAL; + vg = nbp_vlan_group_rcu(p); + br = p->br; + } + + if (!vg) + return 0; + + nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, + RTM_NEWVLAN, sizeof(*bvm), NLM_F_MULTI); + if (!nlh) + return -EMSGSIZE; + bvm = nlmsg_data(nlh); + memset(bvm, 0, sizeof(*bvm)); + bvm->family = PF_BRIDGE; + bvm->ifindex = dev->ifindex; + pvid = br_get_pvid(vg); + + list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { + if (!br_vlan_should_use(v)) + continue; + if (idx < s_idx) + goto skip; + if (!br_vlan_fill_vids(skb, v->vid, br_vlan_flags(v, pvid))) { + err = -EMSGSIZE; + break; + } +skip: + idx++; + } + if (err) + cb->args[1] = idx; + else + cb->args[1] = 0; + nlmsg_end(skb, nlh); + + return err; +} + +static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + int idx = 0, err = 0, s_idx = cb->args[0]; + struct net *net = sock_net(skb->sk); + struct br_vlan_msg *bvm; + struct net_device *dev; + + err = nlmsg_parse(cb->nlh, sizeof(*bvm), NULL, 0, NULL, cb->extack); + if (err < 0) + return err; + + bvm = nlmsg_data(cb->nlh); + + rcu_read_lock(); + if (bvm->ifindex) { + dev = dev_get_by_index_rcu(net, bvm->ifindex); + if (!dev) { + err = -ENODEV; + goto out_err; + } + err = br_vlan_dump_dev(dev, skb, cb); + if (err && err != -EMSGSIZE) + goto out_err; + } else { + for_each_netdev_rcu(net, dev) { + if (idx < s_idx) + goto skip; + + err = br_vlan_dump_dev(dev, skb, cb); + if (err == -EMSGSIZE) + break; +skip: + idx++; + } + } + cb->args[0] = idx; + rcu_read_unlock(); + + return skb->len; + +out_err: + rcu_read_unlock(); + + return err; +} + +void br_vlan_rtnl_init(void) +{ + rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL, + br_vlan_rtm_dump, 0); +} + +void br_vlan_rtnl_uninit(void) +{ + rtnl_unregister(PF_BRIDGE, RTM_GETVLAN); +} diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index c97fdae8f71b..b69231918686 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -85,6 +85,9 @@ static const struct nlmsg_perm nlmsg_route_perms[] = { RTM_GETNEXTHOP, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_NEWLINKPROP, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_DELLINKPROP, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_NEWVLAN, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_DELVLAN, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, + { RTM_GETVLAN, NETLINK_ROUTE_SOCKET__NLMSG_READ }, }; static const struct nlmsg_perm nlmsg_tcpdiag_perms[] = @@ -168,7 +171,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) * structures at the top of this file with the new mappings * before updating the BUILD_BUG_ON() macro! */ - BUILD_BUG_ON(RTM_MAX != (RTM_NEWLINKPROP + 3)); + BUILD_BUG_ON(RTM_MAX != (RTM_NEWVLAN + 3)); err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms, sizeof(nlmsg_route_perms)); break; From patchwork Tue Jan 14 17:56:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222970 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=PCM5PXoV; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyr21jNtz9s4Y for ; Wed, 15 Jan 2020 04:58:42 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728874AbgANR6l (ORCPT ); Tue, 14 Jan 2020 12:58:41 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:39373 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727102AbgANR6h (ORCPT ); Tue, 14 Jan 2020 12:58:37 -0500 Received: by mail-lj1-f193.google.com with SMTP id l2so15360478lja.6 for ; Tue, 14 Jan 2020 09:58:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GqMStuk0JvHvzED0KA0S3hdX9UaNP460NhlyDnEu1VA=; b=PCM5PXoVjOPOlb0K13e3hqwHsFQeCrmKxDyPRhIxo/3ZvwAS9XmPB62iOfbYgcVImW 07dnIiVl1gJvi1L+TI8GifVRHZusqVyevtc9Qe3SznlPdyjmSayWeYORs+ni+tzql2eK ImfTcqwxyBvQvLbwbu3Jfjo0Xl7UO5qv1EnBQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GqMStuk0JvHvzED0KA0S3hdX9UaNP460NhlyDnEu1VA=; b=c2yIGQa9O2m4x3Zqt0aAeI2v8mzP8RQLk7guWLT4qnNwluIk76O3bKRtBpICvLOVW6 Xif4ylaHPruu4TtJaYunhkoi4iA2/wakXxMNooZJ9BCwoFUBChE8wN3yN4JI99jq6z5g MukEjhzU0AOqVKuJ9RK4UmU+pVzlEmRqYENZvI8jqJR9mKvKWWq6Hh2pxN9E4zm0ic8O ttV3SMEBy3JZ3uisdsP+hqvRCVq2BDNYXYhSnd3FECBHUcOLwY8bf2mvgKOu9dAC8tGT SHb3aPCqZSPLZsiWm3ogUTR8RHFfzzAX7/wBucwV9GmOlea9RKmA27CCxLzp5eh0nOW6 KAlw== X-Gm-Message-State: APjAAAU5tGjuFPP1HGK0Fgd0sMZsh9Jw5kpgsa10+d6/EnJ6JAkUfpZO ZiU5W3Q7r0wwscvr+GzarQZjsfGC8PU= X-Google-Smtp-Source: APXvYqzcun2+JVhRwLbbaUGDG8y2iY0xvkMXUyoqaBxle2ixbuRCd5eV2cc6YjRRwEcoT3JLl4B+OA== X-Received: by 2002:a2e:974b:: with SMTP id f11mr15485947ljj.173.1579024715467; Tue, 14 Jan 2020 09:58:35 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:34 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 4/8] net: bridge: vlan: add new rtm message support Date: Tue, 14 Jan 2020 19:56:10 +0200 Message-Id: <20200114175614.17543-5-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add initial RTM_NEWVLAN support which can only create vlans, operating similar to the current br_afspec(). We will use it later to also change per-vlan options. Old-style (flag-based) vlan ranges are not allowed when using RTM messages, we will introduce vlan ranges later via a new nested attribute which would allow us to have all the information about a range encapsulated into a single nl attribute. Signed-off-by: Nikolay Aleksandrov --- v2: use nlmsg_parse() for stricter message validation net/bridge/br_netlink.c | 12 ++--- net/bridge/br_private.h | 6 +++ net/bridge/br_vlan.c | 111 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 75a7ecf95d7f..b3da4f46dc64 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -561,12 +561,12 @@ static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p, return err; } -static int br_process_vlan_info(struct net_bridge *br, - struct net_bridge_port *p, int cmd, - struct bridge_vlan_info *vinfo_curr, - struct bridge_vlan_info **vinfo_last, - bool *changed, - struct netlink_ext_ack *extack) +int br_process_vlan_info(struct net_bridge *br, + struct net_bridge_port *p, int cmd, + struct bridge_vlan_info *vinfo_curr, + struct bridge_vlan_info **vinfo_last, + bool *changed, + struct netlink_ext_ack *extack) { if (!br_vlan_valid_id(vinfo_curr->vid, extack)) return -EINVAL; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1c00411ae938..ee3871dea68f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1237,6 +1237,12 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags, int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, u32 filter_mask, int nlflags); +int br_process_vlan_info(struct net_bridge *br, + struct net_bridge_port *p, int cmd, + struct bridge_vlan_info *vinfo_curr, + struct bridge_vlan_info **vinfo_last, + bool *changed, + struct netlink_ext_ack *extack); #ifdef CONFIG_SYSFS /* br_sysfs_if.c */ diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 5f2ac4f244f5..6da0210b01eb 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1643,13 +1643,124 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) return err; } +static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = { + [BRIDGE_VLANDB_ENTRY_INFO] = { .type = NLA_EXACT_LEN, + .len = sizeof(struct bridge_vlan_info) }, +}; + +static int br_vlan_rtm_process_one(struct net_device *dev, + const struct nlattr *attr, + int cmd, struct netlink_ext_ack *extack) +{ + struct bridge_vlan_info *vinfo, *vinfo_last = NULL; + struct nlattr *tb[BRIDGE_VLANDB_ENTRY_MAX + 1]; + struct net_bridge_vlan_group *vg; + struct net_bridge_port *p = NULL; + int err = 0, cmdmap = 0; + struct net_bridge *br; + bool changed = false; + + if (netif_is_bridge_master(dev)) { + br = netdev_priv(dev); + vg = br_vlan_group(br); + } else { + p = br_port_get_rtnl(dev); + if (WARN_ON(!p)) + return -ENODEV; + br = p->br; + vg = nbp_vlan_group(p); + } + + if (WARN_ON(!vg)) + return -ENODEV; + + err = nla_parse_nested(tb, BRIDGE_VLANDB_ENTRY_MAX, attr, + br_vlan_db_policy, extack); + if (err) + return err; + + if (!tb[BRIDGE_VLANDB_ENTRY_INFO]) { + NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry info"); + return -EINVAL; + } + + vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); + if (vinfo->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | + BRIDGE_VLAN_INFO_RANGE_END)) { + NL_SET_ERR_MSG_MOD(extack, "Old-style vlan ranges are not allowed when using RTM vlan calls"); + return -EINVAL; + } + if (!br_vlan_valid_id(vinfo->vid, extack)) + return -EINVAL; + + switch (cmd) { + case RTM_NEWVLAN: + cmdmap = RTM_SETLINK; + break; + } + + err = br_process_vlan_info(br, p, cmdmap, vinfo, &vinfo_last, &changed, + extack); + if (changed) + br_ifinfo_notify(cmdmap, br, p); + + return err; +} + +static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh, + struct netlink_ext_ack *extack) +{ + struct net *net = sock_net(skb->sk); + struct br_vlan_msg *bvm; + struct net_device *dev; + struct nlattr *attr; + int err, vlans = 0; + int rem; + + /* this should validate the header and check for remaining bytes */ + err = nlmsg_parse(nlh, sizeof(*bvm), NULL, BRIDGE_VLANDB_MAX, NULL, + extack); + if (err < 0) + return err; + + bvm = nlmsg_data(nlh); + dev = __dev_get_by_index(net, bvm->ifindex); + if (!dev) + return -ENODEV; + + if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) { + NL_SET_ERR_MSG_MOD(extack, "The device is not a valid bridge or bridge port"); + return -EINVAL; + } + + nlmsg_for_each_attr(attr, nlh, sizeof(*bvm), rem) { + if (nla_type(attr) != BRIDGE_VLANDB_ENTRY) + continue; + + vlans++; + err = br_vlan_rtm_process_one(dev, attr, nlh->nlmsg_type, + extack); + if (err) + break; + } + if (!vlans) { + NL_SET_ERR_MSG_MOD(extack, "No vlans found to process"); + err = -EINVAL; + } + + return err; +} + void br_vlan_rtnl_init(void) { rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL, br_vlan_rtm_dump, 0); + rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN, + br_vlan_rtm_process, NULL, 0); } void br_vlan_rtnl_uninit(void) { rtnl_unregister(PF_BRIDGE, RTM_GETVLAN); + rtnl_unregister(PF_BRIDGE, RTM_NEWVLAN); } From patchwork Tue Jan 14 17:56:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222968 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=Vu8D4RL6; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyr03hVVz9s4Y for ; Wed, 15 Jan 2020 04:58:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728783AbgANR6j (ORCPT ); Tue, 14 Jan 2020 12:58:39 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:35856 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728773AbgANR6i (ORCPT ); Tue, 14 Jan 2020 12:58:38 -0500 Received: by mail-lj1-f196.google.com with SMTP id r19so15403354ljg.3 for ; Tue, 14 Jan 2020 09:58:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=mr/2MNCOIx0U4K+Pv+vAm/4J6d5/EukzrdHaRzf8ia0=; b=Vu8D4RL6/Waqf9k5QySzdYA8kN/YYdxNE6u5TyyBc96Hjee7hyf456xV2xTRY9m22Y wfz0bVNsBE1FQ8o3LN8L+cpKDvGjCsA5xQBT9qt3s0ZxZq6N0Z8rW0KnR9s7/5Jvqn+T au4rW07YhX9WcRcX9CXKtj7KbrNrcHs2Wh6Zk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mr/2MNCOIx0U4K+Pv+vAm/4J6d5/EukzrdHaRzf8ia0=; b=OjTTMHiqKkqdLCQfGolnmZOfW0e0Fgz0+IsVH5XP50Tm9K50EC0Qy2zHgbGrqt5zWz ylj6IlpuhWA4ipj9whuvUAyrJp0YmryMIOBQPuJzcTvS9TGsUByba9dRg/riQc7ZW3+w mFcoQgOvUvYxnTP0u8IjEUYeMX+eS2bY2hAH6NPAbcepdWPbSu+EKroWMW/Sjiefel+u oX4VwIj+/wq5AyUTAB+/xdpqWKrbc92hYtMukMfsmdwaj7pBcAS2iilwqHdlDLf4gFso d28DZ2aSLxUq0kxnv+/IGAMP29snPp7KKAGVTjs9eqxRftJcJO8eG3QZoU5QBDBSC/d5 2x9w== X-Gm-Message-State: APjAAAUd/YUWM6wrX7vEVNhYtWlFF49HUcu1n+BcBdtJy0oNfsCfH6Ab MwkP0oDtuVWakB9JqpnspPS3kYNIL+U= X-Google-Smtp-Source: APXvYqwqISi5BeDV9j50traAdQe+aBO2Zh+s2xpanT8oNb1FJ8x8ZwAg01rwen2ob2lQSzoIR2YrmQ== X-Received: by 2002:a2e:a486:: with SMTP id h6mr15127964lji.235.1579024716978; Tue, 14 Jan 2020 09:58:36 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:36 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 5/8] net: bridge: vlan: add del rtm message support Date: Tue, 14 Jan 2020 19:56:11 +0200 Message-Id: <20200114175614.17543-6-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Adding RTM_DELVLAN support similar to RTM_NEWVLAN is simple, just need to map DELVLAN to DELLINK and register the handler. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_vlan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 6da0210b01eb..89d5fa75c575 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1697,6 +1697,9 @@ static int br_vlan_rtm_process_one(struct net_device *dev, case RTM_NEWVLAN: cmdmap = RTM_SETLINK; break; + case RTM_DELVLAN: + cmdmap = RTM_DELLINK; + break; } err = br_process_vlan_info(br, p, cmdmap, vinfo, &vinfo_last, &changed, @@ -1757,10 +1760,13 @@ void br_vlan_rtnl_init(void) br_vlan_rtm_dump, 0); rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN, br_vlan_rtm_process, NULL, 0); + rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_DELVLAN, + br_vlan_rtm_process, NULL, 0); } void br_vlan_rtnl_uninit(void) { rtnl_unregister(PF_BRIDGE, RTM_GETVLAN); rtnl_unregister(PF_BRIDGE, RTM_NEWVLAN); + rtnl_unregister(PF_BRIDGE, RTM_DELVLAN); } From patchwork Tue Jan 14 17:56:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222971 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=BWBF61zN; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyr56CHfz9s4Y for ; Wed, 15 Jan 2020 04:58:45 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728924AbgANR6p (ORCPT ); Tue, 14 Jan 2020 12:58:45 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:35018 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728819AbgANR6k (ORCPT ); Tue, 14 Jan 2020 12:58:40 -0500 Received: by mail-lj1-f194.google.com with SMTP id j1so15381129lja.2 for ; Tue, 14 Jan 2020 09:58:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8BMQUcIB7Lnmn69OkgAmX1lL2h6H6nNDHESX6ReQqnI=; b=BWBF61zNVrF1W7SVhJaNugw+asL/A/L5K/P18ECR22GxOYIXEz2VJuphbBjaWevd5p qm4oRNMyQu9odkiuXD9knylTNABPhsud9a//gkbN/sS9p/v94gWtAxdVG5PjAzpZzTEe K9GPxMHjeMR4Y5XyLevZXU/hGEOJmL/CO0Wpg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8BMQUcIB7Lnmn69OkgAmX1lL2h6H6nNDHESX6ReQqnI=; b=f5+7FkTBqzTI7zFzXjVzJtNBV6++KKtenBIk9Y6Fj9qmvm5hCZOlvm0xX+542rM0l5 v/9seOW5FZRFoHQ/I/82k1XH1akXEYsSv4XQRMDiCi5Nbk+2HfrM+k7EVVQYKJj21jU4 J0f8V9l85reYmT+Lb9gsj/sF6eCp7rbY51v/Eb8KVJm2BeylkhH/atdgd3jr/lyNZjhW muJ2Csk01XQZjD48zu662kXtr0uxhnKP6bK66GVsjwHNMpskCq06QWXqolF/Iys0t3Ma mHyXaZsoQd4CEHeZVfOh9S0oBCd9zh1Wlmr3Qgzgn7KbN59oIuVBot3wEA3UlU1rBGoY KrEg== X-Gm-Message-State: APjAAAXn4Afxi9u2rTjC9yoxL0bFDneD8rO6xXegL9aMMNvFn4TdDLl7 tEqmvkNGv1y0POnsDNWA/DYgZr+PYFg= X-Google-Smtp-Source: APXvYqxsyBk8PUWSROdQOIdydXpjEHpVszH5ULVaNHzxA9/FkOaaJpddZKGT/f1rZXerLzy2BvHgpg== X-Received: by 2002:a2e:81c7:: with SMTP id s7mr15546419ljg.3.1579024718361; Tue, 14 Jan 2020 09:58:38 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:37 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 6/8] net: bridge: vlan: add rtm range support Date: Tue, 14 Jan 2020 19:56:12 +0200 Message-Id: <20200114175614.17543-7-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a new vlandb nl attribute - BRIDGE_VLANDB_ENTRY_RANGE which causes RTM_NEWVLAN/DELVAN to act on a range. Dumps now automatically compress similar vlans into ranges. This will be also used when per-vlan options are introduced and vlans' options match, they will be put into a single range which is encapsulated in one netlink attribute. We need to run similar checks as br_process_vlan_info() does because these ranges will be used for options setting and they'll be able to skip br_process_vlan_info(). Signed-off-by: Nikolay Aleksandrov --- include/uapi/linux/if_bridge.h | 1 + net/bridge/br_vlan.c | 86 ++++++++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 4da04f77d9ee..ac38f0b674b8 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -189,6 +189,7 @@ enum { enum { BRIDGE_VLANDB_ENTRY_UNSPEC, BRIDGE_VLANDB_ENTRY_INFO, + BRIDGE_VLANDB_ENTRY_RANGE, __BRIDGE_VLANDB_ENTRY_MAX, }; #define BRIDGE_VLANDB_ENTRY_MAX (__BRIDGE_VLANDB_ENTRY_MAX - 1) diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 89d5fa75c575..9d64a86f2cbd 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1506,7 +1506,8 @@ void br_vlan_port_event(struct net_bridge_port *p, unsigned long event) } } -static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 flags) +static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range, + u16 flags) { struct bridge_vlan_info info; struct nlattr *nest; @@ -1525,6 +1526,11 @@ static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 flags) if (nla_put(skb, BRIDGE_VLANDB_ENTRY_INFO, sizeof(info), &info)) goto out_err; + if (vid_range && vid < vid_range && + !(flags & BRIDGE_VLAN_INFO_PVID) && + nla_put_u16(skb, BRIDGE_VLANDB_ENTRY_RANGE, vid_range)) + goto out_err; + nla_nest_end(skb, nest); return true; @@ -1534,14 +1540,22 @@ static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 flags) return false; } +/* check if v_curr can enter a range ending in range_end */ +static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, + const struct net_bridge_vlan *range_end) +{ + return v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags; +} + static int br_vlan_dump_dev(const struct net_device *dev, struct sk_buff *skb, struct netlink_callback *cb) { + struct net_bridge_vlan *v, *range_start = NULL, *range_end = NULL; struct net_bridge_vlan_group *vg; int idx = 0, s_idx = cb->args[1]; struct nlmsghdr *nlh = NULL; - struct net_bridge_vlan *v; struct net_bridge_port *p; struct br_vlan_msg *bvm; struct net_bridge *br; @@ -1576,22 +1590,49 @@ static int br_vlan_dump_dev(const struct net_device *dev, bvm->ifindex = dev->ifindex; pvid = br_get_pvid(vg); + /* idx must stay at range's beginning until it is filled in */ list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { if (!br_vlan_should_use(v)) continue; - if (idx < s_idx) - goto skip; - if (!br_vlan_fill_vids(skb, v->vid, br_vlan_flags(v, pvid))) { - err = -EMSGSIZE; - break; + if (idx < s_idx) { + idx++; + continue; } -skip: - idx++; + + if (!range_start) { + range_start = v; + range_end = v; + continue; + } + + if (v->vid == pvid || !br_vlan_can_enter_range(v, range_end)) { + u16 flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, + range_end->vid, flags)) { + err = -EMSGSIZE; + break; + } + /* advance number of filled vlans */ + idx += range_end->vid - range_start->vid + 1; + + range_start = v; + } + range_end = v; } - if (err) - cb->args[1] = idx; - else - cb->args[1] = 0; + + /* err will be 0 and range_start will be set in 3 cases here: + * - first vlan (range_start == range_end) + * - last vlan (range_start == range_end, not in range) + * - last vlan range (range_start != range_end, in range) + */ + if (!err && range_start && + !br_vlan_fill_vids(skb, range_start->vid, range_end->vid, + br_vlan_flags(range_start, pvid))) + err = -EMSGSIZE; + + cb->args[1] = err ? idx : 0; + nlmsg_end(skb, nlh); return err; @@ -1646,13 +1687,14 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = { [BRIDGE_VLANDB_ENTRY_INFO] = { .type = NLA_EXACT_LEN, .len = sizeof(struct bridge_vlan_info) }, + [BRIDGE_VLANDB_ENTRY_RANGE] = { .type = NLA_U16 }, }; static int br_vlan_rtm_process_one(struct net_device *dev, const struct nlattr *attr, int cmd, struct netlink_ext_ack *extack) { - struct bridge_vlan_info *vinfo, *vinfo_last = NULL; + struct bridge_vlan_info *vinfo, vrange_end, *vinfo_last = NULL; struct nlattr *tb[BRIDGE_VLANDB_ENTRY_MAX + 1]; struct net_bridge_vlan_group *vg; struct net_bridge_port *p = NULL; @@ -1683,6 +1725,7 @@ static int br_vlan_rtm_process_one(struct net_device *dev, NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry info"); return -EINVAL; } + memset(&vrange_end, 0, sizeof(vrange_end)); vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); if (vinfo->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | @@ -1693,6 +1736,21 @@ static int br_vlan_rtm_process_one(struct net_device *dev, if (!br_vlan_valid_id(vinfo->vid, extack)) return -EINVAL; + if (tb[BRIDGE_VLANDB_ENTRY_RANGE]) { + vrange_end.vid = nla_get_u16(tb[BRIDGE_VLANDB_ENTRY_RANGE]); + /* validate user-provided flags without RANGE_BEGIN */ + vrange_end.flags = BRIDGE_VLAN_INFO_RANGE_END | vinfo->flags; + vinfo->flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN; + + /* vinfo_last is the range start, vinfo the range end */ + vinfo_last = vinfo; + vinfo = &vrange_end; + + if (!br_vlan_valid_id(vinfo->vid, extack) || + !br_vlan_valid_range(vinfo, vinfo_last, extack)) + return -EINVAL; + } + switch (cmd) { case RTM_NEWVLAN: cmdmap = RTM_SETLINK; From patchwork Tue Jan 14 17:56:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222973 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=bJp7qUl8; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyr76l2vz9sR1 for ; Wed, 15 Jan 2020 04:58:47 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728896AbgANR6o (ORCPT ); Tue, 14 Jan 2020 12:58:44 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:39551 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728871AbgANR6m (ORCPT ); Tue, 14 Jan 2020 12:58:42 -0500 Received: by mail-lf1-f67.google.com with SMTP id y1so10521181lfb.6 for ; Tue, 14 Jan 2020 09:58:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aG98qbZFp+XXJpRjorp7YR3pzH22ohcg5CirRKfi8t0=; b=bJp7qUl88B0117YTOUhm2lK9o/3P5JvmVRp20k0MfRuUPONci8CEDcPyJ83HOdGzc5 cw+QggDJ8uo9WY5rSZVZXNyQHf/pZnq2oSkdqlJNp7KwyzG/H1HL62KEkojB/P4Fr1YD XRo2sxBEt8OxYwtHiZksiqePfeRn5R3MpejEI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aG98qbZFp+XXJpRjorp7YR3pzH22ohcg5CirRKfi8t0=; b=tjyKmE6GRee2r2q8N6aNjXUmYabDbwlIGEPfYqqxy5I5ELLhLe47fi/J+loGqalCIz t/G16VLKBsRMTmjLUbdE9RPlf0wB9azf58iKCQs9c3QXNPz73B9EwLQMkQS8aNSpLCs2 315yR7GfHhzK+l801z595xu44Us+iiGaBAZBLwZ1Yof5Zqyy97UzxSeq4y6IbMlihhrY 8IakpMtAa8zLRbqfF4cGcKq5dhwcqfH/Bhr7ChqK8qivQ+bRruVtR5BJZibiqqWkCiQ8 BNeVPZQ1FsjS7+8rM34PG3G6iWvRKvSTm0qV8xVvjmY5kp5KoaPtsmufPGjzZqyOEhy2 vSjQ== X-Gm-Message-State: APjAAAV9IpsX/dtjuwfX2WFzl1M3DzClyRw7KH+IX2u9tkPS5sDmwMoz +s4lkMp81i5AesR/JnR1DorL9m9hKpQ= X-Google-Smtp-Source: APXvYqxkiZ7glj4+BR4FH0+C+DW55C6Jd4OABC8uI8zNP9IzsUCOYgauRHOjFAzKvlMVIjX9VirQ/g== X-Received: by 2002:ac2:5195:: with SMTP id u21mr2464396lfi.141.1579024719599; Tue, 14 Jan 2020 09:58:39 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:39 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 7/8] net: bridge: vlan: add rtnetlink group and notify support Date: Tue, 14 Jan 2020 19:56:13 +0200 Message-Id: <20200114175614.17543-8-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a new rtnetlink group for bridge vlan notifications - RTNLGRP_BRVLAN and add support for sending vlan notifications (both single and ranges). No functional changes intended, the notification support will be used by later patches. Signed-off-by: Nikolay Aleksandrov --- include/uapi/linux/rtnetlink.h | 2 + net/bridge/br_private.h | 11 +++++ net/bridge/br_vlan.c | 79 ++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index e06e3e09a1b4..fe9136f87a97 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -728,6 +728,8 @@ enum rtnetlink_groups { #define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R RTNLGRP_NEXTHOP, #define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP + RTNLGRP_BRVLAN, +#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index ee3871dea68f..ba162c8197da 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -960,6 +960,10 @@ int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr); void br_vlan_rtnl_init(void); void br_vlan_rtnl_uninit(void); +void br_vlan_notify(const struct net_bridge *br, + const struct net_bridge_port *p, + u16 vid, u16 vid_range, + int cmd); static inline struct net_bridge_vlan_group *br_vlan_group( const struct net_bridge *br) @@ -1166,6 +1170,13 @@ static inline void br_vlan_rtnl_init(void) static inline void br_vlan_rtnl_uninit(void) { } + +static inline void br_vlan_notify(const struct net_bridge *br, + const struct net_bridge_port *p, + u16 vid, u16 vid_range, + int cmd) +{ +} #endif struct nf_br_ops { diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 9d64a86f2cbd..5d52a2604547 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1540,6 +1540,85 @@ static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range, return false; } +static size_t rtnl_vlan_nlmsg_size(void) +{ + return NLMSG_ALIGN(sizeof(struct br_vlan_msg)) + + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY */ + + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_ENTRY_RANGE */ + + nla_total_size(sizeof(struct bridge_vlan_info)); /* BRIDGE_VLANDB_ENTRY_INFO */ +} + +void br_vlan_notify(const struct net_bridge *br, + const struct net_bridge_port *p, + u16 vid, u16 vid_range, + int cmd) +{ + struct net_bridge_vlan_group *vg; + struct net_bridge_vlan *v; + struct br_vlan_msg *bvm; + struct nlmsghdr *nlh; + struct sk_buff *skb; + int err = -ENOBUFS; + struct net *net; + u16 flags = 0; + int ifindex; + + /* right now notifications are done only with rtnl held */ + ASSERT_RTNL(); + + if (p) { + ifindex = p->dev->ifindex; + vg = nbp_vlan_group(p); + net = dev_net(p->dev); + } else { + ifindex = br->dev->ifindex; + vg = br_vlan_group(br); + net = dev_net(br->dev); + } + + skb = nlmsg_new(rtnl_vlan_nlmsg_size(), GFP_KERNEL); + if (!skb) + goto out_err; + + err = -EMSGSIZE; + nlh = nlmsg_put(skb, 0, 0, cmd, sizeof(*bvm), 0); + if (!nlh) + goto out_err; + bvm = nlmsg_data(nlh); + memset(bvm, 0, sizeof(*bvm)); + bvm->family = AF_BRIDGE; + bvm->ifindex = ifindex; + + switch (cmd) { + case RTM_NEWVLAN: + /* need to find the vlan due to flags/options */ + v = br_vlan_find(vg, vid); + if (!v || !br_vlan_should_use(v)) + goto out_kfree; + + flags = v->flags; + if (br_get_pvid(vg) == v->vid) + flags |= BRIDGE_VLAN_INFO_PVID; + break; + case RTM_DELVLAN: + break; + default: + goto out_kfree; + } + + if (!br_vlan_fill_vids(skb, vid, vid_range, flags)) + goto out_err; + + nlmsg_end(skb, nlh); + rtnl_notify(skb, net, 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL); + return; + +out_err: + rtnl_set_sk_err(net, RTNLGRP_BRVLAN, err); +out_kfree: + kfree_skb(skb); +} + /* check if v_curr can enter a range ending in range_end */ static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, const struct net_bridge_vlan *range_end) From patchwork Tue Jan 14 17:56:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222972 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) 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=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=FQ077hZM; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xyr706Wkz9sR0 for ; Wed, 15 Jan 2020 04:58:46 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728915AbgANR6o (ORCPT ); Tue, 14 Jan 2020 12:58:44 -0500 Received: from mail-lf1-f66.google.com ([209.85.167.66]:43889 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727102AbgANR6n (ORCPT ); Tue, 14 Jan 2020 12:58:43 -0500 Received: by mail-lf1-f66.google.com with SMTP id 9so10527013lfq.10 for ; Tue, 14 Jan 2020 09:58:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FWYTVpZfR9DeO9mhcxQotDiLyUkY/G8GeLC7Qd8RLcw=; b=FQ077hZMDT9/eY6cLgl6VrrPzP8Uj6Xidkye+rth/pnKSHPzVfVJBMz4IaSoXjP5Nb 2uxbou2FYeP2n+XdVrVXfyHk8TFTlI4584EDWxix0wEJcpWI21y9pFpcpTGd90lXQbFE bBOkY6+w9p0zIlcirwuuKOoueG292kaHuNU68= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FWYTVpZfR9DeO9mhcxQotDiLyUkY/G8GeLC7Qd8RLcw=; b=iTXJp5PSRV0g9BCufOTypo0X8NHrL127Qys+NbMvUoDLXERQpleBrKiqcGV653740W 1zvgVNdA0YaiOk4L38yb6+gW+KG0JEgZXocEDkto+pBpgiakic01beUkgkfH70vaqrYY xAhReWCAQSBB83AwAAyiMlfKQ8Ei0WcMmeGi9h0IESO/7eHMGLqTwBetXskkHpf4rfvl XsVRl9NlPM9qUelnCYppHI7EYi0PgX89aM883CrlVeORw0iMAFD/W8Z65N3kmXi1EN7t QadcC0jIx4p4OXzfFl9PVCPoevblqFucRxcfAWQ9XyHZ1Ykq7xAZPunJzmP9F+EekbvF 5pcw== X-Gm-Message-State: APjAAAUkfauHtDk1dhpj9eSoTecIRT+Ai0mkRy02uf2ZQClJJ4J9E+cK A/cGP0JcGB2zsLLPg4YVaJCF1AT7+nQ= X-Google-Smtp-Source: APXvYqwDQwpp7Eyw90LIKrK7nKSLZ1kJgwf9ltZE61c5bZ7XKr/Frp8k+ngO+jBeTjERdv03xfy+pw== X-Received: by 2002:a19:710a:: with SMTP id m10mr2480790lfc.58.1579024720968; Tue, 14 Jan 2020 09:58:40 -0800 (PST) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id a15sm7685655lfi.60.2020.01.14.09.58.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2020 09:58:40 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, kuba@kernel.org, bridge@lists.linux-foundation.org, dsahern@gmail.com, Nikolay Aleksandrov Subject: [PATCH net-next v2 8/8] net: bridge: vlan: notify on vlan add/delete/change flags Date: Tue, 14 Jan 2020 19:56:14 +0200 Message-Id: <20200114175614.17543-9-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200114175614.17543-1-nikolay@cumulusnetworks.com> References: <20200114175614.17543-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Now that we can notify, send a notification on add/del or change of flags. Notifications are also compressed when possible to reduce their number and relieve user-space of extra processing, due to that we have to manually notify after each add/del in order to avoid double notifications. We try hard to notify only about the vlans which actually changed, thus a single command can result in multiple notifications about disjoint ranges if there were vlans which didn't change inside. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_netlink.c | 34 ++++++++++++++++++-- net/bridge/br_private.h | 12 +++++++ net/bridge/br_vlan.c | 71 ++++++++++++++++++++++++++++++++--------- 3 files changed, 99 insertions(+), 18 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index b3da4f46dc64..43dab4066f91 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -568,9 +568,14 @@ int br_process_vlan_info(struct net_bridge *br, bool *changed, struct netlink_ext_ack *extack) { + int err, rtm_cmd; + if (!br_vlan_valid_id(vinfo_curr->vid, extack)) return -EINVAL; + /* needed for vlan-only NEWVLAN/DELVLAN notifications */ + rtm_cmd = br_afspec_cmd_to_rtm(cmd); + if (vinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) { if (!br_vlan_valid_range(vinfo_curr, *vinfo_last, extack)) return -EINVAL; @@ -580,7 +585,7 @@ int br_process_vlan_info(struct net_bridge *br, if (*vinfo_last) { struct bridge_vlan_info tmp_vinfo; - int v, err; + int v, v_change_start = 0; if (!br_vlan_valid_range(vinfo_curr, *vinfo_last, extack)) return -EINVAL; @@ -588,18 +593,41 @@ int br_process_vlan_info(struct net_bridge *br, memcpy(&tmp_vinfo, *vinfo_last, sizeof(struct bridge_vlan_info)); for (v = (*vinfo_last)->vid; v <= vinfo_curr->vid; v++) { + bool curr_change = false; + tmp_vinfo.vid = v; - err = br_vlan_info(br, p, cmd, &tmp_vinfo, changed, + err = br_vlan_info(br, p, cmd, &tmp_vinfo, &curr_change, extack); if (err) break; + if (curr_change) { + *changed = curr_change; + if (!v_change_start) + v_change_start = v; + } else { + /* nothing to notify yet */ + if (!v_change_start) + continue; + br_vlan_notify(br, p, v_change_start, + v - 1, rtm_cmd); + v_change_start = 0; + } } + /* v_change_start is set only if the last/whole range changed */ + if (v_change_start) + br_vlan_notify(br, p, v_change_start, + v - 1, rtm_cmd); + *vinfo_last = NULL; return err; } - return br_vlan_info(br, p, cmd, vinfo_curr, changed, extack); + err = br_vlan_info(br, p, cmd, vinfo_curr, changed, extack); + if (*changed) + br_vlan_notify(br, p, vinfo_curr->vid, 0, rtm_cmd); + + return err; } static int br_afspec(struct net_bridge *br, diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index ba162c8197da..a6226ff2f0cc 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -554,6 +554,18 @@ static inline bool br_vlan_valid_range(const struct bridge_vlan_info *cur, return true; } +static inline int br_afspec_cmd_to_rtm(int cmd) +{ + switch (cmd) { + case RTM_SETLINK: + return RTM_NEWVLAN; + case RTM_DELLINK: + return RTM_DELVLAN; + } + + return 0; +} + static inline int br_opt_get(const struct net_bridge *br, enum net_bridge_opts opt) { diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 5d52a2604547..e4f7dd10c3f8 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -257,6 +257,10 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags, &changed, extack); if (err) goto out_filt; + + if (changed) + br_vlan_notify(br, NULL, v->vid, 0, + RTM_NEWVLAN); } masterv = br_vlan_get_master(br, v->vid, extack); @@ -380,13 +384,31 @@ static void __vlan_group_free(struct net_bridge_vlan_group *vg) kfree(vg); } -static void __vlan_flush(struct net_bridge_vlan_group *vg) +static void __vlan_flush(const struct net_bridge *br, + const struct net_bridge_port *p, + struct net_bridge_vlan_group *vg) { struct net_bridge_vlan *vlan, *tmp; + u16 v_start = 0, v_end = 0; __vlan_delete_pvid(vg, vg->pvid); - list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) + list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) { + /* take care of disjoint ranges */ + if (!v_start) { + v_start = vlan->vid; + } else if (vlan->vid - v_end != 1) { + /* found range end, notify and start next one */ + br_vlan_notify(br, p, v_start, v_end, RTM_DELVLAN); + v_start = vlan->vid; + } + v_end = vlan->vid; + __vlan_del(vlan); + } + + /* notify about the last/whole vlan range */ + if (v_start) + br_vlan_notify(br, p, v_start, v_end, RTM_DELVLAN); } struct sk_buff *br_handle_vlan(struct net_bridge *br, @@ -716,7 +738,7 @@ void br_vlan_flush(struct net_bridge *br) ASSERT_RTNL(); vg = br_vlan_group(br); - __vlan_flush(vg); + __vlan_flush(br, NULL, vg); RCU_INIT_POINTER(br->vlgrp, NULL); synchronize_rcu(); __vlan_group_free(vg); @@ -925,12 +947,15 @@ static void br_vlan_disable_default_pvid(struct net_bridge *br) /* Disable default_pvid on all ports where it is still * configured. */ - if (vlan_default_pvid(br_vlan_group(br), pvid)) - br_vlan_delete(br, pvid); + if (vlan_default_pvid(br_vlan_group(br), pvid)) { + if (!br_vlan_delete(br, pvid)) + br_vlan_notify(br, NULL, pvid, 0, RTM_DELVLAN); + } list_for_each_entry(p, &br->port_list, list) { - if (vlan_default_pvid(nbp_vlan_group(p), pvid)) - nbp_vlan_delete(p, pvid); + if (vlan_default_pvid(nbp_vlan_group(p), pvid) && + !nbp_vlan_delete(p, pvid)) + br_vlan_notify(br, p, pvid, 0, RTM_DELVLAN); } br->default_pvid = 0; @@ -972,7 +997,10 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, &vlchange, extack); if (err) goto out; - br_vlan_delete(br, old_pvid); + + if (br_vlan_delete(br, old_pvid)) + br_vlan_notify(br, NULL, old_pvid, 0, RTM_DELVLAN); + br_vlan_notify(br, NULL, pvid, 0, RTM_NEWVLAN); set_bit(0, changed); } @@ -992,7 +1020,9 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, &vlchange, extack); if (err) goto err_port; - nbp_vlan_delete(p, old_pvid); + if (nbp_vlan_delete(p, old_pvid)) + br_vlan_notify(br, p, old_pvid, 0, RTM_DELVLAN); + br_vlan_notify(p->br, p, pvid, 0, RTM_NEWVLAN); set_bit(p->port_no, changed); } @@ -1007,22 +1037,28 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, if (!test_bit(p->port_no, changed)) continue; - if (old_pvid) + if (old_pvid) { nbp_vlan_add(p, old_pvid, BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED, &vlchange, NULL); + br_vlan_notify(p->br, p, old_pvid, 0, RTM_NEWVLAN); + } nbp_vlan_delete(p, pvid); + br_vlan_notify(br, p, pvid, 0, RTM_DELVLAN); } if (test_bit(0, changed)) { - if (old_pvid) + if (old_pvid) { br_vlan_add(br, old_pvid, BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED | BRIDGE_VLAN_INFO_BRENTRY, &vlchange, NULL); + br_vlan_notify(br, NULL, old_pvid, 0, RTM_NEWVLAN); + } br_vlan_delete(br, pvid); + br_vlan_notify(br, NULL, pvid, 0, RTM_DELVLAN); } goto out; } @@ -1115,6 +1151,7 @@ int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack) &changed, extack); if (ret) goto err_vlan_add; + br_vlan_notify(p->br, p, p->br->default_pvid, 0, RTM_NEWVLAN); } out: return ret; @@ -1196,7 +1233,7 @@ void nbp_vlan_flush(struct net_bridge_port *port) ASSERT_RTNL(); vg = nbp_vlan_group(port); - __vlan_flush(vg); + __vlan_flush(port->br, port, vg); RCU_INIT_POINTER(port->vlgrp, NULL); synchronize_rcu(); __vlan_group_free(vg); @@ -1462,8 +1499,8 @@ int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr) { struct netdev_notifier_changeupper_info *info; struct net_bridge *br = netdev_priv(dev); - bool changed; - int ret = 0; + int vlcmd = 0, ret = 0; + bool changed = false; switch (event) { case NETDEV_REGISTER: @@ -1471,9 +1508,11 @@ int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr) BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED | BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL); + vlcmd = RTM_NEWVLAN; break; case NETDEV_UNREGISTER: - br_vlan_delete(br, br->default_pvid); + changed = !br_vlan_delete(br, br->default_pvid); + vlcmd = RTM_DELVLAN; break; case NETDEV_CHANGEUPPER: info = ptr; @@ -1487,6 +1526,8 @@ int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr) br_vlan_link_state_change(dev, br); break; } + if (changed) + br_vlan_notify(br, NULL, br->default_pvid, 0, vlcmd); return ret; }