P4_learning——srv6基础实验

本文详细介绍了SRv6(Segment Routing with IPv6)的报文转发流程,通过主机1经节点A、B、C、D、E到主机2的示例,展示了如何在支持SRv6的节点间利用SRH和SID进行路径选择与报文传递。重点涉及封装、路由查找和节点间的交互操作。

实验背景
报文转发流程
采用示例说明SRv6的报文转发流程。

如图所示,假设有报文需要从主机1转发到主机2,主机1将报文发送给节点A处理。节点A、B、D、E均支持SRv6,节点C不支持SRv6,只支持IPv6。我们在源节点A上进行网络编程,希望报文经过B-C、C-D链路,送达节点E,由E节点送达主机2。
在这里插入图片描述
报文转发流程分为以下几步:

  • 源节点A将SRv6路径信息封装在SRH中,指定B-C,C-D链路的SID,另外封装E点发布的SID A5::10(此SID对应于节点E的一个IPv4 VPN),共3个SID,按照逆序形式压入SID序列。此时SL(Segment Left)=2,将Segment List[2]值复制到目的地址DA字段,按照最长匹配原则查找IPv6路由表,将其转发到节点B。
  • 报文到达节点B,B节点查找本地SID表(存储本节点生成的SRv6 SID信息),命中自身的SID(End.X SID),执行SID对应的指令动作。SL值减1,并将Segment List[1]值复制到DA字段,同时将报文从SID绑定的链路(B-C)发送出去。
    报文到达节点C,C无SRv6能力,无法识别SRH,按照正常IPv6报文处理流程,按照最长匹配原则查找IPv6路由表,将其转发到当前目的地址所代表的节点D。
  • 节点D收报文后根据目的地址A4::45查找本地SID表,命中自身的SID(End.X SID)。同节点B,SL值减1,将A5::10作为DA,并将报文发送出去。
  • 节点E收到报文后根据A5::10查找本地SID表,命中自身SID(End.DT4 SID),执行对应的指令动作,解封装报文,去除IPv6报文头,并将内层IPv4报文在SID绑定的VPN实例的IPv4路由表中进程查表转发,最终将报文发送给主机2。

srv6简化实验

本实验进行了简化,仅使用两个交换机作为源节点和end节点
在这里插入图片描述

实验实现流程:当h1向h2通信时,s1作为源节点,插入路径s1、s2。当s2接收到来在s1的报文,检查发现自己为end节点,执行srv6_pop操作,去掉srv6报文头并将安装ipv6地址进行转发到达h2

p4文件

#include <core.p4>
#include <v1model.p4>

/************************************************************************
************************** Defines **************************************
*************************************************************************/

#define ETH_TYPE_IPV4 0x0800
#define ETH_TYPE_IPV6 0x86dd
#define IP_PROTO_TCP 8w6
#define IP_PROTO_UDP 8w17
#define IP_PROTO_SRV6 8w43
#define IP_VERSION_4 4w4

#define SRV6_MAX_HOPS 6

typedef bit<48>  mac_addr_t;
typedef bit<32>  ipv4_addr_t;
typedef bit<128> ipv6_addr_t;
typedef bit<9>   port_t;

const port_t CPU_PORT = 255;



/************************************************************************
************************** Headers **************************************
*************************************************************************/

@controller_header("packet_in")
header packet_in_header_t {
   
   
    bit<9> ingress_port;
    bit<7> _padding;
}

@controller_header("packet_out")
header packet_out_header_t {
   
   
    bit<9> egress_port;
    bit<7> _padding;
}

header ethernet_t {
   
   
    bit<48> dst_addr;
    bit<48> src_addr;
    bit<16> ether_type;
}

header ipv4_t {
   
   
    bit<4>  version;
    bit<4>  ihl;
    bit<6>  dscp;
    bit<2>  ecn;
    bit<16> len;
    bit<16> identification;
    bit<3>  flags;
    bit<13> frag_offset;
    bit<8>  ttl;
    bit<8>  protocol;
    bit<16> hdr_checksum;
    bit<32> src_addr;
    bit<32> dst_addr;
}

header ipv6_t {
   
   
    bit<4> version;
    bit<8> traffic_class;
    bit<20> flow_label;
    bit<16> payload_len;
    bit<8> next_hdr;
    bit<8> hop_limit;
    bit<128> src_addr;
    bit<128> dst_addr;
}

header srv6_header_t {
   
   
    bit<8> next_hdr;
    bit<8> hdr_ext_len;
    bit<8> routing_type;
    bit<8> segment_left;
    bit<8> last_entry;
    bit<8> flags;
    bit<16> tag;
}

header srv6_segment_list_t{
   
   
    bit<128> sid;
}

header tcp_t {
   
   
    bit<16> src_port;
    bit<16> dst_port;
    bit<32> seq_no;
    bit<32> ack_no;
    bit<4>  data_offset;
    bit<3>  res;
    bit<3>  ecn;
    bit<6>  ctrl;
    bit<16> window;
    bit<16> checksum;
    bit<16> urgent_ptr;
}

header udp_t {
   
   
    bit<16> src_port;
    bit<16> dst_port;
    bit<16> length_;
    bit<16> checksum;
}

/************************************************************************
*********************** Custom Headers  *********************************
*************************************************************************/

struct headers_t {
   
   
    packet_out_header_t packet_out;
    packet_in_header_t packet_in;
    ethernet_t ethernet;
    ipv4_t ipv4;
    ipv6_t ipv6;
    srv6_header_t srh;
    srv6_segment_list_t[SRV6_MAX_HOPS] segment_list;
    tcp_t tcp;
    udp_t udp;
}

struct local_metadata_t {
   
   
    bit<16>        l4_src_port;
    bit<16>        l4_dst_port
要合理定义 `ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV`,我们需要理解其作用和参数要求。`ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV` 是 ESP-IDF 提供的宏,用于定义 BLE Mesh 协议中的 **Scene Setup Server Model**,它是对 `Scene Server` 的扩展,用于配置场景状态(如添加、删除、存储场景)。 --- ## ✅ 定义结构体的步骤 ### 1. 定义 `esp_ble_mesh_scene_state_t` 状态结构体 这个结构体用于保存当前场景状态,比如当前激活的场景编号。 ```c esp_ble_mesh_scene_state_t scene_state = { .current = 0x0000, // 当前激活的场景 }; ``` ### 2. 定义 `esp_ble_mesh_scene_setup_srv_t` 结构体 这个结构体是 `Scene Setup Server` 模型需要的状态包装器,必须包含 `scene_state`。 ```c esp_ble_mesh_scene_setup_srv_t scene_setup_srv = { .scene_state = &scene_state, // 指向上面定义的 scene_state }; ``` ### 3. 定义模型发布结构体(可选) 如果你需要模型支持发布功能(如自动上报状态),可以定义一个 `esp_ble_mesh_model_pub_t` 结构体: ```c ESP_BLE_MESH_MODEL_PUB_DEFINE(scene_srv_pub, NULL, 2); // 2 字节消息长度 ``` --- ## ✅ 完整示例:在模型数组中使用 `ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV` ```c #include "esp_ble_mesh_lighting_model_api.h" #include "esp_ble_mesh_generic_model_api.h" // 场景状态结构体 esp_ble_mesh_scene_state_t scene_state = { .current = 0x0000, }; // Scene Setup Server 状态结构体 esp_ble_mesh_scene_setup_srv_t scene_setup_srv = { .scene_state = &scene_state, }; // 定义模型发布结构体(可选) ESP_BLE_MESH_MODEL_PUB_DEFINE(scene_setup_srv_pub, NULL, 2); // 模型数组 esp_ble_mesh_model_t root_models[] = { ESP_BLE_MESH_MODEL_CFG_SRV, // Scene Server ESP_BLE_MESH_MODEL_SCENE_SRV(&scene_setup_srv_pub, &scene_state), // Scene Setup Server ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV(&scene_setup_srv), }; // 元素数组 esp_ble_mesh_element_t elements[] = { { .location = ESP_BLE_MESH_LOC_MAIN, .models = root_models, .model_count = ARRAY_SIZE(root_models), }, }; ``` --- ## ✅ 说明 - `ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV(&scene_setup_srv)` 中的参数是一个指向 `esp_ble_mesh_scene_setup_srv_t` 的指针。 - `scene_setup_srv.scene_state` 必须指向一个有效的 `esp_ble_mesh_scene_state_t` 实例。 - `ESP_BLE_MESH_MODEL_SCENE_SRV` 和 `ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV` 通常一起使用,分别处理场景操作和配置。 --- ## ✅ 常见错误 | 错误信息 | 原因 | 解决方法 | |----------|------|----------| | `Scene Setup Server not present` | 没有在模型数组中添加 `ESP_BLE_MESH_MODEL_SCENE_SETUP_SRV` | 添加该模型 | | `Invalid Scene state` | `scene_state` 或 `scene_setup_srv.scene_state` 为 NULL | 确保结构体正确初始化 | | `Model init failed (err -22)` | 参数错误(如空指针) | 检查模型结构体是否完整、非空 | --- ###
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值