2011-11-28 05:22:18 +00:00
# include <linux/skbuff.h>
2012-01-24 16:03:33 -05:00
# include <linux/export.h>
2011-11-28 05:22:18 +00:00
# include <linux/ip.h>
# include <linux/ipv6.h>
# include <linux/if_vlan.h>
# include <net/ip.h>
# include <linux/if_tunnel.h>
# include <linux/if_pppox.h>
# include <linux/ppp_defs.h>
# include <net/flow_keys.h>
flow_dissector: use a 64bit load/store
Le lundi 28 novembre 2011 à 19:06 -0500, David Miller a écrit :
> From: Dimitris Michailidis <dm@chelsio.com>
> Date: Mon, 28 Nov 2011 08:25:39 -0800
>
> >> +bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys
> >> *flow)
> >> +{
> >> + int poff, nhoff = skb_network_offset(skb);
> >> + u8 ip_proto;
> >> + u16 proto = skb->protocol;
> >
> > __be16 instead of u16 for proto?
>
> I'll take care of this when I apply these patches.
( CC trimmed )
Thanks David !
Here is a small patch to use one 64bit load/store on x86_64 instead of
two 32bit load/stores.
[PATCH net-next] flow_dissector: use a 64bit load/store
gcc compiler is smart enough to use a single load/store if we
memcpy(dptr, sptr, 8) on x86_64, regardless of
CONFIG_CC_OPTIMIZE_FOR_SIZE
In IP header, daddr immediately follows saddr, this wont change in the
future. We only need to make sure our flow_keys (src,dst) fields wont
break the rule.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-28 20:30:35 +00:00
/* copy saddr & daddr, possibly using 64bit load/store
* Equivalent to : flow - > src = iph - > saddr ;
* flow - > dst = iph - > daddr ;
*/
static void iph_to_flow_copy_addrs ( struct flow_keys * flow , const struct iphdr * iph )
{
BUILD_BUG_ON ( offsetof ( typeof ( * flow ) , dst ) ! =
offsetof ( typeof ( * flow ) , src ) + sizeof ( flow - > src ) ) ;
memcpy ( & flow - > src , & iph - > saddr , sizeof ( flow - > src ) + sizeof ( flow - > dst ) ) ;
}
2011-11-28 05:22:18 +00:00
bool skb_flow_dissect ( const struct sk_buff * skb , struct flow_keys * flow )
{
int poff , nhoff = skb_network_offset ( skb ) ;
u8 ip_proto ;
__be16 proto = skb - > protocol ;
memset ( flow , 0 , sizeof ( * flow ) ) ;
again :
switch ( proto ) {
case __constant_htons ( ETH_P_IP ) : {
const struct iphdr * iph ;
struct iphdr _iph ;
ip :
iph = skb_header_pointer ( skb , nhoff , sizeof ( _iph ) , & _iph ) ;
if ( ! iph )
return false ;
if ( ip_is_fragment ( iph ) )
ip_proto = 0 ;
else
ip_proto = iph - > protocol ;
flow_dissector: use a 64bit load/store
Le lundi 28 novembre 2011 à 19:06 -0500, David Miller a écrit :
> From: Dimitris Michailidis <dm@chelsio.com>
> Date: Mon, 28 Nov 2011 08:25:39 -0800
>
> >> +bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys
> >> *flow)
> >> +{
> >> + int poff, nhoff = skb_network_offset(skb);
> >> + u8 ip_proto;
> >> + u16 proto = skb->protocol;
> >
> > __be16 instead of u16 for proto?
>
> I'll take care of this when I apply these patches.
( CC trimmed )
Thanks David !
Here is a small patch to use one 64bit load/store on x86_64 instead of
two 32bit load/stores.
[PATCH net-next] flow_dissector: use a 64bit load/store
gcc compiler is smart enough to use a single load/store if we
memcpy(dptr, sptr, 8) on x86_64, regardless of
CONFIG_CC_OPTIMIZE_FOR_SIZE
In IP header, daddr immediately follows saddr, this wont change in the
future. We only need to make sure our flow_keys (src,dst) fields wont
break the rule.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-28 20:30:35 +00:00
iph_to_flow_copy_addrs ( flow , iph ) ;
2011-11-28 05:22:18 +00:00
nhoff + = iph - > ihl * 4 ;
break ;
}
case __constant_htons ( ETH_P_IPV6 ) : {
const struct ipv6hdr * iph ;
struct ipv6hdr _iph ;
ipv6 :
iph = skb_header_pointer ( skb , nhoff , sizeof ( _iph ) , & _iph ) ;
if ( ! iph )
return false ;
ip_proto = iph - > nexthdr ;
flow - > src = iph - > saddr . s6_addr32 [ 3 ] ;
flow - > dst = iph - > daddr . s6_addr32 [ 3 ] ;
nhoff + = sizeof ( struct ipv6hdr ) ;
break ;
}
case __constant_htons ( ETH_P_8021Q ) : {
const struct vlan_hdr * vlan ;
struct vlan_hdr _vlan ;
vlan = skb_header_pointer ( skb , nhoff , sizeof ( _vlan ) , & _vlan ) ;
if ( ! vlan )
return false ;
proto = vlan - > h_vlan_encapsulated_proto ;
nhoff + = sizeof ( * vlan ) ;
goto again ;
}
case __constant_htons ( ETH_P_PPP_SES ) : {
struct {
struct pppoe_hdr hdr ;
__be16 proto ;
} * hdr , _hdr ;
hdr = skb_header_pointer ( skb , nhoff , sizeof ( _hdr ) , & _hdr ) ;
if ( ! hdr )
return false ;
proto = hdr - > proto ;
nhoff + = PPPOE_SES_HLEN ;
switch ( proto ) {
case __constant_htons ( PPP_IP ) :
goto ip ;
case __constant_htons ( PPP_IPV6 ) :
goto ipv6 ;
default :
return false ;
}
}
default :
return false ;
}
switch ( ip_proto ) {
case IPPROTO_GRE : {
struct gre_hdr {
__be16 flags ;
__be16 proto ;
} * hdr , _hdr ;
hdr = skb_header_pointer ( skb , nhoff , sizeof ( _hdr ) , & _hdr ) ;
if ( ! hdr )
return false ;
/*
* Only look inside GRE if version zero and no
* routing
*/
if ( ! ( hdr - > flags & ( GRE_VERSION | GRE_ROUTING ) ) ) {
proto = hdr - > proto ;
nhoff + = 4 ;
if ( hdr - > flags & GRE_CSUM )
nhoff + = 4 ;
if ( hdr - > flags & GRE_KEY )
nhoff + = 4 ;
if ( hdr - > flags & GRE_SEQ )
nhoff + = 4 ;
goto again ;
}
break ;
}
case IPPROTO_IPIP :
goto again ;
default :
break ;
}
flow - > ip_proto = ip_proto ;
poff = proto_ports_offset ( ip_proto ) ;
if ( poff > = 0 ) {
__be32 * ports , _ports ;
nhoff + = poff ;
ports = skb_header_pointer ( skb , nhoff , sizeof ( _ports ) , & _ports ) ;
if ( ports )
flow - > ports = * ports ;
}
return true ;
}
EXPORT_SYMBOL ( skb_flow_dissect ) ;