1 #include <linux/skbuff.h>
2 #include <linux/export.h>
4 #include <linux/ipv6.h>
5 #include <linux/if_vlan.h>
7 #include <linux/if_tunnel.h>
8 #include <linux/if_pppox.h>
9 #include <linux/ppp_defs.h>
10 #include <net/flow_keys.h>
12 /* copy saddr & daddr, possibly using 64bit load/store
13 * Equivalent to : flow->src = iph->saddr;
14 * flow->dst = iph->daddr;
16 static void iph_to_flow_copy_addrs(struct flow_keys
*flow
, const struct iphdr
*iph
)
18 BUILD_BUG_ON(offsetof(typeof(*flow
), dst
) !=
19 offsetof(typeof(*flow
), src
) + sizeof(flow
->src
));
20 memcpy(&flow
->src
, &iph
->saddr
, sizeof(flow
->src
) + sizeof(flow
->dst
));
23 bool skb_flow_dissect(const struct sk_buff
*skb
, struct flow_keys
*flow
)
25 int poff
, nhoff
= skb_network_offset(skb
);
27 __be16 proto
= skb
->protocol
;
29 memset(flow
, 0, sizeof(*flow
));
33 case __constant_htons(ETH_P_IP
): {
34 const struct iphdr
*iph
;
37 iph
= skb_header_pointer(skb
, nhoff
, sizeof(_iph
), &_iph
);
41 if (ip_is_fragment(iph
))
44 ip_proto
= iph
->protocol
;
45 iph_to_flow_copy_addrs(flow
, iph
);
46 nhoff
+= iph
->ihl
* 4;
49 case __constant_htons(ETH_P_IPV6
): {
50 const struct ipv6hdr
*iph
;
53 iph
= skb_header_pointer(skb
, nhoff
, sizeof(_iph
), &_iph
);
57 ip_proto
= iph
->nexthdr
;
58 flow
->src
= iph
->saddr
.s6_addr32
[3];
59 flow
->dst
= iph
->daddr
.s6_addr32
[3];
60 nhoff
+= sizeof(struct ipv6hdr
);
63 case __constant_htons(ETH_P_8021Q
): {
64 const struct vlan_hdr
*vlan
;
65 struct vlan_hdr _vlan
;
67 vlan
= skb_header_pointer(skb
, nhoff
, sizeof(_vlan
), &_vlan
);
71 proto
= vlan
->h_vlan_encapsulated_proto
;
72 nhoff
+= sizeof(*vlan
);
75 case __constant_htons(ETH_P_PPP_SES
): {
80 hdr
= skb_header_pointer(skb
, nhoff
, sizeof(_hdr
), &_hdr
);
84 nhoff
+= PPPOE_SES_HLEN
;
86 case __constant_htons(PPP_IP
):
88 case __constant_htons(PPP_IPV6
):
105 hdr
= skb_header_pointer(skb
, nhoff
, sizeof(_hdr
), &_hdr
);
109 * Only look inside GRE if version zero and no
112 if (!(hdr
->flags
& (GRE_VERSION
|GRE_ROUTING
))) {
115 if (hdr
->flags
& GRE_CSUM
)
117 if (hdr
->flags
& GRE_KEY
)
119 if (hdr
->flags
& GRE_SEQ
)
131 flow
->ip_proto
= ip_proto
;
132 poff
= proto_ports_offset(ip_proto
);
134 __be32
*ports
, _ports
;
137 ports
= skb_header_pointer(skb
, nhoff
, sizeof(_ports
), &_ports
);
139 flow
->ports
= *ports
;
144 EXPORT_SYMBOL(skb_flow_dissect
);