Lowered protocol packet size limit and changed how it's calculated, also changed testcase to be slightly less worst-case.

The previous testcase was "all nodes communicating randomly", basically a worst-case.
This testcase is somewhat more realistic, a set of nodes communicating between each other via other
 nodes, a given TO node recurring once every 5 seconds (approximately).
Notably, the 'packet transfer total' figure should be halved, as in the testcase pings and responses
 are used, but only responses are counted.
This commit is contained in:
gamemanj 2017-03-18 12:28:46 +00:00
parent 97fd892922
commit 47ec74bc89
5 changed files with 65 additions and 29 deletions

View File

@ -26,18 +26,18 @@ return function (hostname, transmit, onReceive, time)
-- How many packets need to be stored in seenBefore's keyspace
-- before 'panic' is the best response?
local tuningMaxSeenBeforeCountBeforeEmergencyFlush = 0x100
local tuningMaxSeenBeforeCountBeforeEmergencyFlush = 0x300
-- Expect a response by this many seconds,
-- or else clear the known receivers cache and resend.
local tuningExpectResponse = 10
local tuningExpectResponse = 120
-- Flush the loop detector every so often.
-- This is not a complete clear.
local tuningFlushLoopDetector = 10
local tuningFlushLoopDetector = 120
-- Do not change this value. I mean it. Don't. Just. Don't.
local tuningAutorejectLen = 4000
-- Do not change this value unless protocol has changed accordingly.
local tuningAutorejectLen = 1506
local loopDetectorNext = time() + tuningFlushLoopDetector
@ -68,10 +68,11 @@ return function (hostname, transmit, onReceive, time)
seenBeforeCount = seenBeforeCount - 1
end
end
loopDetectorNext = time() + tuningFlushLoopDetector
loopDetectorNext = t + tuningFlushLoopDetector
end
for k, v in pairs(lastKnownReceiver) do
if t >= v[2] then
print("It was decided LKV[" .. k .. "] was out of date @ " .. v[2])
lastKnownReceiver[k] = nil
for _, m in ipairs(v[3]) do
transmit(nil, m)
@ -86,14 +87,16 @@ return function (hostname, transmit, onReceive, time)
culib.hostname = hostname
culib.input = function (node, message)
local t = time()
if message:len() > tuningAutorejectLen then
return
end
-- Eliminate the hops value first of all.
local hops = message:byte(1)
message = message:sub(2)
if seenBefore[message] then
seenBefore[message] = seenBefore[message] + 1
return
else
seenBefore[message] = 0
seenBefore[message] = 2
seenBeforeCount = seenBeforeCount + 1
if seenBeforeCount > tuningMaxSeenBeforeCountBeforeEmergencyFlush then
-- Panic
@ -101,7 +104,8 @@ return function (hostname, transmit, onReceive, time)
seenBefore = {}
end
end
-- Begin parsing
-- Begin parsing.
local rawmessage = message
if message:len() < 2 then return end
@ -114,12 +118,34 @@ return function (hostname, transmit, onReceive, time)
local tnam = message:sub(2, nlen + 1)
message = message:sub(nlen + 2)
lastKnownReceiver[fnam] = {node, t + tuningExpectResponse, {}}
if message:len() > tuningAutorejectLen then
return
end
local restart = true
if lastKnownReceiver[fnam] then
if lastKnownReceiver[fnam][1] == node then
restart = false
-- allow frequently-used links to last longer
lastKnownReceiver[fnam][2] = lastKnownReceiver[fnam][2] + tuningExpectResponse
lastKnownReceiver[fnam][3] = {}
end
else
end
if restart then
lastKnownReceiver[fnam] = {node, t + tuningExpectResponse, {}}
end
onReceive(fnam, tnam, message)
if culib.hostname == tnam then return end
-- Redistribution of messages not aimed here
if hops == 255 then
return
else
rawmessage = string.char(hops + 1) .. rawmessage
end
local lkr = lastKnownReceiver[tnam]
if lkr then
transmit(lkr[1], rawmessage)
@ -137,7 +163,7 @@ return function (hostname, transmit, onReceive, time)
culib.output = function (fnam, tnam, message)
onReceive(fnam, tnam, message)
if tnam == culib.hostname then return end
local m = encodeName(fnam) .. encodeName(tnam) .. message
local m = "\x00" .. encodeName(fnam) .. encodeName(tnam) .. message
transmit(nil, m)
end
return culib

View File

@ -15,14 +15,15 @@ Copper addresses are names.
In the context of a system not implementing a hierarchial gateway,
this is as much about Copper addressing as matters.
Copper base packets contain 3 fields.
Copper base packets contain 4 fields.
One byte indicating how many nodes have retransmitted the message
(the original sender should use 0),
A name (as a length-minus-1-byte-prefixed-string),
another name (in the same format),
and the rest is data.
Copper packets may be up to 4000 bytes long, including base.
(It's assumed the additional 96 bytes will be useful for any additional
framing, assuming a 4K packet limit.)
Copper packet data may be up to 1506 bytes long -
this does not include header data, which may be up to (256*2) + 3 bytes long.
Loop detection should performed by checking if a packet exactly the same has
been seen recently - other rejection, alteration and routing measures
@ -36,4 +37,4 @@ Should a situation be dire enough,
hierarchial networks (described in file 2, 'protocol.1'),
and custom routing software in general,
can be used to split networks however the system requires.
Copper isn't very picky.

View File

@ -8,8 +8,7 @@ They are simply base low-level Copper nodes with two interfaces and the
For the FROM address:
If it's on the parent side, reject if it's prefixed with hostname ..
"/",
If it's on the parent side, reject if it's prefixed with hostname .. "/",
otherwise prefix it with "<" and forward to child side.
If it's on the child side, reject if it's prefixed with "<",
otherwise prefix it with hostname .. "/" and forward to parent side.

View File

@ -17,15 +17,14 @@ All implementations of Copper that synthesize their own packets SHOULD
follow this protocol when doing so, unless they are a custom system
that will not be connected to any global network.
Firstly, note that, to the application, a Reliability Layer packet can
be up to 59,895 bytes in size, though a fragment can only be up to 3993 bytes.
be up to 22,500 bytes in size, though a fragment can only be up to 1500 bytes.
Secondly, note that an application should be able to ask to be notified
when a packet is received successfully or when the implementation gives up,
with a flag indicating which is which.
Reliability Layer packets have a simple format.
Reliability Layer packets have a simple 6-byte header.
The first two bytes are the port number, in big-endian format.
The next three bytes are a number to this application-side packet.
They should be as random as possible.

View File

@ -7,7 +7,7 @@ local nodenames = {}
local systime = 0
local function getsystime()
return systime / 20
return systime / 10
end
local queuedCalls = {}
@ -58,13 +58,24 @@ end)
-- Start testing
local targetables = {}
local targetableCount = 10
for i = 1, targetableCount do
targetables[i] = math.random(#nodes)
end
local function generateMessage()
local na = math.random(#nodes)
local nb = math.random(#nodes)
local na = 1
local nb = 1
while na == nb do
na = targetables[math.random(#targetables)]
nb = targetables[math.random(#targetables)]
end
nodes[na].output(nodenames[na], nodenames[nb], "T" .. tostring(math.random()))
end
local generateEvery = 1
-- ~Once every 5 seconds, think a polling script
local generateEvery = math.floor(50 / targetableCount)
local generateCount = 10000
while (generateCount > 0) or (#queuedCalls > 0) do
if (systime % generateEvery) == 0 then
@ -81,8 +92,8 @@ while (generateCount > 0) or (#queuedCalls > 0) do
for _, v in ipairs(qc) do
v()
end
print("run iteration, " .. #qc .. " calls")
--print("run iteration, " .. #qc .. " calls")
systime = systime + 1
end
print(statSD, statPT)
print(#nodes, statSD, statPT)