Removed scrambler.
This commit is contained in:
@@ -9,7 +9,7 @@ programming, organized into four modules:
|
|||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
* [Basic Forwarding](./basic)
|
* [Basic Forwarding](./basic)
|
||||||
* [Scrambler](./scrambler)
|
* [Basic Tunneling](./basic_tunnel)
|
||||||
|
|
||||||
2. Monitoring and Debugging
|
2. Monitoring and Debugging
|
||||||
* [Explicit Congestion Notification](./ecn)
|
* [Explicit Congestion Notification](./ecn)
|
||||||
@@ -21,7 +21,6 @@ programming, organized into four modules:
|
|||||||
|
|
||||||
4. Dynamic Behavior
|
4. Dynamic Behavior
|
||||||
* [Load Balancing](./load_balance)
|
* [Load Balancing](./load_balance)
|
||||||
* [HULA](./hula)
|
|
||||||
|
|
||||||
## Obtaining required software
|
## Obtaining required software
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
include ../../utils/Makefile
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
# Implementing basic forwarding with scrambled addresses
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
In this exercise, you will extend your solution to the basic
|
|
||||||
forwarding exercise with a new twist: switches will invert the bits
|
|
||||||
representing Ethernet and IPv4 address. Hence, in our triangle
|
|
||||||
topology, the packets in the interior of the network will have
|
|
||||||
unintelligble addresses.
|
|
||||||
|
|
||||||
> **Spoiler alert:** There is a reference solution in the `solution`
|
|
||||||
> sub-directory. Feel free to compare your implementation to the
|
|
||||||
> reference.
|
|
||||||
|
|
||||||
## Step 1: Run the (incomplete) starter code
|
|
||||||
|
|
||||||
The directory with this README also contains a skeleton P4 program,
|
|
||||||
`scrambler.p4`, which initially drops all packets. Your job (in the
|
|
||||||
next step) will be to extend it to properly forward IPv4 packets.
|
|
||||||
|
|
||||||
Before that, let's compile the incomplete `scrambler.p4` and bring
|
|
||||||
up a switch in Mininet to test its behavior.
|
|
||||||
|
|
||||||
1. In your shell, run:
|
|
||||||
```bash
|
|
||||||
make
|
|
||||||
```
|
|
||||||
This will:
|
|
||||||
* compile `scrambler.p4`, and
|
|
||||||
* start a Mininet instance with three switches (`s1`, `s2`, `s3`) configured
|
|
||||||
in a triangle, each connected to one host (`h1`, `h2`, `h3`).
|
|
||||||
* The hosts are assigned IPs of `10.0.1.1`, `10.0.2.2`, etc.
|
|
||||||
|
|
||||||
2. You should now see a Mininet command prompt. Open two terminals
|
|
||||||
for `h1` and `h2`, respectively:
|
|
||||||
```bash
|
|
||||||
mininet> xterm h1 h2
|
|
||||||
```
|
|
||||||
3. Each host includes a small Python-based messaging client and
|
|
||||||
server. In `h2`'s xterm, start the server:
|
|
||||||
```bash
|
|
||||||
./receive.py
|
|
||||||
```
|
|
||||||
4. In `h1`'s xterm, send a message from the client:
|
|
||||||
```bash
|
|
||||||
./send.py 10.0.2.2 "P4 is cool"
|
|
||||||
```
|
|
||||||
The message will not be received.
|
|
||||||
5. Type `exit` to leave each xterm and the Mininet command line.
|
|
||||||
|
|
||||||
The message was not received because each switch is programmed with
|
|
||||||
`scrambler.p4`, which drops all packets on arrival. Your job is to
|
|
||||||
extend this file.
|
|
||||||
|
|
||||||
### A note about the control plane
|
|
||||||
|
|
||||||
P4 programs define a packet-processing pipeline, but the rules
|
|
||||||
governing packet processing are inserted into the pipeline by the
|
|
||||||
control plane. When a rule matches a packet, its action is invoked
|
|
||||||
with parameters supplied by the control plane as part of the rule.
|
|
||||||
|
|
||||||
In this exercise, the control plane logic has already been
|
|
||||||
implemented. As part of bringing up the Mininet instance, the
|
|
||||||
`make` script will install packet-processing rules in the tables of
|
|
||||||
each switch. These are defined in the `sX-commands.txt` files, where
|
|
||||||
`X` corresponds to the switch number.
|
|
||||||
|
|
||||||
**Important:** A P4 program also defines the interface between the
|
|
||||||
switch pipeline and control plane. The `sX-commands.txt` files
|
|
||||||
contain lists of commands for the BMv2 switch API. These commands
|
|
||||||
refer to specific tables, keys, and actions by name, and any changes
|
|
||||||
in the P4 program that add or rename tables, keys, or actions will
|
|
||||||
need to be reflected in these command files.
|
|
||||||
|
|
||||||
## Step 2: Extend the basic forwarding solution to flip bits
|
|
||||||
|
|
||||||
The `scrambler.p4` file contains a skeleton P4 program in which one of
|
|
||||||
the actions has a `TODO` comment. These should guide your
|
|
||||||
implementation---replace the `TODO` with logic implementing the
|
|
||||||
missing piece.
|
|
||||||
|
|
||||||
A complete `scrambler.p4` will add an action `flip()` that inverts the
|
|
||||||
bits in the Ethernet and IPv4 headers.
|
|
||||||
|
|
||||||
## Step 3: Run your solution
|
|
||||||
|
|
||||||
Follow the instructions from Step 1. This time, your message from
|
|
||||||
`h1` should be delivered to `h2`.
|
|
||||||
|
|
||||||
### Troubleshooting
|
|
||||||
|
|
||||||
There are several issues that might arise when developing your
|
|
||||||
solution:
|
|
||||||
|
|
||||||
1. `scrambler.p4` fails to compile. In this case, `make` will
|
|
||||||
report the error emitted from the compiler and stop.
|
|
||||||
|
|
||||||
2. `scrambler.p4` compiles but does not support the control plane
|
|
||||||
rules in the `sX-commands.txt` files that `make` tries to install
|
|
||||||
using the BMv2 CLI. In this case, `make` will report these errors
|
|
||||||
to `stderr`. Use these error messages to fix your `scrambler.p4`
|
|
||||||
implementation.
|
|
||||||
|
|
||||||
3. `scrambler.p4` compiles, and the control plane rules are installed,
|
|
||||||
but the switch does not process packets in the desired way. The
|
|
||||||
`build/logs/<switch-name>.log` files contain trace messages describing
|
|
||||||
how each switch processes each packet. The output is detailed and can
|
|
||||||
help pinpoint logic errors in your implementation.
|
|
||||||
|
|
||||||
#### Cleaning up Mininet
|
|
||||||
|
|
||||||
In the latter two cases above, `make` may leave a Mininet instance
|
|
||||||
running in the background. Use the following command to clean up
|
|
||||||
these instances:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mn -c
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
Congratulations, your implementation works! Move on to the next
|
|
||||||
exercise: implementing [Explicit Congestion Notification](../ecn).
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
import struct
|
|
||||||
import os
|
|
||||||
|
|
||||||
from scapy.all import sniff, sendp, hexdump, get_if_list, get_if_hwaddr
|
|
||||||
from scapy.all import Packet, IPOption
|
|
||||||
from scapy.all import ShortField, IntField, LongField, BitField, FieldListField, FieldLenField
|
|
||||||
from scapy.all import IP, UDP, Raw
|
|
||||||
from scapy.layers.inet import _IPOption_HDR
|
|
||||||
|
|
||||||
def get_if():
|
|
||||||
ifs=get_if_list()
|
|
||||||
iface=None
|
|
||||||
for i in get_if_list():
|
|
||||||
if "eth0" in i:
|
|
||||||
iface=i
|
|
||||||
break;
|
|
||||||
if not iface:
|
|
||||||
print "Cannot find eth0 interface"
|
|
||||||
exit(1)
|
|
||||||
return iface
|
|
||||||
|
|
||||||
class IPOption_MRI(IPOption):
|
|
||||||
name = "MRI"
|
|
||||||
option = 31
|
|
||||||
fields_desc = [ _IPOption_HDR,
|
|
||||||
FieldLenField("length", None, fmt="B",
|
|
||||||
length_of="swids",
|
|
||||||
adjust=lambda pkt,l:l+4),
|
|
||||||
ShortField("count", 0),
|
|
||||||
FieldListField("swids",
|
|
||||||
[],
|
|
||||||
IntField("", 0),
|
|
||||||
length_from=lambda pkt:pkt.count*4) ]
|
|
||||||
def handle_pkt(pkt):
|
|
||||||
print "got a packet"
|
|
||||||
pkt.show2()
|
|
||||||
# hexdump(pkt)
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
ifaces = filter(lambda i: 'eth' in i, os.listdir('/sys/class/net/'))
|
|
||||||
iface = ifaces[0]
|
|
||||||
print "sniffing on %s" % iface
|
|
||||||
sys.stdout.flush()
|
|
||||||
sniff(filter="tcp", iface = iface,
|
|
||||||
prn = lambda x: handle_pkt(x))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
table_set_default ipv4_lpm drop
|
|
||||||
table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:02:02:00 2
|
|
||||||
table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:03:02:00 3
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.254.254/32 => ff:ff:ff:ff:fe:fe 1
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.253.253/32 => 00:00:00:02:02:00 2
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.252.252/32 => 00:00:00:03:02:00 3
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
table_set_default ipv4_lpm drop
|
|
||||||
table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:01:02:00 2
|
|
||||||
table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:03:03:00 3
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.254.254/32 => 00:00:00:01:02:00 2
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.253.253/32 => ff:ff:ff:ff:fd:fd 1
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.252.252/32 => 00:00:00:03:03:00 3
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
table_set_default ipv4_lpm drop
|
|
||||||
table_add ipv4_lpm ipv4_forward 10.0.0.1/32 => 00:00:00:01:02:00 2
|
|
||||||
table_add ipv4_lpm ipv4_forward 10.0.0.2/32 => 00:00:00:02:03:00 3
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.254.254/32 => 00:00:00:01:01:00 2
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.253.253/32 => 00:00:00:02:03:00 3
|
|
||||||
table_add ipv4_lpm ipv4_forward 245.255.252.252/32 => ff:ff:ff:ff:fc:fc 1
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
/* -*- 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 {
|
|
||||||
/* 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 *******************
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
control MyIngress(inout headers hdr,
|
|
||||||
inout metadata meta,
|
|
||||||
inout standard_metadata_t standard_metadata) {
|
|
||||||
action drop() {
|
|
||||||
mark_to_drop();
|
|
||||||
}
|
|
||||||
|
|
||||||
action flip() {
|
|
||||||
/* TODO: add code to flip bits in Ethernet and IPv4 addresses. */
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
table ipv4_lpm {
|
|
||||||
key = {
|
|
||||||
hdr.ipv4.dstAddr: lpm;
|
|
||||||
}
|
|
||||||
actions = {
|
|
||||||
ipv4_forward;
|
|
||||||
drop;
|
|
||||||
NoAction;
|
|
||||||
}
|
|
||||||
size = 1024;
|
|
||||||
default_action = NoAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 **************
|
|
||||||
*************************************************************************/
|
|
||||||
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,41 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
import socket
|
|
||||||
import random
|
|
||||||
import struct
|
|
||||||
|
|
||||||
from scapy.all import sendp, send, get_if_list, get_if_hwaddr
|
|
||||||
from scapy.all import Packet
|
|
||||||
from scapy.all import Ether, IP, UDP, TCP
|
|
||||||
|
|
||||||
def get_if():
|
|
||||||
ifs=get_if_list()
|
|
||||||
iface=None # "h1-eth0"
|
|
||||||
for i in get_if_list():
|
|
||||||
if "eth0" in i:
|
|
||||||
iface=i
|
|
||||||
break;
|
|
||||||
if not iface:
|
|
||||||
print "Cannot find eth0 interface"
|
|
||||||
exit(1)
|
|
||||||
return iface
|
|
||||||
|
|
||||||
def main():
|
|
||||||
|
|
||||||
if len(sys.argv)<3:
|
|
||||||
print 'pass 2 arguments: <destination> "<message>"'
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
addr = socket.gethostbyname(sys.argv[1])
|
|
||||||
iface = get_if()
|
|
||||||
|
|
||||||
print "sending on interface %s to %s" % (iface, str(addr))
|
|
||||||
pkt = Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff')
|
|
||||||
pkt = pkt /IP(dst=addr) / TCP(dport=1234, sport=random.randint(49152,65535)) / sys.argv[2]
|
|
||||||
pkt.show2()
|
|
||||||
sendp(pkt, iface=iface, verbose=False)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
/* -*- 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 {
|
|
||||||
/* 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 *******************
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
control MyIngress(inout headers hdr,
|
|
||||||
inout metadata meta,
|
|
||||||
inout standard_metadata_t standard_metadata) {
|
|
||||||
action drop() {
|
|
||||||
mark_to_drop();
|
|
||||||
}
|
|
||||||
|
|
||||||
action flip_ethernet() {
|
|
||||||
hdr.ethernet.srcAddr = ~hdr.ethernet.srcAddr;
|
|
||||||
hdr.ethernet.dstAddr = ~hdr.ethernet.dstAddr;
|
|
||||||
}
|
|
||||||
action flip_ipv4() {
|
|
||||||
hdr.ipv4.srcAddr = ~hdr.ipv4.srcAddr;
|
|
||||||
hdr.ipv4.dstAddr = ~hdr.ipv4.dstAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
action flip() {
|
|
||||||
flip_ethernet();
|
|
||||||
flip_ipv4();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
table ipv4_lpm {
|
|
||||||
key = {
|
|
||||||
hdr.ipv4.dstAddr: lpm;
|
|
||||||
}
|
|
||||||
actions = {
|
|
||||||
ipv4_forward;
|
|
||||||
drop;
|
|
||||||
NoAction;
|
|
||||||
}
|
|
||||||
size = 1024;
|
|
||||||
default_action = NoAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 **************
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
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,16 +0,0 @@
|
|||||||
{
|
|
||||||
"hosts": [
|
|
||||||
"h1",
|
|
||||||
"h2",
|
|
||||||
"h3"
|
|
||||||
],
|
|
||||||
"switches": {
|
|
||||||
"s1": { "cli_input" : "s1-commands.txt" },
|
|
||||||
"s2": { "cli_input" : "s2-commands.txt" },
|
|
||||||
"s3": { "cli_input" : "s3-commands.txt" }
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
["h1", "s1"], ["s1", "s2"], ["s1", "s3"],
|
|
||||||
["s3", "s2"], ["s2", "h2"], ["s3", "h3"]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user