Phần này chỉ trình bày về mặt định tuyến (bởi IP forwarding) trong truyền thông thông điệp. Nó cung cấp một cách tổng quát về tiến trình, kiểm tra các gói đ−ợc chuyển qua các tầng, chi tiết về các tác động của từng tầng, và tổng quát hóa các mã nguồn trong nhân.
6.1 Tổng quan
Hình d−ới là một sơ đồ tổng quát tiến trình forwarding, nó cũng là sự tổ hợp của các quá trình gửi và nhận.
Một gói tin đ−ợc chuyển đến sẽ với một ngắt, khi hệ thống đ−ợc báo rằng thiết bị có một thông điệp đang chờ. Thiết bị cấp phát không gian l−u trữ và báo cho bus đ−a thông điệp vào không gian đó. Sau đó nó chuyển gói tới tầng liên kết, đ−a nó lên hàng đợi backlog, đánh dấu cờ network để “bottom-half” tiếp theo chạy, và trả điều khiển cho tiến trình hiện hành.
Khi tiến trình lập lịch tiếp theo chạy, nó thấy rằng có tác vụ mạng cần thực hiện và chạy “bottom-half” mạng. Hàm này lấy các gói khỏi hàng đợi backlog, đ−a chúng lên IP và chuyển chúng tới hàm nhận. Tầng IP kiểm tra gói xem có lỗi, và định tuyến nó; gói sẽ đ−ợc chuyển lên tầng Giao vận (TCP hoặc UDP nếu gói tin đ−ợc gửi cho máy này) hoặc h−ớng hàm IP forwarding. Trong hàm forwarding, IP kiểm tra gói và gửi một thông điệp ICMP về cho ng−ời gửi nếu có gì đó sai. Sau đó nó copy gói vào một bộ đệm mới và chia nhỏ chúng nếu cần thiết.
Cuối cùng tầng IP chuyển gói xuống hàm ở tầng liên kết, mà chuyển gói vào hàng đợi xmit của thiết bị gửi và đảm bảo thiết bị biết rằng nó cần truyền dữ liệu đi. Cuối cùng thiết bị (chẳng hạn card mạng) báo cho bus để gửi gói dữ liệu đi.
Hình
7:
IP
forwarding.
6.2 Các b−ớc chuyển IP Nhận một gói Nhận một gói • • • • • • • • Đánh thức thiết bị nhận (interrupt) Kiểm tra thiết bị (device)
Nhận phần header liên kết Cấp phát không gian cho gói Báo cho bus đ−a gói vào bộ đệm Đ−a gói vào hàng đợi backlog
Thiết lập cờ để chạy bottom half mạng khi có thể. Trả điều khiển về cho tiến trình hiện hành.
Chạy “Bottom Half”
• • • • •
Chạy network bottom half (schedule)
Gửi các gói đang chờ giải quyết ngắt (net_bh)
Lặp tất cả các gói trong hàng đợi backlog và chuyển gói lên giao thức chấp nhận Internet (IP).
Làm sạch hàng đợi gửi lại một lần nữa. Thoát khỏi bottom half.
Kiểm tra gói trong IP
• • • •
Kiểm tra lỗi trong gói - xem có quá ngắn không? quá dài không? đúng phiên bản không? checksum có lỗi không?
Chia nhỏ gói nếu cần thiết.
Lấy định tuyến cho gói (có thể cho máy này hoặc có thể cần chuyển) Gửi gói tới thủ tục điều khiển đích (truyền lại tới một máy khác)
Chuyển gói trong IP
• • • • • • •
Kiểm tra tr−ờng TTL (giảm nó đi)
Kiểm tra gói không đúng cho định tuyến Gửi ICMP trở lại cho ng−ời gửi nếu có lỗi.
Copy gói vào bộ đệm mới và giải phóng bộ đệm cũ. Thiết lập các tùy chọn IP.
Chia nhỏ gói nếu nó quá lớn cho đích mới. Gửi gói tới hàm ra thiết bị.
Truyền một gói
• • • •
Đ−a gói lên hàng đợi ra của thiết bị. Đánh thức thiết bị.
Đợi bộ lập lịch (scheduler) chạy driver của thiết bị. Kiểm tra thiết bị.
• Báo cho bus để truyền gói lên thiết bị.
6.3 Các hàm trong Linux
Trong mục này chúng tôi đ−a ra danh sách (theo alphabe) các hàm trong Linux kernel đ−ợc coi là quan trọng trong việc IP forwarding, đồng thời phân tích hoạt động của source code. Các lời gọi hàm bắt đầu từ hàm DEVICE_rx().
Functions/File Descriptions
dev_queue_xmit() có trong tệp
net/core/dev.c
-gọi hàm start_bh_atomic() -nếu thiết bị có một hàng đợi thì:
+gọi hàm enqueue() để thêm gói tin vào hàng đợi +gọi hàm qdisc_wakeup() [= qdisc_restart()] để đánh thức thiết bị
-nếu không có hàng đợi gọi hàm hard_start_xmit() -gọi hàm end_bh_atomic().
DEVICE-
>hard_start_xmit() có trong tệp
drivers/net/DEVICE.c
-hàm này phụ thuộc vào thiết bị
-nó thực hiện kiểm tra ph−ơng tiện truyền xem có mở không
-gửi header
-báo cho bus gửi gói tin
-cuối cùng nó cập nhật trạng thái.
>>> DEVICE_rx() có trong tệp
drivers/net/DEVICE.c
-hàm này phụ thuộc vào thiết bị (lấy điều khiển từ ngắt) -nó thực hiện kiểm tra trạng thái để chắc chắn là ở trạng thái nhận
-gọi hàm dev_alloc_skb() để dự trữ không gian nhớ cho gói tin
-lấy gói tin từ bus hệ thống
-gọi hàm eth_type_trans() để xác định kiểu giao thức -gọi hàm netif_rx()
-cập nhật trạng thái card (trả về từ ngắt).
ip_finish_output() có trong tệp
include/net/ip.h
-thiết lập thiết bị nhận của thiết bị ra chuẩn nhằm mục đích lấy thông tin về tuyến
-gọi hàm đ−a gói tin cho đích[= dev_queue_xmit()].
ip_forward() có trong tệp
net/ipv4/ip_forward.c
-kiểm tra router alert
-nếu gói tin là không của máy nào thì huỷ nó
-nếu TTL đã hết hạn thì bỏ gói tin đó và gửi thông báo ICMP trở lại
-nếu tuyến ngắn nhất không có thì bỏ gói tin và gửi thông báo ICMP trở lại ng−ời gửi
-nếu cần thiết thì gửi thông báo ICMP báo cho gói tin đã chuyển h−ớng
-copy và giải phóng gói tin cũ -giảm TTL
-nếu có một vài tuỳ chọn, gọi hàm
ip_forward_options() để thiết lập chúng -cuối cùng nó gọi hàm ip_send()
ip_rcv() có trong tệp
net/ipv4/ip_input.c -hàm này tiến hành kiểm tra các lỗi của gói tin: +lỗi về độ dài (quá ngắn hoặc quá dài)
+lỗi về phiên bản (không phải ipv4) +lỗi về checksum
-sau đó gọi hàm __skb_trim() để xoá bộ đệm -ghép gói tin nếu cần
-gọi hàm ip_route_input() đ−a gói tin ra tuyến -kiểm tra và điều khiển các tuỳ chọn của IP
-giá trị trả về của hàm là skb->dst->input() [= ip_forward()].
ip_route_input() có trong tệp
net/ipv4/route.c
-gọi hàm rt_hash_code() để lấy thứ tự của bảng định tuyến
-vòng lặp trong bảng định tuyến với giá trị bắt đầu là hash cho đến khi tìm tuyến cho gói tin
-nếu tìm thấy thì:
+cập nhật trạng thái tuyến (thời gian và sử dụng)
+thiết lập đích của gói tin vào trong entry của bảng định tuyến
+ trả về thành công -nếu không tìm thấy thì:
+kiểm tra có phải là các địa chỉ multicast +trả về hàm ip_route_input_slow() ip_route_output_slow(
) có trong tệp
net/ipv4/route.c
-nếu địa chỉ nguồn đã biết thì tìm kiếm thiết bị ra chuẩn -nếu địa chỉ đích đã biết thì thiết lập loopback
-sau đó gọi hàm fib_lookup() để tìm tuyến -cấp phát bộ nhớ mới cho entry bảng định tuyến -khởi tạo entry cho bảng với địa chỉ nguồn, đích, TOS , thiết bị ra và các cờ
-gọi hàm rt_set_nexthop() để tìm đích tiếp theo -giá trị trả về hàm rt_intern_hash().
ip_send() có trong tệp
include/net/ip.h -gọi hàm: bị ip_fragment() nếu gói tin quá lớn so với thiết
-gọi hàm ip_finish_output(). net_bh() có trong tệp
net/core/dev.c -hàm này đ-nó tiến hành kiểm tra nếu có nhiều gói tin đang đợi ở đầu −ợc chạy bởi trình lập lịch
ra thì gọi hàm qdisc_run_queues() (xem phần gửi thông điệp)
-trong khi hàng đợi của backlog không rỗng thì: +cho phép nửa d−ới thực thi
+gọi hàm skb_dequeue() để nhận gói tiếp theo +nếu là gói tin thì cho một số ng−ời khác nếu không (FASTROUTED) thì đ−a nó lên hàng đợi gửi
+tiến hành vòng lặp trong các danh sách giao thức để tìm đúng kiểu của giao thức
+sau đó gọi hàm pt_prev->func() [= ip_rcv()] để đ−a gói tin tới giao thức t−ơng ứng
netif_rx() có trong tệp
net/core/dev.c -đ-nếu hàng đợi của backlog đã quá đầy thì huỷ bỏ gói tin −a thời gian vào skb->stamp
-nếu không thì:
+ gọi hàm skb_queue_tail() để đ−a gói tin vào hàng đợi backlog
+đánh dấu tất cả lại cho lần thực thi sau.
qdisc_restart() có trong tệp
net/sched/sch_generic .c
-đẩy gói tin ra hàng đợi
-gọi hàm dev->hard_start_xmit() -cập nhật trạng thái
-nếu có một lỗi nào đó thì đ−a gói tin trở lại hàng đợi
rt_intern_hash() có trong tệp
net/ipv4/route.c
-đ−a tuyến mới vào trong bảng định tuyến