History

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.

Hangbin Liu committed 4 years ago

Commit 4e24be01 parent 841e9563 files · +237 −21Browse files

Unified · Split

3 files
  1. drivers/net/bonding/bond_main.c +218 −19
  2. drivers/net/bonding/bond_options.c +1 −1
  3. include/net/bonding.h +18 −1
drivers/net/bonding/bond_main.c+218−19
@@ -88,6 +88,7 @@ · 87 unmodified lines
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 · 2881 unmodified lines
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 @@ out_unlock: · 64 unmodified lines
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) · 89 unmodified lines
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) · 207 unmodified lines
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) · 45 unmodified lines
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) · 529 unmodified lines
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) · 1974 unmodified lines
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
@@ -1052,7 +1052,7 @@ static int bond_option_arp_interval_set(struct bonding *bond, · 1051 unmodified lines
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
@@ -29,8 +29,11 @@ · 28 unmodified lines
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 { · 109 unmodified lines
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 { · 476 unmodified lines
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) · 100 unmodified lines
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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t