zl程序教程

您现在的位置是:首页 >  其他

当前栏目

vpp qos policer限速失败

2023-02-19 12:21:05 时间

最近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指向位置是否正确。