本文共 3788 字,大约阅读时间需要 12 分钟。
最近,我偶然发现了P4社区更新的Tutorial Demo代码,觉得非常有学习价值,于是对其进行了简单的源码解读。本文将从多个角度对该代码进行分析,希望能为P4开发者提供一些帮助。
Flowlet Switching 是一种基于ECMP(等价多路径路由)实现的四层负载均衡技术。其核心思想是通过计算数据报的五元组(源IP、目标IP、协议、源端口、目标端口)哈希值,选择一个最佳的下一跳路由。这样,同一流量的所有数据报将被转发到同一个下一跳路由,实现了高效的负载均衡。
主 P4 程序的主要目标是实现Flowlet Switching。为了完成这一目标,程序需要完成以下几个关键步骤:
modify_field_with_hash_based_offset 元动作和 crc16 算法计算五元组的哈希值,以区分不同的流量。simple_router.p4 是实现Flowlet Switching的核心程序。以下是其主要组成部分:
#define FLOWLET_MAP_BITS 13#define FLOWLET_MAP_SIZE 8192#define FLOWLET_INACTIVE_TOUT 50000 // 50msheader_type ingress_metadata_t { fields { flow_ipg : 48; flowlet_map_index : FLOWLET_MAP_BITS; flowlet_id : 16; flowlet_lasttime : 48; ecmp_offset : 14; nhop_ipv4 : 32; }} metadata ingress_metadata_t ingress_metadata;action _drop() { drop();}field_list l3_hash_fields { ipv4.srcAddr; ipv4.dstAddr; ipv4.protocol; tcp.srcPort; tcp.dstPort;}field_list_calculation flowlet_map_hash { input { l3_hash_fields; } algorithm : crc16; output_width : FLOWLET_MAP_BITS;}register flowlet_lasttime { width : 48; instance_count : 8192;}register flowlet_id { width : 16; instance_count : 8192;} control ingress { apply(flowlet); if (ingress_metadata.flow_ipg > FLOWLET_INACTIVE_TOUT) { apply(new_flowlet); } apply(ecmp_group); apply(ecmp_nhop); apply(forward);}control egress { apply(send_frame);} table flowlet { actions { lookup_flowlet_map; }}action lookup_flowlet_map() { // 计算flowlet_map_index modify_field_with_hash_based_offset(ingress_metadata.flowlet_map_index, 0, flowlet_map_hash, FLOWLET_MAP_SIZE); // 获取flowlet_id register_read(ingress_metadata.flowlet_id, flowlet_id, ingress_metadata.flowlet_map_index); // 记录时间戳 modify_field(ingress_metadata.flow_ipg, intrinsic_metadata.ingress_global_timestamp); // 获取flowlet_lasttime register_read(ingress_metadata.flowlet_lasttime, flowlet_lasttime, ingress_metadata.flowlet_map_index); // 更新flow_ipg subtract_from_field(ingress_metadata.flow_ipg, ingress_metadata.flowlet_lasttime); // 更新flowlet_lasttime寄存器 register_write(flowlet_lasttime, ingress_metadata.flowlet_map_index, intrinsic_metadata.ingress_global_timestamp);} action update_flowlet_id() { add_to_field(ingress_metadata.flowlet_id, 1); register_write(flowlet_id, ingress_metadata.flowlet_map_index, ingress_metadata.flowlet_id);}table new_flowlet { actions { update_flowlet_id; }} ECMP 是一种在多个最佳路径之间进行负载均衡的路由策略。P4程序中,ECMP 的实现主要包括以下几个部分:
field_list flowlet_l3_hash_fields { ipv4.srcAddr; ipv4.dstAddr; ipv4.protocol; tcp.srcPort; tcp.dstPort; ingress_metadata.flowlet_id;}#define ECMP_BIT_WIDTH 10#define ECMP_GROUP_TABLE_SIZE 1024#define ECMP_NHOP_TABLE_SIZE 16384field_list_calculation flowlet_ecmp_hash { input { flowlet_l3_hash_fields; } algorithm : crc16; output_width : ECMP_BIT_WIDTH;}action set_ecmp_select(ecmp_base, ecmp_count) { modify_field_with_hash_based_offset(ingress_metadata.ecmp_offset, ecmp_base, flowlet_ecmp_hash, ecmp_count);}table ecmp_group { reads { ipv4.dstAddr : lpm; } actions { _drop; set_ecmp_select; } size : ECMP_GROUP_TABLE_SIZE;}table ecmp_nhop { reads { ingress_metadata.ecmp_offset : exact; } actions { _drop; set_nhop; } size : ECMP_NHOP_TABLE_SIZE;} 通过以上分析,我们可以清晰地看到 P4 Tutorials Flowlet Demo 中 Flowlet Switching 的实现原理。希望这篇文章能为 P4 开发者提供一些参考和帮助。
转载地址:http://bcvfk.baihongyu.com/