Docker容器中setsockopt设置SO_PRIORITY失效问题求助
我在主机上配置了以下MQPRIO qdisc规则:
sudo tc qdisc add dev p2p2 parent root handle 1 mqprio \ num_tc 3 \ map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \ queues 1@0 1@1 1@2 \ hw 0
通过代码设置socket的SO_PRIORITY来指定skb->priority,让MQPRIO将数据包分配到对应队列,代码如下:
if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0) { perror("setsockopt"); return 1; }
该配置在主机环境运行正常:发送1000个优先级为3、2、1的数据包时,各队列统计结果符合预期(额外4个为ARP包):
qdisc pfifo_fast 0: parent 1:3 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 55168 bytes 1004 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 qdisc pfifo_fast 0: parent 1:2 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 55000 bytes 1000 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 qdisc pfifo_fast 0: parent 1:1 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 55000 bytes 1000 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0
但在使用默认docker0网络的容器中运行程序时,所有数据包都进入第三个队列,统计结果如下:
qdisc pfifo_fast 0: parent 1:3 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 165126 bytes 3003 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 qdisc pfifo_fast 0: parent 1:2 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 qdisc pfifo_fast 0: parent 1:1 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0
这说明skb->priority未被正确设置,始终为默认值0。
核心问题:是否可以仅通过容器内调用setsockopt设置SO_PRIORITY,让MQPRIO qdisc正确分类数据包?已知--net=host和TOS/过滤器的解决方案,想确认仅用SO_PRIORITY的可行性。
给容器添加NET_ADMIN权限:启动容器时添加
--cap-add=NET_ADMIN参数,允许容器内进程拥有修改网络优先级的权限。例如:docker run --cap-add=NET_ADMIN your-image权限生效原理:Docker默认的安全隔离策略会限制非特权容器的网络操作权限,即使
setsockopt(SO_PRIORITY)调用返回成功,内核也会将skb->priority重置为0。添加NET_ADMIN权限后,容器进程获得了修改网络优先级的特权,设置的SO_PRIORITY值会被内核保留,从而被MQPRIO的map规则正确映射到对应队列。验证方法:容器内运行程序后,通过主机上的
tc -s qdisc show dev p2p2命令查看各队列的数据包统计,确认不同优先级的数据包被分配到对应队列。
内容的提问来源于stack exchange,提问作者akastack

