* CommonCLI: new "multi.acks" config setting
This commit is contained in:
@@ -339,6 +339,9 @@ protected:
|
|||||||
int getAGCResetInterval() const override {
|
int getAGCResetInterval() const override {
|
||||||
return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds
|
return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds
|
||||||
}
|
}
|
||||||
|
uint8_t getExtraAckTransmitCount() const override {
|
||||||
|
return _prefs.multi_acks;
|
||||||
|
}
|
||||||
|
|
||||||
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override {
|
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override {
|
||||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin client (unknown at this stage)
|
if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin client (unknown at this stage)
|
||||||
|
|||||||
@@ -424,6 +424,9 @@ protected:
|
|||||||
int getAGCResetInterval() const override {
|
int getAGCResetInterval() const override {
|
||||||
return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds
|
return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds
|
||||||
}
|
}
|
||||||
|
uint8_t getExtraAckTransmitCount() const override {
|
||||||
|
return _prefs.multi_acks;
|
||||||
|
}
|
||||||
|
|
||||||
bool allowPacketForward(const mesh::Packet* packet) override {
|
bool allowPacketForward(const mesh::Packet* packet) override {
|
||||||
if (_prefs.disable_fwd) return false;
|
if (_prefs.disable_fwd) return false;
|
||||||
@@ -583,12 +586,16 @@ protected:
|
|||||||
if (ack) sendFlood(ack, TXT_ACK_DELAY);
|
if (ack) sendFlood(ack, TXT_ACK_DELAY);
|
||||||
delay_millis = TXT_ACK_DELAY + REPLY_DELAY_MILLIS;
|
delay_millis = TXT_ACK_DELAY + REPLY_DELAY_MILLIS;
|
||||||
} else {
|
} else {
|
||||||
mesh::Packet* a1 = createMultiAck(ack_hash, 1);
|
uint32_t d = TXT_ACK_DELAY;
|
||||||
if (a1) sendDirect(a1, client->out_path, client->out_path_len, TXT_ACK_DELAY);
|
if (getExtraAckTransmitCount() > 0) {
|
||||||
|
mesh::Packet* a1 = createMultiAck(ack_hash, 1);
|
||||||
|
if (a1) sendDirect(a1, client->out_path, client->out_path_len, d);
|
||||||
|
d += 300;
|
||||||
|
}
|
||||||
|
|
||||||
mesh::Packet* a2 = createAck(ack_hash);
|
mesh::Packet* a2 = createAck(ack_hash);
|
||||||
if (a2) sendDirect(a2, client->out_path, client->out_path_len, TXT_ACK_DELAY + 300);
|
if (a2) sendDirect(a2, client->out_path, client->out_path_len, d);
|
||||||
delay_millis = TXT_ACK_DELAY + REPLY_DELAY_MILLIS + 300;
|
delay_millis = d + REPLY_DELAY_MILLIS;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
delay_millis = 0;
|
delay_millis = 0;
|
||||||
|
|||||||
57
src/Mesh.cpp
57
src/Mesh.cpp
@@ -22,6 +22,9 @@ uint32_t Mesh::getRetransmitDelay(const mesh::Packet* packet) {
|
|||||||
uint32_t Mesh::getDirectRetransmitDelay(const Packet* packet) {
|
uint32_t Mesh::getDirectRetransmitDelay(const Packet* packet) {
|
||||||
return 0; // by default, no delay
|
return 0; // by default, no delay
|
||||||
}
|
}
|
||||||
|
uint8_t Mesh::getExtraAckTransmitCount() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Mesh::getCADFailRetryDelay() const {
|
uint32_t Mesh::getCADFailRetryDelay() const {
|
||||||
return _rng->nextInt(1, 4)*120;
|
return _rng->nextInt(1, 4)*120;
|
||||||
@@ -99,7 +102,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
|||||||
} else if (!_tables->hasSeen(pkt)) {
|
} else if (!_tables->hasSeen(pkt)) {
|
||||||
onAckRecv(pkt, ack_crc);
|
onAckRecv(pkt, ack_crc);
|
||||||
action = routeRecvPacket(pkt);
|
action = routeRecvPacket(pkt);
|
||||||
// routeRecvAcks(pkt, 0); // experimental, double Acks in flood mode(?)
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -280,7 +282,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
|
|||||||
memcpy(&ack_crc, tmp.payload, 4);
|
memcpy(&ack_crc, tmp.payload, 4);
|
||||||
|
|
||||||
onAckRecv(&tmp, ack_crc);
|
onAckRecv(&tmp, ack_crc);
|
||||||
// routeRecvAcks(&tmp, ((uint32_t)remaining) * 600); // expect multipart ACK 300ms apart (x2)
|
|
||||||
//action = routeRecvPacket(&tmp); // NOTE: currently not needed, as multipart ACKs not sent Flood
|
//action = routeRecvPacket(&tmp); // NOTE: currently not needed, as multipart ACKs not sent Flood
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -324,37 +325,6 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
|
|||||||
return ACTION_RELEASE;
|
return ACTION_RELEASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void Mesh::routeRecvAcks(Packet* packet, uint32_t delay_millis) {
|
|
||||||
if (packet->isRouteFlood() && !packet->isMarkedDoNotRetransmit()
|
|
||||||
&& packet->path_len + PATH_HASH_SIZE <= MAX_PATH_SIZE && allowPacketForward(packet)) {
|
|
||||||
// append this node's hash to 'path'
|
|
||||||
packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]);
|
|
||||||
|
|
||||||
uint32_t crc;
|
|
||||||
memcpy(&crc, packet->payload, 4);
|
|
||||||
|
|
||||||
delay_millis += getRetransmitDelay(packet);
|
|
||||||
auto a1 = createMultiAck(crc, 1);
|
|
||||||
if (a1) {
|
|
||||||
memcpy(a1->path, packet->path, a1->path_len = packet->path_len);
|
|
||||||
a1->header &= ~PH_ROUTE_MASK;
|
|
||||||
a1->header |= ROUTE_TYPE_FLOOD;
|
|
||||||
sendPacket(a1, 1, delay_millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
delay_millis += 300;
|
|
||||||
auto a2 = createAck(crc);
|
|
||||||
if (a2) {
|
|
||||||
memcpy(a2->path, packet->path, a2->path_len = packet->path_len);
|
|
||||||
a2->header &= ~PH_ROUTE_MASK;
|
|
||||||
a2->header |= ROUTE_TYPE_FLOOD;
|
|
||||||
sendPacket(a2, 1, delay_millis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
|
DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
|
||||||
uint8_t remaining = pkt->payload[0] >> 4; // num of packets in this multipart sequence still to be sent
|
uint8_t remaining = pkt->payload[0] >> 4; // num of packets in this multipart sequence still to be sent
|
||||||
uint8_t type = pkt->payload[0] & 0x0F;
|
uint8_t type = pkt->payload[0] & 0x0F;
|
||||||
@@ -369,7 +339,7 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
|
|||||||
|
|
||||||
if (!_tables->hasSeen(&tmp)) { // don't retransmit!
|
if (!_tables->hasSeen(&tmp)) { // don't retransmit!
|
||||||
removeSelfFromPath(&tmp);
|
removeSelfFromPath(&tmp);
|
||||||
routeDirectRecvAcks(&tmp, ((uint32_t)remaining) * 600); // expect multipart ACKs 300ms apart (x2)
|
routeDirectRecvAcks(&tmp, ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ACTION_RELEASE;
|
return ACTION_RELEASE;
|
||||||
@@ -380,16 +350,19 @@ void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) {
|
|||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
memcpy(&crc, packet->payload, 4);
|
memcpy(&crc, packet->payload, 4);
|
||||||
|
|
||||||
delay_millis += getDirectRetransmitDelay(packet);
|
uint8_t extra = getExtraAckTransmitCount();
|
||||||
auto a1 = createMultiAck(crc, 1);
|
while (extra > 0) {
|
||||||
if (a1) {
|
delay_millis += getDirectRetransmitDelay(packet) + 300;
|
||||||
memcpy(a1->path, packet->path, a1->path_len = packet->path_len);
|
auto a1 = createMultiAck(crc, extra);
|
||||||
a1->header &= ~PH_ROUTE_MASK;
|
if (a1) {
|
||||||
a1->header |= ROUTE_TYPE_DIRECT;
|
memcpy(a1->path, packet->path, a1->path_len = packet->path_len);
|
||||||
sendPacket(a1, 0, delay_millis);
|
a1->header &= ~PH_ROUTE_MASK;
|
||||||
|
a1->header |= ROUTE_TYPE_DIRECT;
|
||||||
|
sendPacket(a1, 0, delay_millis);
|
||||||
|
}
|
||||||
|
extra--;
|
||||||
}
|
}
|
||||||
|
|
||||||
delay_millis += 300;
|
|
||||||
auto a2 = createAck(crc);
|
auto a2 = createAck(crc);
|
||||||
if (a2) {
|
if (a2) {
|
||||||
memcpy(a2->path, packet->path, a2->path_len = packet->path_len);
|
memcpy(a2->path, packet->path, a2->path_len = packet->path_len);
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual uint32_t getDirectRetransmitDelay(const Packet* packet);
|
virtual uint32_t getDirectRetransmitDelay(const Packet* packet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \returns number of extra (Direct) ACK transmissions wanted.
|
||||||
|
*/
|
||||||
|
virtual uint8_t getExtraAckTransmitCount() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Perform search of local DB of peers/contacts.
|
* \brief Perform search of local DB of peers/contacts.
|
||||||
* \returns Number of peers with matching hash
|
* \returns Number of peers with matching hash
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||||||
file.read((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112
|
file.read((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112
|
||||||
file.read((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113
|
file.read((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113
|
||||||
file.read((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
file.read((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
||||||
file.read((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115
|
file.read((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115
|
||||||
file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116
|
file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116
|
||||||
file.read((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
file.read((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
||||||
file.read(pad, 3); // 121
|
file.read(pad, 3); // 121
|
||||||
@@ -69,6 +69,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||||||
_prefs->sf = constrain(_prefs->sf, 7, 12);
|
_prefs->sf = constrain(_prefs->sf, 7, 12);
|
||||||
_prefs->cr = constrain(_prefs->cr, 5, 8);
|
_prefs->cr = constrain(_prefs->cr, 5, 8);
|
||||||
_prefs->tx_power_dbm = constrain(_prefs->tx_power_dbm, 1, 30);
|
_prefs->tx_power_dbm = constrain(_prefs->tx_power_dbm, 1, 30);
|
||||||
|
_prefs->multi_acks = constrain(_prefs->multi_acks, 0, 1);
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
@@ -106,7 +107,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
|||||||
file.write((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112
|
file.write((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112
|
||||||
file.write((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113
|
file.write((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113
|
||||||
file.write((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
file.write((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
||||||
file.write((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115
|
file.write((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115
|
||||||
file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116
|
file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116
|
||||||
file.write((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
file.write((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
||||||
file.write(pad, 3); // 121
|
file.write(pad, 3); // 121
|
||||||
@@ -180,6 +181,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
sprintf(reply, "> %d", (uint32_t) _prefs->interference_threshold);
|
sprintf(reply, "> %d", (uint32_t) _prefs->interference_threshold);
|
||||||
} else if (memcmp(config, "agc.reset.interval", 18) == 0) {
|
} else if (memcmp(config, "agc.reset.interval", 18) == 0) {
|
||||||
sprintf(reply, "> %d", ((uint32_t) _prefs->agc_reset_interval) * 4);
|
sprintf(reply, "> %d", ((uint32_t) _prefs->agc_reset_interval) * 4);
|
||||||
|
} else if (memcmp(config, "multi.acks", 10) == 0) {
|
||||||
|
sprintf(reply, "> %d", (uint32_t) _prefs->multi_acks);
|
||||||
} else if (memcmp(config, "allow.read.only", 15) == 0) {
|
} else if (memcmp(config, "allow.read.only", 15) == 0) {
|
||||||
sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off");
|
sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off");
|
||||||
} else if (memcmp(config, "flood.advert.interval", 21) == 0) {
|
} else if (memcmp(config, "flood.advert.interval", 21) == 0) {
|
||||||
@@ -235,6 +238,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
_prefs->agc_reset_interval = atoi(&config[19]) / 4;
|
_prefs->agc_reset_interval = atoi(&config[19]) / 4;
|
||||||
savePrefs();
|
savePrefs();
|
||||||
strcpy(reply, "OK");
|
strcpy(reply, "OK");
|
||||||
|
} else if (memcmp(config, "multi.acks ", 11) == 0) {
|
||||||
|
_prefs->multi_acks = atoi(&config[11]);
|
||||||
|
savePrefs();
|
||||||
|
strcpy(reply, "OK");
|
||||||
} else if (memcmp(config, "allow.read.only ", 16) == 0) {
|
} else if (memcmp(config, "allow.read.only ", 16) == 0) {
|
||||||
_prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0;
|
_prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0;
|
||||||
savePrefs();
|
savePrefs();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ struct NodePrefs { // persisted to file
|
|||||||
uint8_t sf;
|
uint8_t sf;
|
||||||
uint8_t cr;
|
uint8_t cr;
|
||||||
uint8_t allow_read_only;
|
uint8_t allow_read_only;
|
||||||
uint8_t reserved2;
|
uint8_t multi_acks;
|
||||||
float bw;
|
float bw;
|
||||||
uint8_t flood_max;
|
uint8_t flood_max;
|
||||||
uint8_t interference_threshold;
|
uint8_t interference_threshold;
|
||||||
|
|||||||
Reference in New Issue
Block a user