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>
This commit is contained in:
@@ -139,21 +139,22 @@ static inline int is_link_local(const unsigned char *dest)
|
||||
* Return NULL if skb is handled
|
||||
* note: already called with rcu_read_lock
|
||||
*/
|
||||
struct sk_buff *br_handle_frame(struct sk_buff *skb)
|
||||
rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
|
||||
{
|
||||
struct net_bridge_port *p;
|
||||
struct sk_buff *skb = *pskb;
|
||||
const unsigned char *dest = eth_hdr(skb)->h_dest;
|
||||
br_should_route_hook_t *rhook;
|
||||
|
||||
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
|
||||
return skb;
|
||||
return RX_HANDLER_PASS;
|
||||
|
||||
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
|
||||
goto drop;
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
return RX_HANDLER_CONSUMED;
|
||||
|
||||
p = br_port_get_rcu(skb->dev);
|
||||
|
||||
@@ -167,10 +168,12 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb)
|
||||
goto forward;
|
||||
|
||||
if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
|
||||
NULL, br_handle_local_finish))
|
||||
return NULL; /* frame consumed by filter */
|
||||
else
|
||||
return skb; /* continue processing */
|
||||
NULL, br_handle_local_finish)) {
|
||||
return RX_HANDLER_CONSUMED; /* consumed by filter */
|
||||
} else {
|
||||
*pskb = skb;
|
||||
return RX_HANDLER_PASS; /* continue processing */
|
||||
}
|
||||
}
|
||||
|
||||
forward:
|
||||
@@ -178,8 +181,10 @@ forward:
|
||||
case BR_STATE_FORWARDING:
|
||||
rhook = rcu_dereference(br_should_route_hook);
|
||||
if (rhook) {
|
||||
if ((*rhook)(skb))
|
||||
return skb;
|
||||
if ((*rhook)(skb)) {
|
||||
*pskb = skb;
|
||||
return RX_HANDLER_PASS;
|
||||
}
|
||||
dest = eth_hdr(skb)->h_dest;
|
||||
}
|
||||
/* fall through */
|
||||
@@ -194,5 +199,5 @@ forward:
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
return NULL;
|
||||
return RX_HANDLER_CONSUMED;
|
||||
}
|
||||
|
@@ -379,7 +379,7 @@ extern void br_features_recompute(struct net_bridge *br);
|
||||
|
||||
/* br_input.c */
|
||||
extern int br_handle_frame_finish(struct sk_buff *skb);
|
||||
extern struct sk_buff *br_handle_frame(struct sk_buff *skb);
|
||||
extern rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
|
||||
|
||||
/* br_ioctl.c */
|
||||
extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
|
@@ -3070,6 +3070,8 @@ out:
|
||||
* on a failure.
|
||||
*
|
||||
* The caller must hold the rtnl_mutex.
|
||||
*
|
||||
* For a general description of rx_handler, see enum rx_handler_result.
|
||||
*/
|
||||
int netdev_rx_handler_register(struct net_device *dev,
|
||||
rx_handler_func_t *rx_handler,
|
||||
@@ -3129,6 +3131,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
|
||||
rx_handler_func_t *rx_handler;
|
||||
struct net_device *orig_dev;
|
||||
struct net_device *null_or_dev;
|
||||
bool deliver_exact = false;
|
||||
int ret = NET_RX_DROP;
|
||||
__be16 type;
|
||||
|
||||
@@ -3181,18 +3184,22 @@ ncls:
|
||||
|
||||
rx_handler = rcu_dereference(skb->dev->rx_handler);
|
||||
if (rx_handler) {
|
||||
struct net_device *prev_dev;
|
||||
|
||||
if (pt_prev) {
|
||||
ret = deliver_skb(skb, pt_prev, orig_dev);
|
||||
pt_prev = NULL;
|
||||
}
|
||||
prev_dev = skb->dev;
|
||||
skb = rx_handler(skb);
|
||||
if (!skb)
|
||||
switch (rx_handler(&skb)) {
|
||||
case RX_HANDLER_CONSUMED:
|
||||
goto out;
|
||||
if (skb->dev != prev_dev)
|
||||
case RX_HANDLER_ANOTHER:
|
||||
goto another_round;
|
||||
case RX_HANDLER_EXACT:
|
||||
deliver_exact = true;
|
||||
case RX_HANDLER_PASS:
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
if (vlan_tx_tag_present(skb)) {
|
||||
@@ -3210,7 +3217,7 @@ ncls:
|
||||
vlan_on_bond_hook(skb);
|
||||
|
||||
/* deliver only exact match when indicated */
|
||||
null_or_dev = skb->deliver_no_wcard ? skb->dev : NULL;
|
||||
null_or_dev = deliver_exact ? skb->dev : NULL;
|
||||
|
||||
type = skb->protocol;
|
||||
list_for_each_entry_rcu(ptype,
|
||||
|
@@ -523,7 +523,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
||||
new->ip_summed = old->ip_summed;
|
||||
skb_copy_queue_mapping(new, old);
|
||||
new->priority = old->priority;
|
||||
new->deliver_no_wcard = old->deliver_no_wcard;
|
||||
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
|
||||
new->ipvs_property = old->ipvs_property;
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user