Skip to content

Commit

Permalink
generator finally working as expected after fixing surprising bug onl…
Browse files Browse the repository at this point in the history
…y found in physical asic (not ref. model)
  • Loading branch information
jsonch committed Jul 2, 2024
1 parent 39e48d6 commit c625209
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 69 deletions.
62 changes: 31 additions & 31 deletions examples/utils/generator/cmd.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
#!/usr/bin/env python3

import sys, time, random, socket, os, struct, json, copy
from dataclasses import dataclass
import binascii
import dpkt
from collections import namedtuple
from scapy.all import sendp, Raw, Ether, sniff
from threading import Thread

# the interface of the
# dataplane from the management cpu
iface = "ens1"
# iface = "enp5s0"


# event defs
# (this should line up with event numbers in lucid program)
evnums = {
"send_pkt": 1,
"query": 3,
"start_flow": 5,
"stop_flow": 6,
}

def rawtime_to_us(rawtime):
Expand All @@ -35,37 +35,32 @@ def rawtime_pps(start, end, pktct):


def handle_report(raw_ev):
reqid, txct, rxct, tx_start, tx_end, rx_start, rx_end = struct.unpack('!IIIIIII', raw_ev[:28])
print(f"reqid = {reqid}")
print(f"tx ct = {txct} rx ct = {rxct}")
port, reqid, txct, rxct, tx_start, tx_end, rx_start, rx_end = struct.unpack('!HIIIIIII', raw_ev[:30])
tx_dur_us = rawtime_to_us(tx_end) - rawtime_to_us(tx_start)
rx_dur_us = rawtime_to_us(rx_end) - rawtime_to_us(rx_start)
rx_rate = rawtime_pps(rx_start, rx_end, rxct)
tx_rate = rawtime_pps(tx_start, tx_end, txct)
print(f"rx rate (pps) = {rx_rate} tx rate (pps) = {tx_rate}")
print("port = %s" % port)
print("reqid = %s" % reqid)
print("tx ct = %s rx ct = %s" % (txct, rxct))
print("tx dur (us) = %s rx dur (us) = %s" % (tx_dur_us, rx_dur_us))
print("rx rate (pps) = %s tx rate (pps) = %s" % (rx_rate, tx_rate))
if rxct > 0:
loss = 1.0 - (float(rxct) / float(txct))
print(f"loss = {loss}")

def send_pkt(ct, src="00:11:22:33:44:55", dst="07:08:09:10:11:12", et="08:00", data="bb:aa:dd:aa:ff"):
print(f"generating command to send {ct} packets")
print("loss = %s" % loss)
def send_pkt(port, ct, src="00:11:22:33:44:55", dst="07:08:09:10:11:12", et="08:00", data="bb:aa:dd:aa:ff"):
print("generating command to send %s packets" % ct)
ct_bytes = unbbytes(ct.to_bytes(2, byteorder='big'))
port = 148
port_bytes = unbbytes(port.to_bytes(2, byteorder='big'))
# send packet is event number 1
return (evnums["send_pkt"], [port_bytes, ct_bytes, dst, src, et, data])

def query(reqid):
def query(port, reqid):
reqid_bytes = unbbytes(reqid.to_bytes(4, byteorder='big'))
port_bytes = unbbytes(port.to_bytes(2, byteorder='big'))
# query is event number 3
return (evnums["query"], [reqid_bytes])

def start_flow(flow_id, max_pkts, src="00:11:22:33:44:55", dst="07:08:09:10:11:12", et="08:00", data="bb:aa:dd:aa:ff"):
flow_id_bytes = unbbytes(flow_id.to_bytes(1, byteorder='big'))
max_pkts_bytes = unbbytes(max_pkts.to_bytes(4, byteorder='big'))
return (evnums["start_flow"], [flow_id_bytes, max_pkts_bytes, dst, src, et, data])

def stop_flow(flow_id):
flow_id_bytes = unbbytes(flow_id.to_bytes(1, byteorder='big'))
return (evnums["stop_flow"], [flow_id_bytes])
return (evnums["query"], [port_bytes, reqid_bytes])

def main():
interface = iface
Expand All @@ -74,22 +69,27 @@ def main():
sys.exit(1)
cmd = sys.argv[1]
if cmd == "send":
if (len(sys.argv) > 2):
generate_port(interface, send_pkt(int(sys.argv[2])))
if (len(sys.argv) == 4):
# send <port> <ct>
generate_port(interface, send_pkt(int(sys.argv[2]), int(sys.argv[3])))
elif (len(sys.argv) == 3):
# send <port>
generate_port(interface, send_pkt(int(sys.argv[2]), 1))
else:
generate_port(interface, send_pkt(1))
elif cmd == "start":
generate_port(interface, start_flow(1, (2^32)-1))
elif cmd == "stop":
generate_port(interface, stop_flow(1))
# send
generate_port(interface, send_pkt(148, 1))
elif cmd == "query":
global handlers
global stop
stop = False
handlers["00:02"] = handle_report
handle_port(interface)
time.sleep(2)
generate_port(interface, query(4))
if (len(sys.argv) == 3):
# query <port>
generate_port(interface, query(int(sys.argv[2]), 0))
else:
generate_port(interface, query(148, 0))
time.sleep(2)
stop = True
else:
Expand Down
59 changes: 21 additions & 38 deletions examples/utils/generator/generator.dpt
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// a packet generator

const int<9> server_port = 148;

// command events from controller
// start generating a flow of ct ethernet packets
event start_flow@1(int<16> port, int<16> ct, int<48> dst, int<48> src, int<16> ety, Payload.t pl);
// ask for a report about flow stats, id is query id
event send_report@3(int id);
event send_report@3(int<16> port, int id);
// the report back to the controller
event report@2(int id, int txct, int rxct, int txstart, int txend, int rxstart, int rxend){skip;}
event report@2(int<16> port, int id, int txct, int rxct, int txstart, int txend, int rxstart, int rxend){skip;}

// ethernet packet to / from the server
packet event eth(int<48> dst, int<48> src, int<16> ety, Payload.t pl);
Expand All @@ -18,7 +17,6 @@ event send_pkt@11(int<16> port, int<16> ct, int<48> dst, int<48> src, int<16> et
/**** program state ****/
// time is in units of 2^16 nanoseconds, or 64 microseconds.
global Array.t<32> txct = Array.create(256);
global Array.t<16> debug = Array.create(1024);
global Array.t<32> tx_start = Array.create(256);
global Array.t<32> tx_end = Array.create(256);

Expand Down Expand Up @@ -53,59 +51,44 @@ handle start_flow(int<16> port, int<16> ct, int<48> dst, int<48> src, int<16> et

}

/*
Insane behavior:
- scenario: start_flow(148, 2, ...)
- expected behavior: send_pkt(148, 2, ...) is called twice
- txct[148] ends at 2
- debug[148] ends at 2
- 2 packets get sent to server
- observed behavior:
- txct[148] ends at 3
- debug[148] ends at 2
- 0 packets get sent to server
*/

handle send_pkt(int<16> port, int<16> ct, int<48> dst, int<48> src, int<16> ety, Payload.t pl) {
int port_cpy = hash<32>(0, port);
int<16> port_cpy = hash<16>(0, port);
int tx_ct = Array.update(txct, port, incr, 1, incr, 1);
// Array.setm(txct, port, incr, 1);
Array.setm(debug, port, incr_16, 1);
// if (tx_ct == 1) {
// Array.set(tx_start, port, Sys.time());
// }
if (tx_ct == 1) {
Array.set(tx_start, port, Sys.time());
}
Array.set(tx_end, port, Sys.time());
// send packet to server
generate_port(server_port, eth(dst, src, ety, pl));
generate_port((int<9>)port_cpy, eth(dst, src, ety, pl));
// if count is not 1, generate another packet
if (ct != 1) {
generate(send_pkt(port, ct - 1, dst, src, ety, pl));
}
}

handle send_report(int id) {
int tx = Array.get(txct, server_port);
int txs = Array.get(tx_start, server_port);
int txe = Array.get(tx_end, server_port);
int rx = Array.get(rxct, server_port);
int rxs = Array.get(rx_start, server_port);
int rxe = Array.get(rx_end, server_port);
generate_port(ingress_port, report(id, tx, rx, txs, txe, rxs, rxe));
handle send_report(int<16> port, int id) {
int tx = Array.get(txct, port);
int txs = Array.get(tx_start, port);
int txe = Array.get(tx_end, port);
int rx = Array.get(rxct, port);
int rxs = Array.get(rx_start, port);
int rxe = Array.get(rx_end, port);
generate_port(ingress_port, report(port, id, tx, rx, txs, txe, rxs, rxe));
}

handle eth(int<48> dst, int<48> src, int<16> ety, Payload.t pl) {
if (ingress_port == server_port) {
int rx_ct = Array.update(rxct, server_port, incr, 1, incr, 1);
if (rx_ct == 1) {
Array.set(rx_start, server_port, Sys.time());
}
Array.set(rx_end, server_port, Sys.time());
int<16> port = hash<16>(0, ingress_port);
int rx_ct = Array.update(rxct, port, incr, 1, incr, 1);
if (rx_ct == 1) {
Array.set(rx_start, port, Sys.time());
}
Array.set(rx_end, port, Sys.time());
}




// const int<9> server_port = 148;
// // infinite flow events
// event start_flow@5(int<8> flow_id, int<32> max_pkts, int<48>dst, int<48> src, int<16> ety, Payload.t pl);
// event stop_flow@6(int<8> flow_id);
Expand Down

0 comments on commit c625209

Please sign in to comment.