diff options
-rw-r--r-- | include/net/ip.h | 9 | ||||
-rw-r--r-- | include/uapi/linux/in.h | 4 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 9 | ||||
-rw-r--r-- | net/ipv4/ip_sockglue.c | 2 |
4 files changed, 16 insertions, 8 deletions
diff --git a/include/net/ip.h b/include/net/ip.h index 4aa781b7f609..b885d75cede4 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
@@ -266,7 +266,8 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst) | |||
266 | 266 | ||
267 | static inline bool ip_sk_accept_pmtu(const struct sock *sk) | 267 | static inline bool ip_sk_accept_pmtu(const struct sock *sk) |
268 | { | 268 | { |
269 | return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE; | 269 | return inet_sk(sk)->pmtudisc != IP_PMTUDISC_INTERFACE && |
270 | inet_sk(sk)->pmtudisc != IP_PMTUDISC_OMIT; | ||
270 | } | 271 | } |
271 | 272 | ||
272 | static inline bool ip_sk_use_pmtu(const struct sock *sk) | 273 | static inline bool ip_sk_use_pmtu(const struct sock *sk) |
@@ -274,6 +275,12 @@ static inline bool ip_sk_use_pmtu(const struct sock *sk) | |||
274 | return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE; | 275 | return inet_sk(sk)->pmtudisc < IP_PMTUDISC_PROBE; |
275 | } | 276 | } |
276 | 277 | ||
278 | static inline bool ip_sk_local_df(const struct sock *sk) | ||
279 | { | ||
280 | return inet_sk(sk)->pmtudisc < IP_PMTUDISC_DO || | ||
281 | inet_sk(sk)->pmtudisc == IP_PMTUDISC_OMIT; | ||
282 | } | ||
283 | |||
277 | static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, | 284 | static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, |
278 | bool forwarding) | 285 | bool forwarding) |
279 | { | 286 | { |
diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h index 393c5de09d42..c33a65e3d62c 100644 --- a/include/uapi/linux/in.h +++ b/include/uapi/linux/in.h | |||
@@ -120,6 +120,10 @@ struct in_addr { | |||
120 | * this socket to prevent accepting spoofed ones. | 120 | * this socket to prevent accepting spoofed ones. |
121 | */ | 121 | */ |
122 | #define IP_PMTUDISC_INTERFACE 4 | 122 | #define IP_PMTUDISC_INTERFACE 4 |
123 | /* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get | ||
124 | * fragmented if they exeed the interface mtu | ||
125 | */ | ||
126 | #define IP_PMTUDISC_OMIT 5 | ||
123 | 127 | ||
124 | #define IP_MULTICAST_IF 32 | 128 | #define IP_MULTICAST_IF 32 |
125 | #define IP_MULTICAST_TTL 33 | 129 | #define IP_MULTICAST_TTL 33 |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 22aa11971ed1..e85445b2b102 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -824,8 +824,7 @@ static int __ip_append_data(struct sock *sk, | |||
824 | 824 | ||
825 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 825 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
826 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 826 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
827 | maxnonfragsize = (inet->pmtudisc >= IP_PMTUDISC_DO) ? | 827 | maxnonfragsize = ip_sk_local_df(sk) ? 0xFFFF : mtu; |
828 | mtu : 0xFFFF; | ||
829 | 828 | ||
830 | if (cork->length + length > maxnonfragsize - fragheaderlen) { | 829 | if (cork->length + length > maxnonfragsize - fragheaderlen) { |
831 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, | 830 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
@@ -1148,8 +1147,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, | |||
1148 | 1147 | ||
1149 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 1148 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
1150 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 1149 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
1151 | maxnonfragsize = (inet->pmtudisc >= IP_PMTUDISC_DO) ? | 1150 | maxnonfragsize = ip_sk_local_df(sk) ? 0xFFFF : mtu; |
1152 | mtu : 0xFFFF; | ||
1153 | 1151 | ||
1154 | if (cork->length + size > maxnonfragsize - fragheaderlen) { | 1152 | if (cork->length + size > maxnonfragsize - fragheaderlen) { |
1155 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, | 1153 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
@@ -1310,8 +1308,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, | |||
1310 | * to fragment the frame generated here. No matter, what transforms | 1308 | * to fragment the frame generated here. No matter, what transforms |
1311 | * how transforms change size of the packet, it will come out. | 1309 | * how transforms change size of the packet, it will come out. |
1312 | */ | 1310 | */ |
1313 | if (inet->pmtudisc < IP_PMTUDISC_DO) | 1311 | skb->local_df = ip_sk_local_df(sk); |
1314 | skb->local_df = 1; | ||
1315 | 1312 | ||
1316 | /* DF bit is set when we want to see DF on outgoing frames. | 1313 | /* DF bit is set when we want to see DF on outgoing frames. |
1317 | * If local_df is set too, we still allow to fragment this frame | 1314 | * If local_df is set too, we still allow to fragment this frame |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 0968b28c4cf3..64741b938632 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -643,7 +643,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
643 | inet->nodefrag = val ? 1 : 0; | 643 | inet->nodefrag = val ? 1 : 0; |
644 | break; | 644 | break; |
645 | case IP_MTU_DISCOVER: | 645 | case IP_MTU_DISCOVER: |
646 | if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_INTERFACE) | 646 | if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT) |
647 | goto e_inval; | 647 | goto e_inval; |
648 | inet->pmtudisc = val; | 648 | inet->pmtudisc = val; |
649 | break; | 649 | break; |