...
 
Commits (267)
......@@ -9,7 +9,7 @@ stages:
- deploy
- clean
build_prrt:
build:prrt:
stage: build
tags:
- cmake
......@@ -27,30 +27,55 @@ build_prrt:
- CC=gcc-5 CXX=g++-5 cmake . -DPRRT_TESTS=1
- make
build_container:
build:container:
stage: build
tags:
- docker
script:
- export DOCKER_TAG=$(echo "$CI_BUILD_REF_NAME" | sed 's#/#_#' | sed 's#^master$#latest#')
- docker build -t $CI_REGISTRY_IMAGE:$DOCKER_TAG --build-arg http_proxy=http://www-proxy.uni-saarland.de:3128 .
- docker build -t $CI_REGISTRY_IMAGE:$DOCKER_TAG --build-arg http_proxy=http://www-proxy.uni-saarland.de:3128 -f docker/Dockerfile .
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker push $CI_REGISTRY_IMAGE:$DOCKER_TAG
- docker rmi $CI_REGISTRY_IMAGE:$DOCKER_TAG
test_prrt_mem:
build:container_tcp:
stage: build
tags:
- docker
script:
- export DOCKER_TAG=$(echo "$CI_BUILD_REF_NAME""_tcp" | sed 's#/#_#' | sed 's#^master$#latest#')
- docker build -t $CI_REGISTRY_IMAGE:$DOCKER_TAG --build-arg http_proxy=http://www-proxy.uni-saarland.de:3128 -f docker/Dockerfile_tcp .
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker push $CI_REGISTRY_IMAGE:$DOCKER_TAG
- docker rmi $CI_REGISTRY_IMAGE:$DOCKER_TAG
test:prrt_mem:
stage: test
dependencies:
- build:prrt
tags:
- valgrind
script:
- bash memtest.sh
- bash tests/memtest.sh
test_prrt_functional:
test:prrt_functional:
stage: test
dependencies:
- build:prrt
tags:
- bash
script:
- exec ./prrtTests
test:prrt_python_bindings:
stage: test
tags:
- bash
- python3
script:
- ./bin/prrtTests
- sh tests/build.sh
package_pypi:
deploy:pypi:
stage: deploy
tags:
- python3
......@@ -64,10 +89,4 @@ package_pypi:
- echo "username=$PYPI_USER" >> ~/.pypirc
- echo "password=$PYPI_PASSWORD" >> ~/.pypirc
- python3 setup.py check sdist bdist upload -r on
clean_pypirc:
stage: clean
when: always
script:
- rm -vf ~/.pypirc
......@@ -3,11 +3,11 @@ project (PRRT)
option(PRRT_TESTS "Build tests" OFF)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_C_FLAGS "-O2 -Wall -std=gnu11 -D_GNU_SOURCE" )
set(CMAKE_C_FLAGS "-O2 -Wall -std=gnu11 -D_GNU_SOURCE -fPIC" )
set(CMAKE_CXX_FLAGS "-fstack-protector -fstack-protector-all -Wall -std=gnu++11 -D_GNU_SOURCE" )
set(CMAKE_CXX_FLAGS_DEBUG "-O2 -Wall -ggdb" )
set(CMAKE_CXX_FLAGS_RELEASE "-Os -Wall" )
......@@ -29,5 +29,5 @@ if(PRRT_TESTS)
add_custom_target(funtest COMMAND ./bin/prrtTests)
endif()
add_custom_target(perftest COMMAND python3 eval.py)
add_custom_target(perftest COMMAND python3 tests/eval.py)
add_custom_target(memtest COMMAND bash ./memtest.sh DEPENDS sender receiver)
MIT License
Copyright (c) 2017 Saarland Informatics Campus and Friedrich-Alexander-Universität Erlangen-Nürnberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Predictable Reliable Realtime Transport
## Docker
sudo docker run --rm --name=prrt_recv --net=host prrt receiver 5000 127
sudo docker run --rm --name=prrt_send --net=host prrt sender 127.0.0.1 5000 127
bridge=docker network create --subnet="10.5.1.0/24" prrt | cut -c1-12
ovs-vsctl add-port of-switch br-$bridge
docker run --rm --name=prrt_recv --network="prrt" -v=/opt/prrt:/output --ip=10.5.1.52 --cap-add NET_ADMIN git.nt.uni-saarland.de:4567/larn/prrt:develop receiver 5000 127
docker run --rm --name=prrt_send --network="prrt" -v=/opt/prrt:/output --ip=10.5.1.51 --cap-add NET_ADMIN git.nt.uni-saarland.de:4567/larn/prrt:develop sender 10.50.1.52 5000 127 rate 1mbit
# Predictably Reliable Real-Time (PRRT) [![pipeline status](https://git.nt.uni-saarland.de/LARN/PRRT/badges/master/pipeline.svg)](https://git.nt.uni-saarland.de/LARN/PRRT/commits/master)
**PRRT** is a transport protocol that aims to provide predictable reliability and latency. [http://larn.systems]()
## Features
* Forward Error Correction (FEC) using systematic Vandermonde codes
* Clock synchronization between sending stack and receiving stack
* Applications can specify packet-level expiration times
* Different receive modes for ASAP and time-synchronized operation
* Passive measurement of propagation delay, bottleneck data rate and packet loss rate
* Packet-level timing analysis using [X-Lap](http://xlap.larn.systems)
* [Hardware timestamping support](https://git.nt.uni-saarland.de/LARN/PRRT/wikis/hardware-timestamping)
## Installation
*See [Installing PRRT](https://git.nt.uni-saarland.de/LARN/PRRT/wikis/installation#python) for instructions on how to install it on your system for using it with C/C++ or Python.*
#### *Try PRRT on your system*
A [minimal receiver](examples/receiver.py), which takes the bind port as an argument, is created as follows:
```python
import sys
import prrt
port = int(sys.argv[1])
s = prrt.PrrtSocket(port=port)
while True:
d = s.recv().decode("utf8")
if d != "Close":
print(d)
else:
break
```
A [minimal sender](sender.py) is created as follows:
```python
import sys
import prrt
host = sys.argv[1]
port = int(sys.argv[2])
localport = int(sys.argv[3])
s = prrt.PrrtSocket(port=localport)
s.connect(host, port)
for i in range(10):
s.send("Packet {}".format(i).encode("utf8"))
s.send("Close".encode("utf8"))
```
Start the receiver by:
```bash
python3 receiver.py 5000
```
In a separate terminal, run:
```bash
python3 sender.py 127.0.0.1 5000 6000
```
This should generate the following output in the receiver console:
```terminal
Packet 0
Packet 1
...
Packet 9
```
## For more information
* [PRRT Wiki](https://git.nt.uni-saarland.de/LARN/PRRT/wikis)
* [LARN Project Website](http://larn.systems)
## License
[MIT Licence](LICENSE)
#!/usr/bin/env bash
rm prrt/prrt.c
python3 setup.py build_ext --inplace
cp prrt*.so ./build/
PRRT Dissector for Wireshark
============================
Installation
------------
* Download Wireshark Source Code: https://www.wireshark.org/
apt-get install qt-sdk libgtk-3-dev libpcap-dev
tar xvjf wireshark-1.10.2.tar.bz2
./configure
* Copy `packet-prrt.c` to `epan/dissectors`.
* Add a line `packet-prrt.c \` in `DISSECTOR_SRC` of `epan/dissectors/Makefile.common`.
* Call make in the root folder. You can now start wireshark using `./wireshark`.
This tutorial will show you how to apply the dissector of PRRT in your wireshark.
What our PRRT dissector can do?
Our PRRT dissector can dissector the following PRRT packets: data, repeated data, redundancy, pre-sent redundancy, feedback and channel feedback. By now it can basically display the header info of PRRT packets. The sophistical display and advanced features will be supported later.
How to use it?
To use this dissector in the wireshark basically you need to perform the following steps:
0. Download the source code of wireshark and extract it.
1. Copy our dissector code (packet-prrt.c) to the directory epan/dissectors/ of the source code.
2. Add a line "packet-prrt.c \" in DISSECTOR_SRC of epan/dissectors/Makefile.common, so that we can compile our dissector code.
3. This step is optional and for advanced usage.
If you want our dissector to call subdissectors for some purposes (e.g. using mp2t to parse the payload as MPEG TS.), you need to register the subdissector by adding the following _pattern_ line in the handoff function of the subdissector:
heur_dissector_add("prrt", heuristic_dissect_method, protocol_id);
e.g. add the line in the function proto_reg_handoff_mp2t() of packet-mp2t.c for parsing PRRT payload as MPEG TS.
heur_dissector_add("prrt", heur_dissect_mp2t, proto_mp2t);
NOTE : The subdissector called by PRRT dissector at the moment must support heuristic dissecting.
NOTE : By now we provide two dissector files respectively for two wireshark versions (1.4.6 and 1.6.1), because different version of wireshark provides different methods used in the dissector code. Even the dissector code for the version 1.4.6 is compatible with wireshark 1.6.1, we still recommand you use the dissector code for the version 1.6.1 and wireshark 1.6.1, since the later version of wireshark would not support the old method any more.
The following is fully commands under a specific scenario (see the prerequisite), you may follow, to install wireshark and apply our dissector code. For installation you can choose 1.a or 1.b depending on the version of wireshark you prefer to.
0. Prerequisite :
+ Linux OS : ubuntu 10.04 or later.
+ wireshark 1.4.6 or wireshark 1.6.1.
+ libgtk2.0-dev, bison, automake1.9 and libpcap. (Maybe more dependencies required.)
1.a Installation (wireshark 1.4.6)
sudo apt-get source wireshark-dev
sudo chown -R your_account:your_account wireshark-1.4.6/
mkdir wireshark-installed
svn co https://projects.nt.uni-saarland.de/svn/prrt-dissector
cp prrt-dissector/wireshark-1.4.6/packet-prrt.c wireshark-1.4.6/epan/dissectors/
cd wireshark-1.4.6
./configure --prefix=$PWD/../wireshark-installed/
make -j 2
make install
2.b Installation (wireshark 1.6.1)
download wireshark 1.6.1 from the www.wireshark.org
tar -xjvf wireshark-1.6.1.tar.bz2
mkdir wireshark-installed
svn co https://projects.nt.uni-saarland.de/svn/prrt-dissector
cp prrt-dissector/wireshark-1.6.1/packet-prrt.c wireshark-1.6.1/epan/dissectors/
cd wireshark-1.6.1
./configure --prefix=$PWD/../wireshark-installed/
make -j 2
make install
3. Running the wireshark
sudo ../wireshark-installed/bin/wireshark
-- For an excellent example script, see
-- https://wiki.wireshark.org/Lua/Examples?action=AttachFile&do=get&target=dissector.lua
-- declare our protocol
local prrt_proto = Proto("prrt","Predictably Reliable Real-time Transport")
local prrtPacketTypeNames = {
[0] = "Data",
[1] = "Repetition",
[2] = "Redundancy",
[3] = "Feedback",
[4] = "Pre-sent Redundancy",
[5] = "Channel Feedback"
}
-- create the fields
local pf_type = ProtoField.uint8("prrt.type", "Type", base.DEC, prrtPacketTypeNames, 240)
local pf_prio = ProtoField.uint8("prrt.priority", "Priority", base.DEC, nil, 15)
local pf_idx = ProtoField.uint8("prrt.index", "Index")
local pf_seqN = ProtoField.uint16("prrt.sequenceNumber", "Sequence Number")
local pf_data = ProtoField.new("Data", "prrt.data", ftypes.BYTES, base.NONE)
local pf_data_length = ProtoField.uint32("prrt.data.length", "Length")
local pf_data_timestamp = ProtoField.uint32("prrt.data.timestamp", "Timestamp")
local pf_data_groupRTprop = ProtoField.uint32("prrt.data.grouprtprop", "Group RTprop")
local pf_data_packettimeout = ProtoField.uint32("prrt.data.packettimeout", "Packet Timeout")
local pf_red = ProtoField.new("Redundancy", "prrt.redundancy", ftypes.BYTES, base.NONE)
local pf_red_baseSeqN = ProtoField.uint16("prrt.redundancy.baseSequenceNumber", "Base Sequence Number", base.DEC)
local pf_red_timestamp = ProtoField.uint32("prrt.redundancy.timestamp", "Timestamp")
local pf_red_n = ProtoField.uint8("prrt.redundancy.n", "n")
local pf_red_k = ProtoField.uint8("prrt.redundancy.k", "k")
local pf_fb = ProtoField.new("Feedback", "prrt.feedback", ftypes.BYTES, base.NONE)
local pf_fb_groupRTT = ProtoField.uint32("prrt.feedback.groupRTT", "Group RTT")
local pf_fb_ftt = ProtoField.uint32("prrt.feedback.FTT", "FTT")
local pf_fb_erasurecount = ProtoField.uint16("prrt.feedback.erasureCount", "Erasure count")
local pf_fb_packetcount = ProtoField.uint16("prrt.feedback.packetCount", "Packet count")
local pf_fb_gaplength = ProtoField.uint16("prrt.feedback.gapLength", "Gap length")
local pf_fb_gapcount = ProtoField.uint16("prrt.feedback.gapCount", "Gap count")
local pf_fb_burstlength = ProtoField.uint16("prrt.feedback.burstLength", "Burst length")
local pf_fb_burstcount = ProtoField.uint16("prrt.feedback.burstCount", "Burst count")
local pf_fb_acktype = ProtoField.uint8("prrt.feedback.ackPacketType", "Ack Packet Type", base.DEC, prrtPacketTypeNames)
local pf_fb_ackSeqN = ProtoField.uint16("prrt.feedback.ackSequenceNumber", "Ack Sequence Number")
-- add the fields to the protocol
prrt_proto.fields = {
pf_type,
pf_prio,
pf_idx,
pf_seqN,
pf_data,
pf_data_length,
pf_data_timestamp,
pf_data_groupRTprop,
pf_data_packettimeout,
pf_red,
pf_red_baseSeqN,
pf_red_timestamp,
pf_red_n,
pf_red_k,
pf_fb,
pf_fb_groupRTT,
pf_fb_ftt,
pf_fb_erasurecount,
pf_fb_packetcount,
pf_fb_gaplength,
pf_fb_gapcount,
pf_fb_burstlength,
pf_fb_burstcount,
pf_fb_acktype,
pf_fb_ackSeqN,
}
-- create expert info fields
local ef_too_short = ProtoExpert.new("prrt.too_short.expert", "PRRT Packet too short",
expert.group.MALFORMED, expert.severity.ERROR)
prrt_proto.experts = {
ef_too_short
}
-- Create extractor fields (for some reason this can't be done with the fields that already exist)
local ex_type = Field.new("prrt.type")
local function getType() return ex_type()() end
local function getTypeName() return prrtPacketTypeNames[getType()] end
local ex_index = Field.new("prrt.index")
local function getIndex() return ex_index()() end
local ex_data_length = Field.new("prrt.data.length")
local function getDataLength() return ex_data_length()() end
local ex_red_baseseqno = Field.new("prrt.redundancy.baseSequenceNumber")
local function getRedBaseSeqNo() return ex_red_baseseqno()() end
local ex_red_n = Field.new("prrt.redundancy.n")
local function getRedN() return ex_red_n()() end
local ex_red_k = Field.new("prrt.redundancy.k")
local function getRedK() return ex_red_k()() end
-- some constants
local PRRT_MIN_SIZE = 8
-- create sub-dissectors for different types
local function dissect_data(buffer, pinfo, root)
local tree = root:add(pf_data, buffer:range(0))
tree:add(pf_data_length, buffer:range(0,4))
tree:add(pf_data_timestamp, buffer:range(4,4))
tree:add(pf_data_groupRTprop, buffer:range(8,4))
tree:add(pf_data_packettimeout, buffer:range(12,4))
local label = "[D] Idx=" .. getIndex() .. " Len=" .. getDataLength()
tree:set_text(label)
pinfo.cols.info:set(label)
end
local function dissect_redundancy(buffer, pinfo, root)
local tree = root:add(pf_red, buffer:range(0))
tree:add(pf_red_baseSeqN, buffer:range(0,2))
tree:add(pf_red_timestamp, buffer:range(2,4))
tree:add(pf_red_n, buffer:range(6,1))
tree:add(pf_red_k, buffer:range(7,1))
local label = "[R] Idx=" .. getIndex() .. " b=" .. getRedBaseSeqNo() .. " n=" .. getRedN() .. " k=" .. getRedK()
tree:set_text(label)
pinfo.cols.info:set(label)
end
local function dissect_feedback(buffer, pinfo, root)
local tree = root:add(pf_fb, buffer:range(0))
tree:add(pf_fb_groupRTT, buffer:range(0,4))
tree:add(pf_fb_ftt, buffer:range(4,4))
tree:add(pf_fb_erasurecount, buffer:range(8,2))
tree:add(pf_fb_packetcount, buffer:range(10,2))
tree:add(pf_fb_gaplength, buffer:range(12,2))
tree:add(pf_fb_gapcount, buffer:range(14,2))
tree:add(pf_fb_burstlength, buffer:range(16,2))
tree:add(pf_fb_burstcount, buffer:range(18,2))
tree:add(pf_fb_acktype, buffer:range(20,1))
tree:add(pf_fb_ackSeqN, buffer:range(21, 2))
local label = "[F]"
tree:set_text(label)
pinfo.cols.info:set(label)
end
local subdissectors = {
[0] = dissect_data,
[2] = dissect_redundancy,
[3] = dissect_feedback
}
-- create a function to dissect each frame
function prrt_proto.dissector(buffer,pinfo,root)
-- set the protocol column
pinfo.cols.protocol:set("PRRT")
local pktlen = buffer:reported_length_remaining()
--[[ TODO
parse whether the packet has a payload first
if it has, do not use the entire buffer:range(0)
in the tree label, but only up to the payload
and add another "Data" subtree containing only
the payload
--]]
local tree = root:add(prrt_proto, buffer:range(0))
if pktlen < PRRT_MIN_SIZE then
tree:add_proto_expert_info(ef_too_short)
return
end
tree:add(pf_type, buffer:range(0,1))
tree:add(pf_prio, buffer:range(0,1))
tree:add(pf_idx, buffer:range(1,1))
tree:add(pf_seqN, buffer:range(2,2))
if subdissectors[getType()] then
subdissectors[getType()](buffer:range(4,nil):tvb(), pinfo, tree)
end
end
local current_port = 6000
DissectorTable.get("udp.port"):add(current_port, prrt_proto)
prrt_proto.prefs.port = Pref.uint("Port number", current_port, "The UDP Port number for PRRT")
function prrt_proto.prefs_changed()
if current_port ~= prrt_proto.prefs.port then
if curent_port ~= 0 then
DissectorTable.get("udp.port"):remove(current_port, prrt_proto)
end
current_port = prrt_proto.prefs.port
if current_port ~= 0 then
DissectorTable.get("udp.port"):add(current_port, prrt_proto)
end
end
end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* packet-prrt.c
* Routines for PRRT packet disassembly
*
* Decoding PRRT packets.
*
* Andreas Schmidt <schmidt@nt.uni-saarland.de>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <glib.h>
#include <epan/packet.h>
#include <epan/prefs.h>
#define MINIMAL_PACKET_SIZE 8
void proto_register_prrt(void);
void proto_reg_handoff_prrt(void);
static int proto_prrt = -1;
static gint ett_prrt = -1;
static dissector_handle_t data_handle = NULL;
static const value_string packet_type_names[] = {
{ 0, "Data" },
{ 1, "Repeated Data" },
{ 2, "Redundancy" },
{ 3, "Feedback" },
{ 4, "Pre-sent Redundancy" },
{ 5, "Channel Feedback" }
};
/* General Header */
static int hf_prrt_packet_type = -1;
static int hf_prrt_priority = -1;
static int hf_prrt_index = -1;
static int hf_prrt_seqnum = -1;
/* Data Header */
static int hf_prrt_timestamp = -1;
static int hf_prrt_group_rtt = -1;
static int hf_prrt_packet_timeout = -1;
static int hf_prrt_decoding_timeout = -1;
static int hf_prrt_feedback_timeout = -1;
/* Redundancy Header */
static int hf_prrt_sn_base = -1;
static int hf_prrt_n = -1;
static int hf_prrt_k = -1;
/* Feedback Header */
static int hf_prrt_receiver_addr = -1;
static int hf_prrt_rtt = -1;
static int hf_prrt_ftt = -1;
static int hf_prrt_erasure_count = -1;
static int hf_prrt_packet_count = -1;
static int hf_prrt_gap = -1;
static int hf_prrt_ngap = -1;
static int hf_prrt_burst = -1;
static int hf_prrt_nburst = -1;
static int hf_prrt_bw_est = -1;
static int hf_prrt_buf_fb = -1;
/* Payload */
static int hf_prrt_payload = -1; /* payload with arbitrary length, depending on the support of UDP. */
/* Preferences */
static guint gPORT_PREF = 5004;
static void dissect_prrt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
tvbuff_t* new_tvb = 0;
int offset = 0;
guint len = 0;
guint8 packet_type = -1;
proto_item *ti;
proto_tree *prrt_tree;
packet_type = tvb_get_guint8(tvb, 0) >> 4;
len = tvb_captured_length(tvb);
/* Plausibility check */
if (len < MINIMAL_PACKET_SIZE) {
return;
}
else if (packet_type == 0) {
if(len < 16)
return;
}
else if (packet_type == 1) {
if (len < 16)
return;
}
else if (packet_type == 2) {
if (len < 8)
return;
}
else if (packet_type == 3) {
if(len < 36)
return;
}
else if (packet_type == 4) {
if (len < 8)
return;
}
else if (packet_type == 5) {
if(len < 36)
return;
}
else {
return; /* Unknown packet type, the packet doesn't belong to PRRT. */
}
col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRRT");
col_clear(pinfo->cinfo, COL_INFO);
if (tree) {
ti = proto_tree_add_item(tree, proto_prrt, tvb, offset, -1, ENC_NA);
prrt_tree = proto_item_add_subtree(ti, ett_prrt);
/* Parsing the general header */
proto_tree_add_item(prrt_tree, hf_prrt_packet_type, tvb, offset, 1, FALSE);
proto_tree_add_item(prrt_tree, hf_prrt_priority, tvb, offset, 1, FALSE);
offset += 1;
proto_tree_add_item(prrt_tree, hf_prrt_index, tvb, offset, 1, FALSE);
offset += 1;
proto_tree_add_item(prrt_tree, hf_prrt_seqnum, tvb, offset, 2, FALSE);
offset += 2;
if(packet_type == 0) {
col_set_str(pinfo->cinfo, COL_INFO, "Data");
proto_tree_add_item(prrt_tree, hf_prrt_timestamp, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_group_rtt, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_packet_timeout, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_decoding_timeout, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_feedback_timeout, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_payload, tvb, offset, len - offset, FALSE);
new_tvb = tvb_new_subset(tvb, offset, len-offset, len-offset);
if(len - offset > 0) {
call_dissector(data_handle, new_tvb, pinfo, tree);
}
} else if(packet_type == 1) {
col_set_str(pinfo->cinfo, COL_INFO, "Repeated Data");
proto_tree_add_item(prrt_tree, hf_prrt_timestamp, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_group_rtt, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_packet_timeout, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_decoding_timeout, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_feedback_timeout, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_payload, tvb, offset, len - offset, FALSE);
new_tvb = tvb_new_subset(tvb, offset, len-offset, len-offset);
if(len - offset > 0) {
call_dissector(data_handle, new_tvb, pinfo, tree);
}
} else if(packet_type == 2) {
col_set_str(pinfo->cinfo, COL_INFO, "Redundancy");
proto_tree_add_item(prrt_tree, hf_prrt_sn_base, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_n, tvb, offset, 1, FALSE);
offset += 1;
proto_tree_add_item(prrt_tree, hf_prrt_k, tvb, offset, 1, FALSE);
} else if(packet_type == 3) {
col_set_str(pinfo->cinfo, COL_INFO, "Feedback");
proto_tree_add_item(prrt_tree, hf_prrt_receiver_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_rtt, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_ftt, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_erasure_count, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_packet_count, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_gap, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_ngap, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_burst, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_nburst, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_bw_est, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_buf_fb, tvb, offset, 4, FALSE);
} else if(packet_type == 4) {
col_set_str(pinfo->cinfo, COL_INFO, "Pre-sent Redundancy");
proto_tree_add_item(prrt_tree, hf_prrt_sn_base, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_n, tvb, offset, 1, FALSE);
offset += 1;
proto_tree_add_item(prrt_tree, hf_prrt_k, tvb, offset, 1, FALSE);
} else if(packet_type == 5) {
col_set_str(pinfo->cinfo, COL_INFO, "Channel Feedback");
proto_tree_add_item(prrt_tree, hf_prrt_receiver_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_rtt, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_ftt, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_erasure_count, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_packet_count, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_gap, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_ngap, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_burst, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_nburst, tvb, offset, 2, FALSE);
offset += 2;
proto_tree_add_item(prrt_tree, hf_prrt_bw_est, tvb, offset, 4, FALSE);
offset += 4;
proto_tree_add_item(prrt_tree, hf_prrt_buf_fb, tvb, offset, 4, FALSE);
} else {
return;
}
}
} /* dissect_prrt */
void proto_register_prrt(void)
{
module_t * prrt_module;
static hf_register_info hf[] = {
{ &hf_prrt_packet_type,
{ "Packet Type", "prrt.base.packettype", FT_UINT8, BASE_DEC, VALS(packet_type_names), 0xF0, "Packet type field in PRRT general header", HFILL }},
{ &hf_prrt_priority,
{ "Packet Priority", "prrt.base.packetpriority", FT_UINT8, BASE_DEC, NULL, 0x0F, "Packet priority field in PRRT general header", HFILL }},
{ &hf_prrt_index,
{ "Packet Index","prrt.base.packetindex", FT_UINT16, BASE_DEC, NULL, 0x0, "Packet index field in PRRT general header", HFILL }},
{ &hf_prrt_seqnum,
{ "Packet Sequence Number","prrt.base.packetseqnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Packet sequence number field in PRRT general header", HFILL }},
{ &hf_prrt_timestamp,
{ "Packet Timestamp (us)", "prrt.data.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0, "(Allocated) Timestamp (us) of the packet in PRRT data header", HFILL }},
{ &hf_prrt_group_rtt,
{ "Group RTT (us)", "prrt.data.grouprtt", FT_UINT32, BASE_DEC, NULL, 0x0, "Group RTT (us) in PRRT data header", HFILL }},
{ &hf_prrt_packet_timeout,
{ "Packet Timeout (us)", "prrt.data.packtimeout", FT_UINT32, BASE_DEC, NULL, 0x0, "Timeout (us) of the packet in PRRT data header", HFILL }},
{ &hf_prrt_decoding_timeout,
{ "Decoding Timeout (us)", "prrt.data.dectimeout", FT_UINT32, BASE_DEC, NULL, 0x0, "Timeout (us) of the decoding in PRRT data header", HFILL }},
{ &hf_prrt_feedback_timeout,
{ "Feedback Timeout (us)", "prrt.data.fbtimeout", FT_UINT32, BASE_DEC, NULL, 0x0, "Timeout (us) of the receiver feedback for this packet in PRRT data header", HFILL }},
{ &hf_prrt_sn_base,
{ "Based Serial Number", "prrt.redundancy.snbase", FT_UINT16, BASE_DEC, NULL, 0x0, "The number of first data packet in block, stored in PRRT redundancy data header", HFILL }},
{ &hf_prrt_n,
{ "Code Length (n)", "prrt.redundancy.n", FT_UINT8, BASE_DEC, NULL, 0x0, "The overall number of packets in the block, stored in PRRT redundancy data header", HFILL }},
{ &hf_prrt_k,
{ "Information Length (k)", "prrt.redundancy.k", FT_UINT8, BASE_DEC, NULL, 0x0, "The number of information packets in the block, stored in PRRT redundancy data header", HFILL }},
{ &hf_prrt_receiver_addr,
{ "Receiver IP", "prrt.feedback.ipaddr", FT_IPv4, BASE_NONE, NULL, 0x0, "The IP address of the receiver, stored in general PRRT feedback header", HFILL }},
{ &hf_prrt_rtt,
{ "RTT", "prrt.feedback.rtt", FT_UINT32, BASE_DEC, NULL, 0x0, "The timestamp of most recent data packet plus delay since reception of this packet, stored in general PRRT feedback header", HFILL }},
{ &hf_prrt_ftt,
{ "FTT", "prrt.feedback.ftt", FT_UINT32, BASE_DEC, NULL, 0x0, "The forward trip time", HFILL }},
{ &hf_prrt_erasure_count,
{ "Erasure Count", "prrt.feedback.erasureCount", FT_UINT16, BASE_DEC, NULL, 0x0, "The erasure count measured at the receiver, stored in general PRRT feedback header", HFILL }},
{ &hf_prrt_packet_count,
{ "Packet Count", "prrt.feedback.packetCount", FT_UINT16, BASE_DEC, NULL, 0x0, "The packet count used for loss calculations at the receiver, stored in general PRRT feedback header", HFILL }},
{ &hf_prrt_gap,
{ "Aggregated Gap Length", "prrt.feedback.gap", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
{ &hf_prrt_ngap,
{ "Gap Count", "prrt.feedback.ngap", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
{ &hf_prrt_burst,
{ "Aggregated Burst Length", "prrt.feedback.burst", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
{ &hf_prrt_nburst,
{ "Burst Count", "prrt.feedback.nburst", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
{ &hf_prrt_bw_est,
{ "Estimated Bandwidth", "prrt.feedback.bw", FT_UINT32, BASE_DEC, NULL, 0x0, "The bandwidth estimated at the receiver, stored in general PRRT feedback header", HFILL }},
{ &hf_prrt_buf_fb,
{ "Buffer Feedback", "prrt.feedback.buf_fb", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
{ &hf_prrt_payload,
{ "PRRT Payload", "prrt.payload", FT_NONE, BASE_NONE, NULL, 0x0, "The payload of the PRRT packet", HFILL }}
};
static gint *ett[] = {
&ett_prrt
};
proto_prrt = proto_register_protocol("PRRT", "PRRT", "prrt");
register_heur_dissector_list("prrt");
proto_register_field_array(proto_prrt, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
prrt_module = prefs_register_protocol(proto_prrt, proto_reg_handoff_prrt);
prefs_register_uint_preference(prrt_module, "udp.port", "PRRT UDP Port", "PRRT UDP port if other than the default of 5004", 10, &gPORT_PREF);
}
void proto_reg_handoff_prrt(void)
{
static gboolean initialized = FALSE;
static dissector_handle_t prrt_handle;
static int current_port;
if(!initialized) {
prrt_handle = create_dissector_handle(dissect_prrt, proto_prrt);
data_handle = find_dissector("data");
initialized = TRUE;
} else {
dissector_delete_uint("udp.port", current_port, prrt_handle);
dissector_delete_uint("udp.port", current_port+1, prrt_handle);
}
current_port = gPORT_PREF;
dissector_add_uint("udp.port", current_port, prrt_handle);
dissector_add_uint("udp.port", current_port+1, prrt_handle);
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local Variables:
* c-basic-offset: 2
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=2 tabstop=8 expandtab:
* :indentSize=2:tabSize=8:noTabs=true:
*/
FROM gcc:5
FROM gcc:7
MAINTAINER Andreas Schmidt <schmidt@nt.uni-saarland.de>
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y cmake
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install --yes --force-yes \
bc \
cmake \
iperf3 \
traceroute \
tshark
COPY CMakeLists.txt /prrt/
COPY prrt /prrt/prrt
COPY tests /prrt/tests
COPY docker/entrypoint.sh /
WORKDIR /prrt
RUN cmake . \
&& make
ENV PATH /prrt/bin:$PATH
WORKDIR /prrt/bin
COPY entrypoint.sh /
ENV PATH /prrt:$PATH
VOLUME /output
......
FROM gcc:7
MAINTAINER Andreas Schmidt <schmidt@nt.uni-saarland.de>
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install --yes --force-yes \
bc \
cmake \
iperf3 \
traceroute \
tshark
COPY CMakeLists.txt /prrt/
COPY prrt /prrt/prrt
COPY tests /prrt/tests
COPY docker/entrypoint.sh /
WORKDIR /prrt
RUN cmake -DTCP=1 . \
&& make
ENV PATH /prrt:$PATH
VOLUME /output
ENTRYPOINT ["/entrypoint.sh"]
#!/bin/bash
dev=eth0
command=$1
shift
if [[ "$command" == "sender" || "$command" == "receiver" || "$command" == "time-sender" || "$command" == "time-receiver" ]]; then
:
else
echo "Command should be either sender or receiver."
exit 0;
fi
TARGET="127.0.0.1"
OUTPUT="/dev/null"
NETEM=()
PRRT=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-t|--target)
if [[ "$command" == "sender" || "$command" == "time-sender" ]]; then
PRRT+=("$1 $2")
fi
TARGET=("$2")
shift
shift
;;
-w|--wireshark)
OUTPUT=("$2")
shift
shift
;;
-T|--threadpinning)
PRRT+=("$1")
shift
;;
-p|--port|-r|--rounds|-s|--size|-R|--rcvbuf|-S|--sndbuf|-o|--output|-a|--appdelay)
PRRT+=("$1 $2")
shift
shift
;;
*) # unknown option
NETEM+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
PRRT_PARAMS="${PRRT[@]}"
NETEM_PARAMS="${NETEM[@]}"
echo "Starting Wireshark."
tshark -i eth0 -w $OUTPUT.pcap &
TSHARK_PID=$!
sleep 2
start=$(date +%s.%N);
echo "Checking reachability of $TARGET."
until ping -c1 $TARGET &>/dev/null; do sleep 1; done
dur=$(echo "$(date +%s.%N) - $start" | bc);
printf "Reachable after %.6f seconds\n" $dur
sleep 5
traceroute $TARGET > $OUTPUT.tr
echo "Traceroute done."
iperf3 --version
if [[ "$command" == "sender" || "$command" == "time-sender" ]]; then
iperf3 -c $TARGET
else
iperf3 -s -1
fi
echo "iperf3 for TCP done."
if [[ "$command" == "sender" || "$command" == "time-sender" ]]; then
iperf3 -u -c $TARGET
else
iperf3 -s -1
fi
echo "iperf3 for UDP done."
sleep 5
echo "Running PRRT with command: \"$command $PRRT_PARAMS\" and link parameters: \"$NETEM_PARAMS\""
tc qdisc add dev $dev root netem $NETEM_PARAMS
/prrt/$command $PRRT_PARAMS
echo "Done."
tc qdisc del dev $dev root
kill $TSHARK_PID
#!/bin/bash
dev=eth0
command=$1
shift
if [[ $command -eq "sender" ]];then
params=$1; shift # Add Host
elif [[ $command -eq "receiver" ]]; then
:
else
echo "Command should be either sender or receiver."
fi
params=$(echo $params $1); shift # Add Port
params=$(echo $params $1); shift # Add Rounds
netem_params="$@"
echo "Running PRRT with command" $command $params "with link params:" $netem_params
tc qdisc add dev $dev root netem $netem_params
/prrt/bin/$command $params /output/log.csv
tc qdisc del dev $dev root
import sys
sys.path.insert(0, "./build")
import tests.perf as perf
def run_setup_and_report(setup):
results = setup.run()
print("Setup:\n ", setup)
print("Results:\n " + str(results).replace("\n","\n "))
if __name__ == "__main__":
# Packet Count Works: 2^15; Segfault at: 2^16
# TODO: support multiple tests via proper socket termination
setups = [
perf.TestSetup(packets=2**10,delay=0,loss=30,reorder=0,duplicate=0)
]
for setup in setups:
run_setup_and_report(setup)
\ No newline at end of file
#!/usr/bin/env bash
zsh build.sh
echo "Build completed."
sudo python3 eval.py
\ No newline at end of file
import sys
import prrt
port = int(sys.argv[1])
s = prrt.PrrtSocket(("127.0.0.1", port))
while True:
d, addr = s.recv()
d = d.decode("utf8")
if d != "Close":
print(d, addr)
else:
break
import sys
import prrt
host = sys.argv[1]
port = int(sys.argv[2])
localport = int(sys.argv[3])
s = prrt.PrrtSocket(("127.0.1.1", localport), maximum_payload_size=150)
s.connect((host, port))
for i in range(10):
s.send("Packet {}".format(i).encode("utf8"))
s.send("Close".encode("utf8"))
......@@ -4,24 +4,28 @@ if (DEBUG)
add_definitions(-DDEBUG)
endif()
option(THREAD_PINNING "Sender and receiver threads are pinned to a core." OFF)
if (THREAD_PINNING)
add_definitions(-DTHREAD_PINNING)
endif()
option(XLAP "Run XLAP to trace packets." OFF)
if (XLAP)
add_definitions(-DXLAP)
endif()
option (TCP "Set time protocol to TCP.")
if (TCP)
add_definitions(-DTCP)
endif()
add_subdirectory(proto)
add_subdirectory(util)
add_executable(sender sender.c)
add_executable(receiver receiver.c)
add_executable(time-sender time-sender.c)
add_executable(time-receiver time-receiver.c)
target_link_libraries(sender LINK_PUBLIC PRRT UTIL ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(receiver LINK_PUBLIC PRRT UTIL ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(time-sender LINK_PUBLIC PRRT UTIL ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(time-receiver LINK_PUBLIC PRRT UTIL ${CMAKE_THREAD_LIBS_INIT})
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
from libc.stdint cimport uint32_t, uint16_t, uint8_t, int32_t
include "posix/time.pxd"
include "sockets.pxd"
from libc.stdint cimport uint32_t, uint16_t, uint8_t, int32_t, uint64_t
from libc.string cimport const_char
cdef extern from "pthread.h" nogil:
ctypedef struct pthread_t:
pass
......@@ -11,29 +15,30 @@ cdef extern from "pthread.h" nogil:
ctypedef struct pthread_cond_t:
pass
cdef extern from "py_defines.h":
pass
cdef extern from "proto/vdmcode/block_code.h":
cdef struct prrtCoder:
pass
ctypedef prrtCoder PrrtCoder
cdef extern from "proto/channelStateInformation.h":
cdef extern from "proto/types/channelStateInformation.h":
cdef struct prrtChannelStateInformation:
pass
ctypedef prrtChannelStateInformation PrrtChannelStateInformation
cdef extern from "proto/codingParams.h":
cdef struct prrtCodingParams:
uint8_t k;
uint8_t r;
uint8_t n;
uint8_t n_p;
cdef extern from "proto/types/codingParams.h":
ctypedef struct prrtCodingConfiguration:
uint8_t k
uint8_t r
uint8_t n
uint8_t c
uint8_t *n_cycle
ctypedef prrtCodingParams PrrtCodingParams
ctypedef prrtCodingConfiguration PrrtCodingConfiguration
PrrtCodingConfiguration *PrrtCodingConfiguration_create()
PrrtCodingConfiguration *PrrtCodingConfiguration_copy(PrrtCodingConfiguration *cpar)
bint PrrtCodingConfiguration_destroy(PrrtCodingConfiguration *cpar)
cdef extern from "util/list.h":
cdef struct list:
......@@ -54,11 +59,11 @@ cdef extern from "util/list.h":
void *List_remove(List *list, const ListNode *node)
cdef extern from "proto/block.h":
cdef extern from "proto/types/block.h":
cdef struct prrtBlock:
uint32_t data_count
uint32_t redundancy_count
PrrtCodingParams coding_params
PrrtCodingConfiguration coding_params
uint32_t largest_data_length
uint16_t baseSequenceNumber
List* data_blocks
......@@ -67,7 +72,7 @@ cdef extern from "proto/block.h":
ctypedef prrtBlock PrrtBlock
cdef extern from "proto/packet.h":
cdef extern from "proto/types/packet.h":
cdef struct prrtPacket:
uint8_t type_priority;
uint8_t index;
......@@ -77,6 +82,8 @@ cdef extern from "proto/packet.h":
ctypedef prrtPacket PrrtPacket
ctypedef uint32_t prrtTimedelta_t;
cdef extern from "proto/receiver.h":
ctypedef struct PrrtReceiver:
const char* host_name
......@@ -88,23 +95,21 @@ cdef extern from "proto/receiver.h":
cdef extern from "proto/socket.h":
cdef struct prrtSocket:
int dataSocketFd
int feedbackSocketFd
pthread_t receiveFeedbackThread
int socketFd
pthread_t sendDataThread
pthread_mutex_t outQueueFilledMutex
pthread_cond_t outQueueFilledCv
List* sendDataQueue
MPSCQueue* sendDataQueue
pthread_t receiveDataThread
pthread_mutex_t inQueueFilledMutex
pthread_cond_t inQueueFilledMutexCv
List *receiveDataQueue
PrrtPacketDeliveryStore *packetDeliveryStore
BPTreeNode* dataStore
List* receivers
PrrtReceiver* receiver
uint16_t packetsCount
uint16_t sequenceNumberSource
......@@ -114,17 +119,54 @@ cdef extern from "proto/socket.h":
ctypedef prrtSocket PrrtSocket
cdef PrrtSocket* PrrtSocket_create(bint isSender)
cdef PrrtSocket* PrrtSocket_create(const uint32_t maximum_payload_size, const uint32_t target_delay)
bint PrrtSocket_bind(PrrtSocket *sock_ptr, const_char *ipAddress, const uint16_t port)
int PrrtSocket_close(const PrrtSocket *sock_ptr)
int PrrtSocket_connect(PrrtSocket *sock_ptr, const_char *host, const uint16_t port)
int PrrtSocket_send(PrrtSocket *sock_ptr, const uint8_t *data, const size_t data_len)
int32_t PrrtSocket_recv(PrrtSocket *sock_ptr, void *buf_ptr) nogil
int32_t PrrtSocket_timedrecv(PrrtSocket *sock_ptr, void *buf_ptr, const uint32_t wait_time) nogil
int PrrtSocket_send_sync(PrrtSocket *sock_ptr, const uint8_t *data, const size_t data_len)
int PrrtSocket_send_async(PrrtSocket *sock_ptr, const uint8_t *data, const size_t data_len)
int32_t PrrtSocket_recv(PrrtSocket *sock_ptr, void *buf_ptr, sockaddr* addr) nogil
int32_t PrrtSocket_receive_asap(PrrtSocket *s, void *buf_ptr, sockaddr* addr) nogil
int32_t PrrtSocket_receive_asap_wait(PrrtSocket *s, void *buf_ptr, sockaddr* addr) nogil
int32_t PrrtSocket_receive_asap_timedwait(PrrtSocket *s, void *buf_ptr, sockaddr* addr, timespec* deadline) nogil
int32_t PrrtSocket_receive_ordered(PrrtSocket *s, void *buf_ptr, sockaddr* addr, prrtTimedelta_t time_window_us) nogil
int32_t PrrtSocket_receive_ordered_wait(PrrtSocket *s, void *buf_ptr, sockaddr* addr, prrtTimedelta_t time_window_us) nogil
int32_t PrrtSocket_receive_ordered_timedwait(PrrtSocket *s, void *buf_ptr, sockaddr* addr, prrtTimedelta_t time_window_us, timespec* deadline) nogil
bint PrrtSocket_set_sock_opt(PrrtSocket *sock_ptr, const_char *name, const uint32_t value)
uint32_t PrrtSocket_get_sock_opt(PrrtSocket *sock_ptr, const_char *name)
bint PrrtSocket_set_coding_parameters(PrrtSocket *s, uint8_t k, uint8_t n, uint8_t c, uint8_t *n_cycle)
PrrtCodingConfiguration *PrrtSocket_get_coding_parameters(PrrtSocket *s)
bint PrrtSocket_uses_thread_pinning(PrrtSocket *socket)
bint PrrtSocket_uses_thread_pinning(PrrtSocket *socket)
uint32_t PrrtSocket_get_rtt(PrrtSocket *socket)
uint32_t PrrtSocket_get_rtprop_fwd(PrrtSocket *socket)
float PrrtSocket_get_plr_fwd(PrrtSocket *socket)
uint32_t PrrtSocket_get_delivery_rate_fwd(PrrtSocket *socket)
uint32_t PrrtSocket_get_btlbw_fwd(PrrtSocket *s);
uint32_t PrrtSocket_get_btlbw_back(PrrtSocket *s);
uint32_t PrrtSocket_get_bbr_state(PrrtSocket *s)
uint64_t PrrtSocket_get_full_bw(PrrtSocket *s)
bint PrrtSocket_get_filled_pipe(PrrtSocket *s)
uint32_t PrrtSocket_get_cycle_index(PrrtSocket *s)
float PrrtSocket_get_pacing_gain(PrrtSocket *s)
uint32_t PrrtSocket_get_cwnd(PrrtSocket *s)
uint32_t PrrtSocket_get_inflight(PrrtSocket *s)
uint32_t PrrtSocket_get_pacing_rate(PrrtSocket *s)
uint32_t PrrtSocket_get_send_quantum(PrrtSocket *s)
uint32_t PrrtSocket_get_pipe(PrrtSocket *s)
uint32_t PrrtSocket_get_delivered(PrrtSocket *s)
bint PrrtSocket_get_bbr_round_start(PrrtSocket *s)
uint32_t PrrtSocket_get_bbr_app_limited(PrrtSocket *socket)
bint PrrtSocket_get_bbr_is_app_limited(PrrtSocket *socket)
bint PrrtSocket_enable_thread_pinning(PrrtSocket *socket)
cdef extern from "proto/stores/packetDeliveryStore.h":
ctypedef struct PrrtPacketDeliveryStore:
pass
cdef extern from "util/bptree.h":
ctypedef struct BPTreeNode:
......@@ -135,3 +177,13 @@ cdef extern from "util/bptree.h":
BPTreeNode *BPTree_destroy(BPTreeNode *root);
void *BPTree_get(BPTreeNode *root, int key);
void BPTree_get_range(BPTreeNode *root, List *list, int key_start, int key_end);
cdef extern from "util/pipe.h":
ctypedef struct Pipe:
pass
cdef extern from "util/mpsc_queue.h":
ctypedef struct MPSCQueue:
pass