Commit a5d03da0 authored by cedgar's avatar cedgar
Browse files

Exercise week 5

parent ad7e1043
This diff is collapsed.
{
"program": "p4src/ecmp.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": 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": "mixed",
"links": [["h1", "s1"], ["h2", "s6"], ["s1", "s2"], ["s1", "s3"], ["s1", "s4"], ["s1", "s5"], ["s2", "s6"], ["s3", "s6"], ["s4", "s6"], ["s5", "s6"]],
"hosts": {
"h1": {
},
"h2": {
}
},
"switches": {
"s1": {
},
"s2": {
},
"s3": {
},
"s4": {
},
"s5": {
},
"s6": {
}
}
}
}
{
"program": "p4src/ecmp.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": 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": "mixed",
"links": [["h1", "s1"], ["h2", "s6"], ["s1", "s2"], ["s1", "s3"], ["s1", "s4"], ["s1", "s5"], ["s2", "s6"], ["s3", "s6"], ["s4", "s6"], ["s5", "s6"]],
"hosts": {
"h1": {
},
"h2": {
}
},
"switches": {
"s1": {
"cli_input": "sX-commands/s1-commands.txt"
},
"s2": {
"cli_input": "sX-commands/s2-commands.txt"
},
"s3": {
"cli_input": "sX-commands/s3-commands.txt"
},
"s4": {
"cli_input": "sX-commands/s4-commands.txt"
},
"s5": {
"cli_input": "sX-commands/s5-commands.txt"
},
"s6": {
"cli_input": "sX-commands/s6-commands.txt"
}
}
}
}
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>
//My includes
#include "include/headers.p4"
#include "include/parsers.p4"
/*************************************************************************
************ 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 ecmp_group(bit<14> ecmp_group_id, bit<16> num_nhops){
//Task 1, TODO 6: define the ecmp_group action, here you need to hash the 5-tuple mod num_ports and safe it in metadata
}
action set_nhop(macAddr_t dstAddr, egressSpec_t port) {
//Task 1, ODO 5: Define the set_nhop action. You can copy it from the previous exercise, they are the same.
}
table ecmp_group_to_nhop {
//Task 1, TODO 7: define the ecmp table, this table is only called when multiple hops are available
}
table ipv4_lpm {
//Task 1, TODO 4: define the ip forwarding table
}
apply {
//Task 1, TODO 8: implement the ingress logic: check validities, apply first table, and if needed the second table.
}
}
/*************************************************************************
**************** 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.dscp,
hdr.ipv4.ecn,
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);
}
}
/*************************************************************************
*********************** S W I T C H *******************************
*************************************************************************/
//switch architecture
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
\ No newline at end of file
/*************************************************************************
*********************** H E A D E R S ***********************************
*************************************************************************/
const bit<16> TYPE_IPV4 = 0x800;
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<6> dscp;
bit<2> ecn;
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;
}
header tcp_t{
bit<16> srcPort;
bit<16> dstPort;
bit<32> seqNo;
bit<32> ackNo;
bit<4> dataOffset;
bit<4> res;
bit<1> cwr;
bit<1> ece;
bit<1> urg;
bit<1> ack;
bit<1> psh;
bit<1> rst;
bit<1> syn;
bit<1> fin;
bit<16> window;
bit<16> checksum;
bit<16> urgentPtr;
}
struct headers {
ethernet_t ethernet;
ipv4_t ipv4;
tcp_t tcp;
}
struct metadata {
//Task 1, TODO 6.1: define the metadata needed to store the ecmp_group_id and the hash output
}
/*************************************************************************
*********************** 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 {
//Task 1, TODO 2: Define a parser for ethernet, ipv4 and tcp
}
}
/*************************************************************************
*********************** D E P A R S E R *******************************
*************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) {
apply {
//Task 1, TODO 3: Deparse the ethernet, ipv4 and tcp headers
}
}
\ No newline at end of file
from p4utils.utils.topology import Topology
from p4utils.utils.sswitch_API import SimpleSwitchAPI
class RoutingController(object):
def __init__(self):
"""Initializes controller
"""
self.topo = Topology(db="topology.db")
self.controllers = {}
self.init()
def init(self):
"""Calls init functions
"""
self.connect_to_switches()
self.reset_states()
self.set_table_defaults()
def reset_states(self):
"""Reset tables and stateful objects
"""
[controller.reset_state() for controller in self.controllers.values()]
def connect_to_switches(self):
"""Connects to all p4 switchs and saves controllers in self.controllers
"""
for p4switch in self.topo.get_p4switches():
thrift_port = self.topo.get_thrift_port(p4switch)
self.controllers[p4switch] = SimpleSwitchAPI(thrift_port)
def set_table_defaults(self):
"""Set table defaults to drop
"""
for controller in self.controllers.values():
controller.table_set_default("ipv4_lpm", "drop", [])
controller.table_set_default("ecmp_group_to_nhop", "drop", [])
def route(self):
"""Populates ECMP routing tables
"""
# Task 2, TODO: Implement route function
def main(self):
self.route()
if __name__ == "__main__":
controller = RoutingController().main()
table_set_default ipv4_lpm drop
table_set_default ecmp_group_to_nhop drop
table_add ipv4_lpm set_nhop 10.0.1.1/32 => 00:00:0a:00:01:01 1
table_add ipv4_lpm ecmp_group 10.0.6.2/32 => 1 4
//ecmp id:1 port indexes 0,1,2,3 -> ports 2,3,4,5
table_add ecmp_group_to_nhop set_nhop 1 0 => 00:00:00:02:01:00 2
table_add ecmp_group_to_nhop set_nhop 1 1 => 00:00:00:03:01:00 3
table_add ecmp_group_to_nhop set_nhop 1 2 => 00:00:00:04:01:00 4
table_add ecmp_group_to_nhop set_nhop 1 3 => 00:00:00:05:01:00 5
\ No newline at end of file
table_set_default ipv4_lpm drop
table_set_default ecmp_group_to_nhop drop
table_add ipv4_lpm set_nhop 10.0.1.1/32 => 00:00:00:01:02:00 1
table_add ipv4_lpm set_nhop 10.0.6.2/32 => 00:00:00:06:02:00 2
table_set_default ipv4_lpm drop
table_set_default ecmp_group_to_nhop drop
table_add ipv4_lpm set_nhop 10.0.1.1/32 => 00:00:00:01:03:00 1
table_add ipv4_lpm set_nhop 10.0.6.2/32 => 00:00:00:06:03:00 2
\ No newline at end of file
table_set_default ipv4_lpm drop
table_set_default ecmp_group_to_nhop drop
table_add ipv4_lpm set_nhop 10.0.1.1/32 => 00:00:00:01:04:00 1
table_add ipv4_lpm set_nhop 10.0.6.2/32 => 00:00:00:06:04:00 2
\ No newline at end of file
table_set_default ipv4_lpm drop
table_set_default ecmp_group_to_nhop drop
table_add ipv4_lpm set_nhop 10.0.1.1/32 => 00:00:00:01:05:00 1
table_add ipv4_lpm set_nhop 10.0.6.2/32 => 00:00:00:06:05:00 2
\ No newline at end of file
table_set_default ipv4_lpm drop
table_set_default ecmp_group_to_nhop drop
table_add ipv4_lpm set_nhop 10.0.6.2/32 => 00:00:0a:00:06:02 1
table_add ipv4_lpm ecmp_group 10.0.1.0/24 => 1 4
//ecmp id:1 port indexes 0,1,2,3 -> ports 2,3,4,5
table_add ecmp_group_to_nhop set_nhop 1 0 => 00:00:00:02:06:00 2
table_add ecmp_group_to_nhop set_nhop 1 1 => 00:00:00:03:06:00 3
table_add ecmp_group_to_nhop set_nhop 1 2 => 00:00:00:04:06:00 4
table_add ecmp_group_to_nhop set_nhop 1 3 => 00:00:00:05:06:00 5
#!/usr/bin/env python
import argparse
import sys
import socket
import random
import struct
from scapy.all import sendp, get_if_list, get_if_hwaddr
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> <number_of_random_packets>'
exit(1)
addr = socket.gethostbyname(sys.argv[1])
iface = get_if()
print "sending on interface %s to %s" % (iface, str(addr))
for _ in range(int(sys.argv[2])):
pkt = Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff')
pkt = pkt /IP(dst=addr) / TCP(dport=random.randint(5000,60000), sport=random.randint(49152,65535))
sendp(pkt, iface=iface, verbose=False)
if __name__ == '__main__':
main()
import json
import argparse
import networkx
topo_base = {
"program": "p4src/ecmp.p4",
"switch": "simple_switch",
"compiler": "p4c",
"options": "--target bmv2 --arch v1model --std p4-16",
"switch_cli": "simple_switch_CLI",
"exec_scripts": [],
"cli": True,
"pcap_dump": True,
"enable_log": True,
"topo_module": {
"file_path": "",
"module_name": "p4utils.mininetlib.apptopo",
"object_name": "AppTopoStrategies"
},
"controller_module": None,
"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": "l3"
}
}
def create_linear_topo(num_switches):
topo_base["topology"]["links"] = []
#connect hosts with switches
for i in range(1, num_switches+1):
topo_base["topology"]["links"].append(["h{}".format(i), "s{0}".format(i)])
#connect switches
for i in range(1, num_switches):
topo_base["topology"]["links"].append(["s{}".format(i), "s{}".format(i + 1)])
topo_base["topology"]["hosts"] = {"h{0}".format(i): {} for i in range(1, num_switches + 1)}
topo_base["topology"]["switches"] = {"s{0}".format(i): {} for i in range(1, num_switches + 1)}
def create_circular_topo(num_switches):
create_linear_topo(num_switches)
#add link between s1 and sN
topo_base["topology"]["links"].append(["s{}".format(1), "s{}".format(num_switches)])
def create_random_topo(degree=4, num_switches=10):
topo_base["topology"]["links"] = []
g = networkx.random_regular_graph(degree, num_switches)
trials = 0
while not networkx.is_connected(g):
g = networkx.random_regular_graph(degree, num_switches)
trials +=1
if trials >= 10:
print "Could not Create a connected graph"
return
# connect hosts with switches
for i in range(1, num_switches + 1):
topo_base["topology"]["links"].append(["h{}".format(i), "s{0}".format(i)])
for edge in g.edges:
topo_base["topology"]["links"].append(["s{}".format(edge[0]+1), "s{}".format(edge[1] + 1)])
topo_base["topology"]["hosts"] = {"h{0}".format(i): {} for i in range(1, num_switches + 1)}
topo_base["topology"]["switches"] = {"s{0}".format(i): {} for i in range(1, num_switches + 1)}
def main():
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--output_name', type=str, required=False, default="p4app_test.json")
parser.add_argument("--topo", type=str, default="linear")
parser.add_argument('-n', type=str, required=False, default=2)
parser.add_argument('-d', type=str, required=False, default=4)
args = parser.parse_args()
if args.topo == "linear":
create_linear_topo(int(args.n))
elif args.topo == "circular":
create_circular_topo(int(args.n))
elif args.topo == "random":
create_random_topo(int(args.d), int(args.n))
json.dump(topo_base, open(args.output_name, "w"), sort_keys=True, indent=2)
\ No newline at end of file
{
"program": "p4src/flowlet_switching.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": 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": "mixed",
"links": [["h1", "s1"], ["h2", "s6"], ["s1", "s2"], ["s1", "s3"], ["s1", "s4"], ["s1", "s5"], ["s2", "s6"], ["s3", "s6"], ["s4", "s6"], ["s5", "s6"]],
"hosts": {
"h1": {
},
"h2": {
}
},
"switches": {
"s1": {
},
"s2": {
},
"s3": {
},
"s4": {
},
"s5": {
},
"s6": {
}
}
}
}
{
"program": "p4src/flowlet_switching.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": true,
"topo_module": {
"file_path": "",
"module_name": "p4utils.mininetlib.apptopo",
"object_name": "AppTopoStrategies"
},