Skip to content

Commit 4e24be0

Browse files
liuhangbindavem330
authored andcommitted
bonding: add new parameter ns_targets
Add a new bonding parameter ns_targets to store IPv6 address. Add required bond_ns_send/rcv functions first before adding IPv6 address option setting. Add two functions bond_send/rcv_validate so we can send/recv ARP and NS at the same time. Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 841e956 commit 4e24be0

File tree

3 files changed

+237
-21
lines changed

3 files changed

+237
-21
lines changed

drivers/net/bonding/bond_main.c

+218-19
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
#if IS_ENABLED(CONFIG_TLS_DEVICE)
8989
#include <net/tls.h>
9090
#endif
91+
#include <net/ip6_route.h>
9192

9293
#include "bonding_priv.h"
9394

@@ -2975,30 +2976,17 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
29752976
slave->target_last_arp_rx[i] = jiffies;
29762977
}
29772978

2978-
int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
2979-
struct slave *slave)
2979+
static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
2980+
struct slave *slave)
29802981
{
29812982
struct arphdr *arp = (struct arphdr *)skb->data;
29822983
struct slave *curr_active_slave, *curr_arp_slave;
29832984
unsigned char *arp_ptr;
29842985
__be32 sip, tip;
2985-
int is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
29862986
unsigned int alen;
29872987

2988-
if (!slave_do_arp_validate(bond, slave)) {
2989-
if ((slave_do_arp_validate_only(bond) && is_arp) ||
2990-
!slave_do_arp_validate_only(bond))
2991-
slave->last_rx = jiffies;
2992-
return RX_HANDLER_ANOTHER;
2993-
} else if (!is_arp) {
2994-
return RX_HANDLER_ANOTHER;
2995-
}
2996-
29972988
alen = arp_hdr_len(bond->dev);
29982989

2999-
slave_dbg(bond->dev, slave->dev, "%s: skb->dev %s\n",
3000-
__func__, skb->dev->name);
3001-
30022990
if (alen > skb_headlen(skb)) {
30032991
arp = kmalloc(alen, GFP_ATOMIC);
30042992
if (!arp)
@@ -3069,6 +3057,216 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
30693057
return RX_HANDLER_ANOTHER;
30703058
}
30713059

3060+
#if IS_ENABLED(CONFIG_IPV6)
3061+
static void bond_ns_send(struct slave *slave, const struct in6_addr *daddr,
3062+
const struct in6_addr *saddr, struct bond_vlan_tag *tags)
3063+
{
3064+
struct net_device *bond_dev = slave->bond->dev;
3065+
struct net_device *slave_dev = slave->dev;
3066+
struct in6_addr mcaddr;
3067+
struct sk_buff *skb;
3068+
3069+
slave_dbg(bond_dev, slave_dev, "NS on slave: dst %pI6c src %pI6c\n",
3070+
daddr, saddr);
3071+
3072+
skb = ndisc_ns_create(slave_dev, daddr, saddr, 0);
3073+
if (!skb) {
3074+
net_err_ratelimited("NS packet allocation failed\n");
3075+
return;
3076+
}
3077+
3078+
addrconf_addr_solict_mult(daddr, &mcaddr);
3079+
if (bond_handle_vlan(slave, tags, skb))
3080+
ndisc_send_skb(skb, &mcaddr, saddr);
3081+
}
3082+
3083+
static void bond_ns_send_all(struct bonding *bond, struct slave *slave)
3084+
{
3085+
struct in6_addr *targets = bond->params.ns_targets;
3086+
struct bond_vlan_tag *tags;
3087+
struct dst_entry *dst;
3088+
struct in6_addr saddr;
3089+
struct flowi6 fl6;
3090+
int i;
3091+
3092+
for (i = 0; i < BOND_MAX_NS_TARGETS && !ipv6_addr_any(&targets[i]); i++) {
3093+
slave_dbg(bond->dev, slave->dev, "%s: target %pI6c\n",
3094+
__func__, &targets[i]);
3095+
tags = NULL;
3096+
3097+
/* Find out through which dev should the packet go */
3098+
memset(&fl6, 0, sizeof(struct flowi6));
3099+
fl6.daddr = targets[i];
3100+
fl6.flowi6_oif = bond->dev->ifindex;
3101+
3102+
dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6);
3103+
if (dst->error) {
3104+
dst_release(dst);
3105+
/* there's no route to target - try to send arp
3106+
* probe to generate any traffic (arp_validate=0)
3107+
*/
3108+
if (bond->params.arp_validate)
3109+
pr_warn_once("%s: no route to ns_ip6_target %pI6c and arp_validate is set\n",
3110+
bond->dev->name,
3111+
&targets[i]);
3112+
bond_ns_send(slave, &targets[i], &in6addr_any, tags);
3113+
continue;
3114+
}
3115+
3116+
/* bond device itself */
3117+
if (dst->dev == bond->dev)
3118+
goto found;
3119+
3120+
rcu_read_lock();
3121+
tags = bond_verify_device_path(bond->dev, dst->dev, 0);
3122+
rcu_read_unlock();
3123+
3124+
if (!IS_ERR_OR_NULL(tags))
3125+
goto found;
3126+
3127+
/* Not our device - skip */
3128+
slave_dbg(bond->dev, slave->dev, "no path to ns_ip6_target %pI6c via dst->dev %s\n",
3129+
&targets[i], dst->dev ? dst->dev->name : "NULL");
3130+
3131+
dst_release(dst);
3132+
continue;
3133+
3134+
found:
3135+
if (!ipv6_dev_get_saddr(dev_net(dst->dev), dst->dev, &targets[i], 0, &saddr))
3136+
bond_ns_send(slave, &targets[i], &saddr, tags);
3137+
dst_release(dst);
3138+
kfree(tags);
3139+
}
3140+
}
3141+
3142+
static int bond_confirm_addr6(struct net_device *dev,
3143+
struct netdev_nested_priv *priv)
3144+
{
3145+
struct in6_addr *addr = (struct in6_addr *)priv->data;
3146+
3147+
return ipv6_chk_addr(dev_net(dev), addr, dev, 0);
3148+
}
3149+
3150+
static bool bond_has_this_ip6(struct bonding *bond, struct in6_addr *addr)
3151+
{
3152+
struct netdev_nested_priv priv = {
3153+
.data = addr,
3154+
};
3155+
int ret = false;
3156+
3157+
if (bond_confirm_addr6(bond->dev, &priv))
3158+
return true;
3159+
3160+
rcu_read_lock();
3161+
if (netdev_walk_all_upper_dev_rcu(bond->dev, bond_confirm_addr6, &priv))
3162+
ret = true;
3163+
rcu_read_unlock();
3164+
3165+
return ret;
3166+
}
3167+
3168+
static void bond_validate_ns(struct bonding *bond, struct slave *slave,
3169+
struct in6_addr *saddr, struct in6_addr *daddr)
3170+
{
3171+
int i;
3172+
3173+
if (ipv6_addr_any(saddr) || !bond_has_this_ip6(bond, daddr)) {
3174+
slave_dbg(bond->dev, slave->dev, "%s: sip %pI6c tip %pI6c not found\n",
3175+
__func__, saddr, daddr);
3176+
return;
3177+
}
3178+
3179+
i = bond_get_targets_ip6(bond->params.ns_targets, saddr);
3180+
if (i == -1) {
3181+
slave_dbg(bond->dev, slave->dev, "%s: sip %pI6c not found in targets\n",
3182+
__func__, saddr);
3183+
return;
3184+
}
3185+
slave->last_rx = jiffies;
3186+
slave->target_last_arp_rx[i] = jiffies;
3187+
}
3188+
3189+
static int bond_na_rcv(const struct sk_buff *skb, struct bonding *bond,
3190+
struct slave *slave)
3191+
{
3192+
struct slave *curr_active_slave, *curr_arp_slave;
3193+
struct icmp6hdr *hdr = icmp6_hdr(skb);
3194+
struct in6_addr *saddr, *daddr;
3195+
3196+
if (skb->pkt_type == PACKET_OTHERHOST ||
3197+
skb->pkt_type == PACKET_LOOPBACK ||
3198+
hdr->icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT)
3199+
goto out;
3200+
3201+
saddr = &ipv6_hdr(skb)->saddr;
3202+
daddr = &ipv6_hdr(skb)->daddr;
3203+
3204+
slave_dbg(bond->dev, slave->dev, "%s: %s/%d av %d sv %d sip %pI6c tip %pI6c\n",
3205+
__func__, slave->dev->name, bond_slave_state(slave),
3206+
bond->params.arp_validate, slave_do_arp_validate(bond, slave),
3207+
saddr, daddr);
3208+
3209+
curr_active_slave = rcu_dereference(bond->curr_active_slave);
3210+
curr_arp_slave = rcu_dereference(bond->current_arp_slave);
3211+
3212+
/* We 'trust' the received ARP enough to validate it if:
3213+
* see bond_arp_rcv().
3214+
*/
3215+
if (bond_is_active_slave(slave))
3216+
bond_validate_ns(bond, slave, saddr, daddr);
3217+
else if (curr_active_slave &&
3218+
time_after(slave_last_rx(bond, curr_active_slave),
3219+
curr_active_slave->last_link_up))
3220+
bond_validate_ns(bond, slave, saddr, daddr);
3221+
else if (curr_arp_slave &&
3222+
bond_time_in_interval(bond,
3223+
dev_trans_start(curr_arp_slave->dev), 1))
3224+
bond_validate_ns(bond, slave, saddr, daddr);
3225+
3226+
out:
3227+
return RX_HANDLER_ANOTHER;
3228+
}
3229+
#endif
3230+
3231+
int bond_rcv_validate(const struct sk_buff *skb, struct bonding *bond,
3232+
struct slave *slave)
3233+
{
3234+
#if IS_ENABLED(CONFIG_IPV6)
3235+
bool is_ipv6 = skb->protocol == __cpu_to_be16(ETH_P_IPV6);
3236+
#endif
3237+
bool is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
3238+
3239+
slave_dbg(bond->dev, slave->dev, "%s: skb->dev %s\n",
3240+
__func__, skb->dev->name);
3241+
3242+
/* Use arp validate logic for both ARP and NS */
3243+
if (!slave_do_arp_validate(bond, slave)) {
3244+
if ((slave_do_arp_validate_only(bond) && is_arp) ||
3245+
#if IS_ENABLED(CONFIG_IPV6)
3246+
(slave_do_arp_validate_only(bond) && is_ipv6) ||
3247+
#endif
3248+
!slave_do_arp_validate_only(bond))
3249+
slave->last_rx = jiffies;
3250+
return RX_HANDLER_ANOTHER;
3251+
} else if (is_arp) {
3252+
return bond_arp_rcv(skb, bond, slave);
3253+
#if IS_ENABLED(CONFIG_IPV6)
3254+
} else if (is_ipv6) {
3255+
return bond_na_rcv(skb, bond, slave);
3256+
#endif
3257+
} else {
3258+
return RX_HANDLER_ANOTHER;
3259+
}
3260+
}
3261+
3262+
static void bond_send_validate(struct bonding *bond, struct slave *slave)
3263+
{
3264+
bond_arp_send_all(bond, slave);
3265+
#if IS_ENABLED(CONFIG_IPV6)
3266+
bond_ns_send_all(bond, slave);
3267+
#endif
3268+
}
3269+
30723270
/* function to verify if we're in the arp_interval timeslice, returns true if
30733271
* (last_act - arp_interval) <= jiffies <= (last_act + mod * arp_interval +
30743272
* arp_interval/2) . the arp_interval/2 is needed for really fast networks.
@@ -3164,7 +3362,7 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
31643362
* to be unstable during low/no traffic periods
31653363
*/
31663364
if (bond_slave_is_up(slave))
3167-
bond_arp_send_all(bond, slave);
3365+
bond_send_validate(bond, slave);
31683366
}
31693367

31703368
rcu_read_unlock();
@@ -3378,7 +3576,7 @@ static bool bond_ab_arp_probe(struct bonding *bond)
33783576
curr_active_slave->dev->name);
33793577

33803578
if (curr_active_slave) {
3381-
bond_arp_send_all(bond, curr_active_slave);
3579+
bond_send_validate(bond, curr_active_slave);
33823580
return should_notify_rtnl;
33833581
}
33843582

@@ -3430,7 +3628,7 @@ static bool bond_ab_arp_probe(struct bonding *bond)
34303628
bond_set_slave_link_state(new_slave, BOND_LINK_BACK,
34313629
BOND_SLAVE_NOTIFY_LATER);
34323630
bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER);
3433-
bond_arp_send_all(bond, new_slave);
3631+
bond_send_validate(bond, new_slave);
34343632
new_slave->last_link_up = jiffies;
34353633
rcu_assign_pointer(bond->current_arp_slave, new_slave);
34363634

@@ -3966,7 +4164,7 @@ static int bond_open(struct net_device *bond_dev)
39664164

39674165
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
39684166
queue_delayed_work(bond->wq, &bond->arp_work, 0);
3969-
bond->recv_probe = bond_arp_rcv;
4167+
bond->recv_probe = bond_rcv_validate;
39704168
}
39714169

39724170
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
@@ -5947,6 +6145,7 @@ static int bond_check_params(struct bond_params *params)
59476145
strscpy_pad(params->primary, primary, sizeof(params->primary));
59486146

59496147
memcpy(params->arp_targets, arp_target, sizeof(arp_target));
6148+
memset(params->ns_targets, 0, sizeof(struct in6_addr) * BOND_MAX_NS_TARGETS);
59506149

59516150
return 0;
59526151
}

drivers/net/bonding/bond_options.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ static int bond_option_arp_interval_set(struct bonding *bond,
10521052
cancel_delayed_work_sync(&bond->arp_work);
10531053
} else {
10541054
/* arp_validate can be set only in active-backup mode */
1055-
bond->recv_probe = bond_arp_rcv;
1055+
bond->recv_probe = bond_rcv_validate;
10561056
cancel_delayed_work_sync(&bond->mii_work);
10571057
queue_delayed_work(bond->wq, &bond->arp_work, 0);
10581058
}

include/net/bonding.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@
2929
#include <net/bond_3ad.h>
3030
#include <net/bond_alb.h>
3131
#include <net/bond_options.h>
32+
#include <net/ipv6.h>
33+
#include <net/addrconf.h>
3234

3335
#define BOND_MAX_ARP_TARGETS 16
36+
#define BOND_MAX_NS_TARGETS BOND_MAX_ARP_TARGETS
3437

3538
#define BOND_DEFAULT_MIIMON 100
3639

@@ -146,6 +149,7 @@ struct bond_params {
146149
struct reciprocal_value reciprocal_packets_per_slave;
147150
u16 ad_actor_sys_prio;
148151
u16 ad_user_port_key;
152+
struct in6_addr ns_targets[BOND_MAX_NS_TARGETS];
149153

150154
/* 2 bytes of padding : see ether_addr_equal_64bits() */
151155
u8 ad_actor_system[ETH_ALEN + 2];
@@ -628,7 +632,7 @@ struct bond_net {
628632
struct class_attribute class_attr_bonding_masters;
629633
};
630634

631-
int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave);
635+
int bond_rcv_validate(const struct sk_buff *skb, struct bonding *bond, struct slave *slave);
632636
netdev_tx_t bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
633637
int bond_create(struct net *net, const char *name);
634638
int bond_create_sysfs(struct bond_net *net);
@@ -735,6 +739,19 @@ static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
735739
return -1;
736740
}
737741

742+
static inline int bond_get_targets_ip6(struct in6_addr *targets, struct in6_addr *ip)
743+
{
744+
int i;
745+
746+
for (i = 0; i < BOND_MAX_NS_TARGETS; i++)
747+
if (ipv6_addr_equal(&targets[i], ip))
748+
return i;
749+
else if (ipv6_addr_any(&targets[i]))
750+
break;
751+
752+
return -1;
753+
}
754+
738755
/* exported from bond_main.c */
739756
extern unsigned int bond_net_id;
740757

0 commit comments

Comments
 (0)