/************************************************************************* *********************** H E A D E R S *********************************** *************************************************************************/
/************************************************************************* *********************** P A R S E R *********************************** *************************************************************************/
/************************************************************************* *********************** P A R S E R *********************************** *************************************************************************/
parser MyParser(packet_in packet, out headers hdr, #out相当于输出的数据,然后它的type是headers inout metadata meta, #inout同时作为输入和输出值,类似 c++ 里面的引用 inout standard_metadata_t standard_metadata) {
state start { transition parse_ethernet;#转移到解析以太包头阶段 } state parse_ethernet{ packet.extract(hdr.ethernet); #把packet提取到hdr的ethernet里面,这里的过程可以理解为根据ethernet的长度截取一段数据 transition select(hdr.ethernet.etherType){#根据etherType的值选择进入的状态 TYPE_IPV4: parse_ipv4;#是IPV4包,进入解析ipv4的状态 default: accept; } } state parse_ipv4{ packet.extract(hdr.ipv4); #接着解析ipv4部分,这里可以理解为指针又往前移动了 transition accept; } }
/************************************************************************* ************ C H E C K S U M V E R I F I C A T I O N ************* *************************************************************************/
/************************************************************************* ************** I N G R E S S P R O C E S S I N G ******************* *************************************************************************/
control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { action drop() { mark_to_drop(standard_metadata);#内置函数,将当前数据包标记为即将丢弃的数据包,standard_metadata的解释见PS部分 } action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) { /* TODO: fill out code in action body */ } table ipv4_lpm { key = { hdr.ipv4.dstAddr: lpm; } actions = { ipv4_forward; drop; NoAction; } size = 1024; default_action = NoAction(); } apply { /* TODO: fix ingress control logic * - ipv4_lpm should be applied only when IPv4 header is valid */ ipv4_lpm.apply(); } }
/************************************************************************* ************** I N G R E S S P R O C E S S I N G ******************* *************************************************************************/
ingress_port (sm14, v1m) - For new packets, the number of the ingress port on which the packet arrived to the device. Read only. packet_length (sm14, v1m) - For new packets from a port, or recirculated packets, the length of the packet in bytes. For cloned or resubmitted packets, you may need to include this in a list of fields to preserve, otherwise its value will become 0. egress_spec (sm14, v1m) - Can be assigned a value in ingress code to control which output port a packet will go to. The P4_14 primitive drop, and the v1model primitive action mark_to_drop, have the side effect of assigning an implementation specific value DROP_PORT to this field (511 decimal for simple_switch by default, but can be changed through the --drop-port target-specific command-line option), such that if egress_spec has that value at the end of ingress processing, the packet will be dropped and not stored in the packet buffer, nor sent to egress processing. See the "after-ingress pseudocode" for relative priority of this vs. other possible packet operations at end of ingress. If your P4 program assigns a value of DROP_PORT to egress_spec, it will still behave according to the "after-ingress pseudocode", even if you never call mark_to_drop (P4_16) or drop (P4_14). egress_port (sm14, v1m) - Only intended to be accessed during egress processing, read only. The output port this packet is destined to. egress_instance (sm14) - Renamed egress_rid in simple_switch. See egress_rid below. instance_type (sm14, v1m) - Contains a value that can be read by your P4 code. In ingress code, the value can be used to distinguish whether the packet is newly arrived from a port (NORMAL), it was the result of a resubmit primitive action (RESUBMIT), or it was the result of a recirculate primitive action (RECIRC). In egress processing, can be used to determine whether the packet was produced as the result of an ingress-to-egress clone primitive action (INGRESS_CLONE), egress-to-egress clone primitive action (EGRESS_CLONE), multicast replication specified during ingress processing (REPLICATION), or none of those, so a normal unicast packet from ingress (NORMAL). Until such time as similar constants are pre-defined for you, you may copy this list of constants into your code. parser_status (sm14) or parser_error (v1m) - parser_status is the name in the P4_14 language specification. It has been renamed to parser_error in v1model. The value 0 (sm14) or error.NoError (P4_16 + v1model) means no error. Otherwise, the value indicates what error occurred during parsing. parser_error_location (sm14) - Not present in v1model.p4, and not implemented in simple_switch. checksum_error (v1m) - Read only. 1 if a call to the verify_checksum primitive action finds a checksum error, otherwise 0. Calls to verify_checksum should be in the VerifyChecksum control in v1model, which is executed after the parser and before ingress.
Egress部分
1 2 3 4 5 6 7 8 9
/************************************************************************* **************** E G R E S S P R O C E S S I N G ******************* *************************************************************************/
/************************************************************************* ************* C H E C K S U M C O M P U T A T I O N ************** *************************************************************************/
/************************************************************************* *********************** D E P A R S E R ******************************* *************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) { apply { /* TODO: add deparser logic */ } }
解答:
1 2 3 4 5 6 7 8 9 10
/************************************************************************* *********************** D E P A R S E R ******************************* *************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) { apply { packet.emit(hdr.ethernet);#按照顺序封装,emit的含义是发射 packet.emit(hdr.ipv4); } }
实例化部分
1 2 3 4 5 6 7 8 9 10 11 12 13
/************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/