├── compiler ├── netcl-compile ├── README.md ├── Makefile ├── netcl_rules ├── templates │ └── table_2_template.py ├── netcl.l ├── compiled_rules ├── netcl.tab.h ├── netcl.y ├── netcl.tab.c └── lex.yy.c ├── custom-recieve.py ├── custom-send.py ├── switch ├── netcl.py ├── controller.py └── p4control.p4 ├── host_agent ├── host_agent.py └── host_agent_ebpf.c └── README.md /compiler/netcl-compile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peng-gao-lab/p4control/HEAD/compiler/netcl-compile -------------------------------------------------------------------------------- /compiler/README.md: -------------------------------------------------------------------------------- 1 | # Rebuild NetCL Compiler 2 | 3 | To rebuild the NetCL compiler after modifying its code, execute the following 4 | ``` 5 | make clean 6 | make netcl 7 | ``` 8 | -------------------------------------------------------------------------------- /compiler/Makefile: -------------------------------------------------------------------------------- 1 | netcl: 2 | bison -d netcl.y 3 | flex netcl.l 4 | g++ netcl.tab.c lex.yy.c -ll -o ./netcl-compile --std=c++0x 5 | 6 | clean: 7 | rm -rf netcl.tab.c netcl.tab.h lex.yy.c 8 | rm -rf netcl-compile netcl 9 | -------------------------------------------------------------------------------- /compiler/netcl_rules: -------------------------------------------------------------------------------- 1 | if match(pktlabel contains 0x01 && IP == "10.0.0.3") then drop 2 | 3 | if match(pktlabel contains 0x02 && IP == "10.0.0.3") then allow 4 | 5 | if match(pktlabel contains 0x01 && IP == "10.0.0.2") then allow 6 | 7 | if match(pktlabel contains 0x02 && IP == "10.0.0.1") then allow -------------------------------------------------------------------------------- /compiler/templates/table_2_template.py: -------------------------------------------------------------------------------- 1 | # table_action3 label -> dst_address 2 | dst_ip_addr = struct.unpack("!L", socket.inet_aton(DST_IP))[0] 3 | tag_label = LABEL 4 | decision = DEC 5 | key = table_action3.make_key([gc.KeyTuple('hdr.flowtag.tag_label',tag_label, tag_label), 6 | gc.KeyTuple('hdr.ipv4.dst_addr',dst_ip_addr)]) 7 | data = table_action.make_data([gc.DataTuple('priority', 1), 8 | gc.DataTuple('decision', decision)], 'SwitchIngress.table_action3') 9 | table_action.entry_add(target, [key], [data]) 10 | 11 | # ======================================================== -------------------------------------------------------------------------------- /compiler/netcl.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | #define YY_DECL extern "C" int yylex() 11 | 12 | #include "netcl.tab.h" 13 | // support tags 0-Alice 1-Bob 2-Sales 3-Dev 14 | %} 15 | %% 16 | "//".* {/* comment */ } 17 | if { return IF; } 18 | then { return THEN; } 19 | drop { return DROP; } 20 | alice { return ALICE; } 21 | bob { return BOB; } 22 | sales { return SALES; } 23 | dev { return DEV; } 24 | modify { return MODIFYTTL; } 25 | fwd { return FWD; } 26 | reroute { return REROUTE; } 27 | match { return MATCH; } 28 | contains { return CONTAINS; } 29 | "(" { return LP; } 30 | ")" { return RP; } 31 | "==" { return EQ; } 32 | "&&" { return AND; } 33 | [ \t\n] ; 34 | "\""[0-9.]+"\"" { yylval.sval = strdup(yytext); return IP; } 35 | [0-9]+ { yylval.ival = atoi(yytext); return CONST; } 36 | [a-zA-Z0-9]+ { 37 | yylval.sval = strdup(yytext); 38 | return VAR; 39 | } 40 | . ; 41 | %% 42 | -------------------------------------------------------------------------------- /custom-recieve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import struct 4 | import os 5 | import re 6 | from scapy.all import sniff, sendp, hexdump, get_if_list, get_if_hwaddr 7 | from scapy.all import Packet, IPOption 8 | from scapy.all import ShortField, IntField, LongField, BitField, FieldListField, FieldLenField 9 | from scapy.all import IP, TCP, UDP, Raw 10 | from scapy.all import bind_layers 11 | from scapy.layers.inet import _IPOption_HDR 12 | 13 | class p4control(Packet): 14 | name = "p4control" 15 | fields_desc = [BitField("label", 0, 64), BitField("tracker", 0, 64)] 16 | 17 | bind_layers(TCP, p4control) 18 | 19 | # Update with your interface 20 | def get_if(): 21 | ifs=get_if_list() 22 | iface=None # "h1-eth0" 23 | for i in get_if_list(): 24 | if re.search("veth.", i): 25 | iface=i 26 | break; 27 | if not iface: 28 | print("Cannot find veth interface") 29 | exit(1) 30 | return iface 31 | 32 | def handle_pkt(pkt): 33 | if TCP in pkt and pkt[TCP].dport == 1234: 34 | print("got a packet") 35 | pkt.show2() 36 | # hexdump(pkt) 37 | sys.stdout.flush() 38 | 39 | 40 | def main(): 41 | ifaces = [i for i in os.listdir('/sys/class/net/') if 'veth' in i] 42 | iface = ifaces[0] 43 | print(("sniffing on %s, port 1234" % iface)) 44 | sys.stdout.flush() 45 | sniff(iface = iface, 46 | prn = lambda x: handle_pkt(x)) 47 | 48 | if __name__ == '__main__': 49 | main() -------------------------------------------------------------------------------- /custom-send.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import sys 4 | import socket 5 | import random 6 | import struct 7 | import re 8 | import binascii 9 | from scapy.all import sendp, send, get_if_list, get_if_hwaddr 10 | from scapy.all import Packet 11 | from scapy.all import Ether, IntField, ShortField, LongField, BitField, IP, UDP, TCP, Raw 12 | from scapy.all import bind_layers 13 | 14 | class p4control(Packet): 15 | name = "p4control" 16 | fields_desc = [BitField("label", 0, 64), BitField("tracker", 0, 64)] 17 | 18 | bind_layers(TCP, p4control) 19 | 20 | # Update with your interface 21 | def get_if(): 22 | ifs=get_if_list() 23 | iface=None # "h1-eth0" 24 | for i in get_if_list(): 25 | if re.search("veth.", i): 26 | iface=i 27 | break; 28 | if not iface: 29 | print("Cannot find veth interface") 30 | exit(1) 31 | return iface 32 | 33 | def main(): 34 | 35 | if len(sys.argv)<4: 36 | print('pass 4 arguments: