Improve html debug statistics

- shift radio rssi onto interace structure
- track packets sent received
- create html output for interface stats
- create html output for link state routing stats
This commit is contained in:
Jeremy Lakeman 2013-09-23 11:11:58 +09:30
parent ae25091fab
commit 08b44e96ed
7 changed files with 202 additions and 75 deletions

View File

@ -204,11 +204,6 @@ int mavlink_heartbeat(unsigned char *frame,int *outlen)
return 0;
}
extern unsigned long long last_rssi_time;
extern int last_radio_rssi;
extern int last_radio_temperature;
extern int last_radio_rxpackets;
static int parse_heartbeat(struct overlay_interface *interface, const unsigned char *payload)
{
if (payload[0]==0xFE
@ -218,9 +213,8 @@ static int parse_heartbeat(struct overlay_interface *interface, const unsigned c
&& payload[5]==MAVLINK_MSG_ID_RADIO){
// we can assume that radio status packets arrive without corruption
last_radio_rssi=(1.0*payload[10]-payload[13])/1.9;
last_radio_temperature=-999; // doesn't get reported
last_radio_rxpackets=-999; // doesn't get reported
interface->radio_rssi=(1.0*payload[10]-payload[13])/1.9;
interface->remote_rssi=(1.0*payload[11] - payload[14])/1.9;
int free_space = payload[12];
int free_bytes = (free_space * 1280) / 100 - 30;
interface->remaining_space = free_bytes;
@ -228,12 +222,11 @@ static int parse_heartbeat(struct overlay_interface *interface, const unsigned c
interface->next_tx_allowed = gettime_ms();
if (free_bytes>720)
interface->next_heartbeat=gettime_ms()+1000;
if (config.debug.mavlink||gettime_ms()-last_rssi_time>30000) {
if (config.debug.packetradio) {
INFOF("Link budget = %+ddB, remote link budget = %+ddB, buffer space = %d%% (approx %d)",
last_radio_rssi,
(int)((1.0*payload[11] - payload[14])/1.9),
interface->radio_rssi,
interface->remote_rssi,
free_space, free_bytes);
last_rssi_time=gettime_ms();
}
return 1;
}

View File

@ -63,6 +63,54 @@ overlay_interface_close(overlay_interface *interface){
interface->state=INTERFACE_STATE_DOWN;
}
void interface_state_html(struct strbuf *b, struct overlay_interface *interface)
{
switch(interface->state){
case INTERFACE_STATE_UP:
strbuf_sprintf(b, "Interface %s is Up<br>", interface->name);
break;
default:
strbuf_puts(b, "Interface Down");
return;
}
switch(interface->type){
case OVERLAY_INTERFACE_PACKETRADIO:
strbuf_puts(b, "Type: Packet Radio<br>");
strbuf_sprintf(b, "RSSI: %ddB<br>",interface->radio_rssi);
strbuf_sprintf(b, "Remote RSSI: %ddB<br>",interface->remote_rssi);
break;
case OVERLAY_INTERFACE_ETHERNET:
strbuf_puts(b, "Type: Ethernet<br>");
break;
case OVERLAY_INTERFACE_WIFI:
strbuf_puts(b, "Type: Wifi<br>");
break;
default:
case OVERLAY_INTERFACE_UNKNOWN:
strbuf_puts(b, "Type: Unknown<br>");
}
switch(interface->socket_type){
case SOCK_STREAM:
strbuf_puts(b, "Socket: Stream<br>");
break;
case SOCK_DGRAM:
{
char addrtxt[INET_ADDRSTRLEN];
strbuf_puts(b, "Socket: DGram<br>");
if (inet_ntop(AF_INET, (const void *)&interface->address.sin_addr, addrtxt, INET_ADDRSTRLEN))
strbuf_sprintf(b, "Address: %s:%d<br>", addrtxt, ntohs(interface->address.sin_port));
if (inet_ntop(AF_INET, (const void *)&interface->destination->address.sin_addr, addrtxt, INET_ADDRSTRLEN))
strbuf_sprintf(b, "Broadcast Address: %s:%d<br>", addrtxt, ntohs(interface->destination->address.sin_port));
}
break;
case SOCK_FILE:
strbuf_puts(b, "Socket: File<br>");
break;
}
strbuf_sprintf(b, "TX: %d<br>", interface->tx_count);
strbuf_sprintf(b, "RX: %d<br>", interface->recv_count);
}
// create a socket with options common to all our UDP sockets
static int
overlay_bind_socket(const struct sockaddr *addr, size_t addr_size, char *interface_name){
@ -230,7 +278,6 @@ overlay_interface_read_any(struct sched_ent *alarm){
DEBUGF("Could not find matching interface for packet received from %s", inet_ntoa(src));
return;
}
packetOkOverlay(interface, packet, plen, recvttl, &src_addr, addrlen);
}
if (alarm->poll.revents & (POLLHUP | POLLERR)) {
@ -374,6 +421,8 @@ overlay_interface_init(const char *name, struct in_addr src_addr, struct in_addr
interface->state=INTERFACE_STATE_DOWN;
interface->alarm.poll.fd=0;
interface->debug = ifconfig->debug;
interface->tx_count=0;
interface->recv_count=0;
// How often do we announce ourselves on this interface?
int tick_ms=-1;
@ -655,8 +704,6 @@ static void interface_read_stream(struct overlay_interface *interface){
OUT();
return;
}
if (config.debug.packetradio)
dump("read bytes", buffer, nread);
struct slip_decode_state *state=&interface->slip_decode_state;
int i;
@ -681,14 +728,12 @@ static void write_stream_buffer(overlay_interface *interface){
// Queue a hearbeat now
mavlink_heartbeat(interface->txbuffer,&interface->tx_bytes_pending);
if (config.debug.packetradio)
DEBUGF("Built %d byte heartbeat", interface->tx_bytes_pending);
DEBUGF("Sending heartbeat");
interface->next_heartbeat = now+1000;
}else if(interface->tx_packet && interface->remaining_space >= 256 + 8+9){
// prepare a new link layer packet in txbuffer
if (mavlink_encode_packet(interface))
break;
if (config.debug.packetradio)
DEBUGF("Built %d byte payload from packet (%d)", interface->tx_bytes_pending, interface->remaining_space);
if (interface->remaining_space - interface->tx_bytes_pending < 256 + 8+9)
interface->next_heartbeat = now;
}
@ -703,8 +748,6 @@ static void write_stream_buffer(overlay_interface *interface){
if (bytes<=0)
break;
if (config.debug.packetradio)
DEBUGF("Trying to write %d bytes of %d%s", bytes, interface->tx_bytes_pending, interface->tx_packet?", pending packet":"");
int written=write(interface->alarm.poll.fd, interface->txbuffer, bytes);
if (written<=0){
DEBUGF("Blocking for POLLOUT");
@ -720,8 +763,6 @@ static void write_stream_buffer(overlay_interface *interface){
interface->tx_bytes_pending);
DEBUGF("Partial write, %d left", interface->tx_bytes_pending);
}
if (config.debug.packetradio)
DEBUGF("Wrote %d bytes (%d left pending, %d remains)", written, interface->tx_bytes_pending, interface->remaining_space);
}
if (total_written>0){
@ -867,6 +908,8 @@ int overlay_broadcast_ensemble(struct network_destination *destination, struct o
if (interface->debug)
DEBUGF("Sending on %s, len %d: %s", interface->name, len, alloca_tohex(bytes, len>64?64:len));
interface->tx_count++;
switch(interface->socket_type){
case SOCK_STREAM:
{

View File

@ -413,6 +413,7 @@ int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, s
RETURN(ret);
}
f.sender_interface = context.sender_interface;
interface->recv_count++;
while(ob_remaining(b)>0){
context.invalid_addresses=0;

View File

@ -543,58 +543,71 @@ int rhizome_server_parse_http_request(rhizome_http_request *r)
if (strcmp(path, "/")==0) {
r->request_type = RHIZOME_HTTP_REQUEST_FROMBUFFER;
char temp[8192];
snprintf(temp,8192,
"<html><body>"
strbuf b=strbuf_local(temp, sizeof(temp));
strbuf_sprintf(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>"
"<h1>Hello, I'm %s*</h1><br>"
"<a href=\"/rssi\">rssi</a><br>"
"<a href=\"/rhizome/status\">rhizome status</a><br>"
"<a href=\"/rhizome/files\">rhizome files</a><br>"
"<a href=\"/rhizome/bars\">rhizome bars</a><br>"
"</body></html>",
"Interfaces;<br>",
alloca_tohex(my_subscriber->sid, 8));
rhizome_server_simple_http_response(r, 200, temp);
int i;
for (i=0;i<OVERLAY_MAX_INTERFACES;i++){
if (overlay_interfaces[i].state==INTERFACE_STATE_UP)
strbuf_sprintf(b, "<a href=\"/interface/%d\">%d: %s, TX: %d, RX: %d</a><br>",
i, i, overlay_interfaces[i].name, overlay_interfaces[i].tx_count, overlay_interfaces[i].recv_count);
}
strbuf_puts(b, "Neighbours;<br>");
link_neighbour_short_status_html(b, "/neighbour");
if (is_rhizome_http_enabled()){
strbuf_puts(b, "<a href=\"/rhizome/status\">Rhizome Status</a><br>");
}
strbuf_puts(b, "</body></html>");
if (strbuf_overrun(b)){
rhizome_server_simple_http_response(r, 500, "<html><h1>Buffer overflow</h1></html>\r\n");
}else{
rhizome_server_simple_http_response(r, 200, temp);
}
} else if (str_startswith(path, "/neighbour/", (const char **)&id)) {
char buf[8*1024];
strbuf b=strbuf_local(buf, sizeof buf);
sid_t neighbour_sid;
if (str_to_sid_t(&neighbour_sid, id) == -1)
rhizome_server_simple_http_response(r, 500, "<html><h1>Invalid subscriber id</h1></html>\r\n");
else{
struct subscriber *neighbour = find_subscriber(neighbour_sid.binary, sizeof(neighbour_sid.binary), 0);
if (neighbour){
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
link_neighbour_status_html(b, neighbour);
strbuf_puts(b, "</body></html>");
if (strbuf_overrun(b)){
rhizome_server_simple_http_response(r, 500, "<html><h1>Buffer overflow</h1></html>\r\n");
}else{
rhizome_server_simple_http_response(r, 200, buf);
}
}else{
rhizome_server_simple_http_response(r, 404, "<html><h1>Subscriber not known</h1></html>\r\n");
}
}
} else if (str_startswith(path, "/interface/", (const char **)&id)) {
char buf[8*1024];
strbuf b=strbuf_local(buf, sizeof buf);
int index=atoi(id);
if (index>=0 && index<OVERLAY_MAX_INTERFACES){
strbuf_puts(b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
interface_state_html(b, &overlay_interfaces[index]);
strbuf_puts(b, "</body></html>");
if (strbuf_overrun(b)){
rhizome_server_simple_http_response(r, 500, "<html><h1>Buffer overflow</h1></html>\r\n");
}else{
rhizome_server_simple_http_response(r, 200, buf);
}
}else{
rhizome_server_simple_http_response(r, 400, "<html><h1>Invalid interface id</h1></html>\r\n");
}
} else if (strcmp(path, "/favicon.ico") == 0) {
r->request_type = RHIZOME_HTTP_REQUEST_FAVICON;
rhizome_server_http_response_header(r, 200, "image/vnd.microsoft.icon", favicon_len);
} else if (strcmp(path, "/rssi.csv") == 0) {
r->request_type = RHIZOME_HTTP_REQUEST_FROMBUFFER;
char temp[8192];
snprintf(temp,8192,
";%lld;%d;%d;%d;%d;%d;%s;%d;%d;%d;%d;%d\n",
gettime_ms(),
last_radio_rssi,last_radio_temperature,last_radio_rxpackets,
(int)bundles_available,
rhizome_active_fetch_count(),
alloca_tohex(my_subscriber->sid, 8),
rhizome_active_fetch_bytes_received(0),
rhizome_active_fetch_bytes_received(1),
rhizome_active_fetch_bytes_received(2),
rhizome_active_fetch_bytes_received(3),
rhizome_active_fetch_bytes_received(4)
);
rhizome_server_simple_http_response(r, 200, temp);
} else if (strcmp(path, "/rssi") == 0) {
r->request_type = RHIZOME_HTTP_REQUEST_FROMBUFFER;
char temp[8192];
snprintf(temp,8192,
"<html><head><meta http-equiv=\"refresh\" content=\"5\" >"
"</head><body><h1>Radio link margin = %+ddB (%d packets received)<br>"
"Radio temperature = %d&deg;C<br>"
"SID: %s*<br>"
"%d rhizome bundles in database<br>"
"%d rhizome transfers in progress<br>(%d,%d,%d,%d,%d bytes)<br>"
"</h1></body></html>\n",
last_radio_rssi,last_radio_rxpackets,last_radio_temperature,
alloca_tohex(my_subscriber->sid, 8),
(int)bundles_available,
rhizome_active_fetch_count(),
rhizome_active_fetch_bytes_received(0),
rhizome_active_fetch_bytes_received(1),
rhizome_active_fetch_bytes_received(2),
rhizome_active_fetch_bytes_received(3),
rhizome_active_fetch_bytes_received(4)
);
rhizome_server_simple_http_response(r, 200, temp);
} else if (is_rhizome_http_enabled()){
if (strcmp(path, "/rhizome/groups") == 0) {
/* Return the list of known groups */
@ -606,7 +619,11 @@ int rhizome_server_parse_http_request(rhizome_http_request *r)
strbuf_puts(&b, "<html><head><meta http-equiv=\"refresh\" content=\"5\" ></head><body>");
rhizome_fetch_status_html(&b);
strbuf_puts(&b, "</body></html>");
rhizome_server_simple_http_response(r, 200, buf);
if (strbuf_overrun(&b)){
rhizome_server_simple_http_response(r, 500, "<html><h1>Buffer overflow</h1></html>\r\n");
}else{
rhizome_server_simple_http_response(r, 200, buf);
}
} else if (strcmp(path, "/rhizome/files") == 0) {
/* Return the list of known files */
rhizome_server_sql_query_http_response(r, "id", "files", "from files", 32, 1);

View File

@ -624,6 +624,75 @@ static void clean_neighbours(time_ms_t now)
}
}
static void link_status_html(struct strbuf *b, struct subscriber *n, struct link *link)
{
if (!link)
return;
link_status_html(b, n, link->_left);
int best=0;
if (link->receiver->next_hop==n)
best=1;
else if(link->receiver==n && n->reachable&REACHABLE_DIRECT)
best=1;
strbuf_sprintf(b, "%s* -%s H: %d, C: %d, via %s*<br>",
alloca_tohex(link->receiver->sid,8),
best?" *best*":"",
link->hop_count, link->path_drop_rate,
link->transmitter?alloca_tohex(link->transmitter->sid,8):"unreachable");
link_status_html(b, n, link->_right);
}
void link_neighbour_short_status_html(struct strbuf *b, const char *link_prefix)
{
struct neighbour *n = neighbours;
if (!n)
strbuf_puts(b, "No peers<br>");
while(n){
strbuf_sprintf(b, "<a href=\"%s/%s\">%s*</a>, seq=%d, mask=%08"PRIx64";<br>",
link_prefix,
alloca_tohex_sid(n->subscriber->sid),
alloca_tohex(n->subscriber->sid,8),
n->mdp_ack_sequence, n->mdp_ack_mask);
n=n->_next;
}
}
void link_neighbour_status_html(struct strbuf *b, struct subscriber *neighbour)
{
time_ms_t now = gettime_ms();
struct neighbour *n = neighbours;
while(n){
if (n->subscriber == neighbour){
strbuf_sprintf(b, "Neighbour %s*;<br>", alloca_tohex(n->subscriber->sid,8));
strbuf_sprintf(b, "Seq=%d, mask=%08"PRIx64"<br>", n->mdp_ack_sequence, n->mdp_ack_mask);
struct link_in *link_in = n->links;
while(link_in){
strbuf_sprintf(b, "In: %s%s, seq=%d, mask=%08"PRIx64"<br>",
link_in->interface->name,
link_in == n->best_link?" *best":"",
link_in->ack_sequence,
link_in->ack_mask);
link_in = link_in->_next;
}
struct link_out *link_out = n->out_links;
while(link_out){
if (link_out->timeout >= now){
strbuf_sprintf(b, "Out: %s %s<br>",
link_out->destination->interface->name,
link_out->destination->unicast?"unicast":"broadcast");
}
link_out = link_out->_next;
}
strbuf_puts(b, "Links;<br>");
link_status_html(b, n->subscriber, n->root);
return;
}
n = n->_next;
}
strbuf_puts(b, "Not found<br>");
}
static int send_legacy_self_announce_ack(struct neighbour *neighbour, struct link_in *link, time_ms_t now){
struct overlay_frame *frame=emalloc_zero(sizeof(struct overlay_frame));
frame->type = OF_TYPE_SELFANNOUNCE_ACK;

View File

@ -472,6 +472,9 @@ typedef struct overlay_interface {
int recv_offset; /* file offset */
int recv_count;
int tx_count;
// stream socket tx state;
struct overlay_buffer *tx_packet;
unsigned char txbuffer[OVERLAY_INTERFACE_RX_BUFFER_SIZE];
@ -483,7 +486,8 @@ typedef struct overlay_interface {
int32_t remaining_space;
time_ms_t next_heartbeat;
int mavlink_seq;
int radio_rssi;
int remote_rssi;
struct slip_decode_state slip_decode_state;
@ -723,6 +727,7 @@ overlay_interface * overlay_interface_find(struct in_addr addr, int return_defau
overlay_interface * overlay_interface_find_name(const char *name);
int overlay_interface_compare(overlay_interface *one, overlay_interface *two);
int overlay_broadcast_ensemble(struct network_destination *destination, struct overlay_buffer *buffer);
void interface_state_html(struct strbuf *b, struct overlay_interface *interface);
int directory_registration();
int directory_service_init();
@ -877,9 +882,6 @@ int slip_decode(struct slip_decode_state *state);
int upper7_decode(struct slip_decode_state *state,unsigned char byte);
uint32_t Crc32_ComputeBuf( uint32_t inCrc32, const void *buf,
size_t bufLen );
extern int last_radio_rssi;
extern int last_radio_temperature;
extern int last_radio_rxpackets;
int rhizome_active_fetch_count();
int rhizome_active_fetch_bytes_received(int q);
extern int64_t bundles_available;
@ -897,6 +899,8 @@ int link_state_ack_soon(struct subscriber *sender);
int link_state_should_forward_broadcast(struct subscriber *transmitter);
int link_unicast_ack(struct subscriber *subscriber, struct overlay_interface *interface, struct sockaddr_in addr);
int link_add_destinations(struct overlay_frame *frame);
void link_neighbour_short_status_html(struct strbuf *b, const char *link_prefix);
void link_neighbour_status_html(struct strbuf *b, struct subscriber *neighbour);
int generate_nonce(unsigned char *nonce,int bytes);

View File

@ -41,7 +41,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
strbuf_init(&b, buf, sizeof buf);
strbuf_puts(&b, "text");
strbuf_sprintf(&b, "fmt", val...);
if (strbuf_overflow(&b))
if (strbuf_overrun(&b))
// error...
else
// use buf