내가 아는 한 UDP 패킷의 수신 프로세스는 다음과 같습니다.
- UDP 헤더에 오류가 있는지 확인하세요.
- 대상을 소켓과 일치
- 해당 소켓이 없으면 오류 메시지가 전송됩니다.
- 패킷을 적절한 소켓 수신 큐에 넣습니다.
- 이 소켓에서 데이터를 기다리는 프로세스를 깨우십시오.
그러나 위 단계에서 /proc/net/udp
쇠퇴로 간주되는 것은 무엇입니까? 위 단계 중 하나라도 실패하면 하락으로 간주됩니까? 아니면 수신 대기열/버퍼가 가득 찼을 때만 수행합니까?
답변1
Linux 5.4.66에서는 /proc/net/udp
다음 함수에 의해 의사 파일이 생성됩니다.net/ipv4/udp.c
:
int udp4_seq_show(struct seq_file *seq, void *v)
{
seq_setwidth(seq, 127);
if (v == SEQ_START_TOKEN)
seq_puts(seq, " sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
"inode ref pointer drops");
else {
struct udp_iter_state *state = seq->private;
udp4_format_sock(v, seq, state->bucket);
}
seq_pad(seq, '\n');
return 0;
}
이는 udp4_format_sock()
동일한 파일에서 호출됩니다.
static void udp4_format_sock(struct sock *sp, struct seq_file *f,
int bucket)
{
struct inet_sock *inet = inet_sk(sp);
__be32 dest = inet->inet_daddr;
__be32 src = inet->inet_rcv_saddr;
__u16 destp = ntohs(inet->inet_dport);
__u16 srcp = ntohs(inet->inet_sport);
seq_printf(f, "%5d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %u",
bucket, src, srcp, dest, destp, sp->sk_state,
sk_wmem_alloc_get(sp),
udp_rqueue_get(sp),
0, 0L, 0,
from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
0, sock_i_ino(sp),
refcount_read(&sp->sk_refcnt), sp,
atomic_read(&sp->sk_drops));
}
이 필드의 값은 drops
다음 atomic_read(&sp->sk_drops)
방법을 사용하여 증가됩니다 atomic_inc(&sk->sk_drops)
. 여러 위치에서 사용될 때 증가됩니다.
수신 큐가 가득 찼습니다.
int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) { ... /* try to avoid the costly atomic add/sub pair when the receive * queue is full; always allow at least a packet */ rmem = atomic_read(&sk->sk_rmem_alloc); if (rmem > sk->sk_rcvbuf) goto drop; ... drop: atomic_inc(&sk->sk_drops);
잘못된 체크섬 프레임
static struct sk_buff *__first_packet_length(struct sock *sk, struct sk_buff_head *rcvq, int *total) { struct sk_buff *skb; while ((skb = skb_peek(rcvq)) != NULL) { if (udp_lib_checksum_complete(skb)) { ... atomic_inc(&sk->sk_drops);
읽을 수 없음
int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, int flags, int *addr_len) { ... if (checksum_valid || udp_skb_csum_unnecessary(skb)) { if (udp_skb_is_linear(skb)) err = copy_linear_skb(skb, copied, off, &msg->msg_iter); else err = skb_copy_datagram_msg(skb, off, msg, copied); } else { err = skb_copy_and_csum_datagram_msg(skb, off, msg); if (err == -EINVAL) goto csum_copy_err; } if (unlikely(err)) { if (!peeking) { atomic_inc(&sk->sk_drops);
수신 중 실패
static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb) { ... drop: ... atomic_inc(&sk->sk_drops);
메시지를 복제하려고 할 때 멀티캐스트 처리 중에 실패했습니다.
static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, struct udphdr *uh, __be32 saddr, __be32 daddr, struct udp_table *udptable, int proto) { ... sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) { ... nskb = skb_clone(skb, GFP_ATOMIC); if (unlikely(!nskb)) { atomic_inc(&sk->sk_drops);