public
Authored by
Salvatore Girolamo @digirols

sPIN interface
Embed
Share
// this gets called every time a new packet needs to be fed into
int packet_in_callback(int packetnum, char *buffer, size_t max_packet_size, size_t *actual_packet_size)
{
//define packet in buffer
...
*actual_packet_size = //put actual packet size
return 20; /* delay (in ns) to the next time this function will be called */
}
// called when a handler sends a new packet out
int packet_out_callback(char *pkt_buffer, size_t pkt_size)
{
// do something with the new packet
}
// called when an handler makes a write_to_host
void pcie_write_callback(uint64_t host_address, uint8_t *buffer, size_t buffer_size)
{
//handle PCIe write
}
// called when an handler makes a read_from_host
void pcie_read_callback(uint64_t host_address, uint8_t *buffer, size_t buffer_size)
{
//handle PCIe read
}
int main()
{
//we have two prefixes:
// - spinsim_* for stuff that is simulation related and does not belong to the API of a real NIC.
// - spin_* for functions that could end up in the real API
int status;
spinsim_boot();
spinsim_install_ni_packet_callback(packet_in_callback);
spinsim_install_no_packet_callback(packet_out_callback);
spinsim_install_pcie_read_callback(pcie_read_callback);
spinsim_install_pcie_write_callback(pcie_write_callback);
// Finds handlers in the passed object file, installs them in NIC memory
// and returns a map "handler_name" -> NIC L2 prog mem poitner).
// timos: I suggest to not return this as a map - hard to use in anything
// but C++, and I don't see a use case. Instead I would have it return only
// sucess/failure and have a seperate function to iterate/print/whatever
// loaded handlers.
status = spin_load_handlers("my_object_file.o");
assert(status == SPIN_SUCCESS);
spin_handler_t hh, ph, th;
status = spin_find_handler_by_name("my_hh_handler", &hh); assert(status==SPIN_SUCCESS);
status = spin_find_handler_by_name("my_ph_handler", &ph); assert(status==SPIN_SUCCESS);
status = spin_find_handler_by_name("my_th_handler", &th); assert(status==SPIN_SUCCESS);
// define matching rule
spin_matching_rule_t r;
r.offset = 16;
r.length = 8;
r.matching[0] = 0x12345678;
// define handler data
size_t handler_data_size;
uint8_t *handler_data = define_handler_data(&handler_data_size);
spin_mem_handle_t handler_data_handle;
status = spin_data_offload(handler_data, handler_data_size, &handler_data_handle);
assert(status==SPIN_SUCCESS);
// define execution context
spin_ec_t ec;
status = spin_make_ec(r, handler_data_handle, hh, ph, th, &ec);
assert(status==SPIN_SUCCESS);
// install execution context
status = spin_install_ec(ec);
assert(status==SPIN_SUCCESS);
// will call packet_in_callback 16 times
spinsim_simulate_packets(16 /* <- num packets */);
//alternatives:
//spinsim_simulate_packet_trace(pkt_file, data_file);
//spinsim_simulate_packet_list(array_of_packet_descriptors, num_of_packets)
// ???
spinsim_shutdown();
return 0;
}
Please register or sign in to comment