diff options
| author | Herbert Xu <herbert@gondor.apana.org.au> | 2010-02-27 14:41:43 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-02-28 03:48:44 -0500 |
| commit | 025d89c27f54c69cd0e51666d88aada33666bb6c (patch) | |
| tree | 73063f6189c25d55c71ae6dad96a3711df87b7a6 /net/bridge/br_forward.c | |
| parent | 6088a539d8d1666dca6979b5759bf966ee9124ef (diff) | |
bridge: Split may_deliver/deliver_clone out of br_flood
This patch moves the main loop body in br_flood into the function
may_deliver. The code that clones an skb and delivers it is moved
into the deliver_clone function.
This allows this to be reused by the future multicast forward
function.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_forward.c')
| -rw-r--r-- | net/bridge/br_forward.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 2e1cb434f6cd..86cd0712d63e 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | * 2 of the License, or (at your option) any later version. | 11 | * 2 of the License, or (at your option) any later version. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/err.h> | ||
| 14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 15 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
| 16 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
| @@ -103,6 +104,44 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | |||
| 103 | kfree_skb(skb); | 104 | kfree_skb(skb); |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 107 | static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, | ||
| 108 | void (*__packet_hook)(const struct net_bridge_port *p, | ||
| 109 | struct sk_buff *skb)) | ||
| 110 | { | ||
| 111 | skb = skb_clone(skb, GFP_ATOMIC); | ||
| 112 | if (!skb) { | ||
| 113 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; | ||
| 114 | |||
| 115 | dev->stats.tx_dropped++; | ||
| 116 | return -ENOMEM; | ||
| 117 | } | ||
| 118 | |||
| 119 | __packet_hook(prev, skb); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static struct net_bridge_port *maybe_deliver( | ||
| 124 | struct net_bridge_port *prev, struct net_bridge_port *p, | ||
| 125 | struct sk_buff *skb, | ||
| 126 | void (*__packet_hook)(const struct net_bridge_port *p, | ||
| 127 | struct sk_buff *skb)) | ||
| 128 | { | ||
| 129 | int err; | ||
| 130 | |||
| 131 | if (!should_deliver(p, skb)) | ||
| 132 | return prev; | ||
| 133 | |||
| 134 | if (!prev) | ||
| 135 | goto out; | ||
| 136 | |||
| 137 | err = deliver_clone(prev, skb, __packet_hook); | ||
| 138 | if (err) | ||
| 139 | return ERR_PTR(err); | ||
| 140 | |||
| 141 | out: | ||
| 142 | return p; | ||
| 143 | } | ||
| 144 | |||
| 106 | /* called under bridge lock */ | 145 | /* called under bridge lock */ |
| 107 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, | 146 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, |
| 108 | struct sk_buff *skb0, | 147 | struct sk_buff *skb0, |
| @@ -111,38 +150,22 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, | |||
| 111 | { | 150 | { |
| 112 | struct net_bridge_port *p; | 151 | struct net_bridge_port *p; |
| 113 | struct net_bridge_port *prev; | 152 | struct net_bridge_port *prev; |
| 114 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; | ||
| 115 | 153 | ||
| 116 | prev = NULL; | 154 | prev = NULL; |
| 117 | 155 | ||
| 118 | list_for_each_entry_rcu(p, &br->port_list, list) { | 156 | list_for_each_entry_rcu(p, &br->port_list, list) { |
| 119 | if (should_deliver(p, skb)) { | 157 | prev = maybe_deliver(prev, p, skb, __packet_hook); |
| 120 | if (prev != NULL) { | 158 | if (IS_ERR(prev)) |
| 121 | struct sk_buff *skb2; | 159 | goto out; |
| 122 | |||
| 123 | if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { | ||
| 124 | dev->stats.tx_dropped++; | ||
| 125 | goto out; | ||
| 126 | } | ||
| 127 | |||
| 128 | __packet_hook(prev, skb2); | ||
| 129 | } | ||
| 130 | |||
| 131 | prev = p; | ||
| 132 | } | ||
| 133 | } | 160 | } |
| 134 | 161 | ||
| 135 | if (!prev) | 162 | if (!prev) |
| 136 | goto out; | 163 | goto out; |
| 137 | 164 | ||
| 138 | if (skb0) { | 165 | if (skb0) |
| 139 | skb = skb_clone(skb, GFP_ATOMIC); | 166 | deliver_clone(prev, skb, __packet_hook); |
| 140 | if (!skb) { | 167 | else |
| 141 | dev->stats.tx_dropped++; | 168 | __packet_hook(prev, skb); |
| 142 | goto out; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | __packet_hook(prev, skb); | ||
| 146 | return; | 169 | return; |
| 147 | 170 | ||
| 148 | out: | 171 | out: |
