Loading .gitignore +1 −0 Original line number Diff line number Diff line Loading @@ -9,3 +9,4 @@ tests/__pycache__/ MANIFEST prrt.cpython*.so prrt.so .ipynb_checkpoints/ .gitlab-ci.yml +28 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,17 @@ build:container: - docker push $CI_REGISTRY_IMAGE:$DOCKER_TAG - docker rmi $CI_REGISTRY_IMAGE:$DOCKER_TAG 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: Loading Loading @@ -79,3 +90,19 @@ deploy:pypi: - echo "password=$PYPI_PASSWORD" >> ~/.pypirc - python3 setup.py check sdist bdist upload -r on - rm -vf ~/.pypirc deploy:profile: stage: deploy tags: - gprof script: - ls -lahv - rm CMakeCache.txt - CC=gcc-5 CXX=g++-5 cmake . -DGPROF=1 - make - bash profiling/profile.sh artifacts: paths: - gprof-send.txt - gprof-recv.txt expire_in: 30 days No newline at end of file CMakeLists.txt +7 −1 Original line number Diff line number Diff line Loading @@ -2,16 +2,22 @@ cmake_minimum_required (VERSION 2.8.11) project (PRRT) option(PRRT_TESTS "Build tests" OFF) option(GPROF "Compile with profiler" OFF) 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 -fPIC" ) set(CMAKE_C_FLAGS_DEBUG "-O0 -fsanitize=undefined -fsanitize=address -g3" ) 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_DEBUG "-O0 -Wall -ggdb -fsanitize=undefined -fsanitize=address -g3" ) set(CMAKE_CXX_FLAGS_RELEASE "-Os -Wall" ) if(GPROF) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") endif() find_package (Threads) find_library(M_LIB m) Loading README.md +26 −8 Original line number Diff line number Diff line Loading @@ -4,12 +4,14 @@ ## Features * Forward Error Correction (FEC) using systematic Vandermonde codes * Hybrid error control (FEC + ARQ) using systematic Vandermonde codes * Congestion control and pacing using a variant of [BBR](https://groups.google.com/forum/#!forum/bbr-dev) * 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) * Wireshark dissector written in Lua * [Hardware timestamping support](https://git.nt.uni-saarland.de/LARN/PRRT/wikis/hardware-timestamping) ## Installation Loading @@ -29,9 +31,9 @@ port = int(sys.argv[1]) s = prrt.PrrtSocket(port=port) while True: d = s.recv() d = s.recv().decode("utf8") if d != "Close": print d print(d) else: break ``` Loading @@ -44,25 +46,27 @@ import prrt host = sys.argv[1] port = int(sys.argv[2]) localport = int(sys.argv[3]) s = prrt.PrrtSocket(port=port) s = prrt.PrrtSocket(port=localport) s.connect(host, port) for i in range(10): s.send("Packet {}".format(i)) s.send("Close") s.send("Packet {}".format(i).encode("utf8")) s.send("Close".encode("utf8")) ``` Start the receiver by: ```bash python receiver.py 5000 python3 receiver.py 5000 ``` In a separate terminal, run: ```bash python sender.py 127.0.0.1 5000 python3 sender.py 127.0.0.1 5000 6000 ``` This should generate the following output in the receiver console: Loading @@ -79,6 +83,20 @@ Packet 9 * [PRRT Wiki](https://git.nt.uni-saarland.de/LARN/PRRT/wikis) * [LARN Project Website](http://larn.systems) ## Citing Us If you find PRRT useful and incorporate it in your works, we are very happy to hear about it. Please also consider to cite us like this: ```bibtex @misc{sic2018prrt, author = {Schmidt, Andreas}, title = {PRRT: Predictably Reliable Real-time Transport}, howpublished={Web page}, url = {http://prrt.larn.systems}, year = {2018} } ``` ## License [MIT Licence](LICENSE) dissect/prrt.lua 0 → 100644 +208 −0 Original line number Diff line number Diff line -- 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 Loading
.gitignore +1 −0 Original line number Diff line number Diff line Loading @@ -9,3 +9,4 @@ tests/__pycache__/ MANIFEST prrt.cpython*.so prrt.so .ipynb_checkpoints/
.gitlab-ci.yml +28 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,17 @@ build:container: - docker push $CI_REGISTRY_IMAGE:$DOCKER_TAG - docker rmi $CI_REGISTRY_IMAGE:$DOCKER_TAG 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: Loading Loading @@ -79,3 +90,19 @@ deploy:pypi: - echo "password=$PYPI_PASSWORD" >> ~/.pypirc - python3 setup.py check sdist bdist upload -r on - rm -vf ~/.pypirc deploy:profile: stage: deploy tags: - gprof script: - ls -lahv - rm CMakeCache.txt - CC=gcc-5 CXX=g++-5 cmake . -DGPROF=1 - make - bash profiling/profile.sh artifacts: paths: - gprof-send.txt - gprof-recv.txt expire_in: 30 days No newline at end of file
CMakeLists.txt +7 −1 Original line number Diff line number Diff line Loading @@ -2,16 +2,22 @@ cmake_minimum_required (VERSION 2.8.11) project (PRRT) option(PRRT_TESTS "Build tests" OFF) option(GPROF "Compile with profiler" OFF) 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 -fPIC" ) set(CMAKE_C_FLAGS_DEBUG "-O0 -fsanitize=undefined -fsanitize=address -g3" ) 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_DEBUG "-O0 -Wall -ggdb -fsanitize=undefined -fsanitize=address -g3" ) set(CMAKE_CXX_FLAGS_RELEASE "-Os -Wall" ) if(GPROF) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") endif() find_package (Threads) find_library(M_LIB m) Loading
README.md +26 −8 Original line number Diff line number Diff line Loading @@ -4,12 +4,14 @@ ## Features * Forward Error Correction (FEC) using systematic Vandermonde codes * Hybrid error control (FEC + ARQ) using systematic Vandermonde codes * Congestion control and pacing using a variant of [BBR](https://groups.google.com/forum/#!forum/bbr-dev) * 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) * Wireshark dissector written in Lua * [Hardware timestamping support](https://git.nt.uni-saarland.de/LARN/PRRT/wikis/hardware-timestamping) ## Installation Loading @@ -29,9 +31,9 @@ port = int(sys.argv[1]) s = prrt.PrrtSocket(port=port) while True: d = s.recv() d = s.recv().decode("utf8") if d != "Close": print d print(d) else: break ``` Loading @@ -44,25 +46,27 @@ import prrt host = sys.argv[1] port = int(sys.argv[2]) localport = int(sys.argv[3]) s = prrt.PrrtSocket(port=port) s = prrt.PrrtSocket(port=localport) s.connect(host, port) for i in range(10): s.send("Packet {}".format(i)) s.send("Close") s.send("Packet {}".format(i).encode("utf8")) s.send("Close".encode("utf8")) ``` Start the receiver by: ```bash python receiver.py 5000 python3 receiver.py 5000 ``` In a separate terminal, run: ```bash python sender.py 127.0.0.1 5000 python3 sender.py 127.0.0.1 5000 6000 ``` This should generate the following output in the receiver console: Loading @@ -79,6 +83,20 @@ Packet 9 * [PRRT Wiki](https://git.nt.uni-saarland.de/LARN/PRRT/wikis) * [LARN Project Website](http://larn.systems) ## Citing Us If you find PRRT useful and incorporate it in your works, we are very happy to hear about it. Please also consider to cite us like this: ```bibtex @misc{sic2018prrt, author = {Schmidt, Andreas}, title = {PRRT: Predictably Reliable Real-time Transport}, howpublished={Web page}, url = {http://prrt.larn.systems}, year = {2018} } ``` ## License [MIT Licence](LICENSE)
dissect/prrt.lua 0 → 100644 +208 −0 Original line number Diff line number Diff line -- 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