forked from mirrors/linux
		
	tcp: Introduce tcp_read_skb()
This patch inroduces tcp_read_skb() based on tcp_read_sock(), a preparation for the next patch which actually introduces a new sock ops. TCP is special here, because it has tcp_read_sock() which is mainly used by splice(). tcp_read_sock() supports partial read and arbitrary offset, neither of them is needed for sockmap. Signed-off-by: Cong Wang <cong.wang@bytedance.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20220615162014.89193-2-xiyou.wangcong@gmail.com
This commit is contained in:
		
							parent
							
								
									4336487e30
								
							
						
					
					
						commit
						04919bed94
					
				
					 2 changed files with 49 additions and 0 deletions
				
			
		|  | @ -672,6 +672,8 @@ void tcp_get_info(struct sock *, struct tcp_info *); | ||||||
| /* Read 'sendfile()'-style from a TCP socket */ | /* Read 'sendfile()'-style from a TCP socket */ | ||||||
| int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | ||||||
| 		  sk_read_actor_t recv_actor); | 		  sk_read_actor_t recv_actor); | ||||||
|  | int tcp_read_skb(struct sock *sk, read_descriptor_t *desc, | ||||||
|  | 		 sk_read_actor_t recv_actor); | ||||||
| 
 | 
 | ||||||
| void tcp_initialize_rcv_mss(struct sock *sk); | void tcp_initialize_rcv_mss(struct sock *sk); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1734,6 +1734,53 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(tcp_read_sock); | EXPORT_SYMBOL(tcp_read_sock); | ||||||
| 
 | 
 | ||||||
|  | int tcp_read_skb(struct sock *sk, read_descriptor_t *desc, | ||||||
|  | 		 sk_read_actor_t recv_actor) | ||||||
|  | { | ||||||
|  | 	struct tcp_sock *tp = tcp_sk(sk); | ||||||
|  | 	u32 seq = tp->copied_seq; | ||||||
|  | 	struct sk_buff *skb; | ||||||
|  | 	int copied = 0; | ||||||
|  | 	u32 offset; | ||||||
|  | 
 | ||||||
|  | 	if (sk->sk_state == TCP_LISTEN) | ||||||
|  | 		return -ENOTCONN; | ||||||
|  | 
 | ||||||
|  | 	while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { | ||||||
|  | 		int used; | ||||||
|  | 
 | ||||||
|  | 		__skb_unlink(skb, &sk->sk_receive_queue); | ||||||
|  | 		used = recv_actor(desc, skb, 0, skb->len); | ||||||
|  | 		if (used <= 0) { | ||||||
|  | 			if (!copied) | ||||||
|  | 				copied = used; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		seq += used; | ||||||
|  | 		copied += used; | ||||||
|  | 
 | ||||||
|  | 		if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) { | ||||||
|  | 			consume_skb(skb); | ||||||
|  | 			++seq; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		consume_skb(skb); | ||||||
|  | 		if (!desc->count) | ||||||
|  | 			break; | ||||||
|  | 		WRITE_ONCE(tp->copied_seq, seq); | ||||||
|  | 	} | ||||||
|  | 	WRITE_ONCE(tp->copied_seq, seq); | ||||||
|  | 
 | ||||||
|  | 	tcp_rcv_space_adjust(sk); | ||||||
|  | 
 | ||||||
|  | 	/* Clean up data we have read: This will do ACK frames. */ | ||||||
|  | 	if (copied > 0) | ||||||
|  | 		tcp_cleanup_rbuf(sk, copied); | ||||||
|  | 
 | ||||||
|  | 	return copied; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL(tcp_read_skb); | ||||||
|  | 
 | ||||||
| int tcp_peek_len(struct socket *sock) | int tcp_peek_len(struct socket *sock) | ||||||
| { | { | ||||||
| 	return tcp_inq(sock->sk); | 	return tcp_inq(sock->sk); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Cong Wang
						Cong Wang