博客
关于我
P4 Tutorials Flowlet Switching
阅读量:800 次
发布时间:2023-02-26

本文共 3788 字,大约阅读时间需要 12 分钟。

P4 Tutorials Flowlet Switching 解读

最近,我偶然发现了P4社区更新的Tutorial Demo代码,觉得非常有学习价值,于是对其进行了简单的源码解读。本文将从多个角度对该代码进行分析,希望能为P4开发者提供一些帮助。

1. 简单理解 P4 Flowlet Demo

Flowlet Switching 是一种基于ECMP(等价多路径路由)实现的四层负载均衡技术。其核心思想是通过计算数据报的五元组(源IP、目标IP、协议、源端口、目标端口)哈希值,选择一个最佳的下一跳路由。这样,同一流量的所有数据报将被转发到同一个下一跳路由,实现了高效的负载均衡。

2. 主 P4 程序的功能解析

主 P4 程序的主要目标是实现Flowlet Switching。为了完成这一目标,程序需要完成以下几个关键步骤:

  • 计算五元组哈希值:使用 modify_field_with_hash_based_offset 元动作和 crc16 算法计算五元组的哈希值,以区分不同的流量。
  • 维护流量状态:对于每条流量,需要记录两个状态:
    • 上一次数据报的时间戳
    • flowlet_id,用以区别不同的TCP流量
  • ECMP路由选择:通过计算得到的哈希值,选择最佳的下一跳路由。
  • 3. simple_router.p4 详细解读

    simple_router.p4 是实现Flowlet Switching的核心程序。以下是其主要组成部分:

    3.1 宏定义与声明

    #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;}

    3.2 流控程序

    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);}

    3.3 Flowlet 流表

    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);}

    3.4 new_flowlet 流表

    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;    }}

    4. ECMP 实现

    ECMP 是一种在多个最佳路径之间进行负载均衡的路由策略。P4程序中,ECMP 的实现主要包括以下几个部分:

    4.1 hash 计算

    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;}

    5. 结语

    通过以上分析,我们可以清晰地看到 P4 Tutorials Flowlet Demo 中 Flowlet Switching 的实现原理。希望这篇文章能为 P4 开发者提供一些参考和帮助。

    转载地址:http://bcvfk.baihongyu.com/

    你可能感兴趣的文章