3

我正在开发一些网络驱动程序,并尝试根据 ip::tos 值将数据包分配给不同的队列。出于测试目的,我正在运行:

ping -Q 1 10.0.0.2

将 ip::tos 值设置为 1。我遇到的问题是在我运行 ping 命令的这个系统上 - 传出的 skb 有 skb->priority==0,但我认为它应该是 1。

我假设设置“-Q 1”会将 skb->priority 设置为 1,但事实并非如此。

有谁知道为什么?

4

2 回答 2

5

首先,skb->priority和IP TOS字段之间没有直接的映射关系。在 linux 内核中是这样完成的:

sk->sk_priority = rt_tos2priority(val)
...

static inline char rt_tos2priority(u8 tos)
{
    return ip_tos2prio[IPTOS_TOS(tos)>>1];
}

(ip_tos2prio 表可以在 ipv4/route.c 中找到)。

在我看来,您必须将“TOS”字节设置为至少 32 才能使 skb->priority 为 0 以外的任何值。

ping -Q 1 将整个 TOS 字节设置为 1。请注意,不推荐使用 TOS 以支持DSCP。低 2 位用于 ECN,而高 6 位用于 DSCP 值(“优先级”)。

因此,您可能必须从 4 开始,以获得 1 的 DSCP 优先级,但根据上表,从 32 开始也可以获得 skb->priority 集,如ping -Q 32 10.0.0.2

但是,我不确定是否会在所有情况下都设置 skb->priority。如果该ping工具使用原始套接字制作数据包,它可能会绕过设置 skb->priority。

但是,如果设置了本地生成的数据包的 skb->priority,例如

 int tos = 32; 
 setsockopt(sock_fd, IPPROTO_IP, IP_TOS,
                          &tos, sizeof(tos));

因此,您可能需要在发送数据包之前编写一个执行上述操作的小示例程序。

于 2013-11-06T11:35:32.933 回答
2

上面的答案是对的,这里补一下

static inline char rt_tos2priority(u8 tos)
{
    return ip_tos2prio[IPTOS_TOS(tos)>>1];
}

其中 IPTOS_TOS 是一个宏,它将“tos”值与 0x1E 进行与运算

所以,如果你给 TOS 为 0xFF,上面的 return 语句减少到

return ip_tos2prio[(0x1E & 0xFF)>>1];

进一步计算,(0x1E & 0xFF) 等于 0x1E,(0x1E >> 1) 给我们 0x0F,即十进制的 15。我们可以说上面的 return 语句等于

return ip_tos2prio[15];

现在“ip_tos2prio”是一个预定义的数组,像这样

const __u8 ip_tos2prio[16]={0,0,0,0,2,2,2,2,6,6,6,4,4,4,4};

其中每个不同的值都有一个含义,0->BESTEFFORT,2->BULK,4->INTERACTIVE BULK,6->INTERACTIVE。

回到 return 语句,它返回ip_tos2prio数组中的第 15 个元素,即 4。

于 2016-02-05T21:23:02.717 回答