Received: by 2002:ac0:8845:0:0:0:0:0 with SMTP id g63csp919180img; Tue, 26 Feb 2019 10:49:38 -0800 (PST) X-Google-Smtp-Source: AHgI3IaEp3TwN6xzViC98EWEfgwhJ2pDYQwozhQXZQFLbHBeEcFkAgGM2OyIP/F12ZOyaojaZyaf X-Received: by 2002:a63:104e:: with SMTP id 14mr21714298pgq.185.1551206978116; Tue, 26 Feb 2019 10:49:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551206978; cv=none; d=google.com; s=arc-20160816; b=mjXCEn83cfgadksRIb5YLmLWB/p3x8///D3ub7KRNFdB/ghLV9g7v2ECd48ADdQQe4 Vg0btHoYlJs/XFoG4d+yCaIi/gDC/VdZ8zX6i64FWaPZCVeVE1eivbwVOLQgBl97bFcE gOWH/AJIKe3ulefgxh9snKgpJHHb3+CI4NwPAWxj03E8Roj51rXclZDka/J1qoDKx34L 8CHH1A8QB+1WTb8F4etQW7EHqZgfG+jVRsfQ339ixaAYCBfcfO+S6hz0CGhvQKQXC3F0 KDNTesKRGaQ7Zgcpqw7oFKi8XAKgenNe1LdgeSXt9uA5Ki5t8YL8vEmuU4HwKHdCqm8t DbRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=DcDw7IrxqjOxRf2I8tQwrAbV9hm03kKacBat2OiHhV8=; b=dWxzjW9eA8Uqc53zqtTxVcFNJMUTkLkL4bZjWwmWvRv9670gdpd1aAUmlKj7AXvjXe QxsVndPcsj4aqxpAWlq7r8LbKtBBPt+GCBXrSPtzgkOnOw0gsp+GfCQ37+QBcCWTBVCt 0GY4Ov37Sy4nMbWqH4aA3KdPhsaIXBGbyOlKYHYFBPorkeU86coC0EuiLytVd5w1/ErK pSxb8JOvgFr69HZbeanwfAFVvEzYCVaNMCkqYU7FYky6NjeCb0jP6bhHTy+5Ij3qgBSJ KBBb5uhm1/QVYK7SZX9QKE0dgxnOUpQQXhemRcpGx6hedjtZVCb3hwYfk0Y+sdn5UPni /rvg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fGy464fU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x14si12854466pgq.185.2019.02.26.10.49.23; Tue, 26 Feb 2019 10:49:38 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fGy464fU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729331AbfBZSrL (ORCPT + 99 others); Tue, 26 Feb 2019 13:47:11 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:37079 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729109AbfBZSqd (ORCPT ); Tue, 26 Feb 2019 13:46:33 -0500 Received: by mail-lf1-f67.google.com with SMTP id z196so9744220lff.4 for ; Tue, 26 Feb 2019 10:46:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DcDw7IrxqjOxRf2I8tQwrAbV9hm03kKacBat2OiHhV8=; b=fGy464fUWN2DY6G0KVw5uTrWDyl77JIUOm4Z9OOb3mluFGnXqneATfRFC2hVcqz9s5 B8vaorp5AihQbJsjaWf1QjmOeY8m9oYAARRuKhl5uJWsxitjDCw0JVt2rlc0DKp6GYQ1 gI72LtJlpTOXsk2aVhQPkRDTRVBnCV7B5KxyJJ4Qt1Iz7esmXtsKTHmjz8sA0JldvZcT FZjdvxegiVOMmf6WJJ4iia1+0E1m2TxB6nNsWxzBrhxohlMCiix/f/oF5UwdBL7fLp+2 A+bLACUJJcs+ql6tXaVfUMZ3UeMtORsXS1EuiVfrTkbhcsV+alcuxyPB45zgv5Rp9Ay2 jQkw== 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; bh=DcDw7IrxqjOxRf2I8tQwrAbV9hm03kKacBat2OiHhV8=; b=K6p+fhsXQ3CxGCgSuTRXkXYrSq4J87UeJqdg5wTu8ip7IdjASAS1/AGfiJwkhQnyE4 v3DB4t6n1nOqWT2w8hRBZNkQv3jsM6zcq4KKGC7iqmIa16Mp1Kin8XyQEP94j77aXkar asIAWq81OIyq1pBiic+wSotvvu/3fEDigS7Ka68suErSxT3t2AOBiq0BqdQPR6IdzW7x +eiEJ27X+c2IdUXRMYm+Kb5oOrcJ1lknfksVW5pER1cyK5gGFZbdxcTHR6gOwCZgFIn8 sigo17rvY5fVP3241ibI/TGu8N/aLlxlaIteSx77b87h5iVTsUrGi/YXjYi5xH/SVLkp 6tYw== X-Gm-Message-State: AHQUAua06S1tiGA1fQFLk0iSzDJrC+Z0f/m+bl4+3LDh8qu9gYsP+viI WPulnDp/W9Wh+SEbQlIrGNmWhisv5Ag= X-Received: by 2002:a19:d411:: with SMTP id l17mr1323106lfg.112.1551206789404; Tue, 26 Feb 2019 10:46:29 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id s129sm3015190lja.49.2019.02.26.10.46.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Feb 2019 10:46:28 -0800 (PST) From: Ivan Khoronzhuk To: davem@davemloft.net, grygorii.strashko@ti.com, f.fainelli@gmail.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jiri@mellanox.com, ilias.apalodimas@linaro.org, Ivan Khoronzhuk Subject: [PATCH net-next 1/6] net: core: dev_addr_lists: add VID to device address Date: Tue, 26 Feb 2019 20:45:51 +0200 Message-Id: <20190226184556.16082-2-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> References: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Despite this is supposed to be used for Ethernet VLANs, not Ethernet addresses with space for VID also can reuse this, so VID is considered as virtual ID extension, not belonging strictly to Ethernet VLAN VIDs, and overall change can be named individual virtual device filtering (IVDF). This patch adds VID tag at the end of each address. The actual reserved address size is 32 bytes. For Ethernet addresses with 6 bytes long that's possible to add tag w/o increasing address size. Thus, each address for the case has 32 - 6 = 26 bytes to hold additional info, say VID for virtual device addresses. Therefore, when addresses are synced to the address list of parent device the address list of latter can contain separate addresses for virtual devices. It allows to track separate address tables for virtual devices if they present and the device can be placed on any place of device tree as the address is propagated to to the end real device thru *_sync()/ndo_set_rx_mode() APIs. Also it simplifies handling VID addresses at real device when it supports IVDF. If parent device doesn't want to have virtual addresses in its address space the vid_len has to be 0, thus its address space is "shrunk" to the state as before this patch. For now it's 0 for every device. It allows two devices with and w/o IVDF to be part of same bond device for instance. The end real device supporting IVDF can retrieve VID tag from an address and set it for a given virtual device only. By default, vid 0 is used for real devices to distinguish it from virtual addresses. See next patches to see how it's used. Signed-off-by: Ivan Khoronzhuk --- include/linux/netdevice.h | 4 ++ net/core/dev_addr_lists.c | 124 +++++++++++++++++++++++++++++++------- 2 files changed, 105 insertions(+), 23 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 58e83bd7a861..74fef35b6bec 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1660,6 +1660,7 @@ enum netdev_priv_flags { * @perm_addr: Permanent hw address * @addr_assign_type: Hw address assignment type * @addr_len: Hardware address length + * @vid_len: Virtual ID length, set in case of IVDF * @neigh_priv_len: Used in neigh_alloc() * @dev_id: Used to differentiate devices that share * the same link layer address @@ -1889,6 +1890,7 @@ struct net_device { unsigned char perm_addr[MAX_ADDR_LEN]; unsigned char addr_assign_type; unsigned char addr_len; + unsigned char vid_len; unsigned short neigh_priv_len; unsigned short dev_id; unsigned short dev_port; @@ -4141,8 +4143,10 @@ int dev_addr_init(struct net_device *dev); /* Functions used for unicast addresses handling */ int dev_uc_add(struct net_device *dev, const unsigned char *addr); +int dev_vid_uc_add(struct net_device *dev, const unsigned char *addr); int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr); int dev_uc_del(struct net_device *dev, const unsigned char *addr); +int dev_vid_uc_del(struct net_device *dev, const unsigned char *addr); int dev_uc_sync(struct net_device *to, struct net_device *from); int dev_uc_sync_multiple(struct net_device *to, struct net_device *from); void dev_uc_unsync(struct net_device *to, struct net_device *from); diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index a6723b306717..e3c80e044b8c 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -545,6 +545,26 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr, } EXPORT_SYMBOL(dev_addr_del); +static int get_addr_len(struct net_device *dev) +{ + return dev->addr_len + dev->vid_len; +} + +static int set_vid_addr(struct net_device *dev, const unsigned char *addr, + unsigned char *naddr) +{ + int i; + + if (!dev->vid_len) + return dev->addr_len; + + memcpy(naddr, addr, dev->addr_len); + for (i = 0; i < dev->vid_len; i++) + naddr[dev->addr_len + i] = 0; + + return get_addr_len(dev); +} + /* * Unicast list handling functions */ @@ -556,18 +576,22 @@ EXPORT_SYMBOL(dev_addr_del); */ int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr) { + unsigned char naddr[MAX_ADDR_LEN]; struct netdev_hw_addr *ha; - int err; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); list_for_each_entry(ha, &dev->uc.list, list) { - if (!memcmp(ha->addr, addr, dev->addr_len) && + if (!memcmp(ha->addr, addr, addr_len) && ha->type == NETDEV_HW_ADDR_T_UNICAST) { err = -EEXIST; goto out; } } - err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len, + err = __hw_addr_create_ex(&dev->uc, addr, addr_len, NETDEV_HW_ADDR_T_UNICAST, true, false); if (!err) __dev_set_rx_mode(dev); @@ -578,47 +602,89 @@ int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr) EXPORT_SYMBOL(dev_uc_add_excl); /** - * dev_uc_add - Add a secondary unicast address + * dev_vid_uc_add - Add a secondary unicast address with tag * @dev: device - * @addr: address to add + * @addr: address to add, includes vid tag already * * Add a secondary unicast address to the device or increase * the reference count if it already exists. */ -int dev_uc_add(struct net_device *dev, const unsigned char *addr) +int dev_vid_uc_add(struct net_device *dev, const unsigned char *addr) { int err; netif_addr_lock_bh(dev); - err = __hw_addr_add(&dev->uc, addr, dev->addr_len, + err = __hw_addr_add(&dev->uc, addr, get_addr_len(dev), NETDEV_HW_ADDR_T_UNICAST); if (!err) __dev_set_rx_mode(dev); netif_addr_unlock_bh(dev); return err; } +EXPORT_SYMBOL(dev_vid_uc_add); + +/** + * dev_uc_add - Add a secondary unicast address + * @dev: device + * @addr: address to add + * + * Add a secondary unicast address to the device or increase + * the reference count if it already exists. + */ +int dev_uc_add(struct net_device *dev, const unsigned char *addr) +{ + unsigned char naddr[MAX_ADDR_LEN]; + int err; + + set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; + + err = dev_vid_uc_add(dev, addr); + return err; +} EXPORT_SYMBOL(dev_uc_add); /** * dev_uc_del - Release secondary unicast address. * @dev: device - * @addr: address to delete + * @addr: address to delete, includes vid tag already * * Release reference to a secondary unicast address and remove it * from the device if the reference count drops to zero. */ -int dev_uc_del(struct net_device *dev, const unsigned char *addr) +int dev_vid_uc_del(struct net_device *dev, const unsigned char *addr) { int err; netif_addr_lock_bh(dev); - err = __hw_addr_del(&dev->uc, addr, dev->addr_len, + err = __hw_addr_del(&dev->uc, addr, get_addr_len(dev), NETDEV_HW_ADDR_T_UNICAST); if (!err) __dev_set_rx_mode(dev); netif_addr_unlock_bh(dev); return err; } +EXPORT_SYMBOL(dev_vid_uc_del); + +/** + * dev_uc_del - Release secondary unicast address. + * @dev: device + * @addr: address to delete + * + * Release reference to a secondary unicast address and remove it + * from the device if the reference count drops to zero. + */ +int dev_uc_del(struct net_device *dev, const unsigned char *addr) +{ + unsigned char naddr[MAX_ADDR_LEN]; + int err; + + set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; + + err = dev_vid_uc_del(dev, addr); + return err; +} EXPORT_SYMBOL(dev_uc_del); /** @@ -642,7 +708,7 @@ int dev_uc_sync(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); + err = __hw_addr_sync(&to->uc, &from->uc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -672,7 +738,7 @@ int dev_uc_sync_multiple(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync_multiple(&to->uc, &from->uc, to->addr_len); + err = __hw_addr_sync_multiple(&to->uc, &from->uc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -696,7 +762,7 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from) netif_addr_lock_bh(from); netif_addr_lock_nested(to); - __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); + __hw_addr_unsync(&to->uc, &from->uc, get_addr_len(to)); __dev_set_rx_mode(to); netif_addr_unlock(to); netif_addr_unlock_bh(from); @@ -740,18 +806,22 @@ EXPORT_SYMBOL(dev_uc_init); */ int dev_mc_add_excl(struct net_device *dev, const unsigned char *addr) { + unsigned char naddr[MAX_ADDR_LEN]; struct netdev_hw_addr *ha; - int err; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); list_for_each_entry(ha, &dev->mc.list, list) { - if (!memcmp(ha->addr, addr, dev->addr_len) && + if (!memcmp(ha->addr, addr, addr_len) && ha->type == NETDEV_HW_ADDR_T_MULTICAST) { err = -EEXIST; goto out; } } - err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len, + err = __hw_addr_create_ex(&dev->mc, addr, addr_len, NETDEV_HW_ADDR_T_MULTICAST, true, false); if (!err) __dev_set_rx_mode(dev); @@ -764,10 +834,14 @@ EXPORT_SYMBOL(dev_mc_add_excl); static int __dev_mc_add(struct net_device *dev, const unsigned char *addr, bool global) { - int err; + unsigned char naddr[MAX_ADDR_LEN]; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); - err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len, + err = __hw_addr_add_ex(&dev->mc, addr, addr_len, NETDEV_HW_ADDR_T_MULTICAST, global, false, 0); if (!err) __dev_set_rx_mode(dev); @@ -804,10 +878,14 @@ EXPORT_SYMBOL(dev_mc_add_global); static int __dev_mc_del(struct net_device *dev, const unsigned char *addr, bool global) { - int err; + unsigned char naddr[MAX_ADDR_LEN]; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); - err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len, + err = __hw_addr_del_ex(&dev->mc, addr, addr_len, NETDEV_HW_ADDR_T_MULTICAST, global, false); if (!err) __dev_set_rx_mode(dev); @@ -863,7 +941,7 @@ int dev_mc_sync(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); + err = __hw_addr_sync(&to->mc, &from->mc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -893,7 +971,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len); + err = __hw_addr_sync_multiple(&to->mc, &from->mc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -917,7 +995,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from) netif_addr_lock_bh(from); netif_addr_lock_nested(to); - __hw_addr_unsync(&to->mc, &from->mc, to->addr_len); + __hw_addr_unsync(&to->mc, &from->mc, get_addr_len(to)); __dev_set_rx_mode(to); netif_addr_unlock(to); netif_addr_unlock_bh(from); -- 2.17.1