2012-11-27 25 views
5

Tôi hiện đang cố gắng gỡ lỗi lớp đóng gói ATM chạy trên đầu Ethernet. Về cơ bản, các tế bào ATM được lưu trữ theo thứ tự sau tiêu đề ethernet. Tuy nhiên tôi nghi ngờ các trình điều khiển ngây thơ cách tiếp cận để sk_buffs bị hỏng.Cách chính xác để xử lý tất cả tải trọng của gói sk_buff trong Linux

Người tài xế một cách mù quáng giả định rằng skb-> Xóa dữ liệu có thể được lặp qua nhưng nhìn vào mã kernel cho virtio_net.c: page_to_skb Tôi thấy những hành vi sau đây:

memcpy(hdr, p, hdr_len); 
len -= hdr_len; 
p += offset; 
copy = len; 

if (copy > skb_tailroom(skb)) 
     copy = skb_tailroom(skb); 

memcpy(skb_put(skb, copy), p, copy); 

Sau đó thêm vào:

while (len) { 
     set_skb_frag(skb, page, offset, &len); 
    page = (struct page *)page->private; 
    offset = 0; 
} 

Có vẻ như bộ đệm bị phân mảnh chỉ với phần đầu tiên có thể truy cập trực tiếp từ dữ liệu skb->.

Tôi nên sử dụng thông tin gì để lấy dữ liệu cơ bản. Lý tưởng nhất là tôi muốn liếc vài byte tại các vị trí tùy ý vào gói ethernet trước khi ghi nhớ các đoạn mã vào bộ đệm khôi phục mà tôi duy trì. Tôi nên sử dụng cái gì để làm điều này?

Trả lời

7

Việc triển khai bộ đệm ổ cắm bao gồm bộ đệm dữ liệu tuyến tính và một hoặc nhiều bộ đệm trang.

Sự tồn tại của dữ liệu được phân trang trong bộ đệm ổ cắm được chỉ định bởi skb->data_len thành viên khác không.

bool skb_is_nonlinear(const struct sk_buff *skb) được xác định trong /include/linux/skbuff.h được sử dụng để kiểm tra điều này.

Số lượng dữ liệu không được phân trang tại skb-> dữ liệu có thể được tính là skb-> len - skb-> data_len. unsigned int skb_headlen(const struct sk_buff *skb) được định nghĩa trong /include/linux/skbuff.h được sử dụng để kiểm tra điều này.

Con trỏ skb->data chỉ trỏ đến dữ liệu không được phân trang, trình điều khiển mà bạn mô tả có thể dựa vào.

void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) được xác định trong /include/linux/skbuff.h. Phải mất bộ đệm ổ cắm, bù đắp byte và độ dài byte bạn muốn và bộ đệm dữ liệu cục bộ chỉ được sử dụng nếu dữ liệu nằm trong một trong các bộ đệm trang.

Nó trả về con trỏ đến dữ liệu trong bộ đệm dữ liệu tuyến tính từ skb->data hoặc con trỏ đến bộ đệm dữ liệu cục bộ được cung cấp, hoặc NULL nếu bù đắp và chiều dài của bạn không chính xác.

Đối với mẩu dữ liệu lớn hơn tiêu đề giao thức bạn có muốn sử dụng

int skb_copy_bits(const struct sk_buff *skb, int offset,void *to, int len);

để sao chép từ một bộ đệm ổ cắm nào đó, byte offset và chiều dài byte để một bộ đệm hạt nhân nhất định.

hoặc

int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, struct iovec *to, int size);

để sao chép từ một bộ đệm ổ cắm nào đó, byte offset và chiều dài byte vào một cấu trúc cho iovec trong không gian sử dụng.

Ví dụ về cách sử dụng có thể được nhìn thấy trong mã netfilter và trong các trình điều khiển Ethernet khác.

Để biết thêm thông tin

Các vấn đề liên quan