P4学习笔记(一)初始P4

P4学习笔记(二)一个简单P4交换机实现

文章目录

  • 1、 架构模型
  • 2、预定义模块详细描述
    • 2.1 Arbiter 模块
    • 2.2 Parser runtime 模块
    • 2.3 Demux 模块
  • 3、代码声明文件
  • 4、代码实现文件

本节主要讲诉利用P4实现一个最简单的交换机。首先会讲一下交换机的架构,然后给出具体的P4代码实现。

1、 架构模型

简单P4交换机(VSS:very simple switch)它只是一个教学示例,说明了可编程交换机如何利用P4实现和代码编写。VSS具有许多固定功能块(在我们的示例中以浅蓝色显示),具体功能在下一小节描述。 白色块为P4代码实现模块(parse、match-action pipeline、 deparse)。

VSS通过8个输入以太网端口之一,通过再循环通道或从直接连接到CPU的端口接收数据包。 VSS有一个单一的Parser,解析后输出到match-action pipline,pipline处理后输出到Deparse模块,经过Deparser后,数据包通过8个输出以太网端口之一或3个“特殊”端口之一发出:

  • 发送到“ CPU端口”的数据包将发送到控制平面
  • 发送到“丢弃端口”的数据包将被丢弃
  • 发送到“再循环端口”的数据包通过特殊的输入端口重新注入到交换机中

图中的白色块是可编程的,用户必须提供相应的P4程序来指定每个此类块的行为。红色箭头指示用户定义的数据流。浅蓝色块是固定功能组件。绿色箭头是数据平面接口,用于在固定功能块和可编程块之间传递信息,这些功能在P4程序中作为内部元数据(译者注:类似于全局变量的概念)。

2、预定义模块详细描述

P4仅能实现部分模块功能,部分功能还是需要预定义模块来实现。

2.1 Arbiter 模块

  • 从物理输入以太网端口之一,控制平面或输入再循环端口接收数据包。
  • 对于从以太网端口接收的数据包,该模块计算以太网尾部校验和并进行验证。 如果校验和不匹配,则丢弃数据包。 如果校验和确实匹配,它已从数据包payload中删除。
  • 如果有多个数据包,则接收数据包涉及运行仲裁算法。(译者注:没有太明白啥意思)
  • 如果Arbiter 模块正在忙于处理先前的数据包,并且没有队列空间可用,则输入端口可能会丢弃到达的数据包,且不会提示。
  • 接收到数据包后,Arbiter 块将inCtrl、inputPort值设置为match-action pipline输入,该值是数据包起源的输入端口的标识。 物理以太网端口的编号为0到7,而输入再循环端口的编号为13,CPU端口的编号为14。

2.2 Parser runtime 模块

Parser runtime模块与Parser协同工作。 它基于Parser的结果match-action pipline提供错误代码,并且向demux 模块提供关于数据包payload的信息(例如,剩余payload数据的大小)。 parser完成数据包的处理后,将使用关联的元数据作为输入(数据包头和用户定义的元数据)调用match-action pipline。

2.3 Demux 模块

Demux模块的核心功能是从deparser接收输出数据包的包头,从parser接收数据包的payload,将它们组合成新的数据包,然后将结果发送到正确的输出端口。 输出端口由outCtrl.ouputPort的值指定,该值由match-action pipline设置。

  • 丢弃报文:将数据包发送到丢弃端口会让数据包消失。
  • 转发报文:将数据包发送到编号在0到7之间的输出以太网端口会导致它在相应的物理接口上发出。 如果输出接口已经在忙于发出另一个数据包,则可以将该数据包放入队列中。 发出数据包时,物理接口会计算正确的以太网校验和尾部并将其附加到数据包中。
  • 上升到CPU:将数据包发送到输出CPU端口会使数据包传输到控制平面。 在这种情况下,发送到CPU的数据包是原始输入数据包,而不是从Parser接收的数据包,从deparser接受后的包会被丢弃。
  • 循环处理包:将数据包发送到输出再循环端口会使它出现在输入再循环端口。 当无法单次完成数据包处理时,循环很有用。
  • 非法包: 如果outputPort的值非法(例如9),则数据包将被丢弃。
  • 业务繁忙丢包:如果Demux 模块正忙于处理先前的数据包,并且没有能力将来自deparser的数据包排队,则解复用器可能会丢弃该数据包,而与指示的输出端口无关

3、代码声明文件

(译者注:文中的语法是基于P4_16的)下面一段代码是VSS的定义文件,定义了VSS所要用到的结构体以及函数声明。

// File "very_simple_switch_model.p4"
// Very Simple Switch P4 declaration
// core library needed for packet_in and packet_out definitions
# include <core.p4>/* Various constants and structure declarations */
/* ports are represented using 4-bit values */
typedef bit<4> PortId;/* only 8 ports are "real" */
const PortId REAL_PORT_COUNT = 4w8; // 4w8 is the number 8 in 4 bits/* metadata accompanying an input packet */
struct InControl {PortId inputPort;
}/* special input port values */
const PortId RECIRCULATE_IN_PORT = 0xD;
const PortId CPU_IN_PORT = 0xE;/* metadata that must be computed for outgoing packets */
struct OutControl {PortId outputPort;
}/* special output port values for outgoing packet */
const PortId DROP_PORT = 0xF;
const PortId CPU_OUT_PORT = 0xE;
const PortId RECIRCULATE_OUT_PORT = 0xD;/* Prototypes for all programmable blocks */
/**
* Programmable parser.
* @param <H> type of headers; defined by user
* @param b input packet
* @param parsedHeaders headers constructed by parser
*/
parser Parser<H>(packet_in b,out H parsedHeaders);/**
* Match-action pipeline
* @param <H> type of input and output headers
* @param headers headers received from the parser and sent to the deparser
* @param parseError error that may have surfaced during parsing
* @param inCtrl information from architecture, accompanying input packet
* @param outCtrl information for architecture, accompanying output packet
*/
control Pipe<H>(inout H headers,in error parseError,// parser errorin InControl inCtrl,// input portout OutControl outCtrl); // output port/**
* VSS deparser.
* @param <H> type of headers; defined by user
* @param b output packet
* @param outputHeaders headers for output packet
*/
control Deparser<H>(inout H outputHeaders,packet_out b);/**
* Top-level package declaration - must be instantiated by user.
* The arguments to the package indicate blocks that
* must be instantiated by the user.
* @param <H> user-defined type of the headers processed.
*/
package VSS<H>(Parser<H> p,Pipe<H> map,Deparser<H> d);// Architecture-specific objects that can be instantiated
// Checksum unit
extern Checksum16 {Checksum16(); // constructorvoid clear(); // prepare unit for computationvoid update<T>(in T data); // add data to checksumvoid remove<T>(in T data); // remove data from existing checksumbit<16> get(); // get the checksum for the data added since last clear
}
  • 引入的 core.p4 是P4语言的内置库,定义了标准数据类型和错误类型

  • bit<4> 是具有4位的位字符串的类型。

  • 语法4w0xF表示使用4位表示值15。 另一种表示法是4w15。在许多情况下,可以省略width修饰符,只写15。

  • error是用于保存错误代码的内置P4类型

  • Parser 声明

    parser Parser<H>(packet_in b, out H parsedHeaders);
    

    该声明描述了解析器的接口,但尚未描述其实现,该接口将由程序员负责实现。 解析器从packet_in读取其输入,packet_in是在core.p4库中声明的P4 extern对象。 解析器将其输出(关键字out)写入parsedHeaders参数。 此参数的类型为H,但是具体类型不知道,需要程序员提供。

  • Match-Action pipeline 声明

    control Pipe<H>(inout H headers,in error parseError,// parser errorin InControl inCtrl,// input portout OutControl outCtrl); // output port
    

    该声明需要输入3个参数: 1、解析后的数据包头,2、解析器错误parseError 3、inCtrl控制数据。上图指出了这些信息的不同来源。 pipeline将其输出写入outCtrl,并且它必须在适当位置更新要由Deparser使用的包头。

  • Package 定义

    package VSS<H>
    

    类型变量H表示尚待用户稍后提供的类型,但未知。 在这种情况下,H是用户程序将要处理的包头的类型。 Parser将生成这些包头的解析表示,并且match-action管道将在适当位置更新输入包头以生成输出包头。

4、代码实现文件


上图展示了VSS交换机数据处理流程。下面用代码来实现上图中的逻辑。

// Include P4 core library
# include <core.p4>
// Include very simple switch architecture declarations
# include "very_simple_switch_model.p4"
// This program processes packets comprising an Ethernet and an IPv4
// header, and it forwards packets using the destination IP address
typedef bit<48> EthernetAddress;
typedef bit<32> IPv4Address;
// Standard Ethernet header
header Ethernet_h {EthernetAddress dstAddr;EthernetAddress srcAddr;bit<16> etherType;
}
// IPv4 header (without options)
header IPv4_h {bit<4> version;bit<4> ihl;bit<8> diffserv;bit<16> totalLen;bit<16> identification;bit<3> flags;bit<13> fragOffset;bit<8> ttl;bit<8> protocol;bit<16> hdrChecksum;IPv4Address srcAddr;IPv4Address dstAddr;
}
// Structure of parsed headers
struct Parsed_packet {Ethernet_h ethernet;IPv4_h ip;
}
// Parser section
// User-defined errors that may be signaled during parsing
error {IPv4OptionsNotSupported,IPv4IncorrectVersion,IPv4ChecksumError
}
parser TopParser(packet_in b, out Parsed_packet p) {Checksum16() ck; // instantiate checksum unitstate start {b.extract(p.ethernet);transition select(p.ethernet.etherType) {0x0800: parse_ipv4;// no default rule: all other packets rejected}}state parse_ipv4 {b.extract(p.ip);verify(p.ip.version == 4w4, error.IPv4IncorrectVersion);verify(p.ip.ihl == 4w5, error.IPv4OptionsNotSupported);ck.clear();ck.update(p.ip);// Verify that packet checksum is zeroverify(ck.get() == 16w0, error.IPv4ChecksumError);transition accept;}
}// Match-action pipeline section
control TopPipe(inout Parsed_packet headers,in error parseError, // parser errorin InControl inCtrl, // input portout OutControl outCtrl) {IPv4Address nextHop; // local variable/*** Indicates that a packet is dropped by setting the* output port to the DROP_PORT*/action Drop_action() {outCtrl.outputPort = DROP_PORT;}/*** Set the next hop and the output port.* Decrements ipv4 ttl field.* @param ivp4_dest ipv4 address of next hop* @param port output port*/action Set_nhop(IPv4Address ipv4_dest, PortId port) {nextHop = ipv4_dest;headers.ip.ttl = headers.ip.ttl - 1;outCtrl.outputPort = port;}/*** Computes address of next IPv4 hop and output port* based on the IPv4 destination of the current packet.* Decrements packet IPv4 TTL.* @param nextHop IPv4 address of next hop*/table ipv4_match {key = { headers.ip.dstAddr: lpm; } // longest-prefix matchactions = {Drop_action;Set_nhop;}size = 1024;default_action = Drop_action;}/*** Send the packet to the CPU port*/action Send_to_cpu() {outCtrl.outputPort = CPU_OUT_PORT;}/*** Check packet TTL and send to CPU if expired.*/table check_ttl {key = { headers.ip.ttl: exact; }actions = { Send_to_cpu; NoAction; }const default_action = NoAction; // defined in core.p4}/*** Set the destination MAC address of the packet* @param dmac destination MAC address.*/action Set_dmac(EthernetAddress dmac) {headers.ethernet.dstAddr = dmac;}/*** Set the destination Ethernet address of the packet* based on the next hop IP address.* @param nextHop IPv4 address of next hop.*/table dmac {key = { nextHop: exact; }actions = {Drop_action;Set_dmac;}size = 1024;default_action = Drop_action;}/*** Set the source MAC address.* @param smac: source MAC address to use*/action Set_smac(EthernetAddress smac) {headers.ethernet.srcAddr = smac;}/*** Set the source mac address based on the output port.*/table smac {key = { outCtrl.outputPort: exact; }actions = {Drop_action;Set_smac;}size = 16;default_action = Drop_action;}apply {if (parseError != error.NoError) {Drop_action(); // invoke drop directlyreturn;}ipv4_match.apply(); // Match result will go into nextHopif (outCtrl.outputPort == DROP_PORT) return;check_ttl.apply();if (outCtrl.outputPort == CPU_OUT_PORT) return;dmac.apply();if (outCtrl.outputPort == DROP_PORT) return;smac.apply();}
}// deparser section
control TopDeparser(inout Parsed_packet p, packet_out b) {Checksum16() ck;apply {b.emit(p.ethernet);if (p.ip.isValid()) {ck.clear(); // prepare checksum unitp.ip.hdrChecksum = 16w0; // clear checksumck.update(p.ip); // compute new checksum.p.ip.hdrChecksum = ck.get();}b.emit(p.ip);}
}// Instantiate the top-level VSS package
VSS(TopParser(),TopPipe(),TopDeparser()) main;

P4学习笔记(二)一个简单P4交换机实现相关推荐

  1. P4学习笔记(三)P4编程语言简介

    文章目录 P4学习笔记(三)P4编程语言简介 基本数据类型 Typedef 声明和初始化变量 元数据 参考资料 P4学习笔记(三)P4编程语言简介 上图展示了P4语言主要结构,下面简单讲解一下P4的基 ...

  2. Flutter学习笔记 —— 完成一个简单的新闻展示页

    Flutter学习笔记 -- 完成一个简单的新闻展示页 前言 思路分析 案例代码 结束语 上图 前言 刚学Flutter不久,今天我们来看看如何使用 Container & ListView实 ...

  3. golang游戏开发学习笔记-开发一个简单的2D游戏(基础篇)

    此文写在golang游戏开发学习笔记-创建一个能自由探索的3D世界之后,感兴趣可以先去那篇文章了解一些基础知识,在这篇文章里我们要创建一个简单的2D游戏场景以及配套的人物,并实现人物运动和碰撞检测功能 ...

  4. P4 学习笔记(1)-- P4程序的构成、基本组件

    首部(Headers) 解析器(Parsers) 表(Tables) 动作(Action) 流控制程序(Controller) 我们在所有的P4程序中(.p4文件),都可以发现其拥有5个基本组件: 首 ...

  5. 设计模式学习笔记二:简单工厂模式

    含义: 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创 ...

  6. 学习笔记:latex.一个简单的个人实验报告模板及部分语法说明

    首先建立一个  my_report.cls  的配置文件.(以后可能会随着使用进行一些修改和补充) \ProvidesClass{my_report}%------------------------ ...

  7. Windows程序设计学习笔记(1):一个简单的windows程序

    <Windows程序设计>(第五版)(美Charles Petzold著) 1 #include<windows.h> 2 3 LRESULT CALLBACK WndProc ...

  8. uni-app学习笔记-实现一个简单统计图(三)

    根据原型需要,先来写一个统计图,其实和vue实现一个统计图的方法是一样的.axios请求Echarts折线图 https://www.jianshu.com/p/9f872bee0e6a 1:在HBu ...

  9. OpenCascade学习笔记-创建一个简单的OpenCascade单文档

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Open ...

最新文章

  1. 关于nginx/lighttpd epoll高并发以及apache为何不采用epoll的的疑惑 不指定
  2. 转:springboot servlet使用配置
  3. smart gesture安装失败_WinCC flexible SMART V3 SP2安装步骤以及常见错误解决方法
  4. 数据结构之最小生成树
  5. php ip2long mysql,PHP基于ip2long实现IP转换整形
  6. pytorch实战案例-手写数字分类-卷积模型——深度AI科普团队
  7. linux 防arp 带宽,linux下防arp
  8. 通用权限管理平台--数据模型定义
  9. java中什么是继承,和继承的接口的关系?
  10. JavaMaven【三、常用指令】
  11. php中用microtime()函数来测试代码运行时间
  12. mysql 主从延迟及对应解决方案
  13. SAP FICO 第三节 BDC和LTMC导入S4财务科目
  14. 我为什么放弃百词斩?
  15. Linux服务与管理-step1
  16. Springboot AOP接口防刷、防重复提交
  17. premiere如何把多个视频放在同一个视频画面
  18. MEMS光学器件— MEMS OXC(光交叉互连开关)
  19. element-plus的el-date-picker中value-format属性失效以及只选择到时分值
  20. 百度地图开发(3)实现本地两点间步行导航

热门文章

  1. python提取数据指定列_Python:提取特定列数据并将其存储到变量中
  2. 字面量、直接量、常量
  3. [I.MX6UL] U-Boot移植(六) 网络驱动修改 LAN8720A(对比原子和NXP官方测试板的网络芯片LAN8720A , KSZ8081 (也是飞凌)唯独复位引脚不同595芯片也涉及改动)
  4. 中兴电信光纤猫F450获取管理员密码方法
  5. 器件封装——SMA/SMB/SMC
  6. html6+树状下拉列表,layui+ztree 树状下拉框
  7. Allegro如何出Gerber文件
  8. jeesite实战(二)——jeesite工具生成基本的页面
  9. 中南大学计算机考研资料汇总
  10. 连接真机,Appium启动Session时报错:settings delete global hidden_api_policy‘‘ exited with code 255‘