From patchwork Mon Jan 13 15:52:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222186 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=EU4bgx6u; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5Z6tH9z9sQp for ; Tue, 14 Jan 2020 02:53:06 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728769AbgAMPxG (ORCPT ); Mon, 13 Jan 2020 10:53:06 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:40717 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726567AbgAMPxF (ORCPT ); Mon, 13 Jan 2020 10:53:05 -0500 Received: by mail-lj1-f194.google.com with SMTP id u1so10643563ljk.7 for ; Mon, 13 Jan 2020 07:53:04 -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=EU4bgx6u3way6NIjZxOKnjaxf5SMcZiKh9iSgZ5u9/HIZCReVaZuyG69vKvYSBobDb Nsx/vpkTqKnICdEWR9BlIpGxlST3LRbGo1z1E+ytuGEFM4n/Wf2sz0OJjsEb5MQUJwbS ynrIClQV+ZYNfFgSemAMwnqXgIPTukyJbrVJI= 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=GIEqtJkbuoD1DjrO25JN8hwChi7y+zdsBRs8yDYT0mIgm4J75qnFWuJKkc+Rdqvl0p jQqir6jtReSt9A+iP3zMJm9CrWk1S4XzXeCnT51LzdW1DaiWRZRPZAeCwweGCgezoaNO RWUjotRqjWhK0gLiggYF4BcKob7ZCg2NYaAwTQcyP6Zh2q/LWRr8ZDJmaBL8swJ+FyBj U/7qCLgORX86ZGqOMZaXN5Y93j9MjqxxdBkCYEmU4VKgHG70aDpqhl1JECU8Zk7pMmlH qMDA+0j/VBN7ghGZtRRLQ2ITUuzUZbe1sIMsIurXgWYQ8YNIe8YAiABAJXkkX5aX5lQw H26A== X-Gm-Message-State: APjAAAVrvcCpirJGtSKFkn4Dp80qfYT4MpSJTtMQoU9Unph5Cyq40Hpj OBXmidSi9uxApmszDeFCT3byASJCZIU= X-Google-Smtp-Source: APXvYqwkJWoH9wyx/Px9XxfQjuyYN60dv/K4oOZrE8L7SAezrGIqb8W8QhGyYt389PhEKdCNn5mQoQ== X-Received: by 2002:a2e:721a:: with SMTP id n26mr11317377ljc.128.1578930782863; Mon, 13 Jan 2020 07:53:02 -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 e20sm6175658ljl.59.2020.01.13.07.53.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:02 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 1/8] net: bridge: vlan: add helpers to check for vlan id/range validity Date: Mon, 13 Jan 2020 17:52:26 +0200 Message-Id: <20200113155233.20771-2-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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 Mon Jan 13 15:52:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222187 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=JJyBw1Bd; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5d6rTjz9sQp for ; Tue, 14 Jan 2020 02:53:09 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728787AbgAMPxJ (ORCPT ); Mon, 13 Jan 2020 10:53:09 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:38732 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728734AbgAMPxH (ORCPT ); Mon, 13 Jan 2020 10:53:07 -0500 Received: by mail-lj1-f193.google.com with SMTP id w1so10652139ljh.5 for ; Mon, 13 Jan 2020 07:53:06 -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=JJyBw1Bdfdn/DXRctvYndAg0AuUSmUbCaylTOhEiNjsqQ4f8/QE2UFY4NwHHcEoUer PxkGvdOOeAZjIRYdL5wT/4tn7JNvJXR+mR85wrex6ZvWA0Q+luITCfvZer6p8kb4tklp Ol0ihmY5HpDqO4oyPFKgU4aK/H0vKrHxvdeXE= 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=nc9Tkww9mfzdcvZFjpKJjTk6RgLVzULii1K6n7PVndJufdCUAyNrNC+p6Z/fMN8uo4 maFT6YPjYLx1a4gTaKQv+jMSdab+l8jpZgxk3UvO3TNTssnVhpFgcTKXKvpi1I9/IQqX hhTIPBHBNWmzjzVFn+JBdLL7itM96dYfDy5Et+qQU0664tJd0xZE64aMDBQNFFPs1kU0 7UQU1WZ/c1o0VmaVMWgX3fwr5E14RPoSQM9bXblpc/TcxAmeCCLTRV811DQs05wkCsBQ cFm59eRVZ7i5VYGfOU5Bh+2aVWAMdMGoRzsJum6N16iPB4qbFBf+0SnF5aDEso2jx8GD 1N/g== X-Gm-Message-State: APjAAAU33nGaq8wPoBok35tCaJ510W8a3L+BDVX0B/lBfLzJBu5DjSMY WKInPno8yy51LelZKLI27+D7iH8gi9A= X-Google-Smtp-Source: APXvYqxceAKLZyUuArHDU7dwD9jiViqFCLrqjxbUGKI+t/EoK6oZ93obLx70UWxUHq4SQzZdAUvS7A== X-Received: by 2002:a2e:8512:: with SMTP id j18mr9188451lji.269.1578930784874; Mon, 13 Jan 2020 07:53:04 -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 e20sm6175658ljl.59.2020.01.13.07.53.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:03 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 2/8] net: bridge: netlink: add extack error messages when processing vlans Date: Mon, 13 Jan 2020 17:52:27 +0200 Message-Id: <20200113155233.20771-3-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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 Mon Jan 13 15:52:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222188 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=FuduCArA; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5h4wvrz9sP6 for ; Tue, 14 Jan 2020 02:53:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728800AbgAMPxL (ORCPT ); Mon, 13 Jan 2020 10:53:11 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:45584 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726567AbgAMPxJ (ORCPT ); Mon, 13 Jan 2020 10:53:09 -0500 Received: by mail-lf1-f67.google.com with SMTP id 203so7201803lfa.12 for ; Mon, 13 Jan 2020 07:53:08 -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=6KhiteAq58/yJLkVm+s0FO5WRg6fiYggtvqwfk58QqA=; b=FuduCArAbwO3Fht2xwe51gZ42JgFlhOhcvXjfB179mM4/qmRlVBygb8HsPoED3U5X5 fLmFItFEExmztMf2ph1NQUbMMjel9nae3R8GrIjnNgY1KwQayttpEk/8SjOaXtEfjIzu B+AW+335auSvRZS5XKh0KDWzWs8oTzHBoC7xU= 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=6KhiteAq58/yJLkVm+s0FO5WRg6fiYggtvqwfk58QqA=; b=qKsJOUBboeYudIQYUq8T8yY9puPqjU3GUifl2cwIJjV0ahh7UsTJyrJ341SFmAWi+9 wGTR/QJhVF7xLgCQrgpWnJXx1AHPJgchY2Hl3jd09RhKq6YEgBcfhpOHZQaP8rZL3RuU X6VhDzEk3VrltdeevFKVEmHI1jjM9mCLi+ikkFcaC4nSqjWYFLgNoyw6bWPEXSApW9rO YRW7R5nS85L4nbyeLERDnXAxu/61kulVFtq7psA9XyAJj1JyRU9brvqDQK6jHoIWmMzi inf4ALMlHrhWRsP6lqEQ9PutAw4zHhAHbWwxDW0PWXGviCN5j5Qpm5ehaGHpbkLF4kOz B7Ug== X-Gm-Message-State: APjAAAVg7Y5vygyu0i9ioj84z0PsTKyAo4EDL3uxYTrbTDidU2tyF8H1 MbFJQjfaKwzBhkaZFxmiWcsuPbpJ74c= X-Google-Smtp-Source: APXvYqyQMFI/EkaKTQ4vad7pvPeuhtEpxuLsSujVWQ8mZ0IgEfDd1GoG7Np1g1aK7dL7woK4oIAvMA== X-Received: by 2002:a19:4901:: with SMTP id w1mr9886397lfa.168.1578930787026; Mon, 13 Jan 2020 07:53:07 -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 e20sm6175658ljl.59.2020.01.13.07.53.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:06 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 3/8] net: bridge: vlan: add rtm definitions and dump support Date: Mon, 13 Jan 2020 17:52:28 +0200 Message-Id: <20200113155233.20771-4-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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). Signed-off-by: Nikolay Aleksandrov --- 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 | 149 +++++++++++++++++++++++++++++++++ security/selinux/nlmsgtab.c | 5 +- 6 files changed, 204 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..0135a67f50a7 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1505,3 +1505,152 @@ 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; + + if (cb->nlh->nlmsg_len < nlmsg_msg_size(sizeof(*bvm))) { + NL_SET_ERR_MSG_MOD(cb->extack, "Invalid header for vlan dump request"); + return -EINVAL; + } + + 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 Mon Jan 13 15:52:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222189 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=L4iZokOI; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5j6fLYz9sP6 for ; Tue, 14 Jan 2020 02:53:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728811AbgAMPxM (ORCPT ); Mon, 13 Jan 2020 10:53:12 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:39429 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728734AbgAMPxL (ORCPT ); Mon, 13 Jan 2020 10:53:11 -0500 Received: by mail-lf1-f67.google.com with SMTP id y1so7215005lfb.6 for ; Mon, 13 Jan 2020 07:53:10 -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=f+/2GADqMNtpYIwPAKPmBkOi5mwefLPM9Y7jtBr04oE=; b=L4iZokOIOSXwxmnN6jVX9IV9GMnghMUoX4vh5ITbgwx+qUBy9EF3X//ad3TIiurn4f c8T3M2E7xRVwBa1irhFnyEwsEsYUnMFMepcyX9twpBPUBWHki1L5qY/xUEuOHq7h0ass 5TpYgX36SwZTmtfZOri385qE7cSrR8VDLfZWo= 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=f+/2GADqMNtpYIwPAKPmBkOi5mwefLPM9Y7jtBr04oE=; b=hclengAzkA3KAJifbaZZctiyegNWHpN/ACXkSvE/27lDU21LFLUf20zbDsS+vG62Mp kwwI8cmfslXqCg5Mht5+RHwmEXEKheRxvxII/onSW0uzJ6GfvGHaen6I3w1f/L6SHT4Y fTJLdfXJcccy6zuuHO4D5xKZIY5KE4PLTCyyKSm4wmnHpXhqx22/5e+pAI6/usN0dtv3 MP8W2qgMBUVNtjmYPmfhYCEebk8O0akyval5/KjnomPWX0l4swJer+mIWRwVfaHXy3UF rD2FSzZc7XxnfSLptfB1AnyF28pM9eenNIDJJm7xmIqkp4AnkGauSJ/skouINogpMBGb IirQ== X-Gm-Message-State: APjAAAUZNMaCl27vOB6L5Eyun/PmP0CwVBvWNinVbFQDoDaNXPNuQBU3 QBQZ4LFNrkAbxQBXwjZItN6JS4VHXm0= X-Google-Smtp-Source: APXvYqxf66P/v7i0OmfrBXWB6Q1LJbJyK6feyMc3E9+/lgivKZT4XWoyRCglKZrSPo/lodBoVCecTA== X-Received: by 2002:ac2:44d9:: with SMTP id d25mr10114606lfm.15.1578930788936; Mon, 13 Jan 2020 07:53:08 -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 e20sm6175658ljl.59.2020.01.13.07.53.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:08 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 4/8] net: bridge: vlan: add new rtm message support Date: Mon, 13 Jan 2020 17:52:29 +0200 Message-Id: <20200113155233.20771-5-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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 --- net/bridge/br_netlink.c | 12 ++--- net/bridge/br_private.h | 6 +++ net/bridge/br_vlan.c | 110 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 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 0135a67f50a7..b8f52a7616c4 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1644,13 +1644,123 @@ 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); + int err = -EINVAL, vlans = 0; + struct br_vlan_msg *bvm; + struct net_device *dev; + struct nlattr *attr; + int rem; + + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*bvm))) { + NL_SET_ERR_MSG_MOD(extack, "Invalid header for vlan request"); + return -EINVAL; + } + + 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 Mon Jan 13 15:52:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222190 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=B3RI9S6u; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5m2ND5z9sP6 for ; Tue, 14 Jan 2020 02:53:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728826AbgAMPxO (ORCPT ); Mon, 13 Jan 2020 10:53:14 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:41254 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728801AbgAMPxN (ORCPT ); Mon, 13 Jan 2020 10:53:13 -0500 Received: by mail-lf1-f67.google.com with SMTP id m30so7215448lfp.8 for ; Mon, 13 Jan 2020 07:53:11 -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=PRyqckMelSpsU5GT1G5t3lfW5edpIQYUQ5mkpJoZLoc=; b=B3RI9S6ux6Bz7F3Z6iJdMne3JGNiJyN/Cf1wlSsDYcpxEHzR2ennhEmVqawknl8aFL p7nlAc9947MP654THkWj7oO8m1jXCVZjjUoktDd9VdqrlWXSCfTAktvPkhCBzQ36JEpe AJTLaT4IhzNlc0tO2hrw2WkZDnaSnQOoCAYC0= 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=PRyqckMelSpsU5GT1G5t3lfW5edpIQYUQ5mkpJoZLoc=; b=S7+TGPOVsnjFdXp4J/+aI5T19gKBDnGzofB8DZ/tlJ3WGOcKhbh2bDfwjbuG746WHX SDhnnTM8fggHTMv6dAaB2nP+sDllcHS0aZKEuT2kErInEUsyScPyWSlCH2EQeFPPRBmm lGFFsBboS3LFv/fkN1udFyc1VS98j45Rn3mZwXVnqgS+/WK8Eax+UxZC6hErbfnM5SHR AmSZfvcbkNGglT0UfcZLp5eaFtrfEaUpZ54oJqNp9BIfPEe4EoI0Z6/TKReqyblpdA7b JEt3zQ3vibvtMHtkU9QcgWBIfA1x/7xygkoj/znqPlCrM8TVmLisrN5U3ccBGh3TgVFL yRmQ== X-Gm-Message-State: APjAAAUFsb5S8nJyIandt20LJ3WB/US1pHoON+AosIGIlwsv0BxccD+R Gs5jbvr8jcd6XvEmWL6125Il6+6GY5w= X-Google-Smtp-Source: APXvYqy7OgenELfveYV0yNpAN8onaC/V7cTEBIy4m7VmDX2ffCKIx3xe6I/Q5UTTJ8OTc/Pt3egUTw== X-Received: by 2002:a19:ae18:: with SMTP id f24mr10001955lfc.155.1578930790551; Mon, 13 Jan 2020 07:53:10 -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 e20sm6175658ljl.59.2020.01.13.07.53.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:09 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 5/8] net: bridge: vlan: add del rtm message support Date: Mon, 13 Jan 2020 17:52:30 +0200 Message-Id: <20200113155233.20771-6-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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 b8f52a7616c4..bd75cee48ad3 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1698,6 +1698,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 Mon Jan 13 15:52:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222191 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=bURUqiF5; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5n2rg3z9sP6 for ; Tue, 14 Jan 2020 02:53:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728831AbgAMPxQ (ORCPT ); Mon, 13 Jan 2020 10:53:16 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:45374 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728734AbgAMPxO (ORCPT ); Mon, 13 Jan 2020 10:53:14 -0500 Received: by mail-lj1-f196.google.com with SMTP id j26so10626121ljc.12 for ; Mon, 13 Jan 2020 07:53:13 -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=GFVS9DTPdsp61/zl9IK27D/N5+n6YcObmh7VS0kCtmc=; b=bURUqiF5arCvJZ31Q18EVkGfIppGYSmfhuf16CLIhrcsMGahYRF75pdJE/GFlvOa5Z pPzg/v1KYT5JnemlR3HAsPPCqqmRbkQtHax4bfLN7KJUEuuAXvUTPUXnd2n0Ddmz8pdd wVolM590Yzp5TYUPqbMGQssX1Kp5wLfaXiWWQ= 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=GFVS9DTPdsp61/zl9IK27D/N5+n6YcObmh7VS0kCtmc=; b=aI/6SyfV3/8C2dnJmm/Cxi0X2BtiSBlo+2wcsijHjdK9hi+zSCFvI6I3ds20eITWw8 /1k/vKb9uqUGpn484XckPhnBl1kRtDhSu0QopzU43wlvVX4KIDtzFh5I+o9Ne3lkZFZs kSNhSM8hfqmey77v8hXSxXZv0iP1AgbJR0XgsOzbXhvtG7bkNq2+5gK1ugsLO8c9IvJ9 1wtr9zYSKkXjiF6V2xBFT6CtksyqOZDhovSh9kTQ9QV1aREisvn9bSLJ5R0W6YGtLyRe smfghPRb7k2BMmiHp1reWHpnCwKJ1H2S/tWGM2kJ64p3HdSTzXy46hBfN9HxLMu+pFQb wOQg== X-Gm-Message-State: APjAAAXQgg8GzKVparo4j82hWWau/N5PHkZ2WTcjgnp4qcaFc/+qlEEU So2j67+Hp4K5rXKKiTA8XZLCRAxq+QQ= X-Google-Smtp-Source: APXvYqw44BrgKBRRhTFt/KLgUpE6nXNAwKPnVTSoDd3VsihnOr4s68hYk94kDBht/kSEJq78vtJp6Q== X-Received: by 2002:a2e:2c04:: with SMTP id s4mr11566035ljs.35.1578930792271; Mon, 13 Jan 2020 07:53:12 -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 e20sm6175658ljl.59.2020.01.13.07.53.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:11 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 6/8] net: bridge: vlan: add rtm range support Date: Mon, 13 Jan 2020 17:52:31 +0200 Message-Id: <20200113155233.20771-7-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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 bd75cee48ad3..4f911742bf5f 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; @@ -1647,13 +1688,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; @@ -1684,6 +1726,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 | @@ -1694,6 +1737,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 Mon Jan 13 15:52:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222193 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=Yz8PvsW5; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5s0pbqz9sPn for ; Tue, 14 Jan 2020 02:53:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728842AbgAMPxU (ORCPT ); Mon, 13 Jan 2020 10:53:20 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:35393 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728801AbgAMPxR (ORCPT ); Mon, 13 Jan 2020 10:53:17 -0500 Received: by mail-lj1-f196.google.com with SMTP id j1so10647445lja.2 for ; Mon, 13 Jan 2020 07:53:15 -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=K4tsQolRiTJlNf5YBGe3vXJoYvSY3RmCQu//d2605Mw=; b=Yz8PvsW5GOaZ1l01Mb4Zz7cachcTSNTwK60Em12EGVnDJT/JHBIbBrB4nwAR+uFbTs jVpZTsf4527twvOe1o3W/prtoPMsv+qtW5TU1YO+EXhbNDQ5UjvZr3NzYNBDsxlj3Vxr kHOwnA5ncmqZvYjCazx3PVn5zwgnm8omPT2k4= 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=K4tsQolRiTJlNf5YBGe3vXJoYvSY3RmCQu//d2605Mw=; b=bIGG9Nu16iSefNPEo+Xi7FDpq4m2YRnIUSAVFn+sXq//rmGg3F+mH23mNi6gOeKJkF RcZ2z96BIoYh72nij9VcREiX49TJZ8V8FEr480Gw4qh0PklNWMXCHSTSWCdDK8xtB+t7 aub/L5k8NVACwPwGI0X1qLy3DU1efbXUnGP4lzSzv5ah4FMJa2faIGNkDmuOQRxILS6T 3T3TTlRy7y+1aRodTzMA/KGn3Lzb04+fCcGwNhhwck4TONNCNy2SXjjOvqU8p0HJuYIH RCpPbzsJlYZZIjtpLb3lR8Tq/uRlbpRezzCzNla/Rwr9/3unSV92qCYlu/o50oqaCy7e Znmg== X-Gm-Message-State: APjAAAUrZcGMF8ViQdpbG9xQP61ag0chbx1HL1BvVFtjz2GsBLPu+Lfe 8GtV4FQdcXQBFe4PuVNz+aldbAYtLSY= X-Google-Smtp-Source: APXvYqyLEn7Zxr2B3vb1N2OBy/OW6m5ZnP+8lwW8L0SOOzd5s95lnWU7ZHINhYKXRx28Ws2GocNSrg== X-Received: by 2002:a2e:7005:: with SMTP id l5mr11807886ljc.230.1578930793820; Mon, 13 Jan 2020 07:53:13 -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 e20sm6175658ljl.59.2020.01.13.07.53.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:13 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 7/8] net: bridge: vlan: add rtnetlink group and notify support Date: Mon, 13 Jan 2020 17:52:32 +0200 Message-Id: <20200113155233.20771-8-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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 4f911742bf5f..46818362d6b7 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 Mon Jan 13 15:52:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1222192 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=WjAoiU9r; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 47xJ5r2ZyTz9sP6 for ; Tue, 14 Jan 2020 02:53:20 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728834AbgAMPxT (ORCPT ); Mon, 13 Jan 2020 10:53:19 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:37329 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728833AbgAMPxS (ORCPT ); Mon, 13 Jan 2020 10:53:18 -0500 Received: by mail-lj1-f194.google.com with SMTP id o13so10645454ljg.4 for ; Mon, 13 Jan 2020 07:53:16 -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=TaiGYJUYXXHQS6oq5Fd35tek1ycnAIZ7u32dcg64PTA=; b=WjAoiU9rP73BCIYmGI8gEPAz/uXm6lVuAQ74eu1sGXaWYNlyFnQk34tH1LhCcMgDsp Fd/4aPRFpbKgQFnzKWwR9Dkx5tRMz2gsi4UntT8S02ybAXdiqzvVAVhc4a7NlrION9tl LVkibyBGVTlXXw5mCsoMYGloBxDXNEP71iCsA= 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=TaiGYJUYXXHQS6oq5Fd35tek1ycnAIZ7u32dcg64PTA=; b=ZZXs6OZvOb4VYwH7wC3W5AXqe9H7USnrIdF/ahaNdrjPsC8qRXk+g95qPPJdsZhMGG 5Tt6SVHBYuyFN99cX/xCD7yCEdSOhtIo1flvy2f+6M7gddyhdXwxyhs/S7C6aG56isBn CrfUgEnBtD6pcrsqZ9rFhebTHydf2rDTcbjlFHIzVeyOtu3IRh27uR/afpt0T1N2fiqV s78rYi1LHESRofv+9xgAUBgOGFD5UAbppSpOGD8Bt7Cl6NMot6MVlFfpUR3sUuFTRxnj nKj+efAHODhdxWcFqDI4kI84ZJAGpcSO5KMXRAQuu+7vXLqquVnO8Sim7L+n5QM3qcKj 9tvg== X-Gm-Message-State: APjAAAWGnbr5Bx19o0QDJ5VTI3he0wZaBb/LbGmbQG44FJ0a68c/siwq DntiyziF7FLvBcymoS0QqCKIAL8BZZM= X-Google-Smtp-Source: APXvYqwXRyy5DhbaOMJu3GZtNzzRjiRuEu0qBsIAB5UT+CZWMX/VmOX0RMDY4TOvcoFePZ/ikpqYnw== X-Received: by 2002:a2e:9ad1:: with SMTP id p17mr11343964ljj.26.1578930795282; Mon, 13 Jan 2020 07:53:15 -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 e20sm6175658ljl.59.2020.01.13.07.53.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 07:53:14 -0800 (PST) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov Subject: [PATCH net-next 8/8] net: bridge: vlan: notify on vlan add/delete/change flags Date: Mon, 13 Jan 2020 17:52:33 +0200 Message-Id: <20200113155233.20771-9-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> References: <20200113155233.20771-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 46818362d6b7..aa6445d11209 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; }