net: replace hooks in __netif_receive_skb V5
What this patch does is it removes two receive frame hooks (for bridge and for macvlan) from __netif_receive_skb. These are replaced them with a single hook for both. It only supports one hook per device because it makes no sense to do bridging and macvlan on the same device. Then a network driver (of virtual netdev like macvlan or bridge) can register an rx_handler for needed net device. Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
20c59de2e6
commit
ab95bfe01f
@@ -63,7 +63,6 @@ static int __init br_init(void)
|
||||
goto err_out4;
|
||||
|
||||
brioctl_set(br_ioctl_deviceless_stub);
|
||||
br_handle_frame_hook = br_handle_frame;
|
||||
|
||||
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
|
||||
br_fdb_test_addr_hook = br_fdb_test_addr;
|
||||
@@ -100,7 +99,6 @@ static void __exit br_deinit(void)
|
||||
br_fdb_test_addr_hook = NULL;
|
||||
#endif
|
||||
|
||||
br_handle_frame_hook = NULL;
|
||||
br_fdb_fini();
|
||||
}
|
||||
|
||||
|
@@ -147,6 +147,7 @@ static void del_nbp(struct net_bridge_port *p)
|
||||
|
||||
list_del_rcu(&p->list);
|
||||
|
||||
netdev_rx_handler_unregister(dev);
|
||||
rcu_assign_pointer(dev->br_port, NULL);
|
||||
|
||||
br_multicast_del_port(p);
|
||||
@@ -429,6 +430,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
||||
goto err2;
|
||||
|
||||
rcu_assign_pointer(dev->br_port, p);
|
||||
|
||||
err = netdev_rx_handler_register(dev, br_handle_frame);
|
||||
if (err)
|
||||
goto err3;
|
||||
|
||||
dev_disable_lro(dev);
|
||||
|
||||
list_add_rcu(&p->list, &br->port_list);
|
||||
@@ -451,6 +457,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
||||
br_netpoll_enable(br, dev);
|
||||
|
||||
return 0;
|
||||
err3:
|
||||
rcu_assign_pointer(dev->br_port, NULL);
|
||||
err2:
|
||||
br_fdb_delete_by_port(br, p, 1);
|
||||
err1:
|
||||
|
@@ -131,15 +131,19 @@ static inline int is_link_local(const unsigned char *dest)
|
||||
}
|
||||
|
||||
/*
|
||||
* Called via br_handle_frame_hook.
|
||||
* Return NULL if skb is handled
|
||||
* note: already called with rcu_read_lock (preempt_disabled)
|
||||
* note: already called with rcu_read_lock (preempt_disabled) from
|
||||
* netif_receive_skb
|
||||
*/
|
||||
struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
|
||||
struct sk_buff *br_handle_frame(struct sk_buff *skb)
|
||||
{
|
||||
struct net_bridge_port *p;
|
||||
const unsigned char *dest = eth_hdr(skb)->h_dest;
|
||||
int (*rhook)(struct sk_buff *skb);
|
||||
|
||||
if (skb->pkt_type == PACKET_LOOPBACK)
|
||||
return skb;
|
||||
|
||||
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
|
||||
goto drop;
|
||||
|
||||
@@ -147,6 +151,8 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
p = rcu_dereference(skb->dev->br_port);
|
||||
|
||||
if (unlikely(is_link_local(dest))) {
|
||||
/* Pause frames shouldn't be passed up by driver anyway */
|
||||
if (skb->protocol == htons(ETH_P_PAUSE))
|
||||
|
@@ -331,8 +331,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 net_bridge_port *p,
|
||||
struct sk_buff *skb);
|
||||
extern struct sk_buff *br_handle_frame(struct sk_buff *skb);
|
||||
|
||||
/* br_ioctl.c */
|
||||
extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
|
Reference in New Issue
Block a user