~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to ntpd/ntp_monitor.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * ntp_monitor.c - monitor who is using the ntpd server
 
2
 * ntp_monitor - monitor ntpd statistics
3
3
 */
4
 
 
5
4
#ifdef HAVE_CONFIG_H
6
5
# include <config.h>
7
6
#endif
18
17
#endif
19
18
 
20
19
/*
21
 
 * I'm still not sure I like what I've done here.  It certainly consumes
 
20
 * I'm still not sure I like what I've done here. It certainly consumes
22
21
 * memory like it is going out of style, and also may not be as low
23
22
 * overhead as I'd imagined.
24
23
 *
25
 
 * Anyway, we record statistics based on source address, mode and version
26
 
 * (for now, anyway.  Check the code).  The receive procedure calls us with
27
 
 * the incoming rbufp before it does anything else.
 
24
 * Anyway, we record statistics based on source address, mode and
 
25
 * version (for now, anyway. Check the code).  The receive procedure
 
26
 * calls us with the incoming rbufp before it does anything else.
28
27
 *
29
28
 * Each entry is doubly linked into two lists, a hash table and a
30
 
 * most-recently-used list.  When a packet arrives it is looked up
31
 
 * in the hash table.  If found, the statistics are updated and the
32
 
 * entry relinked at the head of the MRU list.  If not found, a new
33
 
 * entry is allocated, initialized and linked into both the hash
34
 
 * table and at the head of the MRU list.
 
29
 * most-recently-used list. When a packet arrives it is looked up in
 
30
 * the hash table.  If found, the statistics are updated and the entry
 
31
 * relinked at the head of the MRU list. If not found, a new entry is
 
32
 * allocated, initialized and linked into both the hash table and at the
 
33
 * head of the MRU list.
35
34
 *
36
 
 * Memory is usually allocated by grabbing a big chunk of new memory
37
 
 * and cutting it up into littler pieces.  The exception to this when we
38
 
 * hit the memory limit.  Then we free memory by grabbing entries off
39
 
 * the tail for the MRU list, unlinking from the hash table, and
 
35
 * Memory is usually allocated by grabbing a big chunk of new memory and
 
36
 * cutting it up into littler pieces. The exception to this when we hit
 
37
 * the memory limit. Then we free memory by grabbing entries off the
 
38
 * tail for the MRU list, unlinking from the hash table, and
40
39
 * reinitializing.
41
40
 *
42
41
 * trimmed back memory consumption ... jdg 8/94
43
42
 */
44
 
 
45
43
/*
46
44
 * Limits on the number of structures allocated.  This limit is picked
47
45
 * with the illicit knowlege that we can only return somewhat less
62
60
 */
63
61
#define MON_HASH_SIZE   128
64
62
#define MON_HASH_MASK   (MON_HASH_SIZE-1)
65
 
#define MON_HASH(addr)  ((int)(ntohl((addr)) & MON_HASH_MASK))
 
63
#define MON_HASH(addr)  sock_hash(addr)
66
64
 
67
65
/*
68
66
 * Pointers to the hash table, the MRU list and the count table.  Memory
69
 
 * for the hash and count tables is only allocated if monitoring is turned on.
 
67
 * for the hash and count tables is only allocated if monitoring is
 
68
 * turned on.
70
69
 */
71
 
static  struct mon_data *mon_hash[MON_HASH_SIZE];  /* array of list ptrs */
72
 
struct mon_data mon_mru_list;
73
 
struct mon_data mon_fifo_list;
 
70
static  struct mon_data *mon_hash[MON_HASH_SIZE];  /* list ptrs */
 
71
struct  mon_data mon_mru_list;
 
72
 
74
73
/*
75
74
 * List of free structures structures, and counters of free and total
76
75
 * structures.  The free structures are linked with the hash_next field.
77
76
 */
78
 
static  struct mon_data *mon_free;      /* the free list or null if none */
79
 
 
80
 
static  int mon_total_mem;              /* total number of structures allocated */
81
 
static  int mon_mem_increments;         /* number of times we've called malloc() */
 
77
static  struct mon_data *mon_free;      /* free list or null if none */
 
78
static  int mon_total_mem;              /* total structures allocated */
 
79
static  int mon_mem_increments;         /* times called malloc() */
82
80
 
83
81
/*
84
82
 * Initialization state.  We may be monitoring, we may not.  If
85
83
 * we aren't, we may not even have allocated any memory yet.
86
84
 */
87
 
int mon_enabled;
 
85
int     mon_enabled;                    /* enable switch */
 
86
u_long  mon_age = 3000;                 /* preemption limit */
88
87
static  int mon_have_memory;
89
 
 
90
88
static  void    mon_getmoremem  P((void));
91
89
static  void    remove_from_hash P((struct mon_data *));
92
90
 
106
104
        mon_total_mem = 0;
107
105
        mon_mem_increments = 0;
108
106
        mon_free = NULL;
109
 
        memset((char *)&mon_hash[0], 0, sizeof mon_hash);
110
 
        memset((char *)&mon_mru_list, 0, sizeof mon_mru_list);
111
 
        memset((char *)&mon_fifo_list, 0, sizeof mon_fifo_list);
 
107
        memset(&mon_hash[0], 0, sizeof mon_hash);
 
108
        memset(&mon_mru_list, 0, sizeof mon_mru_list);
112
109
}
113
110
 
114
111
 
126
123
                return;
127
124
        }
128
125
        if (mode == MON_OFF)
129
 
            return;             /* Ooops.. */
 
126
            return;
130
127
        
131
128
        if (!mon_have_memory) {
132
129
                mon_total_mem = 0;
138
135
 
139
136
        mon_mru_list.mru_next = &mon_mru_list;
140
137
        mon_mru_list.mru_prev = &mon_mru_list;
141
 
 
142
 
        mon_fifo_list.fifo_next = &mon_fifo_list;
143
 
        mon_fifo_list.fifo_prev = &mon_fifo_list;
144
 
 
145
138
        mon_enabled = mode;
146
139
}
147
140
 
182
175
 
183
176
        mon_mru_list.mru_next = &mon_mru_list;
184
177
        mon_mru_list.mru_prev = &mon_mru_list;
185
 
 
186
 
        mon_fifo_list.fifo_next = &mon_fifo_list;
187
 
        mon_fifo_list.fifo_prev = &mon_fifo_list;
188
178
}
189
179
 
190
180
 
198
188
{
199
189
        register struct pkt *pkt;
200
190
        register struct mon_data *md;
201
 
        register u_long netnum;
 
191
        struct sockaddr_storage addr;
202
192
        register int hash;
203
193
        register int mode;
204
194
 
205
195
        if (mon_enabled == MON_OFF)
206
 
            return;
 
196
                return;
207
197
 
208
198
        pkt = &rbufp->recv_pkt;
209
 
        netnum = NSRCADR(&rbufp->recv_srcadr);
210
 
        hash = MON_HASH(netnum);
 
199
        memset(&addr, 0, sizeof(addr));
 
200
        memcpy(&addr, &(rbufp->recv_srcadr), sizeof(addr));
 
201
        hash = MON_HASH(&addr);
211
202
        mode = PKT_MODE(pkt->li_vn_mode);
212
 
 
213
203
        md = mon_hash[hash];
214
204
        while (md != NULL) {
215
 
                if (md->rmtadr == netnum && 
216
 
                    /* ?? md->interface == rbufp->dstadr && ?? */
217
 
                    md->mode == (u_char)mode) {
 
205
 
 
206
                /*
 
207
                 * Match address only to conserve MRU size.
 
208
                 */
 
209
                if (SOCKCMP(&md->rmtadr, &addr)) {
 
210
                        md->drop_count = current_time - md->lasttime;
218
211
                        md->lasttime = current_time;
219
212
                        md->count++;
 
213
                        md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
 
214
                        md->mode = (u_char) mode;
220
215
                        md->version = PKT_VERSION(pkt->li_vn_mode);
221
 
                        md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
222
216
 
223
217
                        /*
224
 
                         * Shuffle him to the head of the
225
 
                         * mru list.  What a crock.
 
218
                         * Shuffle to the head of the MRU list.
226
219
                         */
227
220
                        md->mru_next->mru_prev = md->mru_prev;
228
221
                        md->mru_prev->mru_next = md->mru_next;
230
223
                        md->mru_prev = &mon_mru_list;
231
224
                        mon_mru_list.mru_next->mru_prev = md;
232
225
                        mon_mru_list.mru_next = md;
233
 
 
234
226
                        return;
235
227
                }
236
228
                md = md->hash_next;
242
234
         * or from the tail of the MRU list.
243
235
         */
244
236
        if (mon_free == NULL && mon_total_mem >= MAXMONMEM) {
 
237
 
245
238
                /*
246
 
                 * Get it from MRU list
 
239
                 * Preempt from the MRU list if old enough.
247
240
                 */
248
241
                md = mon_mru_list.mru_prev;
 
242
                if (((u_long)RANDOM & 0xffffffff) / FRAC >
 
243
                    (double)(current_time - md->lasttime) / mon_age)
 
244
                        return;
 
245
 
249
246
                md->mru_prev->mru_next = &mon_mru_list;
250
247
                mon_mru_list.mru_prev = md->mru_prev;
251
 
 
252
248
                remove_from_hash(md);
253
 
 
254
 
                /*
255
 
                 * Get it from FIFO list
256
 
                 */
257
 
                md->fifo_prev->fifo_next = md->fifo_next;
258
 
                md->fifo_next->fifo_prev = md->fifo_prev;
259
 
                
260
249
        } else {
261
 
                if (mon_free == NULL)           /* if free list empty */
262
 
                    mon_getmoremem();       /* then get more */
 
250
                if (mon_free == NULL)
 
251
                        mon_getmoremem();
263
252
                md = mon_free;
264
253
                mon_free = md->hash_next;
265
254
        }
267
256
        /*
268
257
         * Got one, initialize it
269
258
         */
270
 
        md->lasttime = md->firsttime = current_time;
271
 
        md->lastdrop = 0;
 
259
        md->avg_interval = 0;
 
260
        md->lasttime = current_time;
272
261
        md->count = 1;
273
 
        md->rmtadr = netnum;
 
262
        md->drop_count = 0;
 
263
        memset(&md->rmtadr, 0, sizeof(md->rmtadr));
 
264
        memcpy(&md->rmtadr, &addr, sizeof(addr));
274
265
        md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
275
266
        md->mode = (u_char) mode;
276
267
        md->version = PKT_VERSION(pkt->li_vn_mode);
277
268
        md->interface = rbufp->dstadr;
278
 
        md->cast_flags = ((rbufp->dstadr->flags & INT_MULTICAST) &&
279
 
                          rbufp->fd == md->interface->fd) ? MDF_MCAST: rbufp->fd ==
280
 
                md->interface->bfd ? MDF_BCAST : MDF_UCAST;
 
269
        md->cast_flags = (u_char)(((rbufp->dstadr->flags & INT_MULTICAST) &&
 
270
            rbufp->fd == md->interface->fd) ? MDF_MCAST: rbufp->fd ==
 
271
                md->interface->bfd ? MDF_BCAST : MDF_UCAST);
281
272
 
282
273
        /*
283
 
         * Drop him into front of the hash table.
284
 
         * Also put him on top of the MRU list
285
 
         * and at bottom of FIFO list
 
274
         * Drop him into front of the hash table. Also put him on top of
 
275
         * the MRU list.
286
276
         */
287
 
 
288
277
        md->hash_next = mon_hash[hash];
289
278
        mon_hash[hash] = md;
290
 
 
291
279
        md->mru_next = mon_mru_list.mru_next;
292
280
        md->mru_prev = &mon_mru_list;
293
281
        mon_mru_list.mru_next->mru_prev = md;
294
282
        mon_mru_list.mru_next = md;
295
 
 
296
 
        md->fifo_prev = mon_fifo_list.fifo_prev;
297
 
        md->fifo_next = &mon_fifo_list;
298
 
        mon_fifo_list.fifo_prev->fifo_next = md;
299
 
        mon_fifo_list.fifo_prev = md;
300
283
}
301
284
 
302
285
 
310
293
        register int i;
311
294
        struct mon_data *freedata;      /* 'old' free list (null) */
312
295
 
313
 
        md = (struct mon_data *)emalloc(MONMEMINC * sizeof(struct mon_data));
 
296
        md = (struct mon_data *)emalloc(MONMEMINC *
 
297
            sizeof(struct mon_data));
314
298
        freedata = mon_free;
315
299
        mon_free = md;
316
 
 
317
300
        for (i = 0; i < (MONMEMINC-1); i++) {
318
301
                md->hash_next = (md + 1);
319
302
                md++;
323
306
         * md now points at the last.  Link in the rest of the chain.
324
307
         */
325
308
        md->hash_next = freedata;
326
 
 
327
309
        mon_total_mem += MONMEMINC;
328
310
        mon_mem_increments++;
329
311
}
336
318
        register int hash;
337
319
        register struct mon_data *md_prev;
338
320
 
339
 
        hash = MON_HASH(md->rmtadr);
 
321
        hash = MON_HASH(&md->rmtadr);
340
322
        if (mon_hash[hash] == md) {
341
323
                mon_hash[hash] = md->hash_next;
342
324
        } else {