diff options
Diffstat (limited to 'net/bridge/br_input.c')
| -rw-r--r-- | net/bridge/br_input.c | 12 | 
1 files changed, 9 insertions, 3 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index d36e700f7a2..99647d8f95c 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -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))  |