Skip to content

Commit 842a9ae

Browse files
Jouni Malinendavem330
authored andcommitted
bridge: Extend Proxy ARP design to allow optional rules for Wi-Fi
This extends the design in commit 9585011 ("bridge: Add support for IEEE 802.11 Proxy ARP") with optional set of rules that are needed to meet the IEEE 802.11 and Hotspot 2.0 requirements for ProxyARP. The previously added BR_PROXYARP behavior is left as-is and a new BR_PROXYARP_WIFI alternative is added so that this behavior can be configured from user space when required. In addition, this enables proxyarp functionality for unicast ARP requests for both BR_PROXYARP and BR_PROXYARP_WIFI since it is possible to use unicast as well as broadcast for these frames. The key differences in functionality: BR_PROXYARP: - uses the flag on the bridge port on which the request frame was received to determine whether to reply - block bridge port flooding completely on ports that enable proxy ARP BR_PROXYARP_WIFI: - uses the flag on the bridge port to which the target device of the request belongs - block bridge port flooding selectively based on whether the proxyarp functionality replied Signed-off-by: Jouni Malinen <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 787fb2b commit 842a9ae

File tree

7 files changed

+22
-8
lines changed

7 files changed

+22
-8
lines changed

include/linux/if_bridge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct br_ip_list {
4444
#define BR_PROMISC BIT(7)
4545
#define BR_PROXYARP BIT(8)
4646
#define BR_LEARNING_SYNC BIT(9)
47+
#define BR_PROXYARP_WIFI BIT(10)
4748

4849
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
4950

include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ enum {
247247
IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */
248248
IFLA_BRPORT_PROXYARP, /* proxy ARP */
249249
IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */
250+
IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */
250251
__IFLA_BRPORT_MAX
251252
};
252253
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)

net/bridge/br_forward.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,
188188
/* Do not flood to ports that enable proxy ARP */
189189
if (p->flags & BR_PROXYARP)
190190
continue;
191+
if ((p->flags & BR_PROXYARP_WIFI) &&
192+
BR_INPUT_SKB_CB(skb)->proxyarp_replied)
193+
continue;
191194

192195
prev = maybe_deliver(prev, p, skb, __packet_hook);
193196
if (IS_ERR(prev))

net/bridge/br_input.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@ static int br_pass_frame_up(struct sk_buff *skb)
6060
}
6161

6262
static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
63-
u16 vid)
63+
u16 vid, struct net_bridge_port *p)
6464
{
6565
struct net_device *dev = br->dev;
6666
struct neighbour *n;
6767
struct arphdr *parp;
6868
u8 *arpptr, *sha;
6969
__be32 sip, tip;
7070

71+
BR_INPUT_SKB_CB(skb)->proxyarp_replied = false;
72+
7173
if (dev->flags & IFF_NOARP)
7274
return;
7375

@@ -105,9 +107,12 @@ static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
105107
}
106108

107109
f = __br_fdb_get(br, n->ha, vid);
108-
if (f)
110+
if (f && ((p->flags & BR_PROXYARP) ||
111+
(f->dst && (f->dst->flags & BR_PROXYARP_WIFI)))) {
109112
arp_send(ARPOP_REPLY, ETH_P_ARP, sip, skb->dev, tip,
110113
sha, n->ha, sha);
114+
BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
115+
}
111116

112117
neigh_release(n);
113118
}
@@ -153,12 +158,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
153158

154159
dst = NULL;
155160

156-
if (is_broadcast_ether_addr(dest)) {
157-
if (IS_ENABLED(CONFIG_INET) &&
158-
p->flags & BR_PROXYARP &&
159-
skb->protocol == htons(ETH_P_ARP))
160-
br_do_proxy_arp(skb, br, vid);
161+
if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP))
162+
br_do_proxy_arp(skb, br, vid, p);
161163

164+
if (is_broadcast_ether_addr(dest)) {
162165
skb2 = skb;
163166
unicast = false;
164167
} else if (is_multicast_ether_addr(dest)) {

net/bridge/br_netlink.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ static int br_port_fill_attrs(struct sk_buff *skb,
143143
nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
144144
nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
145145
nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, !!(p->flags & BR_FLOOD)) ||
146-
nla_put_u8(skb, IFLA_BRPORT_PROXYARP, !!(p->flags & BR_PROXYARP)))
146+
nla_put_u8(skb, IFLA_BRPORT_PROXYARP, !!(p->flags & BR_PROXYARP)) ||
147+
nla_put_u8(skb, IFLA_BRPORT_PROXYARP_WIFI,
148+
!!(p->flags & BR_PROXYARP_WIFI)))
147149
return -EMSGSIZE;
148150

149151
return 0;
@@ -553,6 +555,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
553555
br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
554556
br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
555557
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
558+
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
556559

557560
if (tb[IFLA_BRPORT_COST]) {
558561
err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));

net/bridge/br_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ struct br_input_skb_cb {
305305
#endif
306306

307307
u16 frag_max_size;
308+
bool proxyarp_replied;
308309

309310
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
310311
bool vlan_filtered;

net/bridge/br_sysfs_if.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK);
171171
BRPORT_ATTR_FLAG(learning, BR_LEARNING);
172172
BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD);
173173
BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP);
174+
BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI);
174175

175176
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
176177
static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
@@ -215,6 +216,7 @@ static const struct brport_attribute *brport_attrs[] = {
215216
&brport_attr_multicast_fast_leave,
216217
#endif
217218
&brport_attr_proxyarp,
219+
&brport_attr_proxyarp_wifi,
218220
NULL
219221
};
220222

0 commit comments

Comments
 (0)