最近vpp-dev邮件中有一封邮件关于qos policer限速失败的问题,原文描述如下:
最近尝试做基于loop port的qos限速(用于ESP/VxLAN封装)。但是我发现“l2-policer-classify”节点不会命中数据包,相比之下,acl匹配可以正常工作。所以我跟踪“l2-policer-classify”节点功能“policer_classify_inline”的源代码,它使用“h0 = b0->data;” 做一些匹配动作,但是我认为它应该使用“h0 = (u8 *) vlib_buffer_get_current (b0);” 做相应的匹配动作。顺便说一句,“l2-input-acl”节点函数“l2_in_out_acl_node_fn”也使用“h0 = (u8 *) vlib_buffer_get_current (b0);” 做相应的匹配动作。所以我修改了“policer_classify_inline”函数源代码如下,然后它工作正常。
邮件重要也附了作者的配置命令行及patch文件记录:
1.Qos 限制速率为 800kbps 配置:
configure policer name policy1 cir 800 cb 90000 rate kbps round closest type 1r2c conform-action transmit exceed-action drop
classify table mask l3 ip4 src proto
classify session policer-hit-next policy1 exceed-color table-index 0 match l3 ip4 src 10.100.0.176 proto 50
set policer classify interface loop48 l2-table 0
2. ACL 拒绝配置
classify table mask l3 ip4 src proto
classify session acl-hit-next deny table-index 1 match l3 ip4 src 10.100.0.176 proto 50
set int input acl intfc loop48 l2-table 1
3.show interface features loop48,显示接口feature
l2-input:
POLICER_CLAS (l2-policer-classify)
ACL (l2-input-acl)
FWD (l2-fwd)
UU_FLOOD (l2-flood)
ARP_TERM (arp-term-l2bd)
FLOOD (l2-flood)
4、patch修改记录:
diff --git a/src/vnet/policer/node_funcs.c b/src/vnet/policer/node_funcs.c
index fd7f197e9..bdbb17087 100644
--- a/src/vnet/policer/node_funcs.c
+++ b/src/vnet/policer/node_funcs.c
@@ -559,11 +559,17 @@ policer_classify_inline (vlib_main_t * vm,
bi0 = from[0];
b0 = vlib_get_buffer (vm, bi0);
- h0 = b0->data;
bi1 = from[1];
b1 = vlib_get_buffer (vm, bi1);
+
+#if 0 /* modified by liuman for policer match */
+ h0 = b0->data;
h1 = b1->data;
+#else
+ h0 = (u8 *) vlib_buffer_get_current (b0);
+ h1 = (u8 *) vlib_buffer_get_current (b1);
+#endif
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
table_index0 =
@@ -606,7 +612,11 @@ policer_classify_inline (vlib_main_t * vm,
bi0 = from[0];
b0 = vlib_get_buffer (vm, bi0);
+#if 0 /* modified by liuman for policer match */
h0 = b0->data;
+#else
+ h0 = (u8 *) vlib_buffer_get_current (b0);
+#endif
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
table_index0 =
@@ -673,7 +683,11 @@ policer_classify_inline (vlib_main_t * vm,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
- h0 = b0->data;
+#if 0 /* modified by liuman for policer match */
+ h0 = b0->data;
+#else
+ h0 = (u8 *) vlib_buffer_get_current (b0);
+#endif
table_index0 = vnet_buffer (b0)->l2_classify.table_index;
e0 = 0;
t0 = 0;
作者在文章中并没有给出详细的接口配置和报文trace流量,只能通过猜测作者失败的点应该是vxlan解封装后的流程。失败的原因通过下面的分析应该会一目了然。
vxlan封装报文格式如下:dpdk-input收到报文时,bo->data是执行外层二层头,当vxlan解完封装后在policer节点中仍然使用bo->data作为报文匹配肯定是无法匹配到内层ip信息。作者修改成vlib_buffer_get_current (b0)也就比较容易理解了。
作者的修改方法可能会导致ip-input方向的匹配就存在问题,ip input方向中 vlib_buffer_get_current (b0)指向的就是ip头了。
最近在测试policer绑定到ipsec接口的时候,也发现了同样的问题,对policer进行了改动支持outbound方向的限速。当配置在ipsec接口outbound方向限速时,如果进入限速节点前是存在ip报文分片时,同样存在无法匹配的问题。原因看下图就比较清楚了。ipsec报文在封装前是没有二层头的。
就在代码中增加了接口类型的判断,代码如下:
vnet_hw_interface_t * hw = vnet_get_sup_hw_interface(pcm->vnet_main, sw_if_index0);
if (hw && ipsec_device_class.index == hw->dev_class_index)
{
h0 = (u8 *) vlib_buffer_get_current (b0) - 14; /*dmac+smac+ethtype*/;
}
上述修改肯定会影响处理性能。不知道各位有没有遇到过类似的问题,是如何解决的,有没有更好的修改方案?可以公众号回复“加群”,加我微信号一起交流。
在很多隧道模式下policer限速失败很常见,定位policer限速失败问题时,大致思路就是:
1、show error 查询有否存在匹配miss
2、trace 抓包分析报文转发流程,当“policer_classify_inline节点时报文的bo-data指向位置是否正确。
本文分享自 DPDK VPP源码分析 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!