1 #include <linux/skbuff.h>
2 #include <linux/export.h>
4 #include <linux/ipv6.h>
5 #include <linux/if_vlan.h>
8 #include <linux/if_tunnel.h>
9 #include <linux/if_pppox.h>
10 #include <linux/ppp_defs.h>
11 #include <net/flow_keys.h>
13 /* copy saddr & daddr, possibly using 64bit load/store
14 * Equivalent to : flow->src = iph->saddr;
15 * flow->dst = iph->daddr;
17 static void iph_to_flow_copy_addrs(struct flow_keys
*flow
, const struct iphdr
*iph
)
19 BUILD_BUG_ON(offsetof(typeof(*flow
), dst
) !=
20 offsetof(typeof(*flow
), src
) + sizeof(flow
->src
));
21 memcpy(&flow
->src
, &iph
->saddr
, sizeof(flow
->src
) + sizeof(flow
->dst
));
24 bool skb_flow_dissect(const struct sk_buff
*skb
, struct flow_keys
*flow
)
26 int poff
, nhoff
= skb_network_offset(skb
);
28 __be16 proto
= skb
->protocol
;
30 memset(flow
, 0, sizeof(*flow
));
34 case __constant_htons(ETH_P_IP
): {
35 const struct iphdr
*iph
;
38 iph
= skb_header_pointer(skb
, nhoff
, sizeof(_iph
), &_iph
);
42 if (ip_is_fragment(iph
))
45 ip_proto
= iph
->protocol
;
46 iph_to_flow_copy_addrs(flow
, iph
);
47 nhoff
+= iph
->ihl
* 4;
50 case __constant_htons(ETH_P_IPV6
): {
51 const struct ipv6hdr
*iph
;
54 iph
= skb_header_pointer(skb
, nhoff
, sizeof(_iph
), &_iph
);
58 ip_proto
= iph
->nexthdr
;
59 flow
->src
= (__force __be32
)ipv6_addr_hash(&iph
->saddr
);
60 flow
->dst
= (__force __be32
)ipv6_addr_hash(&iph
->daddr
);
61 nhoff
+= sizeof(struct ipv6hdr
);
64 case __constant_htons(ETH_P_8021Q
): {
65 const struct vlan_hdr
*vlan
;
66 struct vlan_hdr _vlan
;
68 vlan
= skb_header_pointer(skb
, nhoff
, sizeof(_vlan
), &_vlan
);
72 proto
= vlan
->h_vlan_encapsulated_proto
;
73 nhoff
+= sizeof(*vlan
);
76 case __constant_htons(ETH_P_PPP_SES
): {
81 hdr
= skb_header_pointer(skb
, nhoff
, sizeof(_hdr
), &_hdr
);
85 nhoff
+= PPPOE_SES_HLEN
;
87 case __constant_htons(PPP_IP
):
89 case __constant_htons(PPP_IPV6
):
106 hdr
= skb_header_pointer(skb
, nhoff
, sizeof(_hdr
), &_hdr
);
110 * Only look inside GRE if version zero and no
113 if (!(hdr
->flags
& (GRE_VERSION
|GRE_ROUTING
))) {
116 if (hdr
->flags
& GRE_CSUM
)
118 if (hdr
->flags
& GRE_KEY
)
120 if (hdr
->flags
& GRE_SEQ
)
132 flow
->ip_proto
= ip_proto
;
133 poff
= proto_ports_offset(ip_proto
);
135 __be32
*ports
, _ports
;
138 ports
= skb_header_pointer(skb
, nhoff
, sizeof(_ports
), &_ports
);
140 flow
->ports
= *ports
;
145 EXPORT_SYMBOL(skb_flow_dissect
);