Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 혁진이의 프로그램 검증
- 프로그래밍 문제
- pyqt button
- tcp stack
- 하이퍼바이저
- 3D Surface Area
- 리눅스 커널
- git 명령어
- Python
- SWEA
- 해커랭크
- 커널 패킷 처리
- pyqt layout
- 네트워크 스택
- 17609
- 백준
- 도커
- 회문
- git 입문
- 백준 알고리즘
- pyqt status bar
- hackerrank
- pyqt tooltip
- git
- 두 문자열
- Queen's Attack II
- pyqt menu bar
- Queen's Attack
- PyQt
- Two Characters
Archives
- Today
- Total
뜸부기와 공작새
[Linux] 패킷 Flow 분석 - 송신 본문
리눅스 패킷 Flow 분석 송신
[L7 Layer]
send(), write() 함수와 같은 API를 이용하여 패킷의 정보들을 Kernel로 전달한다
해당 함수들을 호출하면 시스템 콜이 발생하여 sock_sendmsg() 함수를 호출한다
[L4 Layer]
시스템 콜 수행되어 sock_sendmsg() 함수에 전송할 패킷에 대한 정보가 전달된다
그다음 사용자 패킷에 mapping되는 버퍼를 읽을 수 있는지 확인하고
L7 Application에서 사용할 소켓 디스크립터를 이용해서 socket 구조체를 얻어오고
sock_sendmsg_nosec() 함수를 호출한다
sock_sendmsg_nosec() 함수는
얻어온 socket 구조체에 해당하는 프로토콜별 처리 함수를 호출한다
프로토콜의 명령과 설정을 담당하는 proto_ops 구조체의 sendmsg 필드에서 프로토콜을 확인하여
프로토콜에 맞는 함수를 호출하는데
TCP인 경우에는 tcp_sendmsg UDP인 경우에는 udp_sendmsg함수가 호출된다.
여기서는 TCP 패킷이라 가정하고 tcp_sendmsg()함수를 호출한다
sock->ops->sendmsg (tcp_sendmsg()) 함수는 아래의 동작을 수행
- socket에서 tcp control block을 가져온다 (tcp_sock)
- L7 Application이 전송 요청한 데이터를 send socket buffer(sk_buff)로 복사한다 (tcp_send_mss())
- 새로운 sk_buff 생성 (sk_sream_alloc_skb())
- send_socket_buffer 리스트에 새로 생성한 sk_buff를 추가 (sk_entail())
- 지금 전송할 수 있는 데이터를 패킷으로 만들고 전송 (tcp_push())
- TCP 헤더 생성 + L3 Layer로 보낼 실제 패킷을 생성 (__tcp_push_pending_frames() -> tcp_write_xmit())
- __tcp_push_pending_frames() -> tcp_write_xmit() -> tcp_transmit_skb() -> queue_xmit()
(ip_queue_xmit() 콜백함수) 순서로 함수를 호출- L3 Layer로 패킷 정보를 전달한다.
ip_queue_xmit() 함수는
- IP헤더 장착, IP헤더 필드 기록(skb_push())
- ip_local_out() 함수 호출하여 Network Layer에서 수행해야 할 작업들을 수행해준다
[L3 Layer]
ip_local_out() 함수는
- IP헤더 checksum을 계산하고, netfilter 함수 호출
(ip_local_out() -> __ip_local_out() -> ip_send_check()) - IP fragment 필요한 경우 fragment 만들어준다.
(ip_local_out() -> dst_output() -> ip_finish_output() -> ip_fragment()) - L2 헤더 추가하여 패킷 완성
(ip_local_out() -> dst_output() -> ip_finish_output() -> ip_finish_output2())
패킷 전송을 완료하면 dev_queue_xmit() 함수를 호출한다
[L2 Layer]
dev_queue_xmit() 함수는
- 만들어진 패킷을 실제로 L2 드라이버로 내려준다
(__dev_xmit_skb() -> sch_direct_xmit() -> dev_hard_start_xmit() -> xmit_one())- NET_TX_SOFTIRQ 실행하여 해당 softirq의 핸들러인 net_tx_action() 함수 호출
net_tx_action() 함수는 아래와 같은 동작을 수행한다
- 디바이스에서 전송해야 할 패킷을 가지고 있는지 확인 (qdisc_run())
- 디바이스의 상태 확인 (queue_disc() -> netif_queue_stopped())
- 디바이스가 활성화되어있다면 qdisc_restart() 호출하여 패킷 전송 시도한다
(디바이스 락 획득하고 dev->hard_start_xmit() 함수 호출하여 진짜로 패킷을 전송한다)
(dev->hard_start_xmit() 함수의 내부 내용은 디바이스마다 다르게 구현되어있다)
- 디바이스가 활성화되어있다면 qdisc_restart() 호출하여 패킷 전송 시도한다
'Linux' 카테고리의 다른 글
[Linux] 패킷 Flow 분석 - 수신 (0) | 2020.03.08 |
---|