@@ -990,9 +990,10 @@ static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
990990{
991991 unsigned int offset ;
992992 struct udphdr * uh = udp_hdr (skb );
993+ struct sk_buff * frags = skb_shinfo (skb )-> frag_list ;
993994 __wsum csum = 0 ;
994995
995- if (skb_queue_len ( & sk -> sk_write_queue ) == 1 ) {
996+ if (! frags ) {
996997 /* Only one fragment on the socket. */
997998 skb -> csum_start = skb_transport_header (skb ) - skb -> head ;
998999 skb -> csum_offset = offsetof(struct udphdr , check );
@@ -1008,9 +1009,9 @@ static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
10081009
10091010 skb -> ip_summed = CHECKSUM_NONE ;
10101011
1011- skb_queue_walk ( & sk -> sk_write_queue , skb ) {
1012- csum = csum_add (csum , skb -> csum );
1013- }
1012+ do {
1013+ csum = csum_add (csum , frags -> csum );
1014+ } while (( frags = frags -> next ));
10141015
10151016 uh -> check = csum_ipv6_magic (saddr , daddr , len , IPPROTO_UDP ,
10161017 csum );
@@ -1023,56 +1024,44 @@ static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
10231024 * Sending
10241025 */
10251026
1026- static int udp_v6_push_pending_frames (struct sock * sk )
1027+ static int udp_v6_send_skb (struct sk_buff * skb , struct flowi6 * fl6 )
10271028{
1028- struct sk_buff * skb ;
1029+ struct sock * sk = skb -> sk ;
10291030 struct udphdr * uh ;
1030- struct udp_sock * up = udp_sk (sk );
1031- struct inet_sock * inet = inet_sk (sk );
1032- struct flowi6 * fl6 ;
10331031 int err = 0 ;
10341032 int is_udplite = IS_UDPLITE (sk );
10351033 __wsum csum = 0 ;
1036-
1037- if (up -> pending == AF_INET )
1038- return udp_push_pending_frames (sk );
1039-
1040- fl6 = & inet -> cork .fl .u .ip6 ;
1041-
1042- /* Grab the skbuff where UDP header space exists. */
1043- skb = skb_peek (& sk -> sk_write_queue );
1044- if (skb == NULL )
1045- goto out ;
1034+ int offset = skb_transport_offset (skb );
1035+ int len = skb -> len - offset ;
10461036
10471037 /*
10481038 * Create a UDP header
10491039 */
10501040 uh = udp_hdr (skb );
10511041 uh -> source = fl6 -> fl6_sport ;
10521042 uh -> dest = fl6 -> fl6_dport ;
1053- uh -> len = htons (up -> len );
1043+ uh -> len = htons (len );
10541044 uh -> check = 0 ;
10551045
10561046 if (is_udplite )
1057- csum = udplite_csum_outgoing ( sk , skb );
1058- else if (up -> no_check6_tx ) { /* UDP csum disabled */
1047+ csum = udplite_csum ( skb );
1048+ else if (udp_sk ( sk ) -> no_check6_tx ) { /* UDP csum disabled */
10591049 skb -> ip_summed = CHECKSUM_NONE ;
10601050 goto send ;
10611051 } else if (skb -> ip_summed == CHECKSUM_PARTIAL ) { /* UDP hardware csum */
1062- udp6_hwcsum_outgoing (sk , skb , & fl6 -> saddr , & fl6 -> daddr ,
1063- up -> len );
1052+ udp6_hwcsum_outgoing (sk , skb , & fl6 -> saddr , & fl6 -> daddr , len );
10641053 goto send ;
10651054 } else
1066- csum = udp_csum_outgoing ( sk , skb );
1055+ csum = udp_csum ( skb );
10671056
10681057 /* add protocol-dependent pseudo-header */
10691058 uh -> check = csum_ipv6_magic (& fl6 -> saddr , & fl6 -> daddr ,
1070- up -> len , fl6 -> flowi6_proto , csum );
1059+ len , fl6 -> flowi6_proto , csum );
10711060 if (uh -> check == 0 )
10721061 uh -> check = CSUM_MANGLED_0 ;
10731062
10741063send :
1075- err = ip6_push_pending_frames ( sk );
1064+ err = ip6_send_skb ( skb );
10761065 if (err ) {
10771066 if (err == - ENOBUFS && !inet6_sk (sk )-> recverr ) {
10781067 UDP6_INC_STATS_USER (sock_net (sk ),
@@ -1082,6 +1071,30 @@ static int udp_v6_push_pending_frames(struct sock *sk)
10821071 } else
10831072 UDP6_INC_STATS_USER (sock_net (sk ),
10841073 UDP_MIB_OUTDATAGRAMS , is_udplite );
1074+ return err ;
1075+ }
1076+
1077+ static int udp_v6_push_pending_frames (struct sock * sk )
1078+ {
1079+ struct sk_buff * skb ;
1080+ struct udp_sock * up = udp_sk (sk );
1081+ struct flowi6 fl6 ;
1082+ int err = 0 ;
1083+
1084+ if (up -> pending == AF_INET )
1085+ return udp_push_pending_frames (sk );
1086+
1087+ /* ip6_finish_skb will release the cork, so make a copy of
1088+ * fl6 here.
1089+ */
1090+ fl6 = inet_sk (sk )-> cork .fl .u .ip6 ;
1091+
1092+ skb = ip6_finish_skb (sk );
1093+ if (!skb )
1094+ goto out ;
1095+
1096+ err = udp_v6_send_skb (skb , & fl6 );
1097+
10851098out :
10861099 up -> len = 0 ;
10871100 up -> pending = 0 ;
0 commit comments