]>
Commit | Line | Data |
---|---|---|
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 |
10 | static 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 |
17 | static 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 | |
36 | static 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 | ||
42 | static 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 | ||
57 | static 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) | |
83 | static 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 | |
92 | static 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 |
119 | int rpl_ip_defrag(struct sk_buff *skb, u32 user); |
120 | #define ip_defrag rpl_ip_defrag | |
121 | ||
122 | int __init rpl_ipfrag_init(void); | |
123 | void 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) | |
130 | static 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 |
138 | static inline int rpl_ipfrag_init(void) { return 0; } |
139 | static 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 |