... | @@ -138,13 +138,13 @@ is hashed using the `algo` algorithm and stored in the `checksum` field of your |
... | @@ -138,13 +138,13 @@ is hashed using the `algo` algorithm and stored in the `checksum` field of your |
|
|
|
|
|
- `void update_checksum_with_payload<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo)`: same than `update_checksum` but includes the packet payload after `data`.
|
|
- `void update_checksum_with_payload<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo)`: same than `update_checksum` but includes the packet payload after `data`.
|
|
|
|
|
|
- `void resubmit<T>(in T data)`: resubmits the original packet to the parser. It can be applied only at the ingress. At the end of the ingress the `original` packet (modifications will not be present) will be submitted again to the parser, however all the fields added in the `data` parameter will keep the value they had at the end of ingress from the `original` packet. If multiple resubmit actions get executed on one packet, only the field list from the last resubmit action is used, and only one packet is resubmitted.
|
|
- `void void resubmit_preserving_field_list(bit<8> index)`: resubmits the original packet to the parser. It can be applied only at the ingress. At the end of the ingress the `original` packet (modifications will not be present) will be submitted again to the parser, however the user metadata fields that are tagged with @field_list(index) will be sent to the parser together with the packet. If multiple resubmit actions get executed on one packet, only the field list from the last resubmit action is used, and only one packet is resubmitted.
|
|
|
|
|
|
- `void recirculate<T>(in T data)`: recirculates the modified packet to the ingress. It can be applied only at the egress. This function marks the packet to be recirculated after egress deparsing, meaning that all the changes made to the packet will be kept in the recirculated one. Similarly to resubmit, some metadata fields can be kept using the `data` parameter.
|
|
- `void recirculate_preserving_field_list(bit<8> index)`: recirculates the modified packet to the ingress. It can be applied only at the egress. This function marks the packet to be recirculated after egress deparsing, meaning that all the changes made to the packet will be kept in the recirculated one. Similarly to resubmit, some metadata fields can be kept using the `index` parameter. The user metadata fields that are tagged with @field_list(index) will besent to the parser together with the packet.
|
|
|
|
|
|
- `void clone(in CloneType type, in bit<32> session)`: this functions allows you to create packet clones. For more information see its specific section [below](#cloning-packets).
|
|
- `void clone(in CloneType type, in bit<32> session)`: this functions allows you to create packet clones. For more information see its specific section [below](#cloning-packets).
|
|
|
|
|
|
- `void clone3<T>(in CloneType type, in bit<32> session, in T data)`: same than `clone` but allows you to copy some metadata fields to the cloned packet.
|
|
- `void clone_preserving_field_list(in CloneType type, in bit<32> session, bit<8> index)`: same than `clone` but allows you to copy some metadata fields to the cloned packet. The mechanism to decide which fields are copied is the same than with recirculate and resubmit, you can indicate that by tagging fields with the right `index`. he user metadata fields that are tagged with @field_list(index) will besent to the parser together with the packet.
|
|
|
|
|
|
- `void truncate(in bit<32> length)`: function that allows you to truncate packets at the egress. The packet will only keep the amount of bytes you specify in the `length` parameter. It can be executed at the ingress or egress, however it will only have effect during deparsing.
|
|
- `void truncate(in bit<32> length)`: function that allows you to truncate packets at the egress. The packet will only keep the amount of bytes you specify in the `length` parameter. It can be executed at the ingress or egress, however it will only have effect during deparsing.
|
|
|
|
|
... | @@ -207,12 +207,12 @@ Finally, once you have programmed the replication engine and added multicast gro |
... | @@ -207,12 +207,12 @@ Finally, once you have programmed the replication engine and added multicast gro |
|
|
|
|
|
### Cloning Packets
|
|
### Cloning Packets
|
|
|
|
|
|
Cloning/mirroring packets is a very common switch feature. Cloning is used in order to create packet replicas and send them somewhere else. This can be used for monitoring, to send data to a control plane, etc.
|
|
Cloning/mirroring packets is a very common feature in programmable switches. Cloning is used to create packet replicas and send them somewhere else. This can be used for monitoring, to send data to a control plane, etc.
|
|
|
|
|
|
The *Simple Switch* provides two `extern` functions that can be used to clone packets:
|
|
The *Simple Switch* provides two `extern` functions that can be used to clone packets:
|
|
|
|
|
|
* `clone(in CloneType type, in bit<32> session)`
|
|
* `clone(in CloneType type, in bit<32> session)`
|
|
* `clone3<T>(in CloneType type, in bit<32> session, in T data)`
|
|
* `clone_preserving_field_list(in CloneType type, in bit<32> session, bit<8> index)`
|
|
|
|
|
|
1. The first parameter in both externs is the type, *Simple Switch* allows two types `CloneType.I2E`, and `CloneType.E2E`. The first type can be used to send a copy of the original packet to the egress pipeline, the later sends a copy of the egress packet to the buffer mechanism.
|
|
1. The first parameter in both externs is the type, *Simple Switch* allows two types `CloneType.I2E`, and `CloneType.E2E`. The first type can be used to send a copy of the original packet to the egress pipeline, the later sends a copy of the egress packet to the buffer mechanism.
|
|
|
|
|
... | @@ -222,8 +222,14 @@ The *Simple Switch* provides two `extern` functions that can be used to clone pa |
... | @@ -222,8 +222,14 @@ The *Simple Switch* provides two `extern` functions that can be used to clone pa |
|
mirroring_add <session> <output_port>
|
|
mirroring_add <session> <output_port>
|
|
```
|
|
```
|
|
|
|
|
|
3. When using `clone3` you can add as a third parameter a metadata `struct`. When a packet is cloned all its metadata fields are reset to the default value (usually `0`). When using `clone3` you can tell the switch to copy some metadata values so the cloned packet will be able to access them.
|
|
3. When using `clone_preserving_field_list` you get an extra parameter `bit<8> index`. This is needed because when a packet is cloned all its metadata fields are reset to the default value (usually `0`). The index can be used to notify the switch which metadata fields have to be perserved in the new cloned packet. To do that, the programmer can tag metadata fields with 1 or multiple indexes as shown below. For more information, refer to the comments in [v1model.p4](https://github.com/p4lang/p4c/blob/main/p4include/v1model.p4).
|
|
|
|
|
|
|
|
```
|
|
|
|
@field_list(1)
|
|
|
|
bit<32> x;
|
|
|
|
```
|
|
|
|
|
|
|
|
Note that the `@field_list` annotation is only supported for user-defined metadata fields. It is not supported for parsed packet header fields, nor for standard metadata fields. If you wish to preserve any of these other values, you should copy their values to user-defined metadata fields that have the `@field_list` annotation on them.
|
|
|
|
|
|
For example, lets say we want to send a copy of every packet to a controller that is listening at port number `7`, to do what we would:
|
|
For example, lets say we want to send a copy of every packet to a controller that is listening at port number `7`, to do what we would:
|
|
|
|
|
... | @@ -277,7 +283,7 @@ Receiving digested packets is not trivial, since the switch adds some control he |
... | @@ -277,7 +283,7 @@ Receiving digested packets is not trivial, since the switch adds some control he |
|
|
|
|
|
*Simple Switch* allows the use of multiple queues per output port. However, in order to use them you will need to do some small modifications.
|
|
*Simple Switch* allows the use of multiple queues per output port. However, in order to use them you will need to do some small modifications.
|
|
|
|
|
|
1. Uncomment `#define SSWITCH_PRIORITY_QUEUEING_ON` in the `bmv2/targets/simple_switch/simple_switch.h` file.
|
|
1. Run the `simple_switch` with `--priority-queues <num>`.
|
|
2. Add this two metadata fields to the `v1model.p4` file:
|
|
2. Add this two metadata fields to the `v1model.p4` file:
|
|
|
|
|
|
```
|
|
```
|
... | @@ -294,7 +300,7 @@ Receiving digested packets is not trivial, since the switch adds some control he |
... | @@ -294,7 +300,7 @@ Receiving digested packets is not trivial, since the switch adds some control he |
|
cp v1model.p4 /usr/local/share/p4c/p4include/
|
|
cp v1model.p4 /usr/local/share/p4c/p4include/
|
|
````
|
|
````
|
|
|
|
|
|
4. Recompile the BMv2, so that multiple queues are added.
|
|
You can find a working example in the `exercises/multiqueueing` in this repository.
|
|
|
|
|
|
By default you will have 8 strict priority queues, being 0 the highest priority and 7 the lowest. Packets in a higher priority queue will always be transmitted before than packets in a lower priority queue. To select the queue you want to use for your packets you need to set the `standard_metadata.priority` field to `0-7`. If needed you can individually configure the rate and the length of each queue. In order to do that you will have to modify the `simple_switch` code. If you want to do this ask and we can show you how to do it.
|
|
By default you will have 8 strict priority queues, being 0 the highest priority and 7 the lowest. Packets in a higher priority queue will always be transmitted before than packets in a lower priority queue. To select the queue you want to use for your packets you need to set the `standard_metadata.priority` field to `0-7`. If needed you can individually configure the rate and the length of each queue. In order to do that you will have to modify the `simple_switch` code. If you want to do this ask and we can show you how to do it.
|
|
|
|
|
... | @@ -308,9 +314,9 @@ In order to understand how things are executed you have to check the [`simple_sw |
... | @@ -308,9 +314,9 @@ In order to understand how things are executed you have to check the [`simple_sw |
|
|
|
|
|
In this section we will show what happens to packets after all the logic from the ingress control has been executed.
|
|
In this section we will show what happens to packets after all the logic from the ingress control has been executed.
|
|
|
|
|
|
1. If `clone` or `clone3` were called, the packet will be cloned to the `egress_port` you specified using the mirroring
|
|
1. If `clone` or `clone_preserving_field_list` were called, the packet will be cloned to the `egress_port` you specified using the mirroring
|
|
id (for more information see the [cloning section](#cloning-packets)). This copies the ingress packet to egress pipeline without
|
|
id (for more information see the [cloning section](#cloning-packets)). This copies the ingress packet to egress pipeline without
|
|
all the ingress control modifications. If `clone3` action is used, the packet will also preserve the metadata fields specified. Finally, it
|
|
all the ingress control modifications. If `clone_preserving_field_list` action is used, the packet will also preserve the metadata fields specified. Finally, it
|
|
will get the `standard_metadata.instance_type` modified to the corresponding value.
|
|
will get the `standard_metadata.instance_type` modified to the corresponding value.
|
|
|
|
|
|
2. If there was a call to `digest` the switch will send a control plane message with the specified fields to the controller.
|
|
2. If there was a call to `digest` the switch will send a control plane message with the specified fields to the controller.
|
... | @@ -328,7 +334,7 @@ the other can not happen. Furthermore, the order in which we show them here matt |
... | @@ -328,7 +334,7 @@ the other can not happen. Furthermore, the order in which we show them here matt |
|
|
|
|
|
In this section we will show what happens to packets after all the logic from the egress control has been executed.
|
|
In this section we will show what happens to packets after all the logic from the egress control has been executed.
|
|
|
|
|
|
1. If `clone` or `clone3` were called in the egress pipeline, the packet will be cloned to the `egress_port` you specified using the mirroring id (for more information see the [cloning section](#cloning-packets)). This will send a copy of the egress packet to the egress control block, with the egress metadata unless specified with `clone3`.
|
|
1. If `clone` or `clone_preserving_field_list` were called in the egress pipeline, the packet will be cloned to the `egress_port` you specified using the mirroring id (for more information see the [cloning section](#cloning-packets)). This will send a copy of the egress packet to the egress control block, with the egress metadata unless specified with `clone_preserving_field_list`.
|
|
|
|
|
|
2. Now we will show some actions that are mutually exclusive, thus if one occurs the other can not happen. Furthermore, the order in which we show them here matter. Only the first true condition is executed by the switch.
|
|
2. Now we will show some actions that are mutually exclusive, thus if one occurs the other can not happen. Furthermore, the order in which we show them here matter. Only the first true condition is executed by the switch.
|
|
|
|
|
... | | ... | |