]> git.proxmox.com Git - ovs.git/blame - datapath/linux/compat/include/net/ip.h
compat: Detect and use upstream ip_fragment().
[ovs.git] / datapath / linux / compat / include / net / ip.h
CommitLineData
02059c09
JG
1#ifndef __NET_IP_WRAPPER_H
2#define __NET_IP_WRAPPER_H 1
3
4#include_next <net/ip.h>
5
213e1f54 6#include <net/route.h>
02059c09 7#include <linux/version.h>
02059c09 8
920fc091 9#ifndef HAVE_IP_IS_FRAGMENT
1b7ee51f
PS
10static inline bool ip_is_fragment(const struct iphdr *iph)
11{
12 return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
13}
14#endif
15
13dd4a97 16#ifndef HAVE_INET_GET_LOCAL_PORT_RANGE_USING_NET
cb25142c
PS
17static inline void rpl_inet_get_local_port_range(struct net *net, int *low,
18 int *high)
19{
20 inet_get_local_port_range(low, high);
21}
22#define inet_get_local_port_range rpl_inet_get_local_port_range
23
24#endif
25
595e069a
JS
26#ifndef IPSKB_FRAG_PMTU
27#define IPSKB_FRAG_PMTU BIT(6)
28#endif
29
cfda4537
JS
30/* IPv4 datagram length is stored into 16bit field (tot_len) */
31#ifndef IP_MAX_MTU
32#define IP_MAX_MTU 0xFFFFU
33#endif
34
35#ifndef HAVE_IP_SKB_DST_MTU
36static inline bool rpl_ip_sk_use_pmtu(const struct sock *sk)
37{
38 return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE;
39}
40#define ip_sk_use_pmtu rpl_ip_sk_use_pmtu
41
42static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
43 bool forwarding)
44{
45#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
46 struct net *net = dev_net(dst->dev);
47
48 if (net->ipv4.sysctl_ip_fwd_use_pmtu ||
49 dst_metric_locked(dst, RTAX_MTU) ||
50 !forwarding)
51 return dst_mtu(dst);
52#endif
53
54 return min(dst->dev->mtu, IP_MAX_MTU);
55}
56
57static inline unsigned int rpl_ip_skb_dst_mtu(const struct sk_buff *skb)
58{
59 if (!skb->sk || ip_sk_use_pmtu(skb->sk)) {
60 bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
61 return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
62 } else {
63 return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU);
64 }
65}
66#define ip_skb_dst_mtu rpl_ip_skb_dst_mtu
67#endif /* HAVE_IP_SKB_DST_MTU */
68
213e1f54
JS
69#ifdef HAVE_IP_FRAGMENT_TAKES_SOCK
70#define OVS_VPORT_OUTPUT_PARAMS struct sock *sock, struct sk_buff *skb
71#else
72#define OVS_VPORT_OUTPUT_PARAMS struct sk_buff *skb
73#endif
74
0f09d6e3
JS
75/* Prior to upstream commit d6b915e29f4a ("ip_fragment: don't forward
76 * defragmented DF packet"), IPCB(skb)->frag_max_size was not always populated
77 * correctly, which would lead to reassembled packets not being refragmented.
78 * So, we backport all of ip_defrag() in these cases.
79 */
80#if !defined(HAVE_CORRECT_MRU_HANDLING) && defined(OVS_FRAGMENT_BACKPORT)
213e1f54
JS
81
82#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
83static inline bool ip_defrag_user_in_between(u32 user,
84 enum ip_defrag_users lower_bond,
85 enum ip_defrag_users upper_bond)
86{
87 return user >= lower_bond && user <= upper_bond;
88}
0f09d6e3 89#endif /* < v4.2 */
213e1f54
JS
90
91#ifndef HAVE_IP_DO_FRAGMENT
92static inline int rpl_ip_do_fragment(struct sock *sk, struct sk_buff *skb,
93 int (*output)(OVS_VPORT_OUTPUT_PARAMS))
94{
95 unsigned int mtu = ip_skb_dst_mtu(skb);
96 struct iphdr *iph = ip_hdr(skb);
97 struct rtable *rt = skb_rtable(skb);
98 struct net_device *dev = rt->dst.dev;
99
100 if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) ||
101 (IPCB(skb)->frag_max_size &&
102 IPCB(skb)->frag_max_size > mtu))) {
103
104 pr_warn("Dropping packet in ip_do_fragment()\n");
105 IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
106 kfree_skb(skb);
107 return -EMSGSIZE;
108 }
109
110#ifndef HAVE_IP_FRAGMENT_TAKES_SOCK
111 return ip_fragment(skb, output);
112#else
113 return ip_fragment(sk, skb, output);
114#endif
115}
116#define ip_do_fragment rpl_ip_do_fragment
117#endif /* IP_DO_FRAGMENT */
595e069a 118
595e069a
JS
119int rpl_ip_defrag(struct sk_buff *skb, u32 user);
120#define ip_defrag rpl_ip_defrag
121
122int __init rpl_ipfrag_init(void);
123void rpl_ipfrag_fini(void);
0f09d6e3 124#else /* HAVE_CORRECT_MRU_HANDLING || !OVS_FRAGMENT_BACKPORT */
792e5ed7
JS
125
126/* We have no good way to detect the presence of upstream commit 8282f27449bf
127 * ("inet: frag: Always orphan skbs inside ip_defrag()"), but it should be
128 * always included in kernels 4.5+. */
129#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
130static inline int rpl_ip_defrag(struct sk_buff *skb, u32 user)
131{
132 skb_orphan(skb);
3f82513a 133 return ip_defrag(skb, user);
792e5ed7
JS
134}
135#define ip_defrag rpl_ip_defrag
136#endif
137
595e069a
JS
138static inline int rpl_ipfrag_init(void) { return 0; }
139static inline void rpl_ipfrag_fini(void) { }
0f09d6e3 140#endif /* HAVE_CORRECT_MRU_HANDLING && OVS_FRAGMENT_BACKPORT */
595e069a
JS
141#define ipfrag_init rpl_ipfrag_init
142#define ipfrag_fini rpl_ipfrag_fini
143
02059c09 144#endif