-
Notifications
You must be signed in to change notification settings - Fork 1
/
status.c
272 lines (229 loc) · 7.94 KB
/
status.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/* status.c - maintain information on connections other cloud boxes
*
* Copyright (C) 2012, Greg Johnson
* Released under the terms of the GNU GPL v2.0.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* $Id: status.c,v 1.9 2012-02-22 19:27:23 greg Exp $
*/
static const char Version[] = "Version "
"$Id: status.c,v 1.9 2012-02-22 19:27:23 greg Exp $";
/* maintain information on connection to another cloud box;
* that cloud box's "name" (i.e., wireless interface mac address),
* signal strength, the number of packets received,
* and the number of packets dropped (based on packet sequence numbers).
*
* if a cloud box is configured to print cloud status, these status
* structs get sent around the cloud in stp_beacon messages.
*/
#include <string.h>
#include "status.h"
#include "cloud.h"
#include "util.h"
#include "print.h"
#include "device_type.h"
/* permanent record of communication to a neighbor identified by
* their one true name (mac address of wlan device).
*
* entries are preserved across disappearance and re-appearance of
* even the raw devices used to communicate with neighbors.
*
* there is also one entry for wlan and one entry for eth. these are
* to count communication events to non-cloud devices. (if a receive
* error occurs on the eth device it is tallied here, since we
* can't read the message and so don't know if it was a cloud message or not.)
*
* at some point, time-stamp last modification of these guys, and if
* we run out reclaim the one with oldest last-modification time.
*/
status_t perm_io_stat[MAX_CLOUD];
int perm_io_stat_count = 0;
/* these guys use indices that match those of perm_io_stat. they are
* separate because instance of status_t go in packets and other places
* where this information is not needed.
*/
int send_sequence[MAX_CLOUD];
int send_data_sequence[MAX_CLOUD];
int send_ping_sequence[MAX_CLOUD];
byte recv_sequence[MAX_CLOUD];
bool_t have_recv_sequence[MAX_CLOUD];
byte recv_data_sequence[MAX_CLOUD];
bool_t have_recv_data_sequence[MAX_CLOUD];
byte recv_ping_sequence[MAX_CLOUD];
bool_t have_recv_ping_sequence[MAX_CLOUD];
/* initialize all fields of the struct to zero */
void status_init(status_t *s)
{
memset(s, 0, sizeof(status_t));
}
/* print column titles for a status report */
void status_dprint_short_title(ddprintf_t fn, FILE *f, int indent)
{
int i;
for (i = 0; i < indent; i++) { fn(f, " "); }
fn(f, "packets received packets lost percent received\n");
}
/* print data right justified in a field of width field_width */
static void print_int(ddprintf_t fn, FILE *f, int data, int field_width)
{
int len = 0, test, i;
test = data;
if (test == 0) {
len = 1;
} else {
if (test > 0) {
len = 0;
} else {
len = 1;
test = -test;
}
while (test != 0) {
test /= 10;
len++;
}
}
if (len >= field_width) {
fn(f, " ");
} else {
for (i = len; i < field_width; i++) { fn(f, " "); }
}
fn(f, "%d", data);
}
/* pretty-print the status struct using printing function fn and
* (optionally) stream f
*/
void status_dprint_short(ddprintf_t fn, FILE *f, status_t *s, char *label,
int todo)
{
int percent;
float den;
int packets_received;
int packets_lost;
if (todo == STATUS_PRINT_DATA) {
packets_received = s->data_packets_received;
packets_lost = s->data_packets_lost;
} else if (todo == STATUS_PRINT_CLOUD) {
packets_received = s->packets_received;
packets_lost = s->packets_lost;
} else if (todo == STATUS_PRINT_PINGS) {
packets_received = s->ping_packets_received;
packets_lost = s->ping_packets_lost;
} else {
packets_received = s->packets_received + s->data_packets_received
+ s->ping_packets_received;
packets_lost = s->packets_lost + s->data_packets_lost
+ s->ping_packets_lost;
}
fn(f, "%s", label);
print_int(fn, f, packets_received, 16);
print_int(fn, f, packets_lost, 16);
den = (float) (packets_received + packets_lost);
if (den == 0) {
percent = 100;
} else {
percent = (int) (.5 + 100. * ((float) packets_received) / den);
}
print_int(fn, f, percent, 19);
fn(f, "%c\n", '%');
}
/* pretty-print the array of status structs using printing function fn and
* (optionally) stream f
*/
void status_dprint_short_array(ddprintf_t fn, FILE *f, status_t *s, int count)
{
int i;
status_dprint_short_title(fn, f, 20);
for (i = 0; i < count; i++) {
char mac_address[64], title[64];
if (s[i].device_type == device_type_eth
|| s[i].device_type == device_type_wlan)
{
int j;
for (j = 0; j < 64; j++) { title[j] = ' '; }
sprintf(title, "%s:", device_type_string(s[i].device_type));
title[strlen(title)] = ' ';
title[23] = '\0';
status_dprint_short(fn, f, &s[i], title, STATUS_PRINT_ALL);
} else {
mac_sprintf(mac_address, s[i].name);
sprintf(title, "%s: ", mac_address);
status_dprint_short(fn, f, &s[i], title, STATUS_PRINT_DATA);
sprintf(title, "%s(c): ", mac_address);
status_dprint_short(fn, f, &s[i], title, STATUS_PRINT_CLOUD);
sprintf(title, "%s(p): ", mac_address);
status_dprint_short(fn, f, &s[i], title, STATUS_PRINT_PINGS);
}
}
}
/* pretty-print the array of status structs to stream f */
void status_print_short_array(FILE *f, status_t *s, int count)
{
status_dprint_short_array(fprint, f, s, count);
}
/* find the index of the status struct in the array that has mac address mac */
int status_find_by_mac(status_t *s, int status_count, mac_address_t mac)
{
int i;
for (i = 0; i < status_count; i++) {
if (mac_equal(s[i].name, mac)) {
return i;
}
}
return -1;
}
/* if the status array does not have an entry with mac address mac, add
* one, with the given device type
*/
int status_add_by_mac(status_t *status, int *status_count, mac_address_t mac,
device_type_t type)
{
int result;
result = status_find_by_mac(status, *status_count, mac);
if (result != -1) { return result; }
if (*status_count >= MAX_CLOUD) { return -1; }
memset(&status[*status_count], 0, sizeof(status[*status_count]));
mac_copy(status[*status_count].name, mac);
status[*status_count].device_type = type;
(*status_count)++;
return *status_count - 1;
}
/* used to add wds or ad-hoc devices. uses cloud_box_t, which would cause
* circularities in .h files, so leave it here.
*/
void add_perm_io_stat_index(int *nbr_perm_io_stat_index,
mac_address_t neighbor_name, device_type_t type)
{
int i;
bool_t found;
status_t *p;
ddprintf("\n\n ADD_PERM_IO_STAT_INDEX \n\n");
found = false;
for (i = 0; i < perm_io_stat_count; i++) {
if (mac_equal(perm_io_stat[i].name, neighbor_name)) {
*nbr_perm_io_stat_index = i;
found = true;
break;
}
}
if (!found) {
if (perm_io_stat_count >= MAX_CLOUD) {
ddprintf("add_perm_io_stat_index; too many perm_io_stat's\n");
/* at some point, garbage collect perm_io_stat with oldest
* last-update time
*/
goto done;
}
p = &perm_io_stat[perm_io_stat_count++];
status_init(p);
mac_copy(p->name, neighbor_name);
p->device_type = type;
*nbr_perm_io_stat_index = perm_io_stat_count - 1;
}
done : ;
status_dprint_short_array(eprintf, stderr, perm_io_stat, perm_io_stat_count);
ddprintf("perm_io_stat_count: %d\n", perm_io_stat_count);
} /* add_perm_io_stat_index */