1
0
mirror of https://github.com/XeonSquared/OC-Copper.git synced 2024-11-23 09:58:06 +11:00

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

View File

@ -15,14 +15,15 @@ Copper addresses are names.
In the context of a system not implementing a hierarchial gateway, In the context of a system not implementing a hierarchial gateway,
this is as much about Copper addressing as matters. 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), A name (as a length-minus-1-byte-prefixed-string),
another name (in the same format), another name (in the same format),
and the rest is data. and the rest is data.
Copper packets may be up to 4000 bytes long, including base. Copper packet data may be up to 1506 bytes long -
(It's assumed the additional 96 bytes will be useful for any additional this does not include header data, which may be up to (256*2) + 3 bytes long.
framing, assuming a 4K packet limit.)
Loop detection should performed by checking if a packet exactly the same has Loop detection should performed by checking if a packet exactly the same has
been seen recently - other rejection, alteration and routing measures 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'), hierarchial networks (described in file 2, 'protocol.1'),
and custom routing software in general, and custom routing software in general,
can be used to split networks however the system requires. 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: 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. otherwise prefix it with "<" and forward to child side.
If it's on the child side, reject if it's prefixed with "<", If it's on the child side, reject if it's prefixed with "<",
otherwise prefix it with hostname .. "/" and forward to parent side. 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 follow this protocol when doing so, unless they are a custom system
that will not be connected to any global network. that will not be connected to any global network.
Firstly, note that, to the application, a Reliability Layer packet can 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 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, when a packet is received successfully or when the implementation gives up,
with a flag indicating which is which. 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 first two bytes are the port number, in big-endian format.
The next three bytes are a number to this application-side packet. The next three bytes are a number to this application-side packet.
They should be as random as possible. They should be as random as possible.

View File

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