aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index cd4ba8c6b609..f86bf69cfb8d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3082,22 +3082,32 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
3082 if (sg && csum && (mss != GSO_BY_FRAGS)) { 3082 if (sg && csum && (mss != GSO_BY_FRAGS)) {
3083 if (!(features & NETIF_F_GSO_PARTIAL)) { 3083 if (!(features & NETIF_F_GSO_PARTIAL)) {
3084 struct sk_buff *iter; 3084 struct sk_buff *iter;
3085 unsigned int frag_len;
3085 3086
3086 if (!list_skb || 3087 if (!list_skb ||
3087 !net_gso_ok(features, skb_shinfo(head_skb)->gso_type)) 3088 !net_gso_ok(features, skb_shinfo(head_skb)->gso_type))
3088 goto normal; 3089 goto normal;
3089 3090
3090 /* Split the buffer at the frag_list pointer. 3091 /* If we get here then all the required
3091 * This is based on the assumption that all 3092 * GSO features except frag_list are supported.
3092 * buffers in the chain excluding the last 3093 * Try to split the SKB to multiple GSO SKBs
3093 * containing the same amount of data. 3094 * with no frag_list.
3095 * Currently we can do that only when the buffers don't
3096 * have a linear part and all the buffers except
3097 * the last are of the same length.
3094 */ 3098 */
3099 frag_len = list_skb->len;
3095 skb_walk_frags(head_skb, iter) { 3100 skb_walk_frags(head_skb, iter) {
3101 if (frag_len != iter->len && iter->next)
3102 goto normal;
3096 if (skb_headlen(iter)) 3103 if (skb_headlen(iter))
3097 goto normal; 3104 goto normal;
3098 3105
3099 len -= iter->len; 3106 len -= iter->len;
3100 } 3107 }
3108
3109 if (len != frag_len)
3110 goto normal;
3101 } 3111 }
3102 3112
3103 /* GSO partial only requires that we trim off any excess that 3113 /* GSO partial only requires that we trim off any excess that
@@ -3694,6 +3704,15 @@ static void sock_rmem_free(struct sk_buff *skb)
3694 atomic_sub(skb->truesize, &sk->sk_rmem_alloc); 3704 atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
3695} 3705}
3696 3706
3707static void skb_set_err_queue(struct sk_buff *skb)
3708{
3709 /* pkt_type of skbs received on local sockets is never PACKET_OUTGOING.
3710 * So, it is safe to (mis)use it to mark skbs on the error queue.
3711 */
3712 skb->pkt_type = PACKET_OUTGOING;
3713 BUILD_BUG_ON(PACKET_OUTGOING == 0);
3714}
3715
3697/* 3716/*
3698 * Note: We dont mem charge error packets (no sk_forward_alloc changes) 3717 * Note: We dont mem charge error packets (no sk_forward_alloc changes)
3699 */ 3718 */
@@ -3707,6 +3726,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
3707 skb->sk = sk; 3726 skb->sk = sk;
3708 skb->destructor = sock_rmem_free; 3727 skb->destructor = sock_rmem_free;
3709 atomic_add(skb->truesize, &sk->sk_rmem_alloc); 3728 atomic_add(skb->truesize, &sk->sk_rmem_alloc);
3729 skb_set_err_queue(skb);
3710 3730
3711 /* before exiting rcu section, make sure dst is refcounted */ 3731 /* before exiting rcu section, make sure dst is refcounted */
3712 skb_dst_force(skb); 3732 skb_dst_force(skb);
@@ -3783,16 +3803,21 @@ EXPORT_SYMBOL(skb_clone_sk);
3783 3803
3784static void __skb_complete_tx_timestamp(struct sk_buff *skb, 3804static void __skb_complete_tx_timestamp(struct sk_buff *skb,
3785 struct sock *sk, 3805 struct sock *sk,
3786 int tstype) 3806 int tstype,
3807 bool opt_stats)
3787{ 3808{
3788 struct sock_exterr_skb *serr; 3809 struct sock_exterr_skb *serr;
3789 int err; 3810 int err;
3790 3811
3812 BUILD_BUG_ON(sizeof(struct sock_exterr_skb) > sizeof(skb->cb));
3813
3791 serr = SKB_EXT_ERR(skb); 3814 serr = SKB_EXT_ERR(skb);
3792 memset(serr, 0, sizeof(*serr)); 3815 memset(serr, 0, sizeof(*serr));
3793 serr->ee.ee_errno = ENOMSG; 3816 serr->ee.ee_errno = ENOMSG;
3794 serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; 3817 serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
3795 serr->ee.ee_info = tstype; 3818 serr->ee.ee_info = tstype;
3819 serr->opt_stats = opt_stats;
3820 serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0;
3796 if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { 3821 if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
3797 serr->ee.ee_data = skb_shinfo(skb)->tskey; 3822 serr->ee.ee_data = skb_shinfo(skb)->tskey;
3798 if (sk->sk_protocol == IPPROTO_TCP && 3823 if (sk->sk_protocol == IPPROTO_TCP &&
@@ -3833,7 +3858,7 @@ void skb_complete_tx_timestamp(struct sk_buff *skb,
3833 */ 3858 */
3834 if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { 3859 if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) {
3835 *skb_hwtstamps(skb) = *hwtstamps; 3860 *skb_hwtstamps(skb) = *hwtstamps;
3836 __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); 3861 __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false);
3837 sock_put(sk); 3862 sock_put(sk);
3838 } 3863 }
3839} 3864}
@@ -3844,7 +3869,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
3844 struct sock *sk, int tstype) 3869 struct sock *sk, int tstype)
3845{ 3870{
3846 struct sk_buff *skb; 3871 struct sk_buff *skb;
3847 bool tsonly; 3872 bool tsonly, opt_stats = false;
3848 3873
3849 if (!sk) 3874 if (!sk)
3850 return; 3875 return;
@@ -3857,9 +3882,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
3857#ifdef CONFIG_INET 3882#ifdef CONFIG_INET
3858 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && 3883 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
3859 sk->sk_protocol == IPPROTO_TCP && 3884 sk->sk_protocol == IPPROTO_TCP &&
3860 sk->sk_type == SOCK_STREAM) 3885 sk->sk_type == SOCK_STREAM) {
3861 skb = tcp_get_timestamping_opt_stats(sk); 3886 skb = tcp_get_timestamping_opt_stats(sk);
3862 else 3887 opt_stats = true;
3888 } else
3863#endif 3889#endif
3864 skb = alloc_skb(0, GFP_ATOMIC); 3890 skb = alloc_skb(0, GFP_ATOMIC);
3865 } else { 3891 } else {
@@ -3878,7 +3904,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
3878 else 3904 else
3879 skb->tstamp = ktime_get_real(); 3905 skb->tstamp = ktime_get_real();
3880 3906
3881 __skb_complete_tx_timestamp(skb, sk, tstype); 3907 __skb_complete_tx_timestamp(skb, sk, tstype, opt_stats);
3882} 3908}
3883EXPORT_SYMBOL_GPL(__skb_tstamp_tx); 3909EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
3884 3910