4.1 Tổng quan
(th−ờng là INET). Hàm gửi này kiểm tra trạng thái của socket, kiểm tra kiểu giao thức của nó, và gửi dữ liệu tới thủ tục của tầng Giao vận (chẳng hạn TCP hoặc UDP). Giao thức này tạo một bộ đệm mới cho gói dữ liệu ra (một bộ đệm socket hoặc struct sk_buff skb), sao chép dữ liệu từ bộ đệm ứng dụng, và đ−a thêm thơng tin header của nó vào (chẳng hạn số cổng, tùy chọn, checksum) tr−ớc khi chuyển bộ đệm mới vào tầng mạng (th−ờng là IP). Các hàm gửi IP đ−a thêm các thơng tin header giao thức của nó (chẳng hạn địa chỉ IP, tùy chọn, checksum). Nó cũng có thể phân mảnh gói nếu cần thiết. Tiếp theo tầng IP chuyển gói tới hàm ở tầng Liên kết, để thực hiện chuyển gói tới hàng đợi xmit của thiết bị và đảm bảo rằng thiết bị biết để truyền. Cuối cùng, thiết bị (chẳng hạn là card mạng) báo cho bus để gửi gói tin đi (xem hình 5).
4.2 Các b−ớc gửi dữ liệu
Ghi dữ liệu vào socket
• • • •
Ghi dữ liệu vào một socket (application)
Đ−a thêm phần đầu thơng điệp cho vị trí dữ liệu (socket)
Kiểm tra các lỗi cơ bản - socket có h−ớng về cổng? socket có thể gửi thơng điệp khơng? có gì sai với socket?
Chuyển thông điệp và phần đầu tới giao thức truyền tin phù hợp (INET socket).
Tạo một gói với UDP
• • • •
Kiểm tra lỗi - dữ liệu có lớn q khơng? Có phải là kết nối UDP?
Bảo đảm có một đ−ờng truyền tới địa chỉ đích (gọi thủ tục định tuyến IP nếu tuyến ch−a đ−ợc thiết lập; lỗi nếu khơng có tuyến).
Tạo phần đầu UDP (cho gói). Gọi hàm tạo IP và truyền.
Tạo một gói với TCP
• • • • • • •
Kiểm tra kết nối - đ−ợc thiết lập ch−a? đã mở ch−a? socket đã làm việc ch−a? Kiểm tra tổ hợp dữ liệu với từng phần gói nếu có thể.
Tạo bộ đệm gói.
Sao chép phần payload từ khơng gian ng−ời dùng. Thêm gói vào hàng đợi gửi.
Tạo thơng tin header TCP hiện hành cho gói (với ACK, SYN, ...) Gọi hàm truyền IP.
Bọc gói trong IP • • • • •
Tạo một bộ đệm gói (nếu cần thiết - UDP). Tìm tuyến tới địa chỉ đích (nếu cần thiết - TCP). Đ−a thêm phần header IP.
Copy phần header truyền và payload từ không gian ng−ời dùng. Gửi gói tới hàm chuyển tới thiết bị của tuyến đích.
Hình 5: Message transmission.
Truyền một gói • • • • • •
Đ−a gói vào hàng đợi thiết bị ra. Đánh thức thiết bị.
Đợi bộ lập lịch để chạy driver thiết bị. Kiểm tra thiết bị.
Gửi phần header liên kết.
Báo cho bus truyền gói dữ liệu qua thiết bị.
4.3 Các hàm Linux
Trong mục này chúng tôi đ−a ra danh sách các hàm trong Linux kernel (theo alphabet) đ−ợc coi là quan trọng trong việc truyền thông điệp (bắt đầu từ lời gọi hàm sock_write()), đồng thời đ−a ra source code và phân tích chức năng của nó. Functions/Tệp Description dev_queue_xmit() ở trong tệp net/core/dev.c -gọi hàm start_bh_atomic()
-nếu thiết bị có hàng đợi thì:
+gọi hàm enqueue() để thêm gói đó vào hàng đợi +sau đó gọi hàm qdisc_wakeup() [=
qdisc_restart()] để đánh thức thiết bị
-nếu khơng có hàng đợi thì lần l−ợt gọi các hàm
hard_start_xmit() -gọi end_bh_atomic(). DEVICE- >hard_start_xmit()ở trong tệp drivers/net/DEVICE.c
-hàm này phụ thuộc vào thiết bị, nó tiến hành kiểm tra xem ph−ơng tiện truyền đ−ợc mở ch−a
-gửi header
-báo bus để gửi gói tin -cập nhật trạng thái.
inet_sendmsg() ở trong tệp
net/ipv4/af_inet.c
-thực hiện việc tách con trỏ socket sock
-kiểm tra socket để chắc chắn rằng nó đang hoạt động -kiểm tra con trỏ tới giao thức
-giá trị trả về của hàm là sk->prot[tcp/udp]- >sendmsg().
ip_build_xmit ở trong tệp
net/ipv4/ip_output.c
-gọi hàm sock_alloc_send_skb() để thiết lập bộ nhớ cho skb
-khởi tạo header của skb
-gọi hàm getfrag() [= udp_getfrag()] để copy buffer trong không gian ng−ời dùng
-giá trị trả về là rt->u.dst.output() [=
dev_queue_xmit()]. ip_queue_xmit() ở
trong tệp
net/ipv4/ip_output.c
-thực hiện việc tìm tuyến -tạo IP header
-phân đoạn nếu cần thiết -thêm vào IP chechsum
-gọi skb->dst->output() [= dev_queue_xmit()].
qdisc_restart()ở
net/sched/sch_generi
c.c -cập nhật trạng thái -nếu có một lỗi nào đó thì đ−a gói trở lại hàng đợi. sock_sendmsg()ở
trong tệp net/socket.c
-gọi hàm scm_sendmsg() [socket control message]
-gọi sock->ops[inet]- >sendmsg(), và huỷ bỏ scm. sock_write() ở
trong tệp net/socket.c
-gọi hàm socki_lookup() để kết hợp socket với fd/file inode
-tạo và điền vào header của thơng báo với dữ liệu về kích th−ớc/địa chỉ
-giá trị trả về là hàm sock_sendmsg()
tcp_do_sendmsg() ở trong tệp
net/ipv4/tcp.c
-chờ kết nối, nếu cần thiết
-gọi skb_tailroom() và thêm data vào gói đang đợi nếu có thể
-kiểm tra trạng thái của window
-gọi hàm sock_wmalloc() để tạo bộ nhớ cho skb
-gọi hàm csum_and_copy_from_user() để copy gói và tổng kiểm tra
-cuối cùng là gọi hàm tcp_send_skb().
tcp_send_skb()ở trong tệp
net/ipv4/tcp_output. c
-gọi __skb_queue_tail() để thêm gói vào trong hàng đợi -gọi hàm tcp_transmit_skb() nếu có thể.
tcp_transmit_skb()ở trong tệp
net/ipv4/tcp_output. c
-tạo TCP header và thêm vào tổng kiểm tra -gọi hàm tcp_build_and_update_options()
-kiểm tra các ACK và SYN
-gọi tp->af_specific[ip]- >queue_xmit().
tcp_v4_sendmsg() ở trong tệp
net/ipv4/tcp_ipv4.c
-kiểm tra kiểu địa chỉ IP,mở kết nối, các địa chỉ cổng -giá trị trả về là hàm tcp_do_sendmsg()
udp_getfrag() ở trong tệp net/ipv4/udp.c
-copy và tổng kiểm tra một buffer từ không gian ng−ời dùng đến
udp_sendmsg() ở trong tệp net/ipv4/udp.c
-kiểm tra độ dài, cờ, giao thức
-thiết lập UDP header và thông tin địa chỉ -kiểm tra multicast
-điền vào bảng định tuyến -điền phần còn lại của header -gọi hàm ip_build_xmit()
-cập nhật trạng thái của UDP
-giá trị trả về của hàm là err.