170 lines
4.5 KiB
Plaintext
170 lines
4.5 KiB
Plaintext
/* -*- P4_16 -*- */
|
|
#include <core.p4>
|
|
#include <v1model.p4>
|
|
|
|
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<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;
|
|
}
|
|
|
|
parser MyParser(packet_in packet,
|
|
out headers hdr,
|
|
inout metadata meta,
|
|
inout standard_metadata_t standard_metadata) {
|
|
|
|
/* each IPv4 thing is wrapped in Ethernet headers so the state is parse_ether
|
|
by default */
|
|
|
|
state start {
|
|
transition parse_ether;
|
|
}
|
|
|
|
state parse_ether {
|
|
packet.extract(hdr.ethernet);
|
|
transition select(hdr.ethernet.etherType) {
|
|
TYPE_IPV4: parse_ipv4;
|
|
default: accept;
|
|
}
|
|
}
|
|
|
|
state parse_ipv4 {
|
|
packet.extract(hdr.ipv4);
|
|
transition accept;
|
|
}
|
|
}
|
|
|
|
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
|
|
apply { }
|
|
}
|
|
|
|
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) {
|
|
/* bu satiri aciklamaya calisirken switch'lerin portlarina bagli cihazlarin
|
|
MAC adreslerini nasil ogrendigini ve nasil sakladigini arastirdim. takip eden ipv4_lpm kismi bu muammanin yanitini verecek. */
|
|
/* disari yonlu paketin switch'in hangi portundan ayrilmasi gerektigi ayarlanir */
|
|
standard_metadata.egress_spec = port;
|
|
|
|
/* paketin kaynagi artik biziz, srcAddr header'dan dstAddr olarak ayarlanir */
|
|
hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
|
|
|
|
/* hedef adres, bir sonraki hop'un alicisi olarak ayarlanir */
|
|
hdr.ethernet.dstAddr = dstAddr;
|
|
|
|
hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
|
|
}
|
|
|
|
/* burasi cokomelli: LPM "Longest Prefix Match"in kisaltmasi
|
|
IP yonlendirmede kullanilan bir teknik. Verilen bir IP adres icin hangi
|
|
(cihaz MAC'i - port) demetinin kullanilacagini seciyor.
|
|
|
|
tablonun kendisi ise IP_prefix : (MAC, port) seklinde bir veri yapisi
|
|
cunku IP_prefix aslinda bir IP agini ifade ediyor (10.0.1.0/24 gibi)
|
|
|
|
biz de burada hedef IPv4 adresimizi LPM tablosundan esleyerek hangi
|
|
porttan cikacagimizi belirliyor ya da tabloda olmayan bir yol sayesinde
|
|
o paketi dropluyoruz (cunku bagli hicbir cihaz o yola sahip degil) */
|
|
table ipv4_lpm {
|
|
key = {
|
|
hdr.ipv4.dstAddr: lpm;
|
|
}
|
|
actions = {
|
|
ipv4_forward;
|
|
drop;
|
|
NoAction;
|
|
}
|
|
size = 1024;
|
|
default_action = NoAction();
|
|
}
|
|
|
|
apply {
|
|
/* buradaki basta sihirli gorunen isValid, P4 tarafindan tanimlanan ve
|
|
bir header'in duzgunce parse edilip pakette yer aldigini dogrulayan bir
|
|
fonksiyonmus. */
|
|
/* eger elimizdeki paket IPv4 paketi ise LPM tablosundaki kurallar
|
|
uygulanacak. */
|
|
if (hdr.ipv4.isValid()) {
|
|
ipv4_lpm.apply();
|
|
}
|
|
}
|
|
}
|
|
|
|
control MyEgress(inout headers hdr,
|
|
inout metadata meta,
|
|
inout standard_metadata_t standard_metadata) {
|
|
apply { }
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
control MyDeparser(packet_out packet, in headers hdr) {
|
|
/* paketi aldigimiz gibi birakiyoruz :) */
|
|
apply {
|
|
packet.emit(hdr.ethernet);
|
|
packet.emit(hdr.ipv4);
|
|
}
|
|
}
|
|
|
|
V1Switch(
|
|
MyParser(),
|
|
MyVerifyChecksum(),
|
|
MyIngress(),
|
|
MyEgress(),
|
|
MyComputeChecksum(),
|
|
MyDeparser()
|
|
) main;
|