2008-07-08 14:23:36 +04:00
# include <linux/skbuff.h>
# include <linux/netdevice.h>
# include <linux/if_vlan.h>
2009-03-01 11:11:52 +03:00
# include <linux/netpoll.h>
2008-07-08 14:23:36 +04:00
# include "vlan.h"
/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */
int __vlan_hwaccel_rx ( struct sk_buff * skb , struct vlan_group * grp ,
2008-07-08 14:24:44 +04:00
u16 vlan_tci , int polling )
2008-07-08 14:23:36 +04:00
{
2009-03-01 11:11:52 +03:00
if ( netpoll_rx ( skb ) )
return NET_RX_DROP ;
2009-01-06 21:50:09 +03:00
if ( skb_bond_should_drop ( skb ) )
goto drop ;
2008-07-08 14:23:36 +04:00
2008-07-15 09:49:30 +04:00
skb - > vlan_tci = vlan_tci ;
2009-01-06 21:50:09 +03:00
skb - > dev = vlan_group_get_device ( grp , vlan_tci & VLAN_VID_MASK ) ;
if ( ! skb - > dev )
goto drop ;
2008-11-05 01:49:57 +03:00
return ( polling ? netif_receive_skb ( skb ) : netif_rx ( skb ) ) ;
2009-01-06 21:50:09 +03:00
drop :
dev_kfree_skb_any ( skb ) ;
return NET_RX_DROP ;
2008-11-05 01:49:57 +03:00
}
EXPORT_SYMBOL ( __vlan_hwaccel_rx ) ;
int vlan_hwaccel_do_receive ( struct sk_buff * skb )
{
2009-01-06 21:50:09 +03:00
struct net_device * dev = skb - > dev ;
2008-11-05 01:49:57 +03:00
struct net_device_stats * stats ;
2009-01-06 21:50:09 +03:00
skb - > dev = vlan_dev_info ( dev ) - > real_dev ;
2008-07-15 09:49:30 +04:00
netif_nit_deliver ( skb ) ;
2008-11-05 01:49:57 +03:00
skb - > dev = dev ;
skb - > priority = vlan_get_ingress_priority ( dev , skb - > vlan_tci ) ;
2008-07-15 09:49:30 +04:00
skb - > vlan_tci = 0 ;
2008-07-08 14:23:36 +04:00
2008-11-05 01:49:57 +03:00
stats = & dev - > stats ;
2008-07-08 14:23:36 +04:00
stats - > rx_packets + + ;
stats - > rx_bytes + = skb - > len ;
switch ( skb - > pkt_type ) {
case PACKET_BROADCAST :
break ;
case PACKET_MULTICAST :
stats - > multicast + + ;
break ;
case PACKET_OTHERHOST :
/* Our lower layer thinks this is not local, let's make sure.
* This allows the VLAN to have a different MAC than the
* underlying device , and still route correctly . */
if ( ! compare_ether_addr ( eth_hdr ( skb ) - > h_dest ,
2008-11-05 01:49:57 +03:00
dev - > dev_addr ) )
2008-07-08 14:23:36 +04:00
skb - > pkt_type = PACKET_HOST ;
break ;
} ;
2008-11-05 01:49:57 +03:00
return 0 ;
2008-07-08 14:23:36 +04:00
}
2008-07-08 14:23:57 +04:00
struct net_device * vlan_dev_real_dev ( const struct net_device * dev )
{
return vlan_dev_info ( dev ) - > real_dev ;
}
2009-01-26 23:37:53 +03:00
EXPORT_SYMBOL ( vlan_dev_real_dev ) ;
2008-07-08 14:23:57 +04:00
u16 vlan_dev_vlan_id ( const struct net_device * dev )
{
return vlan_dev_info ( dev ) - > vlan_id ;
}
2009-01-26 23:37:53 +03:00
EXPORT_SYMBOL ( vlan_dev_vlan_id ) ;
2009-01-06 21:50:09 +03:00
static int vlan_gro_common ( struct napi_struct * napi , struct vlan_group * grp ,
unsigned int vlan_tci , struct sk_buff * skb )
{
struct sk_buff * p ;
2009-03-16 20:50:02 +03:00
if ( netpoll_rx_on ( skb ) )
return GRO_NORMAL ;
2009-01-06 21:50:09 +03:00
if ( skb_bond_should_drop ( skb ) )
goto drop ;
skb - > vlan_tci = vlan_tci ;
skb - > dev = vlan_group_get_device ( grp , vlan_tci & VLAN_VID_MASK ) ;
if ( ! skb - > dev )
goto drop ;
for ( p = napi - > gro_list ; p ; p = p - > next ) {
2009-02-08 21:00:37 +03:00
NAPI_GRO_CB ( p ) - > same_flow =
p - > dev = = skb - > dev & & ! compare_ether_header (
skb_mac_header ( p ) , skb_gro_mac_header ( skb ) ) ;
2009-01-06 21:50:09 +03:00
NAPI_GRO_CB ( p ) - > flush = 0 ;
}
return dev_gro_receive ( napi , skb ) ;
drop :
2009-03-16 20:50:02 +03:00
return GRO_DROP ;
2009-01-06 21:50:09 +03:00
}
int vlan_gro_receive ( struct napi_struct * napi , struct vlan_group * grp ,
unsigned int vlan_tci , struct sk_buff * skb )
{
2009-01-29 17:19:50 +03:00
skb_gro_reset_offset ( skb ) ;
2009-01-29 17:19:48 +03:00
return napi_skb_finish ( vlan_gro_common ( napi , grp , vlan_tci , skb ) , skb ) ;
2009-01-06 21:50:09 +03:00
}
EXPORT_SYMBOL ( vlan_gro_receive ) ;
int vlan_gro_frags ( struct napi_struct * napi , struct vlan_group * grp ,
unsigned int vlan_tci , struct napi_gro_fraginfo * info )
{
struct sk_buff * skb = napi_fraginfo_skb ( napi , info ) ;
if ( ! skb )
2009-01-29 17:19:48 +03:00
return NET_RX_DROP ;
2009-01-06 21:50:09 +03:00
2009-01-29 17:19:48 +03:00
return napi_frags_finish ( napi , skb ,
vlan_gro_common ( napi , grp , vlan_tci , skb ) ) ;
2009-01-06 21:50:09 +03:00
}
EXPORT_SYMBOL ( vlan_gro_frags ) ;