aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/dst.h1
-rw-r--r--include/net/xfrm.h2
-rw-r--r--net/ipv4/xfrm4_policy.c1
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/ipv6/xfrm6_policy.c24
5 files changed, 27 insertions, 3 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index 36d54fc248b0..a8d825f90305 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -54,6 +54,7 @@ struct dst_entry
54 unsigned long expires; 54 unsigned long expires;
55 55
56 unsigned short header_len; /* more space at head required */ 56 unsigned short header_len; /* more space at head required */
57 unsigned short nfheader_len; /* more non-fragment space at head required */
57 unsigned short trailer_len; /* space to reserve at tail */ 58 unsigned short trailer_len; /* space to reserve at tail */
58 59
59 u32 metrics[RTAX_MAX]; 60 u32 metrics[RTAX_MAX];
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index aa3ac994477b..aa93cc1f6299 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -260,6 +260,8 @@ struct xfrm_type
260 char *description; 260 char *description;
261 struct module *owner; 261 struct module *owner;
262 __u8 proto; 262 __u8 proto;
263 __u8 flags;
264#define XFRM_TYPE_NON_FRAGMENT 1
263 265
264 int (*init_state)(struct xfrm_state *x); 266 int (*init_state)(struct xfrm_state *x);
265 void (*destructor)(struct xfrm_state *); 267 void (*destructor)(struct xfrm_state *);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index a5bed741de2c..e517981ceadd 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -135,6 +135,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
135 dst_prev->flags |= DST_HOST; 135 dst_prev->flags |= DST_HOST;
136 dst_prev->lastuse = jiffies; 136 dst_prev->lastuse = jiffies;
137 dst_prev->header_len = header_len; 137 dst_prev->header_len = header_len;
138 dst_prev->nfheader_len = 0;
138 dst_prev->trailer_len = trailer_len; 139 dst_prev->trailer_len = trailer_len;
139 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); 140 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
140 141
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 2a376b7d91b4..258e3e45f5e0 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -971,7 +971,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
971 971
972 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); 972 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
973 973
974 fragheaderlen = sizeof(struct ipv6hdr) + (opt ? opt->opt_nflen : 0); 974 fragheaderlen = sizeof(struct ipv6hdr) + rt->u.dst.nfheader_len + (opt ? opt->opt_nflen : 0);
975 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); 975 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
976 976
977 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { 977 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 9328fc88708a..a3f68c8b737e 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -75,6 +75,24 @@ __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
75 (struct in6_addr*)&x->props.saddr; 75 (struct in6_addr*)&x->props.saddr;
76} 76}
77 77
78static inline void
79__xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x)
80{
81 if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
82 *nflen += x->props.header_len;
83 else
84 *len += x->props.header_len;
85}
86
87static inline void
88__xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x)
89{
90 if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
91 *nflen -= x->props.header_len;
92 else
93 *len -= x->props.header_len;
94}
95
78/* Allocate chain of dst_entry's, attach known xfrm's, calculate 96/* Allocate chain of dst_entry's, attach known xfrm's, calculate
79 * all the metrics... Shortly, bundle a bundle. 97 * all the metrics... Shortly, bundle a bundle.
80 */ 98 */
@@ -99,6 +117,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
99 int i; 117 int i;
100 int err = 0; 118 int err = 0;
101 int header_len = 0; 119 int header_len = 0;
120 int nfheader_len = 0;
102 int trailer_len = 0; 121 int trailer_len = 0;
103 122
104 dst = dst_prev = NULL; 123 dst = dst_prev = NULL;
@@ -135,7 +154,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
135 local = __xfrm6_bundle_addr_local(xfrm[i], local); 154 local = __xfrm6_bundle_addr_local(xfrm[i], local);
136 tunnel = 1; 155 tunnel = 1;
137 } 156 }
138 header_len += xfrm[i]->props.header_len; 157 __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
139 trailer_len += xfrm[i]->props.trailer_len; 158 trailer_len += xfrm[i]->props.trailer_len;
140 159
141 if (tunnel) { 160 if (tunnel) {
@@ -170,6 +189,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
170 dst_prev->flags |= DST_HOST; 189 dst_prev->flags |= DST_HOST;
171 dst_prev->lastuse = jiffies; 190 dst_prev->lastuse = jiffies;
172 dst_prev->header_len = header_len; 191 dst_prev->header_len = header_len;
192 dst_prev->nfheader_len = nfheader_len;
173 dst_prev->trailer_len = trailer_len; 193 dst_prev->trailer_len = trailer_len;
174 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); 194 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
175 195
@@ -188,7 +208,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
188 x->u.rt6.rt6i_src = rt0->rt6i_src; 208 x->u.rt6.rt6i_src = rt0->rt6i_src;
189 x->u.rt6.rt6i_idev = rt0->rt6i_idev; 209 x->u.rt6.rt6i_idev = rt0->rt6i_idev;
190 in6_dev_hold(rt0->rt6i_idev); 210 in6_dev_hold(rt0->rt6i_idev);
191 header_len -= x->u.dst.xfrm->props.header_len; 211 __xfrm6_bundle_len_dec(&header_len, &nfheader_len, x->u.dst.xfrm);
192 trailer_len -= x->u.dst.xfrm->props.trailer_len; 212 trailer_len -= x->u.dst.xfrm->props.trailer_len;
193 } 213 }
194 214