diff options
author | Jiri Pirko <jpirko@redhat.com> | 2011-03-11 22:14:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-16 15:53:54 -0400 |
commit | 8a4eb5734e8d1dc60a8c28576bbbdfdcc643626d (patch) | |
tree | ed4cd2f9a2a04a30994a8f8964a81834c895c0c9 /net | |
parent | 2d7011ca79f1a8792e04d131b8ea21db179ab917 (diff) |
net: introduce rx_handler results and logic around that
This patch allows rx_handlers to better signalize what to do next to
it's caller. That makes skb->deliver_no_wcard no longer needed.
kernel-doc for rx_handler_result is taken from Nicolas' patch.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Reviewed-by: Nicolas de Pesloüan <nicolas.2p.debian@free.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_input.c | 25 | ||||
-rw-r--r-- | net/bridge/br_private.h | 2 | ||||
-rw-r--r-- | net/core/dev.c | 21 | ||||
-rw-r--r-- | net/core/skbuff.c | 1 |
4 files changed, 30 insertions, 19 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 88e4aa9cb1f9..e2160792e1bc 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -139,21 +139,22 @@ static inline int is_link_local(const unsigned char *dest) | |||
139 | * Return NULL if skb is handled | 139 | * Return NULL if skb is handled |
140 | * note: already called with rcu_read_lock | 140 | * note: already called with rcu_read_lock |
141 | */ | 141 | */ |
142 | struct sk_buff *br_handle_frame(struct sk_buff *skb) | 142 | rx_handler_result_t br_handle_frame(struct sk_buff **pskb) |
143 | { | 143 | { |
144 | struct net_bridge_port *p; | 144 | struct net_bridge_port *p; |
145 | struct sk_buff *skb = *pskb; | ||
145 | const unsigned char *dest = eth_hdr(skb)->h_dest; | 146 | const unsigned char *dest = eth_hdr(skb)->h_dest; |
146 | br_should_route_hook_t *rhook; | 147 | br_should_route_hook_t *rhook; |
147 | 148 | ||
148 | if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) | 149 | if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) |
149 | return skb; | 150 | return RX_HANDLER_PASS; |
150 | 151 | ||
151 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) | 152 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) |
152 | goto drop; | 153 | goto drop; |
153 | 154 | ||
154 | skb = skb_share_check(skb, GFP_ATOMIC); | 155 | skb = skb_share_check(skb, GFP_ATOMIC); |
155 | if (!skb) | 156 | if (!skb) |
156 | return NULL; | 157 | return RX_HANDLER_CONSUMED; |
157 | 158 | ||
158 | p = br_port_get_rcu(skb->dev); | 159 | p = br_port_get_rcu(skb->dev); |
159 | 160 | ||
@@ -167,10 +168,12 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb) | |||
167 | goto forward; | 168 | goto forward; |
168 | 169 | ||
169 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 170 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
170 | NULL, br_handle_local_finish)) | 171 | NULL, br_handle_local_finish)) { |
171 | return NULL; /* frame consumed by filter */ | 172 | return RX_HANDLER_CONSUMED; /* consumed by filter */ |
172 | else | 173 | } else { |
173 | return skb; /* continue processing */ | 174 | *pskb = skb; |
175 | return RX_HANDLER_PASS; /* continue processing */ | ||
176 | } | ||
174 | } | 177 | } |
175 | 178 | ||
176 | forward: | 179 | forward: |
@@ -178,8 +181,10 @@ forward: | |||
178 | case BR_STATE_FORWARDING: | 181 | case BR_STATE_FORWARDING: |
179 | rhook = rcu_dereference(br_should_route_hook); | 182 | rhook = rcu_dereference(br_should_route_hook); |
180 | if (rhook) { | 183 | if (rhook) { |
181 | if ((*rhook)(skb)) | 184 | if ((*rhook)(skb)) { |
182 | return skb; | 185 | *pskb = skb; |
186 | return RX_HANDLER_PASS; | ||
187 | } | ||
183 | dest = eth_hdr(skb)->h_dest; | 188 | dest = eth_hdr(skb)->h_dest; |
184 | } | 189 | } |
185 | /* fall through */ | 190 | /* fall through */ |
@@ -194,5 +199,5 @@ forward: | |||
194 | drop: | 199 | drop: |
195 | kfree_skb(skb); | 200 | kfree_skb(skb); |
196 | } | 201 | } |
197 | return NULL; | 202 | return RX_HANDLER_CONSUMED; |
198 | } | 203 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f7afc364d777..19e2f46ed086 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -379,7 +379,7 @@ extern void br_features_recompute(struct net_bridge *br); | |||
379 | 379 | ||
380 | /* br_input.c */ | 380 | /* br_input.c */ |
381 | extern int br_handle_frame_finish(struct sk_buff *skb); | 381 | extern int br_handle_frame_finish(struct sk_buff *skb); |
382 | extern struct sk_buff *br_handle_frame(struct sk_buff *skb); | 382 | extern rx_handler_result_t br_handle_frame(struct sk_buff **pskb); |
383 | 383 | ||
384 | /* br_ioctl.c */ | 384 | /* br_ioctl.c */ |
385 | extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 385 | extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
diff --git a/net/core/dev.c b/net/core/dev.c index 0d39032e9621..0b88eba97dab 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3070,6 +3070,8 @@ out: | |||
3070 | * on a failure. | 3070 | * on a failure. |
3071 | * | 3071 | * |
3072 | * The caller must hold the rtnl_mutex. | 3072 | * The caller must hold the rtnl_mutex. |
3073 | * | ||
3074 | * For a general description of rx_handler, see enum rx_handler_result. | ||
3073 | */ | 3075 | */ |
3074 | int netdev_rx_handler_register(struct net_device *dev, | 3076 | int netdev_rx_handler_register(struct net_device *dev, |
3075 | rx_handler_func_t *rx_handler, | 3077 | rx_handler_func_t *rx_handler, |
@@ -3129,6 +3131,7 @@ static int __netif_receive_skb(struct sk_buff *skb) | |||
3129 | rx_handler_func_t *rx_handler; | 3131 | rx_handler_func_t *rx_handler; |
3130 | struct net_device *orig_dev; | 3132 | struct net_device *orig_dev; |
3131 | struct net_device *null_or_dev; | 3133 | struct net_device *null_or_dev; |
3134 | bool deliver_exact = false; | ||
3132 | int ret = NET_RX_DROP; | 3135 | int ret = NET_RX_DROP; |
3133 | __be16 type; | 3136 | __be16 type; |
3134 | 3137 | ||
@@ -3181,18 +3184,22 @@ ncls: | |||
3181 | 3184 | ||
3182 | rx_handler = rcu_dereference(skb->dev->rx_handler); | 3185 | rx_handler = rcu_dereference(skb->dev->rx_handler); |
3183 | if (rx_handler) { | 3186 | if (rx_handler) { |
3184 | struct net_device *prev_dev; | ||
3185 | |||
3186 | if (pt_prev) { | 3187 | if (pt_prev) { |
3187 | ret = deliver_skb(skb, pt_prev, orig_dev); | 3188 | ret = deliver_skb(skb, pt_prev, orig_dev); |
3188 | pt_prev = NULL; | 3189 | pt_prev = NULL; |
3189 | } | 3190 | } |
3190 | prev_dev = skb->dev; | 3191 | switch (rx_handler(&skb)) { |
3191 | skb = rx_handler(skb); | 3192 | case RX_HANDLER_CONSUMED: |
3192 | if (!skb) | ||
3193 | goto out; | 3193 | goto out; |
3194 | if (skb->dev != prev_dev) | 3194 | case RX_HANDLER_ANOTHER: |
3195 | goto another_round; | 3195 | goto another_round; |
3196 | case RX_HANDLER_EXACT: | ||
3197 | deliver_exact = true; | ||
3198 | case RX_HANDLER_PASS: | ||
3199 | break; | ||
3200 | default: | ||
3201 | BUG(); | ||
3202 | } | ||
3196 | } | 3203 | } |
3197 | 3204 | ||
3198 | if (vlan_tx_tag_present(skb)) { | 3205 | if (vlan_tx_tag_present(skb)) { |
@@ -3210,7 +3217,7 @@ ncls: | |||
3210 | vlan_on_bond_hook(skb); | 3217 | vlan_on_bond_hook(skb); |
3211 | 3218 | ||
3212 | /* deliver only exact match when indicated */ | 3219 | /* deliver only exact match when indicated */ |
3213 | null_or_dev = skb->deliver_no_wcard ? skb->dev : NULL; | 3220 | null_or_dev = deliver_exact ? skb->dev : NULL; |
3214 | 3221 | ||
3215 | type = skb->protocol; | 3222 | type = skb->protocol; |
3216 | list_for_each_entry_rcu(ptype, | 3223 | list_for_each_entry_rcu(ptype, |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1eb526a848ff..801dd08908f9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -523,7 +523,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
523 | new->ip_summed = old->ip_summed; | 523 | new->ip_summed = old->ip_summed; |
524 | skb_copy_queue_mapping(new, old); | 524 | skb_copy_queue_mapping(new, old); |
525 | new->priority = old->priority; | 525 | new->priority = old->priority; |
526 | new->deliver_no_wcard = old->deliver_no_wcard; | ||
527 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 526 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
528 | new->ipvs_property = old->ipvs_property; | 527 | new->ipvs_property = old->ipvs_property; |
529 | #endif | 528 | #endif |