linux-old/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 *      $Id: br_forward.c,v 1.4 2001/08/14 22:05:57 davem Exp $
   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 */
  15
  16#include <linux/kernel.h>
  17#include <linux/netdevice.h>
  18#include <linux/inetdevice.h>
  19#include <linux/skbuff.h>
  20#include <linux/if_bridge.h>
  21#include <linux/netfilter_bridge.h>
  22#include "br_private.h"
  23
  24static inline int should_deliver(struct net_bridge_port *p, struct sk_buff *skb)
  25{
  26        if (skb->dev == p->dev ||
  27            p->state != BR_STATE_FORWARDING)
  28                return 0;
  29
  30        return 1;
  31}
  32
  33static int __dev_queue_push_xmit(struct sk_buff *skb)
  34{
  35        skb_push(skb, ETH_HLEN);
  36        dev_queue_xmit(skb);
  37
  38        return 0;
  39}
  40
  41static int __br_forward_finish(struct sk_buff *skb)
  42{
  43        NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
  44                        __dev_queue_push_xmit);
  45
  46        return 0;
  47}
  48
  49static void __br_deliver(struct net_bridge_port *to, struct sk_buff *skb)
  50{
  51        skb->dev = to->dev;
  52        NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
  53                        __br_forward_finish);
  54}
  55
  56static void __br_forward(struct net_bridge_port *to, struct sk_buff *skb)
  57{
  58        struct net_device *indev;
  59
  60        indev = skb->dev;
  61        skb->dev = to->dev;
  62        skb->ip_summed = CHECKSUM_NONE;
  63
  64        NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
  65                        __br_forward_finish);
  66}
  67
  68/* called under bridge lock */
  69void br_deliver(struct net_bridge_port *to, struct sk_buff *skb)
  70{
  71        if (should_deliver(to, skb)) {
  72                __br_deliver(to, skb);
  73                return;
  74        }
  75
  76        kfree_skb(skb);
  77}
  78
  79/* called under bridge lock */
  80void br_forward(struct net_bridge_port *to, struct sk_buff *skb)
  81{
  82        if (should_deliver(to, skb)) {
  83                __br_forward(to, skb);
  84                return;
  85        }
  86
  87        kfree_skb(skb);
  88}
  89
  90/* called under bridge lock */
  91static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
  92        void (*__packet_hook)(struct net_bridge_port *p, struct sk_buff *skb))
  93{
  94        struct net_bridge_port *p;
  95        struct net_bridge_port *prev;
  96
  97        if (clone) {
  98                struct sk_buff *skb2;
  99
 100                if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 101                        br->statistics.tx_dropped++;
 102                        return;
 103                }
 104
 105                skb = skb2;
 106        }
 107
 108        prev = NULL;
 109
 110        p = br->port_list;
 111        while (p != NULL) {
 112                if (should_deliver(p, skb)) {
 113                        if (prev != NULL) {
 114                                struct sk_buff *skb2;
 115
 116                                if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 117                                        br->statistics.tx_dropped++;
 118                                        kfree_skb(skb);
 119                                        return;
 120                                }
 121
 122                                __packet_hook(prev, skb2);
 123                        }
 124
 125                        prev = p;
 126                }
 127
 128                p = p->next;
 129        }
 130
 131        if (prev != NULL) {
 132                __packet_hook(prev, skb);
 133                return;
 134        }
 135
 136        kfree_skb(skb);
 137}
 138
 139/* called under bridge lock */
 140void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, int clone)
 141{
 142        br_flood(br, skb, clone, __br_deliver);
 143}
 144
 145/* called under bridge lock */
 146void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, int clone)
 147{
 148        br_flood(br, skb, clone, __br_forward);
 149}
 150
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.