@@ -663,75 +663,72 @@ void udp_flush_pending_frames(struct sock *sk)
663663EXPORT_SYMBOL (udp_flush_pending_frames );
664664
665665/**
666- * udp4_hwcsum_outgoing - handle outgoing HW checksumming
667- * @sk: socket we are sending on
666+ * udp4_hwcsum - handle outgoing HW checksumming
668667 * @skb: sk_buff containing the filled-in UDP header
669668 * (checksum field must be zeroed out)
669+ * @src: source IP address
670+ * @dst: destination IP address
670671 */
671- static void udp4_hwcsum_outgoing (struct sock * sk , struct sk_buff * skb ,
672- __be32 src , __be32 dst , int len )
672+ static void udp4_hwcsum (struct sk_buff * skb , __be32 src , __be32 dst )
673673{
674- unsigned int offset ;
675674 struct udphdr * uh = udp_hdr (skb );
675+ struct sk_buff * frags = skb_shinfo (skb )-> frag_list ;
676+ int offset = skb_transport_offset (skb );
677+ int len = skb -> len - offset ;
678+ int hlen = len ;
676679 __wsum csum = 0 ;
677680
678- if (skb_queue_len ( & sk -> sk_write_queue ) == 1 ) {
681+ if (! frags ) {
679682 /*
680683 * Only one fragment on the socket.
681684 */
682685 skb -> csum_start = skb_transport_header (skb ) - skb -> head ;
683686 skb -> csum_offset = offsetof(struct udphdr , check );
684- uh -> check = ~csum_tcpudp_magic (src , dst , len , IPPROTO_UDP , 0 );
687+ uh -> check = ~csum_tcpudp_magic (src , dst , len ,
688+ IPPROTO_UDP , 0 );
685689 } else {
686690 /*
687691 * HW-checksum won't work as there are two or more
688692 * fragments on the socket so that all csums of sk_buffs
689693 * should be together
690694 */
691- offset = skb_transport_offset (skb );
692- skb -> csum = skb_checksum (skb , offset , skb -> len - offset , 0 );
695+ do {
696+ csum = csum_add (csum , frags -> csum );
697+ hlen -= frags -> len ;
698+ } while ((frags = frags -> next ));
693699
700+ csum = skb_checksum (skb , offset , hlen , csum );
694701 skb -> ip_summed = CHECKSUM_NONE ;
695702
696- skb_queue_walk (& sk -> sk_write_queue , skb ) {
697- csum = csum_add (csum , skb -> csum );
698- }
699-
700703 uh -> check = csum_tcpudp_magic (src , dst , len , IPPROTO_UDP , csum );
701704 if (uh -> check == 0 )
702705 uh -> check = CSUM_MANGLED_0 ;
703706 }
704707}
705708
706- /*
707- * Push out all pending data as one UDP datagram. Socket is locked.
708- */
709- static int udp_push_pending_frames (struct sock * sk )
709+ static int udp_send_skb (struct sk_buff * skb , __be32 daddr , __be32 dport )
710710{
711- struct udp_sock * up = udp_sk ( sk ) ;
711+ struct sock * sk = skb -> sk ;
712712 struct inet_sock * inet = inet_sk (sk );
713- struct flowi * fl = & inet -> cork .fl ;
714- struct sk_buff * skb ;
715713 struct udphdr * uh ;
714+ struct rtable * rt = (struct rtable * )skb_dst (skb );
716715 int err = 0 ;
717716 int is_udplite = IS_UDPLITE (sk );
717+ int offset = skb_transport_offset (skb );
718+ int len = skb -> len - offset ;
718719 __wsum csum = 0 ;
719720
720- /* Grab the skbuff where UDP header space exists. */
721- if ((skb = skb_peek (& sk -> sk_write_queue )) == NULL )
722- goto out ;
723-
724721 /*
725722 * Create a UDP header
726723 */
727724 uh = udp_hdr (skb );
728- uh -> source = fl -> fl_ip_sport ;
729- uh -> dest = fl -> fl_ip_dport ;
730- uh -> len = htons (up -> len );
725+ uh -> source = inet -> inet_sport ;
726+ uh -> dest = dport ;
727+ uh -> len = htons (len );
731728 uh -> check = 0 ;
732729
733730 if (is_udplite ) /* UDP-Lite */
734- csum = udplite_csum_outgoing ( sk , skb );
731+ csum = udplite_csum ( skb );
735732
736733 else if (sk -> sk_no_check == UDP_CSUM_NOXMIT ) { /* UDP csum disabled */
737734
@@ -740,20 +737,20 @@ static int udp_push_pending_frames(struct sock *sk)
740737
741738 } else if (skb -> ip_summed == CHECKSUM_PARTIAL ) { /* UDP hardware csum */
742739
743- udp4_hwcsum_outgoing ( sk , skb , fl -> fl4_src , fl -> fl4_dst , up -> len );
740+ udp4_hwcsum ( skb , rt -> rt_src , daddr );
744741 goto send ;
745742
746- } else /* `normal' UDP */
747- csum = udp_csum_outgoing ( sk , skb );
743+ } else
744+ csum = udp_csum ( skb );
748745
749746 /* add protocol-dependent pseudo-header */
750- uh -> check = csum_tcpudp_magic (fl -> fl4_src , fl -> fl4_dst , up -> len ,
747+ uh -> check = csum_tcpudp_magic (rt -> rt_src , daddr , len ,
751748 sk -> sk_protocol , csum );
752749 if (uh -> check == 0 )
753750 uh -> check = CSUM_MANGLED_0 ;
754751
755752send :
756- err = ip_push_pending_frames ( sk );
753+ err = ip_send_skb ( skb );
757754 if (err ) {
758755 if (err == - ENOBUFS && !inet -> recverr ) {
759756 UDP_INC_STATS_USER (sock_net (sk ),
@@ -763,6 +760,26 @@ static int udp_push_pending_frames(struct sock *sk)
763760 } else
764761 UDP_INC_STATS_USER (sock_net (sk ),
765762 UDP_MIB_OUTDATAGRAMS , is_udplite );
763+ return err ;
764+ }
765+
766+ /*
767+ * Push out all pending data as one UDP datagram. Socket is locked.
768+ */
769+ static int udp_push_pending_frames (struct sock * sk )
770+ {
771+ struct udp_sock * up = udp_sk (sk );
772+ struct inet_sock * inet = inet_sk (sk );
773+ struct flowi * fl = & inet -> cork .fl ;
774+ struct sk_buff * skb ;
775+ int err = 0 ;
776+
777+ skb = ip_finish_skb (sk );
778+ if (!skb )
779+ goto out ;
780+
781+ err = udp_send_skb (skb , fl -> fl4_dst , fl -> fl_ip_dport );
782+
766783out :
767784 up -> len = 0 ;
768785 up -> pending = 0 ;
0 commit comments