---
title: 派生数据类型
description: "header是用于定义协议头部结构的关键数据结构。header的作用是将原始比特流映射为具有明确语义的字段集合，以便在后续处理数据包时访问和操作这些字段。"
url: https://www.hikunpeng.com/document/detail/zh/flexda/devguide/dpak_dev0039.html
sourcePath: /source/zh/flexda/devguide/dpak_dev0039.html
indexId: 530c2dad481118e434f3134dbece34e6619c3812ff410fa884016d5233bafbf944
---
# 派生数据类型

#### header类型

header是用于定义协议头部结构的关键数据结构。header的作用是将原始比特流映射为具有明确语义的字段集合，以便在后续处理数据包时访问和操作这些字段。

```
header <header_name> {
<field_type> <field_name>;
}
```

- header_name：头部的名字，通常以协议名称命名。例如ethernet_t、ipv4_t。
- field_type：字段的类型，通常是固定宽度的位类型。例如bit<16>。
- field_name：字段的名字，用于标识协议的某个具体属性。
- header_name与field_name不能作为DSL的关键字，如action、match_kind等，且仅能由数字、大小写字母、下划线组成，且不能为数字开头。

以下代码块展示了ethernet_t的定义。

```
typedef bit<48> macAddr_t;
header ethernet_t {
macAddr_t dstAddr;    // 目的MAC地址
macAddr_t srcAddr;    // 源MAC地址
bit<16>   etherType;  // 协议类型字段
}
```

header数据类型支持setValid()、isValid()和setInvalid()方法：

- setValid()：标记header中生效的协议类型，当报文解析的extract()函数执行后会进行调用。
- isValid()：判断header中协议类型是否生效。在使用该协议层的数据时需先判断该层协议是否生效，若不判断直接使用header的数据会导致空指针异常，致使功能异常。
- setInvalid() : 标记header中不生效的协议类型。

- 架构文件hydra_headers.hdr中会提供常见协议头供用户使用。
- header的成员类型只能为基础类型。


#### header_union类型

header_union是一种数据类型，类似于C语言中的union类型，作用是定义一组协议类型，并在处理数据包时动态选择使用哪一个。其中，header_union的每个成员必须是header类型。

```
header_union <header_union_name> {
header <header_name>;
}
```

- header_union_name：该组协议类型的名字（例如ip_union）。不能作为DSL的关键字，如action、match_kind等，且仅能由数字、大小写字母、下划线组成，且不能为数字开头。

以下代码块展示了ip_union的定义，ip_union类型表示IPv4报文头和IPv6报文头的union。

```
header_union ip_union {
ipv4_t ipv4;
ipv6_t ipv6;
}
```

- header_union的成员只能是header类型。
- header_union不能作为泛型参数传递。
- header_union不能作为action的控制面参数。


#### struct类型

在 DSL 中，struct是用于定义更通用数据结构的数据类型。struct并非像header那样直接映射到数据包的比特流，而是用于存储与数据包相关的元数据或中间处理数据，或者用于存储网络多层header合集。它的灵活性使其适合在程序的逻辑处理中保存额外信息。

struct的定义语法如下所示。

```
struct <struct_name> {
<field_type> <field_name>;
}
```

- struct_name：数据结构的名称，通常以描述其功能的名字命名。例如metadata_t、headers。
- field_type：字段的类型，可以是bit<N>、布尔类型、枚举类型甚至嵌套的struct。
- field_name：字段的名称，用于标识数据结构中的具体属性。
- field_name与struct_name不能作为DSL的关键字，如action、match_kind等，且仅能由数字、大小写字母、下划线组成，且不能为数字开头。


#### enum类型

枚举类型，用于声明一组命名的常量，适用于变量仅允许在定义的有限选项中选择的场景。例如，Hydra架构文件hydra_core.hdr中用枚举类型表示报文的层级类型。

```
enum layers_e {
l2,
l3,
l4,
tunnel,
inner_l2,
inner_l3,
inner_l4
}
```

还可以指定枚举的底层表示，如bit<8>，并为每个成员指定具体的值。

```
enum bit<8> E {
e1 = 0,
e2 = 1,
e3 = 2
}
```

枚举类名与成员名不能作为 DSL 的关键字，如action、match_kind等，且仅能由数字、大小写字母、下划线组成，且不能为数字开头。


#### 泛型类型

泛型类型表示尚未确定的类型，必须由用户提供。用于extern function及package。例如，以下extern function用于修改报文字段：

```
extern void hdr_packet_modify<T>(in T field, in T value);
```

在用户调用该extern function时，类型T须被实例化，且可为任意类型：

```
hdr_packet_modify(hdr.ipv4.sip, new_sip);
hdr_packet_modify(hdr.ethernet.smac, new_smac);
```

其中sip类型为bit<32>，smac类型为bit<48>。

- extern function的泛型类型不可实例化为struct。
- 用户可以使用上述数据类型定义变量。示例：<field_type> <field_name>。
- field_name不能作为DSL的关键字，如action、match_kind等。field_name仅能由数字、大小写字母、下划线组成，且不能为数字开头。
