P4语言——basic

练习一:Basic

本练习的目的是编写一个P4程序 实现了基本的转发。 为了简单起见,我们只要实现IPv4转发。
对于IPv4转发,交换机必须完成以下操作

  1. 更新源MAC地址和目的MAC地址
  2. 减少IP报头中的生存时间(time-to-live, TTL)
  3. 将数据包发送到适当的端口

你的开关将有一个单表,控制平面将用静态规则填充。 每个规则将一个IP地址映射到下一跳的MAC地址和输出端口。 我们已经定义了控制平面的规则,所以只需要实现数据平面
P4程序的逻辑。

查看控制平面的代码

table_entries是一个设置交换机s的控制表
定义了很多tabel,其中有行为和对行为的匹配参数
这里定义了对于IPv4匹配的信息,发送给ipv4_forward端口和mac地址实现转发功能

{
  "target": "bmv2",
  "p4info": "build/basic.p4info",
  "bmv2_json": "build/basic.json",
  "table_entries": [
    {
      "table": "MyIngress.ipv4_lpm",
      "default_action": true,
      "action_name": "MyIngress.drop",
      "action_params": { }
    },
    {
      "table": "MyIngress.ipv4_lpm",
      "match": {
        "hdr.ipv4.dstAddr": ["10.0.1.1", 32]
      },
      "action_name": "MyIngress.ipv4_forward",
      "action_params": {
        "dstAddr": "00:00:00:00:01:01",
        "port": 1
      }
    },
    {
      "table": "MyIngress.ipv4_lpm",
      "match": {
        "hdr.ipv4.dstAddr": ["10.0.2.2", 32]
      },
      "action_name": "MyIngress.ipv4_forward",
      "action_params": {
        "dstAddr": "00:00:00:02:02:00",
        "port": 2
      }
    },
    {
      "table": "MyIngress.ipv4_lpm",
      "match": {
        "hdr.ipv4.dstAddr": ["10.0.3.3", 32]
      },
      "action_name": "MyIngress.ipv4_forward",
      "action_params": {
        "dstAddr": "00:00:00:03:03:00",
        "port": 3
      }
    }
  ]
}

查看拓扑图

有三个交换机和三个主机,设定了他们的json和连线

{
    "hosts": [
        "h1",
        "h2",
        "h3"
    ],
    "switches": {
        "s1": { "runtime_json" : "s1-runtime.json" },
        "s2": { "runtime_json" : "s2-runtime.json" },
        "s3": { "runtime_json" : "s3-runtime.json" }
    },
    "links": [
        ["h1", "s1"], ["s1", "s2"], ["s1", "s3"], 
        ["s3", "s2"], ["s2", "h2"], ["s3", "h3"]
    ]
}

数据平面代码

/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>

const bit<16> TYPE_IPV4 = 0x800;//设定ipv4的标志位

/*************************************************************************
*********************** H E A D E R S  ***********************************
*************************************************************************/

typedef bit<9>  egressSpec_t;//设置变量的位数
typedef bit<48> macAddr_t;
typedef bit<32> ip4Addr_t;

header ethernet_t {
    macAddr_t dstAddr;
    macAddr_t srcAddr;
    bit<16>   etherType;
}

header ipv4_t {
    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;
    ip4Addr_t srcAddr;
    ip4Addr_t dstAddr;
}
//数据结构体
struct metadata {
    /* empty */
}
//头部结构体
struct headers {
    ethernet_t   ethernet;
    ipv4_t       ipv4;
}

/*************************************************************************
*********************** P A R S E R  ***********************************
*************************************************************************/
//入口解析器
parser MyParser(packet_in packet,
                out headers hdr,
                inout metadata meta,
                inout standard_metadata_t standard_metadata) {

    state start {
        transition parse_ethernet;//状态转化
    }

    state parse_ethernet {
        packet.extract(hdr.ethernet);//每次要解析一层协议
        transition select(hdr.ethernet.etherType) {
            TYPE_IPV4: parse_ipv4;
            default: accept;
        }
    }

    state parse_ipv4 {
        packet.extract(hdr.ipv4);
        transition accept;
    }

}

/*************************************************************************
************   C H E C K S U M    V E R I F I C A T I O N   *************
*************************************************************************/

control MyVerifyChecksum(inout headers hdr, inout metadata meta) {   
    apply {  }
}


/*************************************************************************
**************  I N G R E S S   P R O C E S S I N G   *******************
*************************************************************************/
//根据解析的内容触发action
control MyIngress(inout headers hdr,
                  inout metadata meta,
                  inout standard_metadata_t standard_metadata) {
    action drop() {
        mark_to_drop();
    }
    
    action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {
        standard_metadata.egress_spec = port;
        hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
        hdr.ethernet.dstAddr = dstAddr;
        hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
    }
    
    table ipv4_lpm {
        key = {
            hdr.ipv4.dstAddr: lpm;//完全匹配
        }
        actions = {
            ipv4_forward;
            drop;
            NoAction;
        }
        size = 1024;
        default_action = drop();
    }
    
    apply {
        if (hdr.ipv4.isValid()) {
            ipv4_lpm.apply();
        }
    }
}

/*************************************************************************
****************  E G R E S S   P R O C E S S I N G   *******************
*************************************************************************/

control MyEgress(inout headers hdr,
                 inout metadata meta,
                 inout standard_metadata_t standard_metadata) {
    apply {  }
}

/*************************************************************************
*************   C H E C K S U M    C O M P U T A T I O N   **************
*************************************************************************/
//重新计算checksum
control MyComputeChecksum(inout headers  hdr, inout metadata meta) {
     apply {
	update_checksum(
	    hdr.ipv4.isValid(),
            { hdr.ipv4.version,
	      hdr.ipv4.ihl,
              hdr.ipv4.diffserv,
              hdr.ipv4.totalLen,
              hdr.ipv4.identification,
              hdr.ipv4.flags,
              hdr.ipv4.fragOffset,
              hdr.ipv4.ttl,
              hdr.ipv4.protocol,
              hdr.ipv4.srcAddr,
              hdr.ipv4.dstAddr },
            hdr.ipv4.hdrChecksum,
            HashAlgorithm.csum16);
    }
}

/*************************************************************************
***********************  D E P A R S E R  *******************************
*************************************************************************/
//将数据重新打包发送
control MyDeparser(packet_out packet, in headers hdr) {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
    }
}

/*************************************************************************
***********************  S W I T C H  *******************************
*************************************************************************/

V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
P4语言是一种网络编程语言,用于定义和配置网络设备中的数据平面行为。P4(Programmable Protocol-Independent Packet Processing)允许网络管理员定义网络设备如何处理和操作数据包。 首先,P4语言帮助网络管理员定制网络设备的数据平面行为。传统的硬件交换机和路由器通常使用特定的固件或硬件布局来处理数据包,而P4语言提供了一种编程方式,使网络管理员可以自定义数据包的处理过程。通过P4,管理员可以编写自己的数据包解析、分类和操作逻辑,从而更好地适应不同的网络环境和需求。 其次,P4语言可以简化网络设备的开发和部署过程。由于P4语言提供了高度灵活的编程接口,管理员可以针对具体应用场景和需求设计和优化数据平面行为,而无需重新设计或更新硬件设备。这种可编程性使得网络设备的配置和部署变得更加灵活和高效,提高了网络的可扩展性。 此外,P4语言还为网络中的可编程数据平面开启了创新的空间。网络管理员和研究人员可以通过使用P4语言设计和实现自己的网络协议和网络功能,从而为网络带来更多的功能和优化。P4的灵活性使得网络可以根据需求定制和部署各种功能,例如网络安全、负载均衡、QoS等。 总之,P4语言是一种用于定义和配置网络设备中的数据平面行为的编程语言。它使网络管理员能够灵活定制和配置网络设备,简化设备的开发和部署过程,并为网络的创新和优化提供了更多的可能性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值