---
title: 数据面开发样例
description: "1. 了解数据面开发组成。详情可参见OVS场景数据面Hydra编程说明。"
url: https://www.hikunpeng.com/document/detail/zh/flexda/devguide/dpak_dev0061.html
sourcePath: /source/zh/flexda/devguide/dpak_dev0061.html
indexId: 64dea0d0e71a005bf8270e1cbbd0a67f5bfcc79adac6235daeb302396819c92944
---
# 数据面开发样例

1. 了解数据面开发组成。详情可参见OVS场景数据面Hydra编程说明。
2. 在自定义代码工程下创建OVS数据面开发目录，以ovs_project为例。

```
ovs_project/
├── CMakeLists.txt                       # 顶层CMake配置文件
└── src_dsl                              # 用户数据面源代码子目录
├── CMakeLists.txt                   # 数据面的子目录CMake配置文件
└── ovs_project.hdr                  # 数据面Hydra源文件
```


3. 分析业务需要处理的网络数据包协议类型，实现packet parser。
  例如当前业务处理的网络报文类型为标准的VXLAN、TCP、UDP、ICMP报文，通过表1可知，属于硬件解析器支持的范围，可以不实现用户自定义parser或混合parser，直接使用hdr_fix_parser作为解析器。

4. 根据网络数据包处理流程，实现MainPipe。

```
control MainPipe(in hdr_fix_headers hdr) {
@main
table ovs_exact {
key = { ... }
actions = { ... }
size = 0x200000;
default_action = flexda_upcall;
aging_time = 200;
}
apply {
}
}
```


  a. 根据业务网络数据包类型，确定需要卸载的key和对应的action。
    对照表1确定是否需要自定义key，对照表1确定是否需要实现自定义action，完成table定义。

    示例代码如下所示。

```
rte_port_id_hdr_t input_port;
rte_eth_hdr_t eth;
rte_vxlan_hdr_t vxlan_vni;
rte_vlan_hdr_t vlan;
ip_union l3_union;
port_icmp_union l4_union;
@main @rss_fastpath
table ovs_exact {
key = {
l3_union : exact;
l4_union : exact;
input_port : exact;
eth : exact;
vxlan_vni : exact;
vlan : exact;
}
actions = {
rte_port_id;
rte_of_pop_vlan;
rte_of_push_vlan;
rte_of_set_vlan_vid;
rte_of_set_vlan_pcp;
rte_vxlan_decap;
rte_vxlan_encap;
rte_set_ipv4_src;
rte_set_ipv4_dst;
rte_set_ipv6_src;
rte_set_ipv6_dst;
rte_set_tp_src;
rte_set_tp_dst;
rte_set_mac_dst;
rte_set_mac_src;
}
size = 0x200000;
default_action = flexda_upcall;
aging_time = 200;
}
```


    前后辅表key还支持模糊匹配。使用模糊匹配时，需要将key的匹配方式修改为ternary。

```
@pre
table ovs_pre_ternary {
key = {
l3_union : ternary;
l4_union : exact;
}
actions = {}
size = 0x200;
default_action = flexda_no_action;
aging_time = 200;
}
```


    同样的，在postpipe中还可以定义模糊后辅表

```
@post
table ovs_post_ternary {
key = {
l3_union : exact;
l4_union : ternary;
}
actions = {}
size = 0x200;
default_action = flexda_no_action;
aging_time = 200;
}
```


  b. 根据key的定义，实现apply逻辑。
    示例代码如下所示。

```
apply {
input_port.port_id = hdr_input_port_id_get();
if (hdr.tunnel.vxlan.isValid() && (input_port.port_id >> 12) == VPORT_TYPE_BOND) {
if (hdr.inner_ethernet.isValid()) {
eth.dst = hdr.inner_ethernet.dmac;
eth.src = hdr.inner_ethernet.smac;
eth.eth_type = hdr.inner_ethernet.eth_type;
}
if (hdr.inner_vlan.isValid()) {
eth.eth_type = hdr.inner_vlan.eth_type;
vlan.vlan_tci = (bit<16>)hdr.inner_vlan.vid;
}
if (hdr.inner_l3.ipv4.isValid() || hdr.inner_l3.ipv6.isValid()) {
if (hdr.inner_l3.ipv4.isValid()) {
l3_union.dpdk_ipv4.setValid();
l3_union.dpdk_ipv4.protocol = hdr.inner_l3.ipv4.protocol;
l3_union.dpdk_ipv4.sip = hdr.inner_l3.ipv4.sip;
l3_union.dpdk_ipv4.dip = hdr.inner_l3.ipv4.dip;
} else if (hdr.inner_l3.ipv6.isValid()) {
l3_union.dpdk_ipv6.setValid();
l3_union.dpdk_ipv6.next_header = hdr.inner_l3.ipv6.next_header;
l3_union.dpdk_ipv6.sip = hdr.inner_l3.ipv6.sip;
l3_union.dpdk_ipv6.dip = hdr.inner_l3.ipv6.dip;
}
if (hdr.inner_l4.udp.isValid()) {
l4_union.dpdk_udp.setValid();
l4_union.dpdk_udp.src_port = hdr.inner_l4.udp.src_port;
l4_union.dpdk_udp.dst_port = hdr.inner_l4.udp.dst_port;
} else if (hdr.inner_l4.tcp.isValid()) {
l4_union.dpdk_tcp.setValid();
l4_union.dpdk_tcp.src_port = hdr.inner_l4.tcp.src_port;
l4_union.dpdk_tcp.dst_port = hdr.inner_l4.tcp.dst_port;
} else if (hdr.inner_l4.icmp.isValid()) {
if (hdr.inner_l3.ipv4.isValid()) {
l4_union.dpdk_icmp.setValid();
l4_union.dpdk_icmp.type = hdr.inner_l4.icmp.type;
l4_union.dpdk_icmp.code = hdr.inner_l4.icmp.code;
l4_union.dpdk_icmp.ident = hdr.inner_l4.icmp.identifier;
} else if (hdr.inner_l3.ipv6.isValid()) {
l4_union.dpdk_icmp6.setValid();
l4_union.dpdk_icmp6.type = hdr.inner_l4.icmp.type;
l4_union.dpdk_icmp6.code = hdr.inner_l4.icmp.code;
}
}
vxlan_vni.vni = hdr.tunnel.vxlan.vni;
}
ovs_exact.apply();
}
else {
if (hdr.ethernet.isValid()) {
eth.dst = hdr.ethernet.dmac;
eth.src = hdr.ethernet.smac;
eth.eth_type = hdr.ethernet.eth_type;
}
if (hdr.vlan.isValid()) {
eth.eth_type = hdr.vlan.eth_type;
vlan.vlan_tci = (bit<16>)hdr.vlan.vid;
}
if (hdr.l3.ipv4.isValid() || hdr.l3.ipv6.isValid()) {
if (hdr.l3.ipv4.isValid()) {
l3_union.dpdk_ipv4.setValid();
l3_union.dpdk_ipv4.protocol = hdr.l3.ipv4.protocol;
l3_union.dpdk_ipv4.sip = hdr.l3.ipv4.sip;
l3_union.dpdk_ipv4.dip = hdr.l3.ipv4.dip;
} else if (hdr.l3.ipv6.isValid()) {
l3_union.dpdk_ipv6.setValid();
l3_union.dpdk_ipv6.next_header = hdr.l3.ipv6.next_header;
l3_union.dpdk_ipv6.sip = hdr.l3.ipv6.sip;
l3_union.dpdk_ipv6.dip = hdr.l3.ipv6.dip;
}
if (hdr.l4.udp.isValid()) {
l4_union.dpdk_udp.setValid();
l4_union.dpdk_udp.src_port = hdr.l4.udp.src_port;
l4_union.dpdk_udp.dst_port = hdr.l4.udp.dst_port;
} else if (hdr.l4.tcp.isValid()) {
l4_union.dpdk_tcp.setValid();
l4_union.dpdk_tcp.src_port = hdr.l4.tcp.src_port;
l4_union.dpdk_tcp.dst_port = hdr.l4.tcp.dst_port;
} else if (hdr.l4.icmp.isValid()) {
if (hdr.l3.ipv4.isValid()) {
l4_union.dpdk_icmp.setValid();
l4_union.dpdk_icmp.type = hdr.l4.icmp.type;
l4_union.dpdk_icmp.code = hdr.l4.icmp.code;
l4_union.dpdk_icmp.ident = hdr.l4.icmp.identifier;
} else if (hdr.l3.ipv6.isValid()) {
l4_union.dpdk_icmp6.setValid();
l4_union.dpdk_icmp6.type = hdr.l4.icmp.type;
l4_union.dpdk_icmp6.code = hdr.l4.icmp.code;
}
}
}
vxlan_vni.vni = 0;
ovs_exact.apply();
}
}
```


5. 根据网络数据包处理流程，实现PostPipe，可以无实际处理逻辑。
  示例代码如下所示。

```
control PostPipe(in hdr_fix_headers hdr) {
apply {}
}
```


6. 组装parser和control等组件。
  示例代码如下所示。

```
Switch(
TX_OVS(hdr_fix_parser(),MainPipe(),PostPipe()),
RX_OVS(hdr_fix_parser(),MainPipe(),PostPipe())
) main;
```
