---
title: 接口详情
description: "hydra_core.hdr架构文件中提供了用于报文解析的packet_in extern object。"
url: https://www.hikunpeng.com/document/detail/zh/flexda/api/dpak_api033.html
sourcePath: /source/zh/flexda/api/dpak_api033.html
indexId: e9165ec781264920644a66d57e2b7950636b1b2274125a6a40b7f1255667f38638
---
# 接口详情

hydra_core.hdr架构文件中提供了用于报文解析的packet_in extern object。

```
extern packet_in {
void extract<T>(out T hdr, in bit<32> type, in layers_e layer);
void extractOpt<T>(out T hdr);
void advance(in bit<32> sizeInBits);
}
```

其中，各个函数的含义如表1所示。


**表1 函数说明**

| 函数名 | 入参 | 效果 | 示例 |
| --- | --- | --- | --- |
| extract | hdr：header结构体中定义的报文头。 | 按照header结构体中的定义，将协议的某个字段从报文中提取出来。 | packet.extract(hdr.ethernet, TYPE\_ETH, layer.l2); |
| extract | type：报文类型值，基础报文的type在hydra\_core.hdr架构文件中有提供。 | 按照header结构体中的定义，将协议的某个字段从报文中提取出来。 | packet.extract(hdr.ethernet, TYPE\_ETH, layer.l2); |
| extract | layer：协议所在层级，hydra\_core.hdr架构文件中有提供层级枚举。 | 按照header结构体中的定义，将协议的某个字段从报文中提取出来。 | packet.extract(hdr.ethernet, TYPE\_ETH, layer.l2); |
| extractOpt | hdr：struct中定义的optional的header字段。例如GRE的可选字段。 | 提取报文中的可选字段。 | if (hdr.gre.C == 1w1) { packet.extractOpt(hdr.gre\_opt\_c); } |
| advance | sizeInBits：要移动的长度，以bit为单位。 | 将报文解析流程当前指向的位置指针从低地址往高地址移动。 | packet.advance(((bit<32>) hdr.inner\_ipv4.ihl \- 32w5) \* 32w32); |
| hdr\_last\_layer\_get | / | layers\_e hdr\_last\_layer\_get(); | 获取已硬件解析完成的最后一层报文的层级 |
| hdr\_last\_layer\_type\_get | / | bit<16> hdr\_last\_layer\_type\_get(); | 获取已硬件解析完成的最后一层报文的协议类型 |


hydra_externs.hdr架构文件中提供了丰富的extern函数，用户在自定义action中可组合不同的extern函数以实现隧道封装、隧道解封装、报文修改等功能。


**表2 函数说明**

| 函数名称 | 参数 | 签名 | 描述 |
| --- | --- | --- | --- |
| hdr\_packet\_delete\_from\_head | len：要删除的报文头长度。 | extern void hdr\_packet\_delete\_from\_head(in bit<8> len); | 从原始报文头删除报文头，可用于隧道解封装。用户应保证删除总长度不能超过原始报文头总长度，且不超过255B。 |
| hdr\_packet\_insert\_from\_head | hdr：要插入的报文头，类型为header。 | extern void hdr\_packet\_insert\_from\_head<T>(in T hdr); | 从原始报文头插入报文头，可用于隧道封装。对于发往网络侧的报文用户应保证新插入的报文头长度不超过128B；对于发往主机侧的报文用户应保证新插入的报文头长度不超过64B。 |
| hdr\_packet\_modify | field：要修改的报文头字段。 value：修改的值。 | extern void hdr\_packet\_modify<T>(in T field, in T value); | 修改报文头的指定字段。 |
| hdr\_packet\_calc\_checksum\_incr | modified\_field：修改的报文字段。 cs\_field：要修改的checksum字段。 params：结构体类型，用于参数配置，具体成员如下： old\_val：在修改报文头相关字段场景且需增量更新报文头checksum场景下，该成员为待修改字段的旧值。 new\_val：在修改报文头相关字段场景且需增量更新报文头checksum场景下，该成员为待修改字段的新值。 old\_cs：在修改报文头相关字段场景且需增量更新报文头checksum场景下，该成员为待修改报文头的旧checksum值。 cs\_alg：checksum算法选择，hydra\_externs.hdr架构文件中有提供算法枚举供用户选择。 | extern void hdr\_packet\_calc\_checksum\_incr<M,C>(in M modified\_field,in C cs\_field,in packet\_incr\_cs\_param params); | 增量修改原始报文头中的checksum字段。 示例如下： 修改IPv4的TTL字段后更新checksum。 packet\_incr\_cs\_param incr\_checksum\_para; incr\_checksum\_para.old\_val = (bit<32>)hdr.ipv4.ttl; //待修改字段的旧值 incr\_checksum\_para.new\_val = (bit<32>)(hdr.ipv4.ttl \- 1); //待修改字段的新值 incr\_checksum\_para.old\_cs = hdr.ipv4.hdr\_checksum; //待修改报文头的旧checksum值 incr\_checksum\_para.cs\_alg = RFC.RFC\_1624; //使用RFC\_1624算法 hdr\_packet\_modify(hdr.ipv4.ttl, hdr.ipv4.ttl \- 1); //先修改ttl字段 hdr\_packet\_calc\_checksum\_incr(hdr.ipv4.ttl,hdr.ipv4.hdr\_checksum,incr\_checksum\_para); //更新checksum字段 |
| hdr\_packet\_calc\_inserted\_checksum\_incr | 前三个参数含义同接口hdr\_packet\_calc\_checksum\_incr。 offset：待计算协议头在所插入报文头中的偏移。 | extern void hdr\_packet\_calc\_inserted\_checksum\_incr<M, C>(in M modified\_field,in C cs\_field,in packet\_incr\_cs\_param param,in bit<32> offset); | 增量修改新插入报文头中的checksum字段。用户应保证offset小于插入的报文头总长度。 |
| hdr\_packet\_calc\_checksum | cs\_field的含义同hdr\_packet\_calc\_checksum\_incr param：结构体类型，用于参数配置，具体成员如下： init\_value：当前原始报文头的初始checksum value，需设置为0。 mask：用于标识原始报文头中需要参与checksum计算的字段。掩码长度为64比特，每位对应报文头中连续的2个字节，对应总计128字节的报文头长度。掩码位为‘0’时，表示其对应的报文头字节段需参与计算。若需要掩去IPv4层的checksum字段（位于第11字节），mask取值为0x0400000000000000。 cs\_alg：checksum算法选择，hydra\_externs.hdr架构文件中有提供算法枚举供用户选择。 | extern void hdr\_packet\_calc\_checksum<T>(in T cs\_field,in packet\_checksum\_param param); | 全量修改原始报文头中的checksum字段。 目前该接口不支持包含伪首部的协议的checksum计算，例如TCP和UDP。 该接口需在报文头字段不再被修改后调用。 |
| hdr\_packet\_calc\_inserted\_checksum | cs\_field和param的含义同hdr\_packet\_calc\_checksum。 layer\_offset：待计算协议头在所插入报文头中的偏移。 layer\_len：待计算协议头的长度。 | extern void hdr\_packet\_calc\_inserted\_checksum<T>(in T cs\_field,in packet\_checksum\_param param,in bit<32> layer\_offset,in bit<32>layer\_len); | 全量修改新插入报文头中的checksum字段。 计算插入报文头的checksum时，计算顺序应严格按照从外层到内层。 目前该接口不支持包含伪首部的协议的checksum计算，例如TCP和UDP。 |
| hdr\_ovs\_pipeline\_action\_upcall | / | extern void hdr\_ovs\_pipeline\_action\_upcall(); | 执行上送操作，注意只可用于前置control流程中，不可用于后置control流程。 |
| hdr\_ovs\_pipeline\_action\_drop | / | extern void hdr\_ovs\_pipeline\_action\_drop(); | 执行丢包操作，可用于前置control流程和后置control流程中。 |
| hdr\_input\_port\_id\_get | / | extern bit<16> hdr\_input\_port\_id\_get(); | 获取当前报文输入的port\_id。 |


Hydra在架构文件hydra_log.hdr中提供了USER_LOG宏用于日志打印。

```
#define USER_LOG(type,fmt,args...)hydra_log_##type(FILE_ID,__LINE__,0,fmt,##args)
```

- type：日志级别。取值范围：ERR、WARN、INFO、DEBUG。
- fmt：日志信息。字符串类型，最大字符数为128。
- args：变长参数列表。最多打印4个参数，占位符使用0x%x。

#### 使用范围

- parser的state内
- action内
- control apply内


#### 使用示例

```
control MyPrePipe(in headers hdr) {
apply {
USER_LOG(ERR, "[DSL][MyPrePipe]hdr.ipv4.ttl  0x%x\n", hdr.ipv4.ttl);
}
}
```
