aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevich@gmail.com>2015-01-31 10:40:13 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-02 22:28:04 -0500
commit366e41d9774d7010cb63112b6db2fce6dc7809c0 (patch)
treed29cf61b02e8b31f41373e82e710645c768de0e9 /net/ipv6/ip6_output.c
parentba0c39cb98a1eec3635ae5f959fef963738d12a5 (diff)
ipv6: pull cork initialization into its own function.
Pull IPv6 cork initialization into its own function that can be re-used. IPv6 specific cork data did not have an explicit data structure. This patch creats eone so that just ipv6 cork data can be as arguemts. Also, since IPv6 tries to save the flow label into inet_cork_full tructure, pass the full cork. Adjust ip6_cork_release() to take cork data structures. Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c158
1 files changed, 89 insertions, 69 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index ce69a12ae48c..f9f08c43c6e1 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1135,6 +1135,74 @@ static void ip6_append_data_mtu(unsigned int *mtu,
1135 } 1135 }
1136} 1136}
1137 1137
1138static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
1139 struct inet6_cork *v6_cork,
1140 int hlimit, int tclass, struct ipv6_txoptions *opt,
1141 struct rt6_info *rt, struct flowi6 *fl6)
1142{
1143 struct ipv6_pinfo *np = inet6_sk(sk);
1144 unsigned int mtu;
1145
1146 /*
1147 * setup for corking
1148 */
1149 if (opt) {
1150 if (WARN_ON(v6_cork->opt))
1151 return -EINVAL;
1152
1153 v6_cork->opt = kzalloc(opt->tot_len, sk->sk_allocation);
1154 if (unlikely(v6_cork->opt == NULL))
1155 return -ENOBUFS;
1156
1157 v6_cork->opt->tot_len = opt->tot_len;
1158 v6_cork->opt->opt_flen = opt->opt_flen;
1159 v6_cork->opt->opt_nflen = opt->opt_nflen;
1160
1161 v6_cork->opt->dst0opt = ip6_opt_dup(opt->dst0opt,
1162 sk->sk_allocation);
1163 if (opt->dst0opt && !v6_cork->opt->dst0opt)
1164 return -ENOBUFS;
1165
1166 v6_cork->opt->dst1opt = ip6_opt_dup(opt->dst1opt,
1167 sk->sk_allocation);
1168 if (opt->dst1opt && !v6_cork->opt->dst1opt)
1169 return -ENOBUFS;
1170
1171 v6_cork->opt->hopopt = ip6_opt_dup(opt->hopopt,
1172 sk->sk_allocation);
1173 if (opt->hopopt && !v6_cork->opt->hopopt)
1174 return -ENOBUFS;
1175
1176 v6_cork->opt->srcrt = ip6_rthdr_dup(opt->srcrt,
1177 sk->sk_allocation);
1178 if (opt->srcrt && !v6_cork->opt->srcrt)
1179 return -ENOBUFS;
1180
1181 /* need source address above miyazawa*/
1182 }
1183 dst_hold(&rt->dst);
1184 cork->base.dst = &rt->dst;
1185 cork->fl.u.ip6 = *fl6;
1186 v6_cork->hop_limit = hlimit;
1187 v6_cork->tclass = tclass;
1188 if (rt->dst.flags & DST_XFRM_TUNNEL)
1189 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
1190 rt->dst.dev->mtu : dst_mtu(&rt->dst);
1191 else
1192 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
1193 rt->dst.dev->mtu : dst_mtu(rt->dst.path);
1194 if (np->frag_size < mtu) {
1195 if (np->frag_size)
1196 mtu = np->frag_size;
1197 }
1198 cork->base.fragsize = mtu;
1199 if (dst_allfrag(rt->dst.path))
1200 cork->base.flags |= IPCORK_ALLFRAG;
1201 cork->base.length = 0;
1202
1203 return 0;
1204}
1205
1138int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, 1206int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1139 int offset, int len, int odd, struct sk_buff *skb), 1207 int offset, int len, int odd, struct sk_buff *skb),
1140 void *from, int length, int transhdrlen, 1208 void *from, int length, int transhdrlen,
@@ -1162,59 +1230,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1162 /* 1230 /*
1163 * setup for corking 1231 * setup for corking
1164 */ 1232 */
1165 if (opt) { 1233 err = ip6_setup_cork(sk, &inet->cork, &np->cork, hlimit,
1166 if (WARN_ON(np->cork.opt)) 1234 tclass, opt, rt, fl6);
1167 return -EINVAL; 1235 if (err)
1168 1236 return err;
1169 np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation);
1170 if (unlikely(np->cork.opt == NULL))
1171 return -ENOBUFS;
1172
1173 np->cork.opt->tot_len = opt->tot_len;
1174 np->cork.opt->opt_flen = opt->opt_flen;
1175 np->cork.opt->opt_nflen = opt->opt_nflen;
1176
1177 np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt,
1178 sk->sk_allocation);
1179 if (opt->dst0opt && !np->cork.opt->dst0opt)
1180 return -ENOBUFS;
1181
1182 np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt,
1183 sk->sk_allocation);
1184 if (opt->dst1opt && !np->cork.opt->dst1opt)
1185 return -ENOBUFS;
1186
1187 np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt,
1188 sk->sk_allocation);
1189 if (opt->hopopt && !np->cork.opt->hopopt)
1190 return -ENOBUFS;
1191
1192 np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt,
1193 sk->sk_allocation);
1194 if (opt->srcrt && !np->cork.opt->srcrt)
1195 return -ENOBUFS;
1196
1197 /* need source address above miyazawa*/
1198 }
1199 dst_hold(&rt->dst);
1200 cork->dst = &rt->dst;
1201 inet->cork.fl.u.ip6 = *fl6;
1202 np->cork.hop_limit = hlimit;
1203 np->cork.tclass = tclass;
1204 if (rt->dst.flags & DST_XFRM_TUNNEL)
1205 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
1206 rt->dst.dev->mtu : dst_mtu(&rt->dst);
1207 else
1208 mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
1209 rt->dst.dev->mtu : dst_mtu(rt->dst.path);
1210 if (np->frag_size < mtu) {
1211 if (np->frag_size)
1212 mtu = np->frag_size;
1213 }
1214 cork->fragsize = mtu;
1215 if (dst_allfrag(rt->dst.path))
1216 cork->flags |= IPCORK_ALLFRAG;
1217 cork->length = 0;
1218 exthdrlen = (opt ? opt->opt_flen : 0); 1237 exthdrlen = (opt ? opt->opt_flen : 0);
1219 length += exthdrlen; 1238 length += exthdrlen;
1220 transhdrlen += exthdrlen; 1239 transhdrlen += exthdrlen;
@@ -1226,8 +1245,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1226 transhdrlen = 0; 1245 transhdrlen = 0;
1227 exthdrlen = 0; 1246 exthdrlen = 0;
1228 dst_exthdrlen = 0; 1247 dst_exthdrlen = 0;
1229 mtu = cork->fragsize;
1230 } 1248 }
1249 mtu = cork->fragsize;
1231 orig_mtu = mtu; 1250 orig_mtu = mtu;
1232 1251
1233 hh_len = LL_RESERVED_SPACE(rt->dst.dev); 1252 hh_len = LL_RESERVED_SPACE(rt->dst.dev);
@@ -1503,23 +1522,24 @@ error:
1503} 1522}
1504EXPORT_SYMBOL_GPL(ip6_append_data); 1523EXPORT_SYMBOL_GPL(ip6_append_data);
1505 1524
1506static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) 1525static void ip6_cork_release(struct inet_cork_full *cork,
1526 struct inet6_cork *v6_cork)
1507{ 1527{
1508 if (np->cork.opt) { 1528 if (v6_cork->opt) {
1509 kfree(np->cork.opt->dst0opt); 1529 kfree(v6_cork->opt->dst0opt);
1510 kfree(np->cork.opt->dst1opt); 1530 kfree(v6_cork->opt->dst1opt);
1511 kfree(np->cork.opt->hopopt); 1531 kfree(v6_cork->opt->hopopt);
1512 kfree(np->cork.opt->srcrt); 1532 kfree(v6_cork->opt->srcrt);
1513 kfree(np->cork.opt); 1533 kfree(v6_cork->opt);
1514 np->cork.opt = NULL; 1534 v6_cork->opt = NULL;
1515 } 1535 }
1516 1536
1517 if (inet->cork.base.dst) { 1537 if (cork->base.dst) {
1518 dst_release(inet->cork.base.dst); 1538 dst_release(cork->base.dst);
1519 inet->cork.base.dst = NULL; 1539 cork->base.dst = NULL;
1520 inet->cork.base.flags &= ~IPCORK_ALLFRAG; 1540 cork->base.flags &= ~IPCORK_ALLFRAG;
1521 } 1541 }
1522 memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); 1542 memset(&cork->fl, 0, sizeof(cork->fl));
1523} 1543}
1524 1544
1525int ip6_push_pending_frames(struct sock *sk) 1545int ip6_push_pending_frames(struct sock *sk)
@@ -1599,7 +1619,7 @@ int ip6_push_pending_frames(struct sock *sk)
1599 } 1619 }
1600 1620
1601out: 1621out:
1602 ip6_cork_release(inet, np); 1622 ip6_cork_release(&inet->cork, &np->cork);
1603 return err; 1623 return err;
1604error: 1624error:
1605 IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); 1625 IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
@@ -1618,6 +1638,6 @@ void ip6_flush_pending_frames(struct sock *sk)
1618 kfree_skb(skb); 1638 kfree_skb(skb);
1619 } 1639 }
1620 1640
1621 ip6_cork_release(inet_sk(sk), inet6_sk(sk)); 1641 ip6_cork_release(&inet_sk(sk)->cork, &inet6_sk(sk)->cork);
1622} 1642}
1623EXPORT_SYMBOL_GPL(ip6_flush_pending_frames); 1643EXPORT_SYMBOL_GPL(ip6_flush_pending_frames);