|
88 | 88 | #if IS_ENABLED(CONFIG_TLS_DEVICE)
|
89 | 89 | #include <net/tls.h>
|
90 | 90 | #endif
|
| 91 | +#include <net/ip6_route.h> |
91 | 92 |
|
92 | 93 | #include "bonding_priv.h"
|
93 | 94 |
|
@@ -2975,30 +2976,17 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
|
2975 | 2976 | slave->target_last_arp_rx[i] = jiffies;
|
2976 | 2977 | }
|
2977 | 2978 |
|
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) |
2980 | 2981 | {
|
2981 | 2982 | struct arphdr *arp = (struct arphdr *)skb->data;
|
2982 | 2983 | struct slave *curr_active_slave, *curr_arp_slave;
|
2983 | 2984 | unsigned char *arp_ptr;
|
2984 | 2985 | __be32 sip, tip;
|
2985 |
| - int is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP); |
2986 | 2986 | unsigned int alen;
|
2987 | 2987 |
|
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 |
| - |
2997 | 2988 | alen = arp_hdr_len(bond->dev);
|
2998 | 2989 |
|
2999 |
| - slave_dbg(bond->dev, slave->dev, "%s: skb->dev %s\n", |
3000 |
| - __func__, skb->dev->name); |
3001 |
| - |
3002 | 2990 | if (alen > skb_headlen(skb)) {
|
3003 | 2991 | arp = kmalloc(alen, GFP_ATOMIC);
|
3004 | 2992 | if (!arp)
|
@@ -3069,6 +3057,216 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
|
3069 | 3057 | return RX_HANDLER_ANOTHER;
|
3070 | 3058 | }
|
3071 | 3059 |
|
| 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 | + |
3072 | 3270 | /* function to verify if we're in the arp_interval timeslice, returns true if
|
3073 | 3271 | * (last_act - arp_interval) <= jiffies <= (last_act + mod * arp_interval +
|
3074 | 3272 | * 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)
|
3164 | 3362 | * to be unstable during low/no traffic periods
|
3165 | 3363 | */
|
3166 | 3364 | if (bond_slave_is_up(slave))
|
3167 |
| - bond_arp_send_all(bond, slave); |
| 3365 | + bond_send_validate(bond, slave); |
3168 | 3366 | }
|
3169 | 3367 |
|
3170 | 3368 | rcu_read_unlock();
|
@@ -3378,7 +3576,7 @@ static bool bond_ab_arp_probe(struct bonding *bond)
|
3378 | 3576 | curr_active_slave->dev->name);
|
3379 | 3577 |
|
3380 | 3578 | if (curr_active_slave) {
|
3381 |
| - bond_arp_send_all(bond, curr_active_slave); |
| 3579 | + bond_send_validate(bond, curr_active_slave); |
3382 | 3580 | return should_notify_rtnl;
|
3383 | 3581 | }
|
3384 | 3582 |
|
@@ -3430,7 +3628,7 @@ static bool bond_ab_arp_probe(struct bonding *bond)
|
3430 | 3628 | bond_set_slave_link_state(new_slave, BOND_LINK_BACK,
|
3431 | 3629 | BOND_SLAVE_NOTIFY_LATER);
|
3432 | 3630 | 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); |
3434 | 3632 | new_slave->last_link_up = jiffies;
|
3435 | 3633 | rcu_assign_pointer(bond->current_arp_slave, new_slave);
|
3436 | 3634 |
|
@@ -3966,7 +4164,7 @@ static int bond_open(struct net_device *bond_dev)
|
3966 | 4164 |
|
3967 | 4165 | if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
|
3968 | 4166 | queue_delayed_work(bond->wq, &bond->arp_work, 0);
|
3969 |
| - bond->recv_probe = bond_arp_rcv; |
| 4167 | + bond->recv_probe = bond_rcv_validate; |
3970 | 4168 | }
|
3971 | 4169 |
|
3972 | 4170 | if (BOND_MODE(bond) == BOND_MODE_8023AD) {
|
@@ -5947,6 +6145,7 @@ static int bond_check_params(struct bond_params *params)
|
5947 | 6145 | strscpy_pad(params->primary, primary, sizeof(params->primary));
|
5948 | 6146 |
|
5949 | 6147 | memcpy(params->arp_targets, arp_target, sizeof(arp_target));
|
| 6148 | + memset(params->ns_targets, 0, sizeof(struct in6_addr) * BOND_MAX_NS_TARGETS); |
5950 | 6149 |
|
5951 | 6150 | return 0;
|
5952 | 6151 | }
|
|
0 commit comments