* [PATCH net-next v12 1/7] bonding: Adding struct bond_arp_target
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
@ 2025-09-30 23:38 ` David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 2/7] bonding: Adding extra_len field to struct bond_opt_value David Wilder
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Wilder @ 2025-09-30 23:38 UTC (permalink / raw)
To: netdev; +Cc: wilder
Replacing the definition of bond_params.arp_targets (__be32 arp_targets[])
with:
struct bond_arp_target {
__be32 target_ip;
u32 flags;
struct bond_vlan_tag *tags;
};
To provide storage for a list of vlan tags for each target.
All references to arp_target are change to use the new structure.
Signed-off-by: David Wilder <wilder@us.ibm.com>
---
drivers/net/bonding/bond_main.c | 29 ++++++++++++++++-------------
drivers/net/bonding/bond_netlink.c | 4 ++--
drivers/net/bonding/bond_options.c | 18 +++++++++---------
drivers/net/bonding/bond_procfs.c | 4 ++--
drivers/net/bonding/bond_sysfs.c | 4 ++--
include/net/bond_options.h | 20 ++++++++++++++++++++
include/net/bonding.h | 15 +++++----------
7 files changed, 56 insertions(+), 38 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1ea41f1a9190..57cf4585816d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3066,26 +3066,29 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
{
struct rtable *rt;
struct bond_vlan_tag *tags;
- __be32 *targets = bond->params.arp_targets, addr;
+ struct bond_arp_target *targets = bond->params.arp_targets;
+ __be32 target_ip, addr;
int i;
- for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) {
+ for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i].target_ip; i++) {
+ target_ip = targets[i].target_ip;
+ tags = targets[i].tags;
+
slave_dbg(bond->dev, slave->dev, "%s: target %pI4\n",
- __func__, &targets[i]);
- tags = NULL;
+ __func__, &target_ip);
/* Find out through which dev should the packet go */
- rt = ip_route_output(dev_net(bond->dev), targets[i], 0, 0, 0,
+ rt = ip_route_output(dev_net(bond->dev), target_ip, 0, 0, 0,
RT_SCOPE_LINK);
if (IS_ERR(rt)) {
- /* there's no route to target - try to send arp
+ /* there's no route to target_ip - try to send arp
* probe to generate any traffic (arp_validate=0)
*/
if (bond->params.arp_validate)
pr_warn_once("%s: no route to arp_ip_target %pI4 and arp_validate is set\n",
bond->dev->name,
- &targets[i]);
- bond_arp_send(slave, ARPOP_REQUEST, targets[i],
+ &target_ip);
+ bond_arp_send(slave, ARPOP_REQUEST, target_ip,
0, tags);
continue;
}
@@ -3103,15 +3106,15 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
/* Not our device - skip */
slave_dbg(bond->dev, slave->dev, "no path to arp_ip_target %pI4 via rt.dev %s\n",
- &targets[i], rt->dst.dev ? rt->dst.dev->name : "NULL");
+ &target_ip, rt->dst.dev ? rt->dst.dev->name : "NULL");
ip_rt_put(rt);
continue;
found:
- addr = bond_confirm_addr(rt->dst.dev, targets[i], 0);
+ addr = bond_confirm_addr(rt->dst.dev, target_ip, 0);
ip_rt_put(rt);
- bond_arp_send(slave, ARPOP_REQUEST, targets[i], addr, tags);
+ bond_arp_send(slave, ARPOP_REQUEST, target_ip, addr, tags);
kfree(tags);
}
}
@@ -6066,7 +6069,7 @@ static int __init bond_check_params(struct bond_params *params)
int arp_all_targets_value = 0;
u16 ad_actor_sys_prio = 0;
u16 ad_user_port_key = 0;
- __be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0 };
+ struct bond_arp_target arp_target[BOND_MAX_ARP_TARGETS] = { 0 };
int arp_ip_count;
int bond_mode = BOND_MODE_ROUNDROBIN;
int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
@@ -6260,7 +6263,7 @@ static int __init bond_check_params(struct bond_params *params)
arp_interval = 0;
} else {
if (bond_get_targets_ip(arp_target, ip) == -1)
- arp_target[arp_ip_count++] = ip;
+ arp_target[arp_ip_count++].target_ip = ip;
else
pr_warn("Warning: duplicate address %pI4 in arp_ip_target, skipping\n",
&ip);
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index ba71d95a82d2..cc00fbad9dd3 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -714,8 +714,8 @@ static int bond_fill_info(struct sk_buff *skb,
targets_added = 0;
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
- if (bond->params.arp_targets[i]) {
- if (nla_put_be32(skb, i, bond->params.arp_targets[i]))
+ if (bond->params.arp_targets[i].target_ip) {
+ if (nla_put_be32(skb, i, bond->params.arp_targets[i].target_ip))
goto nla_put_failure;
targets_added = 1;
}
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 495a87f2ea7c..91d57ba968d6 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1125,7 +1125,7 @@ static int bond_option_arp_interval_set(struct bonding *bond,
netdev_dbg(bond->dev, "ARP monitoring cannot be used with MII monitoring. Disabling MII monitoring\n");
bond->params.miimon = 0;
}
- if (!bond->params.arp_targets[0])
+ if (!bond->params.arp_targets[0].target_ip)
netdev_dbg(bond->dev, "ARP monitoring has been set up, but no ARP targets have been specified\n");
}
if (bond->dev->flags & IFF_UP) {
@@ -1153,20 +1153,20 @@ static void _bond_options_arp_ip_target_set(struct bonding *bond, int slot,
__be32 target,
unsigned long last_rx)
{
- __be32 *targets = bond->params.arp_targets;
+ struct bond_arp_target *targets = bond->params.arp_targets;
struct list_head *iter;
struct slave *slave;
if (slot >= 0 && slot < BOND_MAX_ARP_TARGETS) {
bond_for_each_slave(bond, slave, iter)
slave->target_last_arp_rx[slot] = last_rx;
- targets[slot] = target;
+ targets[slot].target_ip = target;
}
}
static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
{
- __be32 *targets = bond->params.arp_targets;
+ struct bond_arp_target *targets = bond->params.arp_targets;
int ind;
if (!bond_is_ip_target_ok(target)) {
@@ -1201,7 +1201,7 @@ static int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
{
- __be32 *targets = bond->params.arp_targets;
+ struct bond_arp_target *targets = bond->params.arp_targets;
struct list_head *iter;
struct slave *slave;
unsigned long *targets_rx;
@@ -1220,20 +1220,20 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
return -EINVAL;
}
- if (ind == 0 && !targets[1] && bond->params.arp_interval)
+ if (ind == 0 && !targets[1].target_ip && bond->params.arp_interval)
netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
netdev_dbg(bond->dev, "Removing ARP target %pI4\n", &target);
bond_for_each_slave(bond, slave, iter) {
targets_rx = slave->target_last_arp_rx;
- for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++)
+ for (i = ind; (i < BOND_MAX_ARP_TARGETS - 1) && targets[i + 1].target_ip; i++)
targets_rx[i] = targets_rx[i+1];
targets_rx[i] = 0;
}
- for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++)
+ for (i = ind; (i < BOND_MAX_ARP_TARGETS - 1) && targets[i + 1].target_ip; i++)
targets[i] = targets[i+1];
- targets[i] = 0;
+ targets[i].target_ip = 0;
return 0;
}
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 7edf72ec816a..94e6fd7041ee 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -121,11 +121,11 @@ static void bond_info_show_master(struct seq_file *seq)
seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
- if (!bond->params.arp_targets[i])
+ if (!bond->params.arp_targets[i].target_ip)
break;
if (printed)
seq_printf(seq, ",");
- seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
+ seq_printf(seq, " %pI4", &bond->params.arp_targets[i].target_ip);
printed = 1;
}
seq_printf(seq, "\n");
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 9a75ad3181ab..7114bd4d7735 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -290,9 +290,9 @@ static ssize_t bonding_show_arp_targets(struct device *d,
int i, res = 0;
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
- if (bond->params.arp_targets[i])
+ if (bond->params.arp_targets[i].target_ip)
res += sysfs_emit_at(buf, res, "%pI4 ",
- &bond->params.arp_targets[i]);
+ &bond->params.arp_targets[i].target_ip);
}
if (res)
buf[res-1] = '\n'; /* eat the leftover space */
diff --git a/include/net/bond_options.h b/include/net/bond_options.h
index e6eedf23aea1..dea58a07e4cc 100644
--- a/include/net/bond_options.h
+++ b/include/net/bond_options.h
@@ -121,6 +121,26 @@ struct bond_option {
int (*set)(struct bonding *bond, const struct bond_opt_value *val);
};
+struct bond_vlan_tag {
+ __be16 vlan_proto;
+ unsigned short vlan_id;
+};
+
+/* Value type flags:
+ * BOND_TARGET_DONTFREE - never free the tags
+ * BOND_TARGET_USERTAGS - tags have been supplied by the user
+ */
+enum {
+ BOND_TARGET_DONTFREE = BIT(0),
+ BOND_TARGET_USERTAGS = BIT(1),
+};
+
+struct bond_arp_target {
+ __be32 target_ip;
+ u32 flags;
+ struct bond_vlan_tag *tags;
+};
+
int __bond_opt_set(struct bonding *bond, unsigned int option,
struct bond_opt_value *val,
struct nlattr *bad_attr, struct netlink_ext_ack *extack);
diff --git a/include/net/bonding.h b/include/net/bonding.h
index 37335f62f579..a0eae209315f 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -136,7 +136,7 @@ struct bond_params {
int ad_select;
char primary[IFNAMSIZ];
int primary_reselect;
- __be32 arp_targets[BOND_MAX_ARP_TARGETS];
+ struct bond_arp_target arp_targets[BOND_MAX_ARP_TARGETS];
int tx_queues;
int all_slaves_active;
int resend_igmp;
@@ -276,11 +276,6 @@ struct bonding {
void bond_queue_slave_event(struct slave *slave);
void bond_lower_state_changed(struct slave *slave);
-struct bond_vlan_tag {
- __be16 vlan_proto;
- unsigned short vlan_id;
-};
-
/*
* Returns NULL if the net_device does not belong to any of the bond's slaves
*
@@ -524,7 +519,7 @@ static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond,
int i = 1;
unsigned long ret = slave->target_last_arp_rx[0];
- for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++)
+ for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i].target_ip; i++)
if (time_before(slave->target_last_arp_rx[i], ret))
ret = slave->target_last_arp_rx[i];
@@ -762,14 +757,14 @@ static inline bool bond_slave_has_mac_rcu(struct bonding *bond, const u8 *mac)
/* Check if the ip is present in arp ip list, or first free slot if ip == 0
* Returns -1 if not found, index if found
*/
-static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
+static inline int bond_get_targets_ip(struct bond_arp_target *targets, __be32 ip)
{
int i;
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
- if (targets[i] == ip)
+ if (targets[i].target_ip == ip)
return i;
- else if (targets[i] == 0)
+ else if (targets[i].target_ip == 0)
break;
return -1;
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v12 2/7] bonding: Adding extra_len field to struct bond_opt_value.
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 1/7] bonding: Adding struct bond_arp_target David Wilder
@ 2025-09-30 23:38 ` David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 3/7] bonding: arp_ip_target helpers David Wilder
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Wilder @ 2025-09-30 23:38 UTC (permalink / raw)
To: netdev; +Cc: wilder
Used to record the size of the extra array.
__bond_opt_init() is updated to set extra_len.
BOND_OPT_EXTRA_MAXLEN is increased from 16 to 64.
This is needed for the extended arp_ip_target option.
The ip command will now pass a variable length value when
setting arp_ip_target.
Signed-off-by: David Wilder <wilder@us.ibm.com>
---
include/net/bond_options.h | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/include/net/bond_options.h b/include/net/bond_options.h
index dea58a07e4cc..e3eb5fe6d1e8 100644
--- a/include/net/bond_options.h
+++ b/include/net/bond_options.h
@@ -87,14 +87,15 @@ enum {
* - if value != ULLONG_MAX -> parse value
* - if string != NULL -> parse string
* - if the opt is RAW data and length less than maxlen,
- * copy the data to extra storage
+ * copy the data to extra storage, extra_len is set to the size of data copied.
*/
-#define BOND_OPT_EXTRA_MAXLEN 16
+#define BOND_OPT_EXTRA_MAXLEN 64
struct bond_opt_value {
char *string;
u64 value;
u32 flags;
+ size_t extra_len;
union {
char extra[BOND_OPT_EXTRA_MAXLEN];
struct net_device *slave_dev;
@@ -169,8 +170,10 @@ static inline void __bond_opt_init(struct bond_opt_value *optval,
else if (string)
optval->string = string;
- if (extra && extra_len <= BOND_OPT_EXTRA_MAXLEN)
+ if (extra && extra_len <= BOND_OPT_EXTRA_MAXLEN) {
memcpy(optval->extra, extra, extra_len);
+ optval->extra_len = extra_len;
+ }
}
#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value, NULL, 0)
#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX, NULL, 0)
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v12 3/7] bonding: arp_ip_target helpers.
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 1/7] bonding: Adding struct bond_arp_target David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 2/7] bonding: Adding extra_len field to struct bond_opt_value David Wilder
@ 2025-09-30 23:38 ` David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 4/7] bonding: Processing extended arp_ip_target from user space David Wilder
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Wilder @ 2025-09-30 23:38 UTC (permalink / raw)
To: netdev; +Cc: wilder
Adding helpers and defines needed for extending the
arp_ip_target parameters.
Signed-off-by: David Wilder <wilder@us.ibm.com>
---
include/net/bonding.h | 46 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/include/net/bonding.h b/include/net/bonding.h
index a0eae209315f..75f6b1e32b3d 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -808,4 +808,50 @@ static inline netdev_tx_t bond_tx_drop(struct net_device *dev, struct sk_buff *s
return NET_XMIT_DROP;
}
+/* Helpers for handling arp_ip_target */
+#define BOND_OPTION_STRING_MAX_SIZE 64
+#define BOND_MAX_VLAN_TAGS 5
+#define BOND_VLAN_PROTO_NONE cpu_to_be16(0xffff)
+
+static inline char *bond_arp_target_to_string(struct bond_arp_target *target,
+ char *buf, int size)
+{
+ struct bond_vlan_tag *tags = target->tags;
+ int i, num = 0;
+
+ if (!(target->flags & BOND_TARGET_USERTAGS)) {
+ num = snprintf(&buf[0], size, "%pI4", &target->target_ip);
+ return buf;
+ }
+
+ num = snprintf(&buf[0], size, "%pI4[", &target->target_ip);
+ if (tags) {
+ for (i = 0; (tags[i].vlan_proto != BOND_VLAN_PROTO_NONE); i++) {
+ if (!tags[i].vlan_id)
+ continue;
+ if (i != 0)
+ num = num + snprintf(&buf[num], size - num, "/");
+ num = num + snprintf(&buf[num], size - num, "%u",
+ tags[i].vlan_id);
+ }
+ }
+ snprintf(&buf[num], size - num, "]");
+ return buf;
+}
+
+static inline void bond_free_vlan_tag(struct bond_arp_target *target)
+{
+ kfree(target->tags);
+}
+
+static inline void __bond_free_vlan_tags(struct bond_arp_target *targets)
+{
+ int i;
+
+ for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i].tags; i++)
+ bond_free_vlan_tag(&targets[i]);
+}
+
+#define bond_free_vlan_tags(targets) __bond_free_vlan_tags(targets)
+
#endif /* _NET_BONDING_H */
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v12 4/7] bonding: Processing extended arp_ip_target from user space.
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
` (2 preceding siblings ...)
2025-09-30 23:38 ` [PATCH net-next v12 3/7] bonding: arp_ip_target helpers David Wilder
@ 2025-09-30 23:38 ` David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 5/7] bonding: Update to bond_arp_send_all() to use supplied vlan tags David Wilder
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Wilder @ 2025-09-30 23:38 UTC (permalink / raw)
To: netdev; +Cc: wilder
Changes to bond_netlink and bond_options to process extended
format arp_ip_target option sent from user space via the ip
command.
The extended format adds a list of vlan tags to the ip target address.
Signed-off-by: David Wilder <wilder@us.ibm.com>
---
drivers/net/bonding/bond_netlink.c | 5 +-
drivers/net/bonding/bond_options.c | 126 +++++++++++++++++++++++------
2 files changed, 104 insertions(+), 27 deletions(-)
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index cc00fbad9dd3..97fdbd962513 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -307,9 +307,10 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
if (nla_len(attr) < sizeof(target))
return -EINVAL;
- target = nla_get_be32(attr);
+ bond_opt_initextra(&newval,
+ (__force void *)nla_data(attr),
+ nla_len(attr));
- bond_opt_initval(&newval, (__force u64)target);
err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
&newval,
data[IFLA_BOND_ARP_IP_TARGET],
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 91d57ba968d6..ba97479080ba 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -13,6 +13,7 @@
#include <linux/ctype.h>
#include <linux/inet.h>
#include <linux/sched/signal.h>
+#include <linux/if_vlan.h>
#include <net/bonding.h>
#include <net/ndisc.h>
@@ -31,8 +32,10 @@ static int bond_option_use_carrier_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_arp_interval_set(struct bonding *bond,
const struct bond_opt_value *newval);
-static int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target);
-static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target);
+static int bond_option_arp_ip_target_add(struct bonding *bond,
+ struct bond_arp_target target);
+static int bond_option_arp_ip_target_rem(struct bonding *bond,
+ struct bond_arp_target target);
static int bond_option_arp_ip_targets_set(struct bonding *bond,
const struct bond_opt_value *newval);
static int bond_option_ns_ip6_targets_set(struct bonding *bond,
@@ -1150,7 +1153,7 @@ static int bond_option_arp_interval_set(struct bonding *bond,
}
static void _bond_options_arp_ip_target_set(struct bonding *bond, int slot,
- __be32 target,
+ struct bond_arp_target target,
unsigned long last_rx)
{
struct bond_arp_target *targets = bond->params.arp_targets;
@@ -1160,24 +1163,26 @@ static void _bond_options_arp_ip_target_set(struct bonding *bond, int slot,
if (slot >= 0 && slot < BOND_MAX_ARP_TARGETS) {
bond_for_each_slave(bond, slave, iter)
slave->target_last_arp_rx[slot] = last_rx;
- targets[slot].target_ip = target;
+ memcpy(&targets[slot], &target, sizeof(target));
}
}
-static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
+static int _bond_option_arp_ip_target_add(struct bonding *bond,
+ struct bond_arp_target target)
{
struct bond_arp_target *targets = bond->params.arp_targets;
+ char pbuf[BOND_OPTION_STRING_MAX_SIZE];
int ind;
- if (!bond_is_ip_target_ok(target)) {
+ if (!bond_is_ip_target_ok(target.target_ip)) {
netdev_err(bond->dev, "invalid ARP target %pI4 specified for addition\n",
- &target);
+ &target.target_ip);
return -EINVAL;
}
- if (bond_get_targets_ip(targets, target) != -1) { /* dup */
+ if (bond_get_targets_ip(targets, target.target_ip) != -1) { /* dup */
netdev_err(bond->dev, "ARP target %pI4 is already present\n",
- &target);
+ &target.target_ip);
return -EINVAL;
}
@@ -1187,43 +1192,46 @@ static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
return -EINVAL;
}
- netdev_dbg(bond->dev, "Adding ARP target %pI4\n", &target);
+ netdev_dbg(bond->dev, "Adding ARP target %s\n",
+ bond_arp_target_to_string(&target, pbuf, sizeof(pbuf)));
_bond_options_arp_ip_target_set(bond, ind, target, jiffies);
return 0;
}
-static int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
+static int bond_option_arp_ip_target_add(struct bonding *bond,
+ struct bond_arp_target target)
{
return _bond_option_arp_ip_target_add(bond, target);
}
-static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
+static int bond_option_arp_ip_target_rem(struct bonding *bond,
+ struct bond_arp_target target)
{
struct bond_arp_target *targets = bond->params.arp_targets;
+ unsigned long *targets_rx;
struct list_head *iter;
struct slave *slave;
- unsigned long *targets_rx;
int ind, i;
- if (!bond_is_ip_target_ok(target)) {
+ if (!bond_is_ip_target_ok(target.target_ip)) {
netdev_err(bond->dev, "invalid ARP target %pI4 specified for removal\n",
- &target);
+ &target.target_ip);
return -EINVAL;
}
- ind = bond_get_targets_ip(targets, target);
+ ind = bond_get_targets_ip(targets, target.target_ip);
if (ind == -1) {
netdev_err(bond->dev, "unable to remove nonexistent ARP target %pI4\n",
- &target);
+ &target.target_ip);
return -EINVAL;
}
if (ind == 0 && !targets[1].target_ip && bond->params.arp_interval)
netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
- netdev_dbg(bond->dev, "Removing ARP target %pI4\n", &target);
+ netdev_dbg(bond->dev, "Removing ARP target %pI4\n", &target.target_ip);
bond_for_each_slave(bond, slave, iter) {
targets_rx = slave->target_last_arp_rx;
@@ -1231,30 +1239,77 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
targets_rx[i] = targets_rx[i+1];
targets_rx[i] = 0;
}
- for (i = ind; (i < BOND_MAX_ARP_TARGETS - 1) && targets[i + 1].target_ip; i++)
- targets[i] = targets[i+1];
+
+ bond_free_vlan_tag(&targets[ind]);
+
+ for (i = ind; (i < BOND_MAX_ARP_TARGETS - 1) && targets[i + 1].target_ip; i++) {
+ targets[i].target_ip = targets[i + 1].target_ip;
+ targets[i].tags = targets[i + 1].tags;
+ targets[i].flags = targets[i + 1].flags;
+ }
targets[i].target_ip = 0;
+ targets[i].flags = 0;
+ targets[i].tags = NULL;
return 0;
}
void bond_option_arp_ip_targets_clear(struct bonding *bond)
{
+ struct bond_arp_target empty_target = {};
int i;
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
- _bond_options_arp_ip_target_set(bond, i, 0, 0);
+ _bond_options_arp_ip_target_set(bond, i, empty_target, 0);
+}
+
+/**
+ * bond_validate_tags - validate an array of bond_vlan_tag.
+ * @tags: the array to validate
+ * @len: the length in bytes of @tags
+ *
+ * Validate that @tags points to a valid array of struct bond_vlan_tag.
+ * Returns: the length of the validated bytes in the array or -1 if no
+ * valid list is found.
+ */
+static int bond_validate_tags(struct bond_vlan_tag *tags, size_t len)
+{
+ size_t i, ntags = 0;
+
+ if (len == 0 || !tags)
+ return 0;
+
+ if (len % sizeof(struct bond_vlan_tag) != 0)
+ return -1;
+
+ for (i = 0; i <= len; i = i + sizeof(struct bond_vlan_tag)) {
+ if (ntags > BOND_MAX_VLAN_TAGS)
+ break;
+
+ if (tags->vlan_proto == BOND_VLAN_PROTO_NONE)
+ return i + sizeof(struct bond_vlan_tag);
+
+ if (!tags->vlan_id || tags->vlan_id >= VLAN_VID_MASK)
+ break;
+ tags++;
+ ntags++;
+ }
+ return -1;
}
static int bond_option_arp_ip_targets_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- int ret = -EPERM;
- __be32 target;
+ size_t len = (size_t)newval->extra_len;
+ char *extra = (char *)newval->extra;
+ struct bond_arp_target target;
+ int size, ret = -EPERM;
if (newval->string) {
+ /* Adding or removing arp_ip_target from sysfs */
if (strlen(newval->string) < 1 ||
- !in4_pton(newval->string + 1, -1, (u8 *)&target, -1, NULL)) {
+ !in4_pton(newval->string + 1, -1, (u8 *)&target.target_ip,
+ -1, NULL)) {
netdev_err(bond->dev, "invalid ARP target specified\n");
return ret;
}
@@ -1265,8 +1320,29 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond,
else
netdev_err(bond->dev, "no command found in arp_ip_targets file - use +<addr> or -<addr>\n");
} else {
- target = newval->value;
+ /* Adding arp_ip_target from netlink. aka: ip command */
+ memcpy(&target.target_ip, newval->extra, sizeof(__be32));
+ len = len - sizeof(target.target_ip);
+ extra = extra + sizeof(target.target_ip);
+
+ size = bond_validate_tags((struct bond_vlan_tag *)extra, len);
+
+ if (size > 0) {
+ target.tags = kmalloc((size_t)size, GFP_ATOMIC);
+ if (!target.tags)
+ return -ENOMEM;
+ memcpy(target.tags, extra, size);
+ target.flags |= BOND_TARGET_USERTAGS;
+ } else if (size == -1) {
+ netdev_err(bond->dev, "Invalid list of vlans provided with %pI4\n",
+ &target.target_ip);
+ return -EINVAL;
+ }
+
ret = bond_option_arp_ip_target_add(bond, target);
+
+ if (ret)
+ kfree(target.tags);
}
return ret;
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v12 5/7] bonding: Update to bond_arp_send_all() to use supplied vlan tags
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
` (3 preceding siblings ...)
2025-09-30 23:38 ` [PATCH net-next v12 4/7] bonding: Processing extended arp_ip_target from user space David Wilder
@ 2025-09-30 23:38 ` David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 6/7] bonding: Update for extended arp_ip_target format David Wilder
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Wilder @ 2025-09-30 23:38 UTC (permalink / raw)
To: netdev; +Cc: wilder
bond_arp_send_all() will pass the vlan tags supplied by
the user to bond_arp_send(). If vlan tags have not been
supplied the vlans in the path to the target will be
discovered by bond_verify_device_path().
bond_uninit() is also updated to free vlan tags when a
bond is destroyed.
Signed-off-by: David Wilder <wilder@us.ibm.com>
---
drivers/net/bonding/bond_main.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 57cf4585816d..8ef8b062d6f3 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3064,18 +3064,21 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
{
- struct rtable *rt;
- struct bond_vlan_tag *tags;
struct bond_arp_target *targets = bond->params.arp_targets;
+ char pbuf[BOND_OPTION_STRING_MAX_SIZE];
+ struct bond_vlan_tag *tags;
__be32 target_ip, addr;
+ struct rtable *rt;
+ u32 flags;
int i;
for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i].target_ip; i++) {
target_ip = targets[i].target_ip;
tags = targets[i].tags;
+ flags = targets[i].flags;
- slave_dbg(bond->dev, slave->dev, "%s: target %pI4\n",
- __func__, &target_ip);
+ slave_dbg(bond->dev, slave->dev, "%s: target %s\n", __func__,
+ bond_arp_target_to_string(&targets[i], pbuf, sizeof(pbuf)));
/* Find out through which dev should the packet go */
rt = ip_route_output(dev_net(bond->dev), target_ip, 0, 0, 0,
@@ -3097,9 +3100,11 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
if (rt->dst.dev == bond->dev)
goto found;
- rcu_read_lock();
- tags = bond_verify_device_path(bond->dev, rt->dst.dev, 0);
- rcu_read_unlock();
+ if (!tags) {
+ rcu_read_lock();
+ tags = bond_verify_device_path(bond->dev, rt->dst.dev, 0);
+ rcu_read_unlock();
+ }
if (!IS_ERR_OR_NULL(tags))
goto found;
@@ -3115,7 +3120,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
addr = bond_confirm_addr(rt->dst.dev, target_ip, 0);
ip_rt_put(rt);
bond_arp_send(slave, ARPOP_REQUEST, target_ip, addr, tags);
- kfree(tags);
+ if (!(flags & BOND_TARGET_USERTAGS))
+ kfree(tags);
}
}
@@ -6047,6 +6053,7 @@ static void bond_uninit(struct net_device *bond_dev)
bond_for_each_slave(bond, slave, iter)
__bond_release_one(bond_dev, slave->dev, true, true);
netdev_info(bond_dev, "Released all slaves\n");
+ // bond_free_vlan_tags(bond->params.arp_targets);
#ifdef CONFIG_XFRM_OFFLOAD
mutex_destroy(&bond->ipsec_lock);
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v12 6/7] bonding: Update for extended arp_ip_target format.
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
` (4 preceding siblings ...)
2025-09-30 23:38 ` [PATCH net-next v12 5/7] bonding: Update to bond_arp_send_all() to use supplied vlan tags David Wilder
@ 2025-09-30 23:38 ` David Wilder
2025-09-30 23:38 ` [PATCH net-next v12 7/7] bonding: Selftest and documentation for the arp_ip_target parameter David Wilder
2025-10-01 0:34 ` [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags Jakub Kicinski
7 siblings, 0 replies; 9+ messages in thread
From: David Wilder @ 2025-09-30 23:38 UTC (permalink / raw)
To: netdev; +Cc: wilder
Updated bond_fill_info() to support extended arp_ip_target format.
Forward and backward compatibility between the kernel and iproute2 is
preserved.
Signed-off-by: David Wilder <wilder@us.ibm.com>
---
drivers/net/bonding/bond_netlink.c | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 97fdbd962513..349b5525d007 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -676,6 +676,7 @@ static int bond_fill_info(struct sk_buff *skb,
const struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct bond_arp_target *arptargets;
unsigned int packets_per_slave;
int ifindex, i, targets_added;
struct nlattr *targets;
@@ -714,12 +715,31 @@ static int bond_fill_info(struct sk_buff *skb,
goto nla_put_failure;
targets_added = 0;
- for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
- if (bond->params.arp_targets[i].target_ip) {
- if (nla_put_be32(skb, i, bond->params.arp_targets[i].target_ip))
- goto nla_put_failure;
- targets_added = 1;
+
+ arptargets = bond->params.arp_targets;
+ for (i = 0; i < BOND_MAX_ARP_TARGETS && arptargets[i].target_ip ; i++) {
+ struct data {
+ __be32 addr;
+ struct bond_vlan_tag vlans[BOND_MAX_VLAN_TAGS + 1];
+ } __packed data;
+ int level, size;
+
+ data.addr = arptargets[i].target_ip;
+ size = sizeof(__be32);
+ targets_added = 1;
+
+ if (arptargets[i].flags & BOND_TARGET_USERTAGS) {
+ for (level = 0; level < BOND_MAX_VLAN_TAGS + 1 ; level++) {
+ data.vlans[level].vlan_proto = arptargets[i].tags[level].vlan_proto;
+ data.vlans[level].vlan_id = arptargets[i].tags[level].vlan_id;
+ size = size + sizeof(struct bond_vlan_tag);
+ if (arptargets[i].tags[level].vlan_proto == BOND_VLAN_PROTO_NONE)
+ break;
+ }
}
+
+ if (nla_put(skb, i, size, &data))
+ goto nla_put_failure;
}
if (targets_added)
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v12 7/7] bonding: Selftest and documentation for the arp_ip_target parameter.
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
` (5 preceding siblings ...)
2025-09-30 23:38 ` [PATCH net-next v12 6/7] bonding: Update for extended arp_ip_target format David Wilder
@ 2025-09-30 23:38 ` David Wilder
2025-10-01 0:34 ` [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags Jakub Kicinski
7 siblings, 0 replies; 9+ messages in thread
From: David Wilder @ 2025-09-30 23:38 UTC (permalink / raw)
To: netdev; +Cc: wilder
Selftest provided as a functional test for the arp_ip_target parameter
both with and without user supplied vlan tags. Bonding documentation
has been updated for the arp_ip_target option.
Signed-off-by: David Wilder <wilder@us.ibm.com>
---
Documentation/networking/bonding.rst | 11 +
.../selftests/drivers/net/bonding/Makefile | 3 +-
.../drivers/net/bonding/bond-arp-ip-target.sh | 205 ++++++++++++++++++
3 files changed, 218 insertions(+), 1 deletion(-)
create mode 100755 tools/testing/selftests/drivers/net/bonding/bond-arp-ip-target.sh
diff --git a/Documentation/networking/bonding.rst b/Documentation/networking/bonding.rst
index e700bf1d095c..08a3191a0322 100644
--- a/Documentation/networking/bonding.rst
+++ b/Documentation/networking/bonding.rst
@@ -330,6 +330,17 @@ arp_ip_target
maximum number of targets that can be specified is 16. The
default value is no IP addresses.
+ When an arp_ip_target is configured the bonding driver will
+ attempt to automatically determine what vlans the arp probe will
+ pass through. This process of gathering vlan tags is required
+ for the arp probe to be sent. However, in some configurations
+ this process may fail. In these cases you may manually
+ supply a list of vlan tags. To specify a list of vlan tags
+ append the ipv4 address with [tag1/tag2...]. For example:
+ arp_ip_target=10.0.0.1[10]. If you simply need to disable the
+ vlan discovery process you may provide an empty list, for example:
+ arp_ip_target=10.0.0.1[].
+
ns_ip6_target
Specifies the IPv6 addresses to use as IPv6 monitoring peers when
diff --git a/tools/testing/selftests/drivers/net/bonding/Makefile b/tools/testing/selftests/drivers/net/bonding/Makefile
index 3462783ed3ac..44965026fe45 100644
--- a/tools/testing/selftests/drivers/net/bonding/Makefile
+++ b/tools/testing/selftests/drivers/net/bonding/Makefile
@@ -12,7 +12,8 @@ TEST_PROGS := \
bond-eth-type-change.sh \
bond_macvlan_ipvlan.sh \
bond_passive_lacp.sh \
- bond_lacp_prio.sh
+ bond_lacp_prio.sh \
+ bond-arp-ip-target.sh
TEST_FILES := \
lag_lib.sh \
diff --git a/tools/testing/selftests/drivers/net/bonding/bond-arp-ip-target.sh b/tools/testing/selftests/drivers/net/bonding/bond-arp-ip-target.sh
new file mode 100755
index 000000000000..40cbd56c00f9
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/bonding/bond-arp-ip-target.sh
@@ -0,0 +1,205 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test bonding arp_ip_target.
+# Topology for Bond mode 1,5,6 testing
+#
+# +-------------------------+
+# | | Server
+# | bond0.10.20 | 192.20.2.1/24
+# | | |
+# | bond0.10 | 192.10.2.1/24
+# | | |
+# | bond0 | 192.0.2.1/24
+# | | |
+# | + |
+# | eth0 | eth1 |
+# | +---+---+ |
+# | | | |
+# +-------------------------+
+# | |
+# +-------------------------+
+# | | | |
+# | +---+-------+---+ | Gateway
+# | | br0 | |
+# | +-------+-------+ |
+# | | |
+# +-------------------------+
+# |
+# +-------------------------+
+# | | | Client
+# | eth0 | 192.0.0.2/24
+# | | |
+# | eth0.10 | 192.10.10.2/24
+# | | |
+# | eth0.10.20 | 192.20.20.2/24
+# +-------------------------+
+
+# shellcheck disable=SC2317
+
+lib_dir=$(dirname "$0")
+
+# shellcheck source=/dev/null # Ignore source warning.
+source "${lib_dir}"/bond_topo_2d1c.sh
+
+# shellcheck disable=SC2154 # Ignore unassigned referenced warning.
+echo "${c_ns}" "${s_ns}" > /dev/null
+
+DEBUG=${DEBUG:-0}
+test "${DEBUG}" -ne 0 && set -x
+
+# vlan subnets
+c_ip4="192.0.2.10"
+c_ip4v10="192.10.2.10"
+c_ip4v20="192.20.2.10"
+
+export ALL_TESTS="
+ no_vlan_hints
+ with_vlan_hints
+"
+
+# Build stacked vlans on top of an interface.
+stack_vlans()
+{
+ RET=0
+ local interface="$1"
+ local ns=$2
+ local last="$interface"
+ local tags="10 20"
+
+ if ! ip -n "${ns}" link show "${interface}" > /dev/null; then
+ RET=1
+ msg="Failed to create ${interface}"
+ return 1
+ fi
+
+ if [ "$ns" == "${s_ns}" ]; then host=1; else host=10;fi
+
+ for tag in $tags; do
+ ip -n "${ns}" link add link "$last" name "$last"."$tag" type vlan id "$tag"
+ ip -n "${ns}" address add 192."$tag".2."$host"/24 dev "$last"."$tag"
+ ip -n "${ns}" link set up dev "$last"."$tag"
+ last=$last.$tag
+ done
+}
+
+wait_for_arp_request()
+{
+ local target=$1
+ local ip
+ local interface
+
+ ip=$(echo "${target}" | awk -F "[" '{print $1}')
+ interface="$(ip -n "${c_ns}" -br addr show | grep "${ip}" | awk -F @ '{print $1}')"
+
+ tc -n "${c_ns}" qdisc add dev "${interface}" clsact
+ tc -n "${c_ns}" filter add dev "${interface}" ingress protocol arp \
+ handle 101 flower skip_hw arp_op request arp_tip "${ip}" action pass
+
+ slowwait_for_counter 5 5 tc_rule_handle_stats_get \
+ "dev ${interface} ingress" 101 ".packets" "-n ${c_ns}" &> /dev/null || RET=1
+
+ tc -n "${c_ns}" filter del dev "${interface}" ingress
+ tc -n "${c_ns}" qdisc del dev "${interface}" clsact
+
+ if [ "$RET" -ne 0 ]; then
+ msg="Arp probe not received by ${interface}"
+ return 1
+ fi
+}
+
+# Check for link flapping.
+# First verify the arp requests are being received
+# by the target. Then verify that the Link Failure
+# Counts are not increasing over time.
+# Arp probes are sent every 100ms, two probes must
+# be missed to trigger a slave failure. A one second
+# wait should be sufficient.
+check_failure_count()
+{
+ local bond=$1
+ local target=$2
+ local proc_file=/proc/net/bonding/${bond}
+
+ wait_for_arp_request "${target}" || return 1
+
+ LinkFailureCount1=$(ip netns exec "${s_ns}" grep -F "Link Failure Count" "${proc_file}" \
+ | awk -F: '{ sum += $2 } END { print sum }')
+ sleep 1
+ LinkFailureCount2=$(ip netns exec "${s_ns}" grep -F "Link Failure Count" "${proc_file}" \
+ | awk -F: '{ sum += $2 } END { print sum }')
+
+ [ "$LinkFailureCount1" != "$LinkFailureCount2" ] && RET=1
+}
+
+setup_bond_topo()
+{
+ setup_prepare
+ setup_wait
+ stack_vlans bond0 "${s_ns}"
+ stack_vlans eth0 "${c_ns}"
+}
+
+skip_with_vlan_hints()
+{
+ # check if iproute supports arp_ip_target with vlans option.
+ if ! ip -n "${s_ns}" link add bond2 type bond arp_ip_target 10.0.0.1[10]; then
+ ip -n "${s_ns}" link del bond2 2> /dev/null
+ return 0
+ fi
+ return 1
+}
+
+no_vlan_hints()
+{
+ RET=0
+ local targets="${c_ip4} ${c_ip4v10} ${c_ip4v20}"
+ local target
+ msg=""
+
+ for target in $targets; do
+ bond_reset "mode $mode arp_interval 100 arp_ip_target ${target}"
+ stack_vlans bond0 "${s_ns}"
+ if [ "$RET" -ne 0 ]; then
+ log_test "no_vlan_hints" "${msg}"
+ return
+ fi
+ check_failure_count bond0 "${target}"
+ log_test "arp_ip_target=${target} ${msg}"
+ done
+}
+
+with_vlan_hints()
+{
+ RET=0
+ local targets="${c_ip4}[] ${c_ip4v10}[10] ${c_ip4v20}[10/20]"
+ local target
+ msg=""
+
+ if skip_with_vlan_hints; then
+ log_test_skip "skip_with_vlan_hints" \
+ "Installed iproute doesn't support extended arp_ip_target options."
+ return 0
+ fi
+
+ for target in $targets; do
+ bond_reset "mode $mode arp_interval 100 arp_ip_target ${target}"
+ stack_vlans bond0 "${s_ns}"
+ if [ "$RET" -ne 0 ]; then
+ log_test "no_vlan_hints" "${msg}"
+ return
+ fi
+
+ check_failure_count bond0 "${target}"
+ log_test "arp_ip_target=${target} ${msg}"
+ done
+}
+
+trap cleanup EXIT
+
+mode=active-backup
+
+setup_bond_topo
+tests_run
+
+exit "$EXIT_STATUS"
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags.
2025-09-30 23:38 [PATCH net-next v12 0/7] bonding: Extend arp_ip_target format to allow for a list of vlan tags David Wilder
` (6 preceding siblings ...)
2025-09-30 23:38 ` [PATCH net-next v12 7/7] bonding: Selftest and documentation for the arp_ip_target parameter David Wilder
@ 2025-10-01 0:34 ` Jakub Kicinski
7 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2025-10-01 0:34 UTC (permalink / raw)
To: David Wilder; +Cc: netdev
On Tue, 30 Sep 2025 16:38:00 -0700 David Wilder wrote:
> The current implementation of the arp monitor builds a list of vlan-tags by
> following the chain of net_devices above the bond. See bond_verify_device_path().
> Unfortunately, with some configurations, this is not possible. One example is
> when an ovs switch is configured above the bond.
>
> This change extends the "arp_ip_target" parameter format to allow for a list of
> vlan tags to be included for each arp target. This new list of tags is optional
> and may be omitted to preserve the current format and process of discovering
> vlans.
Please read:
https://www.kernel.org/doc/html/next/process/maintainer-netdev.html
You're reposting this too soon in more than one way - there should be
at least 24h between postings. What's more net-next is closed right now
and Paolo told you this in his reply on v11.
--
pw-bot: defer
^ permalink raw reply [flat|nested] 9+ messages in thread