aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_forward.c14
-rw-r--r--net/bridge/br_input.c2
-rw-r--r--net/bridge/br_private.h2
3 files changed, 13 insertions, 5 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d61e6f741125..8347916efe88 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -19,6 +19,10 @@
19#include <linux/netfilter_bridge.h> 19#include <linux/netfilter_bridge.h>
20#include "br_private.h" 20#include "br_private.h"
21 21
22static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb,
23 void (*__packet_hook)(const struct net_bridge_port *p,
24 struct sk_buff *skb));
25
22/* Don't forward packets to originating port or forwarding diasabled */ 26/* Don't forward packets to originating port or forwarding diasabled */
23static inline int should_deliver(const struct net_bridge_port *p, 27static inline int should_deliver(const struct net_bridge_port *p,
24 const struct sk_buff *skb) 28 const struct sk_buff *skb)
@@ -94,14 +98,18 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
94} 98}
95 99
96/* called with rcu_read_lock */ 100/* called with rcu_read_lock */
97void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) 101void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
98{ 102{
99 if (should_deliver(to, skb)) { 103 if (should_deliver(to, skb)) {
100 __br_forward(to, skb); 104 if (skb0)
105 deliver_clone(to, skb, __br_forward);
106 else
107 __br_forward(to, skb);
101 return; 108 return;
102 } 109 }
103 110
104 kfree_skb(skb); 111 if (!skb0)
112 kfree_skb(skb);
105} 113}
106 114
107static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, 115static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb,
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 53b39851d87d..08a72e63fb8e 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -90,7 +90,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
90 90
91 if (skb) { 91 if (skb) {
92 if (dst) 92 if (dst)
93 br_forward(dst->dst, skb); 93 br_forward(dst->dst, skb, skb2);
94 else 94 else
95 br_flood_forward(br, skb, skb2); 95 br_flood_forward(br, skb, skb2);
96 } 96 }
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index fef0384e3c0b..bfb8feb310a6 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -252,7 +252,7 @@ extern void br_deliver(const struct net_bridge_port *to,
252 struct sk_buff *skb); 252 struct sk_buff *skb);
253extern int br_dev_queue_push_xmit(struct sk_buff *skb); 253extern int br_dev_queue_push_xmit(struct sk_buff *skb);
254extern void br_forward(const struct net_bridge_port *to, 254extern void br_forward(const struct net_bridge_port *to,
255 struct sk_buff *skb); 255 struct sk_buff *skb, struct sk_buff *skb0);
256extern int br_forward_finish(struct sk_buff *skb); 256extern int br_forward_finish(struct sk_buff *skb);
257extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); 257extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb);
258extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, 258extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,