Commit f350a0a87374418635689471606454abc7beaa3a

Authored by Jiri Pirko
Committed by David S. Miller
1 parent a35e2c1b6d

bridge: use rx_handler_data pointer to store net_bridge_port pointer

Register net_bridge_port pointer as rx_handler data pointer. As br_port is
removed from struct net_device, another netdev priv_flag is added to indicate
the device serves as a bridge port. Also rcuized pointers are now correctly
dereferenced in br_fdb.c and in netfilter parts.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 20 changed files with 71 additions and 50 deletions Side-by-side Diff

drivers/net/ksz884x.c
... ... @@ -5718,7 +5718,7 @@
5718 5718 * from the bridge.
5719 5719 */
5720 5720 if ((hw->features & STP_SUPPORT) && !promiscuous &&
5721   - dev->br_port) {
  5721 + (dev->priv_flags & IFF_BRIDGE_PORT)) {
5722 5722 struct ksz_switch *sw = hw->ksz_switch;
5723 5723 int port = priv->port.first_port;
5724 5724  
drivers/staging/batman-adv/hard-interface.c
... ... @@ -71,7 +71,7 @@
71 71 #endif
72 72  
73 73 /* Device is being bridged */
74   - /* if (net_dev->br_port != NULL)
  74 + /* if (net_dev->priv_flags & IFF_BRIDGE_PORT)
75 75 return 0; */
76 76  
77 77 return 1;
... ... @@ -74,6 +74,7 @@
74 74 #define IFF_IN_NETPOLL 0x1000 /* whether we are processing netpoll */
75 75 #define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */
76 76 #define IFF_MACVLAN_PORT 0x4000 /* device used as macvlan port */
  77 +#define IFF_BRIDGE_PORT 0x8000 /* device used as bridge port */
77 78  
78 79 #define IF_GET_IFACE 0x0001 /* for querying only */
79 80 #define IF_GET_PROTO 0x0002
include/linux/netdevice.h
... ... @@ -1047,8 +1047,6 @@
1047 1047 /* mid-layer private */
1048 1048 void *ml_priv;
1049 1049  
1050   - /* bridge stuff */
1051   - struct net_bridge_port *br_port;
1052 1050 /* GARP */
1053 1051 struct garp_port *garp_port;
1054 1052  
... ... @@ -242,11 +242,11 @@
242 242 struct net_bridge_fdb_entry *fdb;
243 243 int ret;
244 244  
245   - if (!dev->br_port)
  245 + if (!br_port_exists(dev))
246 246 return 0;
247 247  
248 248 rcu_read_lock();
249   - fdb = __br_fdb_get(dev->br_port->br, addr);
  249 + fdb = __br_fdb_get(br_port_get_rcu(dev)->br, addr);
250 250 ret = fdb && fdb->dst->dev != dev &&
251 251 fdb->dst->state == BR_STATE_FORWARDING;
252 252 rcu_read_unlock();
... ... @@ -147,8 +147,9 @@
147 147  
148 148 list_del_rcu(&p->list);
149 149  
  150 + dev->priv_flags &= ~IFF_BRIDGE_PORT;
  151 +
150 152 netdev_rx_handler_unregister(dev);
151   - rcu_assign_pointer(dev->br_port, NULL);
152 153  
153 154 br_multicast_del_port(p);
154 155  
... ... @@ -400,7 +401,7 @@
400 401 return -ELOOP;
401 402  
402 403 /* Device is already being bridged */
403   - if (dev->br_port != NULL)
  404 + if (br_port_exists(dev))
404 405 return -EBUSY;
405 406  
406 407 /* No bridging devices that dislike that (e.g. wireless) */
407 408  
408 409  
... ... @@ -431,12 +432,12 @@
431 432 if (br_netpoll_info(br) && ((err = br_netpoll_enable(p))))
432 433 goto err3;
433 434  
434   - rcu_assign_pointer(dev->br_port, p);
435   -
436   - err = netdev_rx_handler_register(dev, br_handle_frame, NULL);
  435 + err = netdev_rx_handler_register(dev, br_handle_frame, p);
437 436 if (err)
438   - goto err4;
  437 + goto err3;
439 438  
  439 + dev->priv_flags |= IFF_BRIDGE_PORT;
  440 +
440 441 dev_disable_lro(dev);
441 442  
442 443 list_add_rcu(&p->list, &br->port_list);
... ... @@ -457,8 +458,6 @@
457 458 kobject_uevent(&p->kobj, KOBJ_ADD);
458 459  
459 460 return 0;
460   -err4:
461   - rcu_assign_pointer(dev->br_port, NULL);
462 461 err3:
463 462 sysfs_remove_link(br->ifobj, p->dev->name);
464 463 err2:
465 464  
... ... @@ -477,9 +476,13 @@
477 476 /* called with RTNL */
478 477 int br_del_if(struct net_bridge *br, struct net_device *dev)
479 478 {
480   - struct net_bridge_port *p = dev->br_port;
  479 + struct net_bridge_port *p;
481 480  
482   - if (!p || p->br != br)
  481 + if (!br_port_exists(dev))
  482 + return -EINVAL;
  483 +
  484 + p = br_port_get(dev);
  485 + if (p->br != br)
483 486 return -EINVAL;
484 487  
485 488 del_nbp(p);
net/bridge/br_input.c
... ... @@ -41,7 +41,7 @@
41 41 int br_handle_frame_finish(struct sk_buff *skb)
42 42 {
43 43 const unsigned char *dest = eth_hdr(skb)->h_dest;
44   - struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
  44 + struct net_bridge_port *p = br_port_get_rcu(skb->dev);
45 45 struct net_bridge *br;
46 46 struct net_bridge_fdb_entry *dst;
47 47 struct net_bridge_mdb_entry *mdst;
48 48  
... ... @@ -111,10 +111,9 @@
111 111 /* note: already called with rcu_read_lock (preempt_disabled) */
112 112 static int br_handle_local_finish(struct sk_buff *skb)
113 113 {
114   - struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
  114 + struct net_bridge_port *p = br_port_get_rcu(skb->dev);
115 115  
116   - if (p)
117   - br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
  116 + br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
118 117 return 0; /* process further */
119 118 }
120 119  
... ... @@ -151,7 +150,7 @@
151 150 if (!skb)
152 151 return NULL;
153 152  
154   - p = rcu_dereference(skb->dev->br_port);
  153 + p = br_port_get_rcu(skb->dev);
155 154  
156 155 if (unlikely(is_link_local(dest))) {
157 156 /* Pause frames shouldn't be passed up by driver anyway */
net/bridge/br_netfilter.c
... ... @@ -127,16 +127,17 @@
127 127  
128 128 static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
129 129 {
130   - struct net_bridge_port *port = rcu_dereference(dev->br_port);
131   -
132   - return port ? &port->br->fake_rtable : NULL;
  130 + if (!br_port_exists(dev))
  131 + return NULL;
  132 + return &br_port_get_rcu(dev)->br->fake_rtable;
133 133 }
134 134  
135 135 static inline struct net_device *bridge_parent(const struct net_device *dev)
136 136 {
137   - struct net_bridge_port *port = rcu_dereference(dev->br_port);
  137 + if (!br_port_exists(dev))
  138 + return NULL;
138 139  
139   - return port ? port->br->dev : NULL;
  140 + return br_port_get_rcu(dev)->br->dev;
140 141 }
141 142  
142 143 static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
net/bridge/br_netlink.c
... ... @@ -120,10 +120,11 @@
120 120 idx = 0;
121 121 for_each_netdev(net, dev) {
122 122 /* not a bridge port */
123   - if (dev->br_port == NULL || idx < cb->args[0])
  123 + if (!br_port_exists(dev) || idx < cb->args[0])
124 124 goto skip;
125 125  
126   - if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid,
  126 + if (br_fill_ifinfo(skb, br_port_get(dev),
  127 + NETLINK_CB(cb->skb).pid,
127 128 cb->nlh->nlmsg_seq, RTM_NEWLINK,
128 129 NLM_F_MULTI) < 0)
129 130 break;
130 131  
... ... @@ -168,9 +169,9 @@
168 169 if (!dev)
169 170 return -ENODEV;
170 171  
171   - p = dev->br_port;
172   - if (!p)
  172 + if (!br_port_exists(dev))
173 173 return -EINVAL;
  174 + p = br_port_get(dev);
174 175  
175 176 /* if kernel STP is running, don't allow changes */
176 177 if (p->br->stp_enabled == BR_KERNEL_STP)
net/bridge/br_notify.c
... ... @@ -32,14 +32,15 @@
32 32 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
33 33 {
34 34 struct net_device *dev = ptr;
35   - struct net_bridge_port *p = dev->br_port;
  35 + struct net_bridge_port *p = br_port_get(dev);
36 36 struct net_bridge *br;
37 37 int err;
38 38  
39 39 /* not a port of a bridge */
40   - if (p == NULL)
  40 + if (!br_port_exists(dev))
41 41 return NOTIFY_DONE;
42 42  
  43 + p = br_port_get(dev);
43 44 br = p->br;
44 45  
45 46 switch (event) {
net/bridge/br_private.h
... ... @@ -150,6 +150,11 @@
150 150 #endif
151 151 };
152 152  
  153 +#define br_port_get_rcu(dev) \
  154 + ((struct net_bridge_port *) rcu_dereference(dev->rx_handler_data))
  155 +#define br_port_get(dev) ((struct net_bridge_port *) dev->rx_handler_data)
  156 +#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
  157 +
153 158 struct br_cpu_netstats {
154 159 unsigned long rx_packets;
155 160 unsigned long rx_bytes;
net/bridge/br_stp_bpdu.c
... ... @@ -137,12 +137,13 @@
137 137 struct net_device *dev)
138 138 {
139 139 const unsigned char *dest = eth_hdr(skb)->h_dest;
140   - struct net_bridge_port *p = rcu_dereference(dev->br_port);
  140 + struct net_bridge_port *p;
141 141 struct net_bridge *br;
142 142 const unsigned char *buf;
143 143  
144   - if (!p)
  144 + if (!br_port_exists(dev))
145 145 goto err;
  146 + p = br_port_get_rcu(dev);
146 147  
147 148 if (!pskb_may_pull(skb, 4))
148 149 goto err;
net/bridge/netfilter/ebt_redirect.c
... ... @@ -24,8 +24,9 @@
24 24 return EBT_DROP;
25 25  
26 26 if (par->hooknum != NF_BR_BROUTING)
  27 + /* rcu_read_lock()ed by nf_hook_slow */
27 28 memcpy(eth_hdr(skb)->h_dest,
28   - par->in->br_port->br->dev->dev_addr, ETH_ALEN);
  29 + br_port_get_rcu(par->in)->br->dev->dev_addr, ETH_ALEN);
29 30 else
30 31 memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN);
31 32 skb->pkt_type = PACKET_HOST;
net/bridge/netfilter/ebt_ulog.c
... ... @@ -177,8 +177,9 @@
177 177 if (in) {
178 178 strcpy(pm->physindev, in->name);
179 179 /* If in isn't a bridge, then physindev==indev */
180   - if (in->br_port)
181   - strcpy(pm->indev, in->br_port->br->dev->name);
  180 + if (br_port_exists(in))
  181 + /* rcu_read_lock()ed by nf_hook_slow */
  182 + strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name);
182 183 else
183 184 strcpy(pm->indev, in->name);
184 185 } else
... ... @@ -187,7 +188,8 @@
187 188 if (out) {
188 189 /* If out exists, then out is a bridge port */
189 190 strcpy(pm->physoutdev, out->name);
190   - strcpy(pm->outdev, out->br_port->br->dev->name);
  191 + /* rcu_read_lock()ed by nf_hook_slow */
  192 + strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name);
191 193 } else
192 194 pm->outdev[0] = pm->physoutdev[0] = '\0';
193 195  
net/bridge/netfilter/ebtables.c
... ... @@ -140,11 +140,14 @@
140 140 return 1;
141 141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
142 142 return 1;
143   - if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
144   - e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
  143 + /* rcu_read_lock()ed by nf_hook_slow */
  144 + if (in && br_port_exists(in) &&
  145 + FWINV2(ebt_dev_check(e->logical_in, br_port_get_rcu(in)->br->dev),
  146 + EBT_ILOGICALIN))
145 147 return 1;
146   - if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
147   - e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
  148 + if (out && br_port_exists(out) &&
  149 + FWINV2(ebt_dev_check(e->logical_out, br_port_get_rcu(out)->br->dev),
  150 + EBT_ILOGICALOUT))
148 151 return 1;
149 152  
150 153 if (e->bitmask & EBT_SOURCEMAC) {
... ... @@ -2765,7 +2765,8 @@
2765 2765 if (master->priv_flags & IFF_MASTER_ARPMON)
2766 2766 dev->last_rx = jiffies;
2767 2767  
2768   - if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
  2768 + if ((master->priv_flags & IFF_MASTER_ALB) &&
  2769 + (master->priv_flags & IFF_BRIDGE_PORT)) {
2769 2770 /* Do address unmangle. The local destination address
2770 2771 * will be always the one master has. Provides the right
2771 2772 * functionality in a bridge.
net/netfilter/nfnetlink_log.c
... ... @@ -403,8 +403,9 @@
403 403 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
404 404 htonl(indev->ifindex));
405 405 /* this is the bridge group "brX" */
  406 + /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
406 407 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
407   - htonl(indev->br_port->br->dev->ifindex));
  408 + htonl(br_port_get_rcu(indev)->br->dev->ifindex));
408 409 } else {
409 410 /* Case 2: indev is bridge group, we need to look for
410 411 * physical device (when called from ipv4) */
411 412  
... ... @@ -430,8 +431,9 @@
430 431 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
431 432 htonl(outdev->ifindex));
432 433 /* this is the bridge group "brX" */
  434 + /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
433 435 NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
434   - htonl(outdev->br_port->br->dev->ifindex));
  436 + htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
435 437 } else {
436 438 /* Case 2: indev is a bridge group, we need to look
437 439 * for physical device (when called from ipv4) */
net/netfilter/nfnetlink_queue.c
... ... @@ -296,8 +296,9 @@
296 296 NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV,
297 297 htonl(indev->ifindex));
298 298 /* this is the bridge group "brX" */
  299 + /* rcu_read_lock()ed by __nf_queue */
299 300 NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
300   - htonl(indev->br_port->br->dev->ifindex));
  301 + htonl(br_port_get_rcu(indev)->br->dev->ifindex));
301 302 } else {
302 303 /* Case 2: indev is bridge group, we need to look for
303 304 * physical device (when called from ipv4) */
304 305  
... ... @@ -321,8 +322,9 @@
321 322 NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV,
322 323 htonl(outdev->ifindex));
323 324 /* this is the bridge group "brX" */
  325 + /* rcu_read_lock()ed by __nf_queue */
324 326 NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
325   - htonl(outdev->br_port->br->dev->ifindex));
  327 + htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
326 328 } else {
327 329 /* Case 2: outdev is bridge group, we need to look for
328 330 * physical output device (when called from ipv4) */
net/wireless/nl80211.c
... ... @@ -1107,7 +1107,7 @@
1107 1107 enum nl80211_iftype iftype)
1108 1108 {
1109 1109 if (!use_4addr) {
1110   - if (netdev && netdev->br_port)
  1110 + if (netdev && (netdev->priv_flags & IFF_BRIDGE_PORT))
1111 1111 return -EBUSY;
1112 1112 return 0;
1113 1113 }
... ... @@ -770,8 +770,8 @@
770 770 return -EOPNOTSUPP;
771 771  
772 772 /* if it's part of a bridge, reject changing type to station/ibss */
773   - if (dev->br_port && (ntype == NL80211_IFTYPE_ADHOC ||
774   - ntype == NL80211_IFTYPE_STATION))
  773 + if ((dev->priv_flags & IFF_BRIDGE_PORT) &&
  774 + (ntype == NL80211_IFTYPE_ADHOC || ntype == NL80211_IFTYPE_STATION))
775 775 return -EBUSY;
776 776  
777 777 if (ntype != otype) {