# 20210607 Programming Protocol-independent Packet Processors ( P4 ) - Finish

## 課堂資料

### Meter

{% embed url="<https://www.dropbox.com/sh/9qzkarvkwehgn9q/AAC69iOm_Jghjp51EJGcw1J4a/p4-utils-example/test-meter?dl=0&subfolder_nav_tracking=1>" %}

{% embed url="<http://csie.nqu.edu.tw/smallko/sdn/p4_meter.htm>" %}

### Recirculate

{% embed url="<https://www.dropbox.com/sh/9qzkarvkwehgn9q/AABiTv3bxnMcoBdPwmCP1OQ6a/p4-utils-example/test-recirculate?dl=0&subfolder_nav_tracking=1>" %}

### Multipath

{% embed url="<https://www.dropbox.com/sh/9qzkarvkwehgn9q/AADTXZ-EnYFPp1LLqeNNw6zFa/p4-utils-example/multipath?dl=0&subfolder_nav_tracking=1>" %}

## 課堂練習

### Meter

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbZx1xAecDiHmavviTm%2F-Mb_C8AMMVyPED_SSmcz%2Fimage.png?alt=media\&token=db662b98-4513-47a2-876b-6b74630b3b46)

{% tabs %}
{% tab title="Terminal 01" %}

```
cd p4-test/test-meter
```

```
gedit p4app.json ip_forward.p4 cmd.txt &
```

```
p4run
```

```
xterm h1 h2
```

{% endtab %}

{% tab title="gedit" %}
{% hint style="info" %}
**p4app.json**

```
{
  "program": "ip_forward.p4",
  "switch": "simple_switch",
  "compiler": "p4c",
  "options": "--target bmv2 --arch v1model --std p4-16",
  "switch_cli": "simple_switch_CLI",
  "cli": true,
  "pcap_dump": false,
  "enable_log": false,
  "topo_module": {
    "file_path": "",
    "module_name": "p4utils.mininetlib.apptopo",
    "object_name": "AppTopoStrategies"
  },
  "controller_module": null,
  "topodb_module": {
    "file_path": "",
    "module_name": "p4utils.utils.topology",
    "object_name": "Topology"
  },
  "mininet_module": {
    "file_path": "",
    "module_name": "p4utils.mininetlib.p4net",
    "object_name": "P4Mininet"
  },
  "topology": {
    "assignment_strategy": "manual",
    "auto_arp_tables": "true",
    "auto_gw_arp": "true",
    "links": [["h1", "s1"], ["h2", "s1"]],
    "hosts": {
      "h1": {
        "ip": "10.0.1.1/24",
        "gw": "10.0.1.254"
      },
      "h2": {
        "ip": "10.0.2.1/24",
       "gw": "10.0.2.254"
      }
    },
    "switches": {
      "s1": {
        "cli_input": "cmd.txt",
        "program": "ip_forward.p4"
      }
    }
  }
}
```

**ip\_forward.p4**

```
#include <core.p4>
#include <v1model.p4>
typedef bit<48> macAddr_t;
typedef bit<9> egressSpec_t;
  
header ethernet_t {
    bit<48> dstAddr;
    bit<48> 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;
    bit<32> srcAddr;
    bit<32> dstAddr;
}
 
struct metadata {
    bit<32> meter_tag;
}
 
struct headers {
    @name(".ethernet")
    ethernet_t ethernet;
    @name(".ipv4")
    ipv4_t     ipv4;
}
 
parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {

    @name(".parse_ethernet") state parse_ethernet {
        packet.extract(hdr.ethernet);
        transition select(hdr.ethernet.etherType) {
            16w0x800: parse_ipv4;
            default: accept;
        }
    }
    @name(".parse_ipv4") state parse_ipv4 {
        packet.extract(hdr.ipv4);
        transition accept;
    }
    @name(".start") state start {
        transition parse_ethernet;
    }
}
 
control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    apply {
    }
}
 
control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {

    meter(10, MeterType.packets) my_meter;

    action m_action(bit<32> meter_idx) {
        my_meter.execute_meter((bit<32>)meter_idx, meta.meter_tag);
    }      

    action set_tos(bit<8> tos) {
        hdr.ipv4.diffserv=tos;
    }      

    @name(".set_nhop") action set_nhop(macAddr_t dstAddr, egressSpec_t port) {
        //set the src mac address as the previous dst, this is not correct right?
        hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
 
        //set the destination mac address that we got from the match in the table
        hdr.ethernet.dstAddr = dstAddr;
 
        //set the output port that we also get from the table
        standard_metadata.egress_spec = port;
 
        //decrease ttl by 1
        hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
    }
    @name("._drop") action _drop() {
        mark_to_drop(standard_metadata);
    }
    @name(".ipv4_lpm") table ipv4_lpm {
        actions = {
            set_nhop;
            _drop;
        }
        key = {
            hdr.ipv4.dstAddr: lpm;
        }
        size = 512;
        const default_action = _drop();
    }

     table m_table {
        key = {
            hdr.ethernet.dstAddr: exact;
        }

        actions = {
            m_action;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }

    table m_filter {
        key = {
            meta.meter_tag: exact;
        }

        actions = {
            set_tos;
            _drop;
            NoAction;
        }
        size = 1024;
        default_action = _drop();
    }      
    apply {
        ipv4_lpm.apply();
        m_table.apply();
        m_filter.apply();
    }
}
 
control DeparserImpl(packet_out packet, in headers hdr) {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
    }
}
 
control verifyChecksum(inout headers hdr, inout metadata meta) {
    apply {
        verify_checksum(true, { 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);
    }
}
 
control computeChecksum(inout headers hdr, inout metadata meta) {
    apply {
        update_checksum(true, { 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);
    }
}
 
V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main;
```

**cmd.txt**

```
table_add ipv4_lpm set_nhop 10.0.1.1/32 => 00:00:0a:00:01:01 1
table_add ipv4_lpm set_nhop 10.0.2.1/32 => 00:00:0a:00:02:01 2
table_add m_table m_action 00:00:0a:00:02:01 => 2
table_add m_filter NoAction 0 =>
meter_set_rates my_meter 2 0.0001:1 0.0005:1
```

{% endhint %}
{% endtab %}

{% tab title="h2" %}

```
iperf -s -i 1 -u
```

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbmkL3sqbHBIX3wZJa3%2F-MbmmJiN56HY5mCibPIO%2Fimage.png?alt=media\&token=d8e71b6b-6f4a-4f99-ae3f-66729e97319d)
{% endtab %}

{% tab title="h1" %}

```
iperf -c 10.0.2.1 -u -b 10M -l 1000 -t 100
```

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbmkL3sqbHBIX3wZJa3%2F-MbmmqJOhULu1QbrDjnY%2Fimage.png?alt=media\&token=a4704353-e841-4d15-bf70-de91033c39fd)
{% endtab %}
{% endtabs %}

### Recirculate

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbZx1xAecDiHmavviTm%2F-Mb_NskHCbUWYV2ym0NC%2Fimage.png?alt=media\&token=0635b9ce-88df-4b37-8e64-e3acbd7d7d33)

{% tabs %}
{% tab title="Terminal 01" %}

```
cd p4-test/test-recirculate
```

```
gedit p4app.json ip_forward.p4 cmd.txt &
```

```
p4run
```

```
xterm h1 h2
```

{% endtab %}

{% tab title="gedit" %}
{% hint style="info" %}
**p4app.json**

```
{
  "program": "ip_forward.p4",
  "switch": "simple_switch",
  "compiler": "p4c",
  "options": "--target bmv2 --arch v1model --std p4-16",
  "switch_cli": "simple_switch_CLI",
  "cli": true,
  "pcap_dump": true,
  "enable_log": true,
  "topo_module": {
    "file_path": "",
    "module_name": "p4utils.mininetlib.apptopo",
    "object_name": "AppTopoStrategies"
  },
  "controller_module": null,
  "topodb_module": {
    "file_path": "",
    "module_name": "p4utils.utils.topology",
    "object_name": "Topology"
  },
  "mininet_module": {
    "file_path": "",
    "module_name": "p4utils.mininetlib.p4net",
    "object_name": "P4Mininet"
  },
  "topology": {
    "assignment_strategy": "manual",
    "auto_arp_tables": "true",
    "auto_gw_arp": "true",
    "links": [["h1", "s1"], ["h2", "s1"]],
    "hosts": {
      "h1": {
        "ip": "10.0.1.1/24",
        "gw": "10.0.1.254"
      },
      "h2": {
        "ip": "10.0.2.1/24",
       "gw": "10.0.2.254"
      }
    },
    "switches": {
      "s1": {
        "cli_input": "cmd.txt",
        "program": "ip_forward.p4"
      }
    }
  }
}
```

**ip\_forward.p4**

```
#include <core.p4>
#include <v1model.p4>
typedef bit<48> macAddr_t;
typedef bit<9> egressSpec_t;
  
header ethernet_t {
    bit<48> dstAddr;
    bit<48> 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;
    bit<32> srcAddr;
    bit<32> dstAddr;
}
 
struct metadata {
}
 
struct headers {
    @name(".ethernet")
    ethernet_t ethernet;
    @name(".ipv4")
    ipv4_t     ipv4;
}
 
parser ParserImpl(packet_in packet, out headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {

    @name(".parse_ethernet") state parse_ethernet {
        packet.extract(hdr.ethernet);
        transition select(hdr.ethernet.etherType) {
            16w0x800: parse_ipv4;
            default: accept;
        }
    }
    @name(".parse_ipv4") state parse_ipv4 {
        packet.extract(hdr.ipv4);
        transition accept;
    }
    @name(".start") state start {
        transition parse_ethernet;
    }
}
 
control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    action set_mytos() {
        hdr.ipv4.diffserv=hdr.ipv4.diffserv-1;
        recirculate<headers>(hdr);
    }              

    table set_tos {
        key = {
            hdr.ipv4.diffserv: range;
        }

        actions = {
            set_mytos;
            NoAction;
        }

        size = 1024;
        default_action = NoAction();

        const entries = {
        1..10 : set_mytos();
        _ : NoAction();
        }
    }

    apply {
      set_tos.apply();
    }
}
 
control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    @name(".set_nhop") action set_nhop(macAddr_t dstAddr, egressSpec_t port) {
        //set the src mac address as the previous dst, this is not correct right?
        hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
 
        //set the destination mac address that we got from the match in the table
        hdr.ethernet.dstAddr = dstAddr;
 
        //set the output port that we also get from the table
        standard_metadata.egress_spec = port;
 
        //decrease ttl by 1
        hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
    }
    @name("._drop") action _drop() {
        mark_to_drop(standard_metadata);
    }
    @name(".ipv4_lpm") table ipv4_lpm {
        actions = {
            set_nhop;
            _drop;
        }
        key = {
            hdr.ipv4.dstAddr: lpm;
        }
        size = 512;
        const default_action = _drop();
    }
    apply {
        ipv4_lpm.apply();
    }
}
 
control DeparserImpl(packet_out packet, in headers hdr) {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
    }
}
 
control verifyChecksum(inout headers hdr, inout metadata meta) {
    apply {
        verify_checksum(true, { 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);
    }
}
 
control computeChecksum(inout headers hdr, inout metadata meta) {
    apply {
        update_checksum(true, { 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);
    }
}
 
V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main;
```

**cmd.txt**

```
table_add ipv4_lpm set_nhop 10.0.1.1/32 => 00:00:0a:00:01:01 1
table_add ipv4_lpm set_nhop 10.0.2.1/32 => 00:00:0a:00:02:01 2
```

{% endhint %}
{% endtab %}

{% tab title="h2" %}

```
wireshark
```

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbmobKrqEVcIIHF0eIC%2F-MbmpZedS_uV8vMCpU9T%2Fimage.png?alt=media\&token=a3524e0c-4f92-4b13-b7ac-52f47ac2b0b4)
{% endtab %}

{% tab title="h1" %}

```
ping 10.0.2.1 -c 5 -Q 12
```

* `-Q`：設定封包的`tos`欄位

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbmobKrqEVcIIHF0eIC%2F-Mbmp--9CuL2Tk9wGGUO%2Fimage.png?alt=media\&token=35f6a99d-00ba-4b32-9900-28177f4b36c9)
{% endtab %}
{% endtabs %}

### Multipath

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbZx1xAecDiHmavviTm%2F-Mb_ZYoP9qfmyFpdUU-c%2Fimage.png?alt=media\&token=b5d317f5-2dd0-499f-98c0-1cda6b3f560d)

{% tabs %}
{% tab title="Terminal 01" %}

```
cd p4-test/multipath
```

```
gedit p4app.json ip_forward.p4 s1-singlepath.txt s2.txt s3.txt s1-multipath.txt &
```

```
p4run
```

```
xterm h1 h2
```

{% endtab %}

{% tab title="gedit" %}
{% hint style="info" %}
**p4app.json**

```
{
  "program": "ip_forward.p4",
  "switch": "simple_switch",
  "compiler": "p4c",
  "options": "--target bmv2 --arch v1model --std p4-16",
  "switch_cli": "simple_switch_CLI",
  "cli": true,
  "pcap_dump": false,
  "enable_log": false,
  "topo_module": {
    "file_path": "",
    "module_name": "p4utils.mininetlib.apptopo",
    "object_name": "AppTopoStrategies"
  },
  "controller_module": null,
  "topodb_module": {
    "file_path": "",
    "module_name": "p4utils.utils.topology",
    "object_name": "Topology"
  },
  "mininet_module": {
    "file_path": "",
    "module_name": "p4utils.mininetlib.p4net",
    "object_name": "P4Mininet"
  },
  "topology": {
    "assignment_strategy": "manual",
    "auto_arp_tables": "true",
    "auto_gw_arp": "true",
    "links": [["h1", "s1"], ["h2", "s2"], ["s1", "s2", {"bw":0.5}], ["s1", "s3", {"bw":0.5}], ["s3", "s2", {"bw":0.5}]],
    "hosts": {
      "h1": {
        "ip": "10.0.1.1/24",
        "gw": "10.0.1.254"
      },
      "h2": {
        "ip": "10.0.2.1/24",
       "gw": "10.0.2.254"
      }
    },
    "switches": {
      "s1": {
        "cli_input": "s1-multipath.txt",
        "program": "ip_forward.p4"
      },
      "s2": {
        "cli_input": "s2.txt",
        "program": "ip_forward.p4"
      },	
      "s3": {
        "cli_input": "s3.txt",
        "program": "ip_forward.p4"
      }
    }
  }
}
```

**ip\_forward.p4**

```
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>
 
const bit<16> TYPE_IPV4 = 0x800;
 
/*************************************************************************
*********************** 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 {
    macAddr_t dstAddr;
    egressSpec_t port;
    bit<8>  lower;
    bit<8>  upper;      
    bit<8>  result;
    bit<1>  final;
}
 
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 {
        meta.result=127;
        meta.final=0;
        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   *******************
*************************************************************************/
 
control MyIngress(inout headers hdr,
                  inout metadata meta,
                  inout standard_metadata_t standard_metadata) {
    action drop() {
        mark_to_drop(standard_metadata);
    }
   
    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 = NoAction();
    }
 
    action myforward(){
        standard_metadata.egress_spec = meta.port;
        hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
        hdr.ethernet.dstAddr = meta.dstAddr;
        hdr.ipv4.ttl = hdr.ipv4.ttl - 1; 
        meta.final=1;
    }      
 
    action set_param1(bit<8> lower, bit<8> upper, macAddr_t dstAddr, egressSpec_t port) {
        random(meta.result, (bit<8>)0,(bit<8>)100);
        meta.lower=lower;
        meta.upper=upper;
        meta.dstAddr=dstAddr;
        meta.port=port;
    }
 
    action set_param2(bit<8> lower, bit<8> upper, macAddr_t dstAddr, egressSpec_t port) {
        meta.lower=lower;
        meta.upper=upper;
        meta.dstAddr=dstAddr;
        meta.port=port;
    }
 
    table ipv4_lpm2 {
        key = {
            hdr.ipv4.dstAddr: lpm;
            meta.final: exact;
        }
        actions = {
            set_param1;
            drop;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }
 
    table ipv4_lpm3 {
        key = {
            hdr.ipv4.dstAddr: lpm;
            meta.final: exact;
        }
        actions = {
            set_param2;
            drop;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }
   
    apply {
        if (hdr.ipv4.isValid()) {
            ipv4_lpm2.apply();
            if (meta.result >= meta.lower && meta.result <= meta.upper){
                myforward();
            }
           
            if (meta.final==0){
                ipv4_lpm3.apply();
                if (meta.result >= meta.lower && meta.result <= meta.upper){
                  myforward();
                }
            }
        }
       
        if (hdr.ipv4.isValid() && meta.result==127) {
            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   **************
*************************************************************************/
 
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;
```

**s1-singlepath.txt**

```
table_set_default ipv4_lpm drop
table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:0a:00:01:01 1
table_add ipv4_lpm ipv4_forward 10.0.2.1/32 => 00:00:00:02:00:00 2
```

**s2.txt**

```
table_set_default ipv4_lpm drop
table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:01:00:00 2
table_add ipv4_lpm ipv4_forward 10.0.2.1/32 => 00:00:0a:00:02:01 1
```

**s3.txt**

```
table_set_default ipv4_lpm drop
table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:01:00:00 1
table_add ipv4_lpm ipv4_forward 10.0.2.1/32 => 00:00:00:02:00:00 2
```

**s1-multipath.txt**

```
table_set_default ipv4_lpm drop
table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:00:01:01 1
table_add ipv4_lpm2 set_param1 10.0.2.1/32 0 => 0   49 00:00:00:02:00:00 2
table_add ipv4_lpm3 set_param2 10.0.2.1/32 0 => 50 100 00:00:00:03:00:00 3
```

{% endhint %}
{% endtab %}

{% tab title="h2" %}

```
iperf -s -i 1 -u
```

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-Mbmqx30gTnFKJDQK-V8%2F-Mbmsh9UoeuUraonDLSA%2Fimage.png?alt=media\&token=903bf828-3576-4781-9fe9-46965c630422)
{% endtab %}

{% tab title="h1" %}

```
perf -c 10.0.2.1 -u -b 10M
```

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-Mbmqx30gTnFKJDQK-V8%2F-Mbmsyu3lHofU42mVphX%2Fimage.png?alt=media\&token=8a1beef8-503a-408e-8b44-c2bdc00f0dac)
{% endtab %}
{% endtabs %}

## 課堂作業

![](https://1624492921-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MU7EdDCmxVnXY6VZf4s%2F-MbZx1xAecDiHmavviTm%2F-Mb_I_ih66jUpeAxzKJl%2Fimage.png?alt=media\&token=6e595df4-6c3d-474c-a56c-eb2d86ca8ec6)

{% tabs %}
{% tab title="Terminal 01" %}

{% endtab %}

{% tab title="gedit" %}

{% endtab %}

{% tab title="Terminal 02" %}

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://anida-huang.gitbook.io/notes-network-simulation-and-analysis/qi-mo/20210531-dijkstras-algorith.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
