linux/net/bridge/br_forward.c
<<
>>
Prefs
   1/*
   2 *      Forwarding decision
   3 *      Linux ethernet bridge
   4 *
   5 *      Authors:
   6 *      Lennert Buytenhek               <buytenh@gnu.org>
   7 *
   8 *      This program is free software; you can redistribute it and/or
   9 *      modify it under the terms of the GNU General Public License
  10 *      as published by the Free Software Foundation; either version
  11 *      2 of the License, or (at your option) any later version.
  12 */
  13
  14#include <linux/err.h>
  15#include <linux/slab.h>
  16#include <linux/kernel.h>
  17#include <linux/netdevice.h>
  18#include <linux/netpoll.h>
  19#include <linux/skbuff.h>
  20#include <linux/if_vlan.h>
  21#include <linux/netfilter_bridge.h>
  22#include "br_private.h"
  23
  24static int deliver_clone(const struct net_bridge_port *prev,
  25                         struct sk_buff *skb,
  26                         void (*__packet_hook)(const struct net_bridge_port *p,
  27                                               struct sk_buff *skb));
  28
  29/* Don't forward packets to originating port or forwarding disabled */
  30static inline int should_deliver(const struct net_bridge_port *p,
  31                                 const struct sk_buff *skb)
  32{
  33        return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
  34                br_allowed_egress(p->br, nbp_get_vlan_info(p), skb) &&
  35                p->state == BR_STATE_FORWARDING;
  36}
  37
  38int br_dev_queue_push_xmit(struct sk_buff *skb)
  39{
  40        /* ip_fragment doesn't copy the MAC header */
  41        if (nf_bridge_maybe_copy_header(skb) ||
  42            !is_skb_forwardable(skb->dev, skb)) {
  43                kfree_skb(skb);
  44        } else {
  45                skb_push(skb, ETH_HLEN);
  46                br_drop_fake_rtable(skb);
  47                dev_queue_xmit(skb);
  48        }
  49
  50        return 0;
  51}
  52EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
  53
  54int br_forward_finish(struct sk_buff *skb)
  55{
  56        return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
  57                       br_dev_queue_push_xmit);
  58
  59}
  60EXPORT_SYMBOL_GPL(br_forward_finish);
  61
  62static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
  63{
  64        skb = br_handle_vlan(to->br, nbp_get_vlan_info(to), skb);
  65        if (!skb)
  66                return;
  67
  68        skb->dev = to->dev;
  69
  70        if (unlikely(netpoll_tx_running(to->br->dev))) {
  71                if (!is_skb_forwardable(skb->dev, skb))
  72                        kfree_skb(skb);
  73                else {
  74                        skb_push(skb, ETH_HLEN);
  75                        br_netpoll_send_skb(to, skb);
  76                }
  77                return;
  78        }
  79
  80        NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
  81                br_forward_finish);
  82}
  83
  84static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
  85{
  86        struct net_device *indev;
  87
  88        if (skb_warn_if_lro(skb)) {
  89                kfree_skb(skb);
  90                return;
  91        }
  92
  93        skb = br_handle_vlan(to->br, nbp_get_vlan_info(to), skb);
  94        if (!skb)
  95                return;
  96
  97        indev = skb->dev;
  98        skb->dev = to->dev;
  99        skb_forward_csum(skb);
 100
 101        NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
 102                br_forward_finish);
 103}
 104
 105/* called with rcu_read_lock */
 106void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
 107{
 108        if (to && should_deliver(to, skb)) {
 109                __br_deliver(to, skb);
 110                return;
 111        }
 112
 113        kfree_skb(skb);
 114}
 115EXPORT_SYMBOL_GPL(br_deliver);
 116
 117/* called with rcu_read_lock */
 118void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
 119{
 120        if (should_deliver(to, skb)) {
 121                if (skb0)
 122                        deliver_clone(to, skb, __br_forward);
 123                else
 124                        __br_forward(to, skb);
 125                return;
 126        }
 127
 128        if (!skb0)
 129                kfree_skb(skb);
 130}
 131
 132static int deliver_clone(const struct net_bridge_port *prev,
 133                         struct sk_buff *skb,
 134                         void (*__packet_hook)(const struct net_bridge_port *p,
 135                                               struct sk_buff *skb))
 136{
 137        struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
 138
 139        skb = skb_clone(skb, GFP_ATOMIC);
 140        if (!skb) {
 141                dev->stats.tx_dropped++;
 142                return -ENOMEM;
 143        }
 144
 145        __packet_hook(prev, skb);
 146        return 0;
 147}
 148
 149static struct net_bridge_port *maybe_deliver(
 150        struct net_bridge_port *prev, struct net_bridge_port *p,
 151        struct sk_buff *skb,
 152        void (*__packet_hook)(const struct net_bridge_port *p,
 153                              struct sk_buff *skb))
 154{
 155        int err;
 156
 157        if (!should_deliver(p, skb))
 158                return prev;
 159
 160        if (!prev)
 161                goto out;
 162
 163        err = deliver_clone(prev, skb, __packet_hook);
 164        if (err)
 165                return ERR_PTR(err);
 166
 167out:
 168        return p;
 169}
 170
 171/* called under bridge lock */
 172static void br_flood(struct net_bridge *br, struct sk_buff *skb,
 173                     struct sk_buff *skb0,
 174                     void (*__packet_hook)(const struct net_bridge_port *p,
 175                                           struct sk_buff *skb),
 176                     bool unicast)
 177{
 178        struct net_bridge_port *p;
 179        struct net_bridge_port *prev;
 180
 181        prev = NULL;
 182
 183        list_for_each_entry_rcu(p, &br->port_list, list) {
 184                /* Do not flood unicast traffic to ports that turn it off */
 185                if (unicast && !(p->flags & BR_FLOOD))
 186                        continue;
 187
 188                /* Do not flood to ports that enable proxy ARP */
 189                if (p->flags & BR_PROXYARP)
 190                        continue;
 191
 192                prev = maybe_deliver(prev, p, skb, __packet_hook);
 193                if (IS_ERR(prev))
 194                        goto out;
 195        }
 196
 197        if (!prev)
 198                goto out;
 199
 200        if (skb0)
 201                deliver_clone(prev, skb, __packet_hook);
 202        else
 203                __packet_hook(prev, skb);
 204        return;
 205
 206out:
 207        if (!skb0)
 208                kfree_skb(skb);
 209}
 210
 211
 212/* called with rcu_read_lock */
 213void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast)
 214{
 215        br_flood(br, skb, NULL, __br_deliver, unicast);
 216}
 217
 218/* called under bridge lock */
 219void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
 220                      struct sk_buff *skb2, bool unicast)
 221{
 222        br_flood(br, skb, skb2, __br_forward, unicast);
 223}
 224
 225#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 226/* called with rcu_read_lock */
 227static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
 228                               struct sk_buff *skb, struct sk_buff *skb0,
 229                               void (*__packet_hook)(
 230                                        const struct net_bridge_port *p,
 231                                        struct sk_buff *skb))
 232{
 233        struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
 234        struct net_bridge *br = netdev_priv(dev);
 235        struct net_bridge_port *prev = NULL;
 236        struct net_bridge_port_group *p;
 237        struct hlist_node *rp;
 238
 239        rp = rcu_dereference(hlist_first_rcu(&br->router_list));
 240        p = mdst ? rcu_dereference(mdst->ports) : NULL;
 241        while (p || rp) {
 242                struct net_bridge_port *port, *lport, *rport;
 243
 244                lport = p ? p->port : NULL;
 245                rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
 246                             NULL;
 247
 248                port = (unsigned long)lport > (unsigned long)rport ?
 249                       lport : rport;
 250
 251                prev = maybe_deliver(prev, port, skb, __packet_hook);
 252                if (IS_ERR(prev))
 253                        goto out;
 254
 255                if ((unsigned long)lport >= (unsigned long)port)
 256                        p = rcu_dereference(p->next);
 257                if ((unsigned long)rport >= (unsigned long)port)
 258                        rp = rcu_dereference(hlist_next_rcu(rp));
 259        }
 260
 261        if (!prev)
 262                goto out;
 263
 264        if (skb0)
 265                deliver_clone(prev, skb, __packet_hook);
 266        else
 267                __packet_hook(prev, skb);
 268        return;
 269
 270out:
 271        if (!skb0)
 272                kfree_skb(skb);
 273}
 274
 275/* called with rcu_read_lock */
 276void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
 277                          struct sk_buff *skb)
 278{
 279        br_multicast_flood(mdst, skb, NULL, __br_deliver);
 280}
 281
 282/* called with rcu_read_lock */
 283void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
 284                          struct sk_buff *skb, struct sk_buff *skb2)
 285{
 286        br_multicast_flood(mdst, skb, skb2, __br_forward);
 287}
 288#endif
 289