.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Handle bridge arp/nd proxy/suppress |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * |
---|
7 | 8 | * Authors: |
---|
8 | 9 | * Roopa Prabhu <roopa@cumulusnetworks.com> |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or |
---|
11 | | - * modify it under the terms of the GNU General Public License |
---|
12 | | - * as published by the Free Software Foundation; either version |
---|
13 | | - * 2 of the License, or (at your option) any later version. |
---|
14 | 10 | */ |
---|
15 | 11 | |
---|
16 | 12 | #include <linux/kernel.h> |
---|
.. | .. |
---|
21 | 17 | #include <linux/if_vlan.h> |
---|
22 | 18 | #include <linux/inetdevice.h> |
---|
23 | 19 | #include <net/addrconf.h> |
---|
| 20 | +#include <net/ipv6_stubs.h> |
---|
24 | 21 | #if IS_ENABLED(CONFIG_IPV6) |
---|
25 | 22 | #include <net/ip6_checksum.h> |
---|
26 | 23 | #endif |
---|
.. | .. |
---|
39 | 36 | } |
---|
40 | 37 | } |
---|
41 | 38 | |
---|
42 | | - br->neigh_suppress_enabled = neigh_suppress; |
---|
| 39 | + br_opt_toggle(br, BROPT_NEIGH_SUPPRESS_ENABLED, neigh_suppress); |
---|
43 | 40 | } |
---|
44 | 41 | |
---|
45 | 42 | #if IS_ENABLED(CONFIG_INET) |
---|
.. | .. |
---|
91 | 88 | } |
---|
92 | 89 | } |
---|
93 | 90 | |
---|
94 | | -static int br_chk_addr_ip(struct net_device *dev, void *data) |
---|
| 91 | +static int br_chk_addr_ip(struct net_device *dev, |
---|
| 92 | + struct netdev_nested_priv *priv) |
---|
95 | 93 | { |
---|
96 | | - __be32 ip = *(__be32 *)data; |
---|
| 94 | + __be32 ip = *(__be32 *)priv->data; |
---|
97 | 95 | struct in_device *in_dev; |
---|
98 | 96 | __be32 addr = 0; |
---|
99 | 97 | |
---|
.. | .. |
---|
110 | 108 | |
---|
111 | 109 | static bool br_is_local_ip(struct net_device *dev, __be32 ip) |
---|
112 | 110 | { |
---|
113 | | - if (br_chk_addr_ip(dev, &ip)) |
---|
| 111 | + struct netdev_nested_priv priv = { |
---|
| 112 | + .data = (void *)&ip, |
---|
| 113 | + }; |
---|
| 114 | + |
---|
| 115 | + if (br_chk_addr_ip(dev, &priv)) |
---|
114 | 116 | return true; |
---|
115 | 117 | |
---|
116 | 118 | /* check if ip is configured on upper dev */ |
---|
117 | | - if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip, &ip)) |
---|
| 119 | + if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip, &priv)) |
---|
118 | 120 | return true; |
---|
119 | 121 | |
---|
120 | 122 | return false; |
---|
.. | .. |
---|
130 | 132 | u8 *arpptr, *sha; |
---|
131 | 133 | __be32 sip, tip; |
---|
132 | 134 | |
---|
133 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = false; |
---|
| 135 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 0; |
---|
134 | 136 | |
---|
135 | 137 | if ((dev->flags & IFF_NOARP) || |
---|
136 | 138 | !pskb_may_pull(skb, arp_hdr_len(dev))) |
---|
.. | .. |
---|
155 | 157 | ipv4_is_multicast(tip)) |
---|
156 | 158 | return; |
---|
157 | 159 | |
---|
158 | | - if (br->neigh_suppress_enabled) { |
---|
| 160 | + if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) { |
---|
159 | 161 | if (p && (p->flags & BR_NEIGH_SUPPRESS)) |
---|
160 | 162 | return; |
---|
161 | 163 | if (parp->ar_op != htons(ARPOP_RREQUEST) && |
---|
162 | 164 | parp->ar_op != htons(ARPOP_RREPLY) && |
---|
163 | 165 | (ipv4_is_zeronet(sip) || sip == tip)) { |
---|
164 | 166 | /* prevent flooding to neigh suppress ports */ |
---|
165 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; |
---|
| 167 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; |
---|
166 | 168 | return; |
---|
167 | 169 | } |
---|
168 | 170 | } |
---|
.. | .. |
---|
177 | 179 | return; |
---|
178 | 180 | } |
---|
179 | 181 | |
---|
180 | | - if (br->neigh_suppress_enabled && br_is_local_ip(vlandev, tip)) { |
---|
| 182 | + if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) && |
---|
| 183 | + br_is_local_ip(vlandev, tip)) { |
---|
181 | 184 | /* its our local ip, so don't proxy reply |
---|
182 | 185 | * and don't forward to neigh suppress ports |
---|
183 | 186 | */ |
---|
184 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; |
---|
| 187 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; |
---|
185 | 188 | return; |
---|
186 | 189 | } |
---|
187 | 190 | |
---|
.. | .. |
---|
215 | 218 | /* If we have replied or as long as we know the |
---|
216 | 219 | * mac, indicate to arp replied |
---|
217 | 220 | */ |
---|
218 | | - if (replied || br->neigh_suppress_enabled) |
---|
219 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; |
---|
| 221 | + if (replied || |
---|
| 222 | + br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) |
---|
| 223 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; |
---|
220 | 224 | } |
---|
221 | 225 | |
---|
222 | 226 | neigh_release(n); |
---|
.. | .. |
---|
364 | 368 | } |
---|
365 | 369 | } |
---|
366 | 370 | |
---|
367 | | -static int br_chk_addr_ip6(struct net_device *dev, void *data) |
---|
| 371 | +static int br_chk_addr_ip6(struct net_device *dev, |
---|
| 372 | + struct netdev_nested_priv *priv) |
---|
368 | 373 | { |
---|
369 | | - struct in6_addr *addr = (struct in6_addr *)data; |
---|
| 374 | + struct in6_addr *addr = (struct in6_addr *)priv->data; |
---|
370 | 375 | |
---|
371 | 376 | if (ipv6_chk_addr(dev_net(dev), addr, dev, 0)) |
---|
372 | 377 | return 1; |
---|
.. | .. |
---|
377 | 382 | static bool br_is_local_ip6(struct net_device *dev, struct in6_addr *addr) |
---|
378 | 383 | |
---|
379 | 384 | { |
---|
380 | | - if (br_chk_addr_ip6(dev, addr)) |
---|
| 385 | + struct netdev_nested_priv priv = { |
---|
| 386 | + .data = (void *)addr, |
---|
| 387 | + }; |
---|
| 388 | + |
---|
| 389 | + if (br_chk_addr_ip6(dev, &priv)) |
---|
381 | 390 | return true; |
---|
382 | 391 | |
---|
383 | 392 | /* check if ip is configured on upper dev */ |
---|
384 | | - if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip6, addr)) |
---|
| 393 | + if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip6, &priv)) |
---|
385 | 394 | return true; |
---|
386 | 395 | |
---|
387 | 396 | return false; |
---|
.. | .. |
---|
396 | 405 | struct ipv6hdr *iphdr; |
---|
397 | 406 | struct neighbour *n; |
---|
398 | 407 | |
---|
399 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = false; |
---|
| 408 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 0; |
---|
400 | 409 | |
---|
401 | 410 | if (p && (p->flags & BR_NEIGH_SUPPRESS)) |
---|
402 | 411 | return; |
---|
.. | .. |
---|
404 | 413 | if (msg->icmph.icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT && |
---|
405 | 414 | !msg->icmph.icmp6_solicited) { |
---|
406 | 415 | /* prevent flooding to neigh suppress ports */ |
---|
407 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; |
---|
| 416 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; |
---|
408 | 417 | return; |
---|
409 | 418 | } |
---|
410 | 419 | |
---|
.. | .. |
---|
417 | 426 | |
---|
418 | 427 | if (ipv6_addr_any(saddr) || !ipv6_addr_cmp(saddr, daddr)) { |
---|
419 | 428 | /* prevent flooding to neigh suppress ports */ |
---|
420 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; |
---|
| 429 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; |
---|
421 | 430 | return; |
---|
422 | 431 | } |
---|
423 | 432 | |
---|
.. | .. |
---|
435 | 444 | /* its our own ip, so don't proxy reply |
---|
436 | 445 | * and don't forward to arp suppress ports |
---|
437 | 446 | */ |
---|
438 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; |
---|
| 447 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; |
---|
439 | 448 | return; |
---|
440 | 449 | } |
---|
441 | 450 | |
---|
.. | .. |
---|
466 | 475 | * mac, indicate to NEIGH_SUPPRESS ports that we |
---|
467 | 476 | * have replied |
---|
468 | 477 | */ |
---|
469 | | - if (replied || br->neigh_suppress_enabled) |
---|
470 | | - BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; |
---|
| 478 | + if (replied || |
---|
| 479 | + br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) |
---|
| 480 | + BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1; |
---|
471 | 481 | } |
---|
472 | 482 | neigh_release(n); |
---|
473 | 483 | } |
---|