* [PATCH net-next v2 0/7] net: constify netdev->dev_addr
@ 2021-11-19 14:21 Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 1/7] 82596: use eth_hw_addr_set() Jakub Kicinski
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski
Take care of a few stragglers and make netdev->dev_addr const.
netdev->dev_addr can be held on the address tree like any other
address now.
Jakub Kicinski (7):
82596: use eth_hw_addr_set()
bnx2x: constify static inline stub for dev_addr
net: constify netdev->dev_addr
net: unexport dev_addr_init() & dev_addr_flush()
dev_addr: add a modification check
dev_addr_list: put the first addr on the tree
net: kunit: add a test for dev_addr_lists
.../net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 +-
drivers/net/ethernet/i825xx/82596.c | 3 +-
include/linux/netdevice.h | 19 +-
net/Kconfig | 5 +
net/core/Makefile | 2 +
net/core/dev.c | 1 +
net/core/dev_addr_lists.c | 93 ++++---
net/core/dev_addr_lists_test.c | 236 ++++++++++++++++++
8 files changed, 320 insertions(+), 41 deletions(-)
create mode 100644 net/core/dev_addr_lists_test.c
--
2.31.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net-next v2 1/7] 82596: use eth_hw_addr_set()
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
@ 2021-11-19 14:21 ` Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 2/7] bnx2x: constify static inline stub for dev_addr Jakub Kicinski
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski
Byte by byte assignments.
Fixes build on m68k.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/i825xx/82596.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index b482f6f633bd..3ee89ae496d0 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -1178,7 +1178,8 @@ static struct net_device * __init i82596_probe(void)
DEB(DEB_PROBE,printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
for (i = 0; i < 6; i++)
- DEB(DEB_PROBE,printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]));
+ DEB(DEB_PROBE,printk(" %2.2X", eth_addr[i]));
+ eth_hw_addr_set(dev, eth_addr);
DEB(DEB_PROBE,printk(" IRQ %d.\n", dev->irq));
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 2/7] bnx2x: constify static inline stub for dev_addr
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 1/7] 82596: use eth_hw_addr_set() Jakub Kicinski
@ 2021-11-19 14:21 ` Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 3/7] net: constify netdev->dev_addr Jakub Kicinski
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski, kernel test robot
bnx2x_vfpf_config_mac() was constified by not its stub.
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 8c2cf5519787..2dac704dc346 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -586,7 +586,7 @@ static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; }
static inline int bnx2x_vfpf_init(struct bnx2x *bp) {return 0; }
static inline void bnx2x_vfpf_close_vf(struct bnx2x *bp) {}
static inline int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp, bool is_leading) {return 0; }
-static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr,
+static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, const u8 *addr,
u8 vf_qid, bool set) {return 0; }
static inline int bnx2x_vfpf_config_rss(struct bnx2x *bp,
struct bnx2x_config_rss_params *params) {return 0; }
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 3/7] net: constify netdev->dev_addr
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 1/7] 82596: use eth_hw_addr_set() Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 2/7] bnx2x: constify static inline stub for dev_addr Jakub Kicinski
@ 2021-11-19 14:21 ` Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 4/7] net: unexport dev_addr_init() & dev_addr_flush() Jakub Kicinski
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski
Commit 406f42fa0d3c ("net-next: When a bond have a massive amount
of VLANs...") introduced a rbtree for faster Ethernet address look
up. We converted all users to make modifications via appropriate
helpers, make netdev->dev_addr const.
The update helpers need to upcast from the buffer to
struct netdev_hw_addr.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
include/linux/netdevice.h | 14 +++++---------
net/core/dev_addr_lists.c | 10 ++++++++++
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4f4a299e92de..2462195784a9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2117,7 +2117,7 @@ struct net_device {
* Cache lines mostly used on receive path (including eth_type_trans())
*/
/* Interface address info used in eth_type_trans() */
- unsigned char *dev_addr;
+ const unsigned char *dev_addr;
struct netdev_rx_queue *_rx;
unsigned int num_rx_queues;
@@ -4268,10 +4268,13 @@ void __hw_addr_unsync_dev(struct netdev_hw_addr_list *list,
void __hw_addr_init(struct netdev_hw_addr_list *list);
/* Functions used for device addresses handling */
+void dev_addr_mod(struct net_device *dev, unsigned int offset,
+ const void *addr, size_t len);
+
static inline void
__dev_addr_set(struct net_device *dev, const void *addr, size_t len)
{
- memcpy(dev->dev_addr, addr, len);
+ dev_addr_mod(dev, 0, addr, len);
}
static inline void dev_addr_set(struct net_device *dev, const u8 *addr)
@@ -4279,13 +4282,6 @@ static inline void dev_addr_set(struct net_device *dev, const u8 *addr)
__dev_addr_set(dev, addr, dev->addr_len);
}
-static inline void
-dev_addr_mod(struct net_device *dev, unsigned int offset,
- const void *addr, size_t len)
-{
- memcpy(&dev->dev_addr[offset], addr, len);
-}
-
int dev_addr_add(struct net_device *dev, const unsigned char *addr,
unsigned char addr_type);
int dev_addr_del(struct net_device *dev, const unsigned char *addr,
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index f0cb38344126..ae8b1ef00fec 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -549,6 +549,16 @@ int dev_addr_init(struct net_device *dev)
}
EXPORT_SYMBOL(dev_addr_init);
+void dev_addr_mod(struct net_device *dev, unsigned int offset,
+ const void *addr, size_t len)
+{
+ struct netdev_hw_addr *ha;
+
+ ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]);
+ memcpy(&ha->addr[offset], addr, len);
+}
+EXPORT_SYMBOL(dev_addr_mod);
+
/**
* dev_addr_add - Add a device address
* @dev: device
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 4/7] net: unexport dev_addr_init() & dev_addr_flush()
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
` (2 preceding siblings ...)
2021-11-19 14:21 ` [PATCH net-next v2 3/7] net: constify netdev->dev_addr Jakub Kicinski
@ 2021-11-19 14:21 ` Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 5/7] dev_addr: add a modification check Jakub Kicinski
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski
There are no module callers in-tree and it's hard to justify
why anyone would init or flush addresses of a netdev (note
the flush is more of a destructor, it frees netdev->dev_addr).
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
net/core/dev_addr_lists.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index ae8b1ef00fec..a23a83ac18e5 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -513,7 +513,6 @@ void dev_addr_flush(struct net_device *dev)
__hw_addr_flush(&dev->dev_addrs);
dev->dev_addr = NULL;
}
-EXPORT_SYMBOL(dev_addr_flush);
/**
* dev_addr_init - Init device address list
@@ -547,7 +546,6 @@ int dev_addr_init(struct net_device *dev)
}
return err;
}
-EXPORT_SYMBOL(dev_addr_init);
void dev_addr_mod(struct net_device *dev, unsigned int offset,
const void *addr, size_t len)
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 5/7] dev_addr: add a modification check
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
` (3 preceding siblings ...)
2021-11-19 14:21 ` [PATCH net-next v2 4/7] net: unexport dev_addr_init() & dev_addr_flush() Jakub Kicinski
@ 2021-11-19 14:21 ` Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 6/7] dev_addr_list: put the first addr on the tree Jakub Kicinski
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski
netdev->dev_addr should only be modified via helpers,
but someone may be casting off the const. Add a runtime
check to catch abuses.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
include/linux/netdevice.h | 5 +++++
net/core/dev.c | 1 +
net/core/dev_addr_lists.c | 19 +++++++++++++++++++
3 files changed, 25 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2462195784a9..cb7f2661d187 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1942,6 +1942,8 @@ enum netdev_ml_priv_type {
* @unlink_list: As netif_addr_lock() can be called recursively,
* keep a list of interfaces to be deleted.
*
+ * @dev_addr_shadow: Copy of @dev_addr to catch direct writes.
+ *
* FIXME: cleanup struct net_device such that network protocol info
* moves out.
*/
@@ -2268,6 +2270,8 @@ struct net_device {
/* protected by rtnl_lock */
struct bpf_xdp_entity xdp_state[__MAX_XDP_MODE];
+
+ u8 dev_addr_shadow[MAX_ADDR_LEN];
};
#define to_net_dev(d) container_of(d, struct net_device, dev)
@@ -4288,6 +4292,7 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr,
unsigned char addr_type);
void dev_addr_flush(struct net_device *dev);
int dev_addr_init(struct net_device *dev);
+void dev_addr_check(struct net_device *dev);
/* Functions used for unicast addresses handling */
int dev_uc_add(struct net_device *dev, const unsigned char *addr);
diff --git a/net/core/dev.c b/net/core/dev.c
index 92c9258cbf28..9219e319e901 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1377,6 +1377,7 @@ static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack)
int ret;
ASSERT_RTNL();
+ dev_addr_check(dev);
if (!netif_device_present(dev)) {
/* may be detached because parent is runtime-suspended */
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index a23a83ac18e5..969942734951 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -498,6 +498,21 @@ EXPORT_SYMBOL(__hw_addr_init);
* Device addresses handling functions
*/
+/* Check that netdev->dev_addr is not written to directly as this would
+ * break the rbtree layout. All changes should go thru dev_addr_set() and co.
+ * Remove this check in mid-2024.
+ */
+void dev_addr_check(struct net_device *dev)
+{
+ if (!memcmp(dev->dev_addr, dev->dev_addr_shadow, MAX_ADDR_LEN))
+ return;
+
+ netdev_warn(dev, "Current addr: %*ph\n", MAX_ADDR_LEN, dev->dev_addr);
+ netdev_warn(dev, "Expected addr: %*ph\n",
+ MAX_ADDR_LEN, dev->dev_addr_shadow);
+ netdev_WARN(dev, "Incorrect netdev->dev_addr\n");
+}
+
/**
* dev_addr_flush - Flush device address list
* @dev: device
@@ -509,6 +524,7 @@ EXPORT_SYMBOL(__hw_addr_init);
void dev_addr_flush(struct net_device *dev)
{
/* rtnl_mutex must be held here */
+ dev_addr_check(dev);
__hw_addr_flush(&dev->dev_addrs);
dev->dev_addr = NULL;
@@ -552,8 +568,11 @@ void dev_addr_mod(struct net_device *dev, unsigned int offset,
{
struct netdev_hw_addr *ha;
+ dev_addr_check(dev);
+
ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]);
memcpy(&ha->addr[offset], addr, len);
+ memcpy(&dev->dev_addr_shadow[offset], addr, len);
}
EXPORT_SYMBOL(dev_addr_mod);
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 6/7] dev_addr_list: put the first addr on the tree
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
` (4 preceding siblings ...)
2021-11-19 14:21 ` [PATCH net-next v2 5/7] dev_addr: add a modification check Jakub Kicinski
@ 2021-11-19 14:21 ` Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 7/7] net: kunit: add a test for dev_addr_lists Jakub Kicinski
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski
Since all netdev->dev_addr modifications go via dev_addr_mod()
we can put it on the list. When address is change remove it
and add it back.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
net/core/dev_addr_lists.c | 62 +++++++++++++++++++++------------------
1 file changed, 34 insertions(+), 28 deletions(-)
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 969942734951..bead38ca50bd 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -16,6 +16,35 @@
* General list handling functions
*/
+static int __hw_addr_insert(struct netdev_hw_addr_list *list,
+ struct netdev_hw_addr *new, int addr_len)
+{
+ struct rb_node **ins_point = &list->tree.rb_node, *parent = NULL;
+ struct netdev_hw_addr *ha;
+
+ while (*ins_point) {
+ int diff;
+
+ ha = rb_entry(*ins_point, struct netdev_hw_addr, node);
+ diff = memcmp(new->addr, ha->addr, addr_len);
+ if (diff == 0)
+ diff = memcmp(&new->type, &ha->type, sizeof(new->type));
+
+ parent = *ins_point;
+ if (diff < 0)
+ ins_point = &parent->rb_left;
+ else if (diff > 0)
+ ins_point = &parent->rb_right;
+ else
+ return -EEXIST;
+ }
+
+ rb_link_node_rcu(&new->node, parent, ins_point);
+ rb_insert_color(&new->node, &list->tree);
+
+ return 0;
+}
+
static struct netdev_hw_addr*
__hw_addr_create(const unsigned char *addr, int addr_len,
unsigned char addr_type, bool global, bool sync)
@@ -50,11 +79,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
if (addr_len > MAX_ADDR_LEN)
return -EINVAL;
- ha = list_first_entry(&list->list, struct netdev_hw_addr, list);
- if (ha && !memcmp(addr, ha->addr, addr_len) &&
- (!addr_type || addr_type == ha->type))
- goto found_it;
-
while (*ins_point) {
int diff;
@@ -69,7 +93,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
} else if (diff > 0) {
ins_point = &parent->rb_right;
} else {
-found_it:
if (exclusive)
return -EEXIST;
if (global) {
@@ -94,16 +117,8 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
if (!ha)
return -ENOMEM;
- /* The first address in dev->dev_addrs is pointed to by dev->dev_addr
- * and mutated freely by device drivers and netdev ops, so if we insert
- * it into the tree we'll end up with an invalid rbtree.
- */
- if (list->count > 0) {
- rb_link_node(&ha->node, parent, ins_point);
- rb_insert_color(&ha->node, &list->tree);
- } else {
- RB_CLEAR_NODE(&ha->node);
- }
+ rb_link_node(&ha->node, parent, ins_point);
+ rb_insert_color(&ha->node, &list->tree);
list_add_tail_rcu(&ha->list, &list->list);
list->count++;
@@ -138,8 +153,7 @@ static int __hw_addr_del_entry(struct netdev_hw_addr_list *list,
if (--ha->refcount)
return 0;
- if (!RB_EMPTY_NODE(&ha->node))
- rb_erase(&ha->node, &list->tree);
+ rb_erase(&ha->node, &list->tree);
list_del_rcu(&ha->list);
kfree_rcu(ha, rcu_head);
@@ -151,18 +165,8 @@ static struct netdev_hw_addr *__hw_addr_lookup(struct netdev_hw_addr_list *list,
const unsigned char *addr, int addr_len,
unsigned char addr_type)
{
- struct netdev_hw_addr *ha;
struct rb_node *node;
- /* The first address isn't inserted into the tree because in the dev->dev_addrs
- * list it's the address pointed to by dev->dev_addr which is freely mutated
- * in place, so we need to check it separately.
- */
- ha = list_first_entry(&list->list, struct netdev_hw_addr, list);
- if (ha && !memcmp(addr, ha->addr, addr_len) &&
- (!addr_type || addr_type == ha->type))
- return ha;
-
node = list->tree.rb_node;
while (node) {
@@ -571,8 +575,10 @@ void dev_addr_mod(struct net_device *dev, unsigned int offset,
dev_addr_check(dev);
ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]);
+ rb_erase(&ha->node, &dev->dev_addrs.tree);
memcpy(&ha->addr[offset], addr, len);
memcpy(&dev->dev_addr_shadow[offset], addr, len);
+ WARN_ON(__hw_addr_insert(&dev->dev_addrs, ha, dev->addr_len));
}
EXPORT_SYMBOL(dev_addr_mod);
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 7/7] net: kunit: add a test for dev_addr_lists
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
` (5 preceding siblings ...)
2021-11-19 14:21 ` [PATCH net-next v2 6/7] dev_addr_list: put the first addr on the tree Jakub Kicinski
@ 2021-11-19 14:21 ` Jakub Kicinski
2021-11-19 15:46 ` [PATCH net-next v2 0/7] net: constify netdev->dev_addr David Miller
2021-11-20 12:30 ` patchwork-bot+netdevbpf
8 siblings, 0 replies; 10+ messages in thread
From: Jakub Kicinski @ 2021-11-19 14:21 UTC (permalink / raw)
To: davem; +Cc: netdev, Jakub Kicinski
Add a KUnit test for the dev_addr API.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
net/Kconfig | 5 +
net/core/Makefile | 2 +
net/core/dev_addr_lists_test.c | 236 +++++++++++++++++++++++++++++++++
3 files changed, 243 insertions(+)
create mode 100644 net/core/dev_addr_lists_test.c
diff --git a/net/Kconfig b/net/Kconfig
index 074472dfa94a..8a1f9d0287de 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -455,4 +455,9 @@ config ETHTOOL_NETLINK
netlink. It provides better extensibility and some new features,
e.g. notification messages.
+config NETDEV_ADDR_LIST_TEST
+ tristate "Unit tests for device address list"
+ default KUNIT_ALL_TESTS
+ depends on KUNIT
+
endif # if NET
diff --git a/net/core/Makefile b/net/core/Makefile
index 6bdcb2cafed8..a8e4f737692b 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -13,6 +13,8 @@ obj-y += dev.o dev_addr_lists.o dst.o netevent.o \
sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \
fib_notifier.o xdp.o flow_offload.o gro.o
+obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o
+
obj-y += net-sysfs.o
obj-$(CONFIG_PAGE_POOL) += page_pool.o
obj-$(CONFIG_PROC_FS) += net-procfs.o
diff --git a/net/core/dev_addr_lists_test.c b/net/core/dev_addr_lists_test.c
new file mode 100644
index 000000000000..049cfbc58aa9
--- /dev/null
+++ b/net/core/dev_addr_lists_test.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <kunit/test.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+
+static const struct net_device_ops dummy_netdev_ops = {
+};
+
+struct dev_addr_test_priv {
+ u32 addr_seen;
+};
+
+static int dev_addr_test_sync(struct net_device *netdev, const unsigned char *a)
+{
+ struct dev_addr_test_priv *datp = netdev_priv(netdev);
+
+ if (a[0] < 31 && !memchr_inv(a, a[0], ETH_ALEN))
+ datp->addr_seen |= 1 << a[0];
+ return 0;
+}
+
+static int dev_addr_test_unsync(struct net_device *netdev,
+ const unsigned char *a)
+{
+ struct dev_addr_test_priv *datp = netdev_priv(netdev);
+
+ if (a[0] < 31 && !memchr_inv(a, a[0], ETH_ALEN))
+ datp->addr_seen &= ~(1 << a[0]);
+ return 0;
+}
+
+static int dev_addr_test_init(struct kunit *test)
+{
+ struct dev_addr_test_priv *datp;
+ struct net_device *netdev;
+ int err;
+
+ netdev = alloc_etherdev(sizeof(*datp));
+ KUNIT_ASSERT_TRUE(test, !!netdev);
+
+ test->priv = netdev;
+ netdev->netdev_ops = &dummy_netdev_ops;
+
+ err = register_netdev(netdev);
+ if (err) {
+ free_netdev(netdev);
+ KUNIT_FAIL(test, "Can't register netdev %d", err);
+ }
+
+ rtnl_lock();
+ return 0;
+}
+
+static void dev_addr_test_exit(struct kunit *test)
+{
+ struct net_device *netdev = test->priv;
+
+ rtnl_unlock();
+ unregister_netdev(netdev);
+ free_netdev(netdev);
+}
+
+static void dev_addr_test_basic(struct kunit *test)
+{
+ struct net_device *netdev = test->priv;
+ u8 addr[ETH_ALEN];
+
+ KUNIT_EXPECT_TRUE(test, !!netdev->dev_addr);
+
+ memset(addr, 2, sizeof(addr));
+ eth_hw_addr_set(netdev, addr);
+ KUNIT_EXPECT_EQ(test, 0, memcmp(netdev->dev_addr, addr, sizeof(addr)));
+
+ memset(addr, 3, sizeof(addr));
+ dev_addr_set(netdev, addr);
+ KUNIT_EXPECT_EQ(test, 0, memcmp(netdev->dev_addr, addr, sizeof(addr)));
+}
+
+static void dev_addr_test_sync_one(struct kunit *test)
+{
+ struct net_device *netdev = test->priv;
+ struct dev_addr_test_priv *datp;
+ u8 addr[ETH_ALEN];
+
+ datp = netdev_priv(netdev);
+
+ memset(addr, 1, sizeof(addr));
+ eth_hw_addr_set(netdev, addr);
+
+ __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
+ dev_addr_test_unsync);
+ KUNIT_EXPECT_EQ(test, 2, datp->addr_seen);
+
+ memset(addr, 2, sizeof(addr));
+ eth_hw_addr_set(netdev, addr);
+
+ datp->addr_seen = 0;
+ __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
+ dev_addr_test_unsync);
+ /* It's not going to sync anything because the main address is
+ * considered synced and we overwrite in place.
+ */
+ KUNIT_EXPECT_EQ(test, 0, datp->addr_seen);
+}
+
+static void dev_addr_test_add_del(struct kunit *test)
+{
+ struct net_device *netdev = test->priv;
+ struct dev_addr_test_priv *datp;
+ u8 addr[ETH_ALEN];
+ int i;
+
+ datp = netdev_priv(netdev);
+
+ for (i = 1; i < 4; i++) {
+ memset(addr, i, sizeof(addr));
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+ }
+ /* Add 3 again */
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+
+ __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
+ dev_addr_test_unsync);
+ KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen);
+
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+
+ __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
+ dev_addr_test_unsync);
+ KUNIT_EXPECT_EQ(test, 0xf, datp->addr_seen);
+
+ for (i = 1; i < 4; i++) {
+ memset(addr, i, sizeof(addr));
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+ }
+
+ __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
+ dev_addr_test_unsync);
+ KUNIT_EXPECT_EQ(test, 1, datp->addr_seen);
+}
+
+static void dev_addr_test_del_main(struct kunit *test)
+{
+ struct net_device *netdev = test->priv;
+ u8 addr[ETH_ALEN];
+
+ memset(addr, 1, sizeof(addr));
+ eth_hw_addr_set(netdev, addr);
+
+ KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_del(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+ KUNIT_EXPECT_EQ(test, -ENOENT, dev_addr_del(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+}
+
+static void dev_addr_test_add_set(struct kunit *test)
+{
+ struct net_device *netdev = test->priv;
+ struct dev_addr_test_priv *datp;
+ u8 addr[ETH_ALEN];
+ int i;
+
+ datp = netdev_priv(netdev);
+
+ /* There is no external API like dev_addr_add_excl(),
+ * so shuffle the tree a little bit and exploit aliasing.
+ */
+ for (i = 1; i < 16; i++) {
+ memset(addr, i, sizeof(addr));
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+ }
+
+ memset(addr, i, sizeof(addr));
+ eth_hw_addr_set(netdev, addr);
+ KUNIT_EXPECT_EQ(test, 0, dev_addr_add(netdev, addr,
+ NETDEV_HW_ADDR_T_LAN));
+ memset(addr, 0, sizeof(addr));
+ eth_hw_addr_set(netdev, addr);
+
+ __hw_addr_sync_dev(&netdev->dev_addrs, netdev, dev_addr_test_sync,
+ dev_addr_test_unsync);
+ KUNIT_EXPECT_EQ(test, 0xffff, datp->addr_seen);
+}
+
+static void dev_addr_test_add_excl(struct kunit *test)
+{
+ struct net_device *netdev = test->priv;
+ u8 addr[ETH_ALEN];
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ memset(addr, i, sizeof(addr));
+ KUNIT_EXPECT_EQ(test, 0, dev_uc_add_excl(netdev, addr));
+ }
+ KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr));
+
+ for (i = 0; i < 10; i += 2) {
+ memset(addr, i, sizeof(addr));
+ KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr));
+ }
+ for (i = 1; i < 10; i += 2) {
+ memset(addr, i, sizeof(addr));
+ KUNIT_EXPECT_EQ(test, -EEXIST, dev_uc_add_excl(netdev, addr));
+ }
+}
+
+static struct kunit_case dev_addr_test_cases[] = {
+ KUNIT_CASE(dev_addr_test_basic),
+ KUNIT_CASE(dev_addr_test_sync_one),
+ KUNIT_CASE(dev_addr_test_add_del),
+ KUNIT_CASE(dev_addr_test_del_main),
+ KUNIT_CASE(dev_addr_test_add_set),
+ KUNIT_CASE(dev_addr_test_add_excl),
+ {}
+};
+
+static struct kunit_suite dev_addr_test_suite = {
+ .name = "dev-addr-list-test",
+ .test_cases = dev_addr_test_cases,
+ .init = dev_addr_test_init,
+ .exit = dev_addr_test_exit,
+};
+kunit_test_suite(dev_addr_test_suite);
+
+MODULE_LICENSE("GPL");
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 0/7] net: constify netdev->dev_addr
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
` (6 preceding siblings ...)
2021-11-19 14:21 ` [PATCH net-next v2 7/7] net: kunit: add a test for dev_addr_lists Jakub Kicinski
@ 2021-11-19 15:46 ` David Miller
2021-11-20 12:30 ` patchwork-bot+netdevbpf
8 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2021-11-19 15:46 UTC (permalink / raw)
To: kuba; +Cc: netdev
From: Jakub Kicinski <kuba@kernel.org>
Date: Fri, 19 Nov 2021 06:21:48 -0800
> Take care of a few stragglers and make netdev->dev_addr const.
>
> netdev->dev_addr can be held on the address tree like any other
> address now.
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 0/7] net: constify netdev->dev_addr
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
` (7 preceding siblings ...)
2021-11-19 15:46 ` [PATCH net-next v2 0/7] net: constify netdev->dev_addr David Miller
@ 2021-11-20 12:30 ` patchwork-bot+netdevbpf
8 siblings, 0 replies; 10+ messages in thread
From: patchwork-bot+netdevbpf @ 2021-11-20 12:30 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: davem, netdev
Hello:
This series was applied to netdev/net-next.git (master)
by David S. Miller <davem@davemloft.net>:
On Fri, 19 Nov 2021 06:21:48 -0800 you wrote:
> Take care of a few stragglers and make netdev->dev_addr const.
>
> netdev->dev_addr can be held on the address tree like any other
> address now.
>
> Jakub Kicinski (7):
> 82596: use eth_hw_addr_set()
> bnx2x: constify static inline stub for dev_addr
> net: constify netdev->dev_addr
> net: unexport dev_addr_init() & dev_addr_flush()
> dev_addr: add a modification check
> dev_addr_list: put the first addr on the tree
> net: kunit: add a test for dev_addr_lists
>
> [...]
Here is the summary with links:
- [net-next,v2,1/7] 82596: use eth_hw_addr_set()
https://git.kernel.org/netdev/net-next/c/0f98d7e47843
- [net-next,v2,2/7] bnx2x: constify static inline stub for dev_addr
https://git.kernel.org/netdev/net-next/c/c9646a18033e
- [net-next,v2,3/7] net: constify netdev->dev_addr
https://git.kernel.org/netdev/net-next/c/adeef3e32146
- [net-next,v2,4/7] net: unexport dev_addr_init() & dev_addr_flush()
https://git.kernel.org/netdev/net-next/c/5f0b69238427
- [net-next,v2,5/7] dev_addr: add a modification check
https://git.kernel.org/netdev/net-next/c/d07b26f5bbea
- [net-next,v2,6/7] dev_addr_list: put the first addr on the tree
https://git.kernel.org/netdev/net-next/c/a387ff8e5dda
- [net-next,v2,7/7] net: kunit: add a test for dev_addr_lists
https://git.kernel.org/netdev/net-next/c/2c193f2cb110
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2021-11-20 12:30 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-11-19 14:21 [PATCH net-next v2 0/7] net: constify netdev->dev_addr Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 1/7] 82596: use eth_hw_addr_set() Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 2/7] bnx2x: constify static inline stub for dev_addr Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 3/7] net: constify netdev->dev_addr Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 4/7] net: unexport dev_addr_init() & dev_addr_flush() Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 5/7] dev_addr: add a modification check Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 6/7] dev_addr_list: put the first addr on the tree Jakub Kicinski
2021-11-19 14:21 ` [PATCH net-next v2 7/7] net: kunit: add a test for dev_addr_lists Jakub Kicinski
2021-11-19 15:46 ` [PATCH net-next v2 0/7] net: constify netdev->dev_addr David Miller
2021-11-20 12:30 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).