1 #include <linux/skbuff.h>
3 #include <linux/ipv6.h>
4 #include <linux/if_vlan.h>
6 #include <linux/if_tunnel.h>
7 #include <linux/if_pppox.h>
8 #include <linux/ppp_defs.h>
9 #include <net/flow_keys.h>
11 /* copy saddr & daddr, possibly using 64bit load/store
12 * Equivalent to : flow->src = iph->saddr;
13 * flow->dst = iph->daddr;
15 static void iph_to_flow_copy_addrs(struct flow_keys
*flow
, const struct iphdr
*iph
)
17 BUILD_BUG_ON(offsetof(typeof(*flow
), dst
) !=
18 offsetof(typeof(*flow
), src
) + sizeof(flow
->src
));
19 memcpy(&flow
->src
, &iph
->saddr
, sizeof(flow
->src
) + sizeof(flow
->dst
));
22 bool skb_flow_dissect(const struct sk_buff
*skb
, struct flow_keys
*flow
)
24 int poff
, nhoff
= skb_network_offset(skb
);
26 __be16 proto
= skb
->protocol
;
28 memset(flow
, 0, sizeof(*flow
));
32 case __constant_htons(ETH_P_IP
): {
33 const struct iphdr
*iph
;
36 iph
= skb_header_pointer(skb
, nhoff
, sizeof(_iph
), &_iph
);
40 if (ip_is_fragment(iph
))
43 ip_proto
= iph
->protocol
;
44 iph_to_flow_copy_addrs(flow
, iph
);
45 nhoff
+= iph
->ihl
* 4;
48 case __constant_htons(ETH_P_IPV6
): {
49 const struct ipv6hdr
*iph
;
52 iph
= skb_header_pointer(skb
, nhoff
, sizeof(_iph
), &_iph
);
56 ip_proto
= iph
->nexthdr
;
57 flow
->src
= iph
->saddr
.s6_addr32
[3];
58 flow
->dst
= iph
->daddr
.s6_addr32
[3];
59 nhoff
+= sizeof(struct ipv6hdr
);
62 case __constant_htons(ETH_P_8021Q
): {
63 const struct vlan_hdr
*vlan
;
64 struct vlan_hdr _vlan
;
66 vlan
= skb_header_pointer(skb
, nhoff
, sizeof(_vlan
), &_vlan
);
70 proto
= vlan
->h_vlan_encapsulated_proto
;
71 nhoff
+= sizeof(*vlan
);
74 case __constant_htons(ETH_P_PPP_SES
): {
79 hdr
= skb_header_pointer(skb
, nhoff
, sizeof(_hdr
), &_hdr
);
83 nhoff
+= PPPOE_SES_HLEN
;
85 case __constant_htons(PPP_IP
):
87 case __constant_htons(PPP_IPV6
):
104 hdr
= skb_header_pointer(skb
, nhoff
, sizeof(_hdr
), &_hdr
);
108 * Only look inside GRE if version zero and no
111 if (!(hdr
->flags
& (GRE_VERSION
|GRE_ROUTING
))) {
114 if (hdr
->flags
& GRE_CSUM
)
116 if (hdr
->flags
& GRE_KEY
)
118 if (hdr
->flags
& GRE_SEQ
)
130 flow
->ip_proto
= ip_proto
;
131 poff
= proto_ports_offset(ip_proto
);
133 __be32
*ports
, _ports
;
136 ports
= skb_header_pointer(skb
, nhoff
, sizeof(_ports
), &_ports
);
138 flow
->ports
= *ports
;
143 EXPORT_SYMBOL(skb_flow_dissect
);