import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / net / bridge / br_forward.c
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
24 static 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
33 static 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
41 static 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
49 static 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
56 static 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 */
69 void 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 */
80 void 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 */
91 static 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 */
140 void 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 */
146 void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, int clone)
147 {
148         br_flood(br, skb, clone, __br_forward);
149 }