diff --git a/src/accept.c b/src/accept.c
index 6fddd31..fb3856a 100644
--- a/src/accept.c
+++ b/src/accept.c
@@ -1340,6 +1340,7 @@ int accept_listener_status(cJSON *listeners, cJSON *totals)
cJSON_AddNumberToObject(jl, "pkts_rx", l->portaccount->rxpackets);
cJSON_AddNumberToObject(jl, "pkts_tx", l->portaccount->txpackets);
cJSON_AddNumberToObject(jl, "pkts_ign", l->portaccount->rxdrops);
+ cJSON_AddNumberToObject(jl, "pkts_dup", l->portaccount->rxdupes);
json_add_rxerrs(jl, "rx_errs", l->portaccount->rxerrs);
cJSON_AddItemToArray(listeners, jl);
diff --git a/src/incoming.c b/src/incoming.c
index 182ac72..79ebc60 100644
--- a/src/incoming.c
+++ b/src/incoming.c
@@ -968,7 +968,7 @@ in_drop:
/* Account the one incoming packet.
* Incoming bytes were already accounted earlier.
*/
- clientaccount_add(c, l4proto, 0, 1, 0, 0, (e < 0) ? e : 0);
+ clientaccount_add(c, l4proto, 0, 1, 0, 0, (e < 0) ? e : 0, 0);
return 0;
}
diff --git a/src/outgoing.c b/src/outgoing.c
index 952b522..8806203 100644
--- a/src/outgoing.c
+++ b/src/outgoing.c
@@ -27,9 +27,9 @@
static inline void send_single(struct worker_t *self, struct client_t *c, struct pbuf_t *pb)
{
if (c->udp_port && c->udpclient)
- clientaccount_add( c, IPPROTO_UDP, 0, 0, 0, 1, 0);
+ clientaccount_add( c, IPPROTO_UDP, 0, 0, 0, 1, 0, 0);
else
- clientaccount_add( c, IPPROTO_TCP, 0, 0, 0, 1, 0);
+ clientaccount_add( c, IPPROTO_TCP, 0, 0, 0, 1, 0, 0);
client_write(self, c, pb->data, pb->packet_len);
}
@@ -59,6 +59,17 @@ static void process_outgoing_single(struct worker_t *self, struct pbuf_t *pb)
send_single(self, c, pb);
}
+ /* Check if I have the client which sent this dupe, and
+ * increment it's dupe counter
+ */
+ /* OPTIMIZE: we walk through all clients for each dupe - how to find it quickly? */
+ for (c = self->clients; (c); c = c->next) {
+ if (c == pb->origin) {
+ clientaccount_add(c, -1, 0, 0, 0, 0, 0, 1);
+ break;
+ }
+ }
+
return;
}
diff --git a/src/web/aprsc.css b/src/web/aprsc.css
index 05e9c59..643efe1 100644
--- a/src/web/aprsc.css
+++ b/src/web/aprsc.css
@@ -68,7 +68,7 @@ div.msg_e, div.msg_i, div.msg_s {
padding: 5px;
margin: 5px 25px 5px 0px;
border-radius: 5px;
- width: 450px;
+ width: 480px;
}
/* tooltip */
diff --git a/src/web/aprsc.js b/src/web/aprsc.js
index 8604959..d82ad5a 100644
--- a/src/web/aprsc.js
+++ b/src/web/aprsc.js
@@ -98,12 +98,12 @@ function client_bytes_rates(c, k)
function client_pkts_rx(c, k)
{
- if (isUndefined(c['pkts_ign']))
- return c['pkts_rx'];
+ //if (isUndefined(c['pkts_ign']))
+ // return c['pkts_rx'];
- var s = c['pkts_rx'] + '/' + c['pkts_ign'];
+ var s = c['pkts_rx'] + '/' + c['pkts_dup'] + '/' + c['pkts_ign'];
- if (c['pkts_ign'] > 0)
+ if (c['pkts_ign'] > 0 || c['pkts_dup'] > 0)
return '' + s + '';
@@ -386,7 +386,7 @@ function rx_err_contents(fd)
if (isUndefined(er))
return 'No rx errors for client on fd ' + fd;
- var s = 'Received packets dropped: ' + fd_clients[fd]['pkts_ign'] + ' out of ' + fd_clients[fd]['pkts_rx'] + '
';
+ var s = 'Receive drops: ' + fd_clients[fd]['pkts_dup'] + ' dupes, ' + fd_clients[fd]['pkts_ign'] + ' errors in ' + fd_clients[fd]['pkts_rx'] + '
';
for (var i = 0; i < rx_err_codes.length; i++) {
if (er[i] < 1)
diff --git a/src/worker.c b/src/worker.c
index adf2f5e..65be5e1 100644
--- a/src/worker.c
+++ b/src/worker.c
@@ -587,7 +587,7 @@ char *hexsockaddr(const struct sockaddr *sa, const int addr_len)
return hstrdup(eb);
}
-void clientaccount_add(struct client_t *c, int l4proto, int rxbytes, int rxpackets, int txbytes, int txpackets, int rxerr)
+void clientaccount_add(struct client_t *c, int l4proto, int rxbytes, int rxpackets, int txbytes, int txpackets, int rxerr, int rxdupes)
{
struct portaccount_t *pa = NULL;
int rxdrops = 0;
@@ -604,6 +604,7 @@ void clientaccount_add(struct client_t *c, int l4proto, int rxbytes, int rxpacke
c->localaccount.txbytes += txbytes;
c->localaccount.rxpackets += rxpackets;
c->localaccount.txpackets += txpackets;
+ c->localaccount.rxdupes += rxdupes;
if (rxdrops) {
c->localaccount.rxdrops += 1;
c->localaccount.rxerrs[rxerr] += 1;
@@ -621,6 +622,7 @@ void clientaccount_add(struct client_t *c, int l4proto, int rxbytes, int rxpacke
__sync_fetch_and_add(&pa->txbytes, txbytes);
__sync_fetch_and_add(&pa->rxpackets, rxpackets);
__sync_fetch_and_add(&pa->txpackets, txpackets);
+ __sync_fetch_and_add(&pa->rxdupes, rxdupes);
if (rxdrops) {
__sync_fetch_and_add(&pa->rxdrops, 1);
__sync_fetch_and_add(&pa->rxerrs[rxerr], 1);
@@ -631,6 +633,7 @@ void clientaccount_add(struct client_t *c, int l4proto, int rxbytes, int rxpacke
pa->txbytes += txbytes;
pa->rxpackets += rxpackets;
pa->txpackets += txpackets;
+ pa->rxdupes += rxdupes;
if (rxdrops) {
pa->rxdrops += 1;
pa->rxerrs[rxerr] += 1;
@@ -848,7 +851,7 @@ int client_write(struct worker_t *self, struct client_t *c, char *p, int len)
// hlog( LOG_DEBUG, "UDP from %d to client port %d, sendto rc=%d", c->udpclient->portnum, c->udp_port, i );
if (i > 0)
- clientaccount_add( c, IPPROTO_UDP, 0, 0, i, 0, 0);
+ clientaccount_add( c, IPPROTO_UDP, 0, 0, i, 0, 0, 0);
return i;
}
@@ -863,7 +866,7 @@ int client_write(struct worker_t *self, struct client_t *c, char *p, int len)
* will be incremented only when we actually transmit a packet
* instead of a keepalive.
*/
- clientaccount_add( c, IPPROTO_TCP, 0, 0, len, 0, 0);
+ clientaccount_add( c, IPPROTO_TCP, 0, 0, len, 0, 0, 0);
}
if (c->obuf_end + len > c->obuf_size) {
@@ -1088,7 +1091,7 @@ static int handle_corepeer_readable(struct worker_t *self, struct client_t *c)
hlog(LOG_DEBUG, "worker thread passing UDP packet from %s to handler: %*s", addrs, r, c->ibuf);
hfree(addrs);
*/
- clientaccount_add( rc, IPPROTO_UDP, r, 0, 0, 0, 0); /* Account byte count. incoming_handler() will account packets. */
+ clientaccount_add( rc, IPPROTO_UDP, r, 0, 0, 0, 0, 0); /* Account byte count. incoming_handler() will account packets. */
rc->last_read = tick;
/* Ignore CRs and LFs in UDP input packet - the current core peer system puts 1 APRS packet in each
@@ -1150,7 +1153,7 @@ static int handle_client_readable(struct worker_t *self, struct client_t *c)
return -1;
}
- clientaccount_add(c, IPPROTO_TCP, r, 0, 0, 0, 0); /* Number of packets is now unknown,
+ clientaccount_add(c, IPPROTO_TCP, r, 0, 0, 0, 0, 0); /* Number of packets is now unknown,
byte count is collected.
The incoming_handler() will account
packets. */
@@ -1931,6 +1934,7 @@ static struct cJSON *worker_client_json(struct client_t *c, int liveup_info)
cJSON_AddNumberToObject(jc, "pkts_rx", c->localaccount.rxpackets);
cJSON_AddNumberToObject(jc, "pkts_tx", c->localaccount.txpackets);
cJSON_AddNumberToObject(jc, "pkts_ign", c->localaccount.rxdrops);
+ cJSON_AddNumberToObject(jc, "pkts_dup", c->localaccount.rxdupes);
cJSON_AddNumberToObject(jc, "heard_count", c->client_heard_count);
cJSON_AddNumberToObject(jc, "courtesy_count", c->client_courtesy_count);
diff --git a/src/worker.h b/src/worker.h
index 6e0b585..65312fe 100644
--- a/src/worker.h
+++ b/src/worker.h
@@ -210,7 +210,7 @@ struct portaccount_t { /* Port accounter tracks port usage, and traffic
long long rxbytes, txbytes;
long long rxpackets, txpackets;
- long long rxdrops;
+ long long rxdrops, rxdupes;
long long rxerrs[INERR_BUCKETS];
/* record usage references */
@@ -469,7 +469,7 @@ extern void port_accounter_drop(struct portaccount_t *p);
extern char *strsockaddr(const struct sockaddr *sa, const int addr_len);
extern char *hexsockaddr(const struct sockaddr *sa, const int addr_len);
-extern void clientaccount_add(struct client_t *c, int l4proto, int rxbytes, int rxpackets, int txbytes, int txpackets, int rxerr);
+extern void clientaccount_add(struct client_t *c, int l4proto, int rxbytes, int rxpackets, int txbytes, int txpackets, int rxerr, int rxdupes);
extern void json_add_rxerrs(cJSON *root, const char *key, long long vals[]);
extern int worker_client_list(cJSON *workers, cJSON *clients, cJSON *uplinks, cJSON *peers, cJSON *totals, cJSON *memory);