1 /*
2  * mod_drop.c
3  *
4  * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
5  *
6  * $Id: mod_drop.c,v 1.3 2002/04/07 22:55:20 dugsong Exp $
7  */
8 
9 #include "config.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "pkt.h"
16 #include "mod.h"
17 
18 #define DROP_FIRST	1
19 #define DROP_LAST	2
20 #define DROP_RANDOM	3
21 
22 struct drop_data {
23 	rand_t	*rnd;
24 	int	 which;
25 	int	 percent;
26 };
27 
28 void *
drop_close(void * d)29 drop_close(void *d)
30 {
31 	struct drop_data *data = (struct drop_data *)d;
32 
33 	if (data != NULL) {
34 		rand_close(data->rnd);
35 		free(data);
36 	}
37 	return (NULL);
38 }
39 
40 void *
drop_open(int argc,char * argv[])41 drop_open(int argc, char *argv[])
42 {
43 	struct drop_data *data;
44 
45 	if (argc != 3)
46 		return (NULL);
47 
48 	if ((data = calloc(1, sizeof(*data))) == NULL)
49 		return (NULL);
50 
51 	data->rnd = rand_open();
52 
53 	if (strcasecmp(argv[1], "first") == 0)
54 		data->which = DROP_FIRST;
55 	else if (strcasecmp(argv[1], "last") == 0)
56 		data->which = DROP_LAST;
57 	else if (strcasecmp(argv[1], "random") == 0)
58 		data->which = DROP_RANDOM;
59 	else
60 		return (drop_close(data));
61 
62 	if ((data->percent = atoi(argv[2])) <= 0 || data->percent > 100)
63 		return (drop_close(data));
64 
65 	return (data);
66 }
67 
68 int
drop_apply(void * d,struct pktq * pktq)69 drop_apply(void *d, struct pktq *pktq)
70 {
71 	struct drop_data *data = (struct drop_data *)d;
72 	struct pkt *pkt;
73 
74 	if (data->percent < 100 &&
75 	    (rand_uint16(data->rnd) % 100) > data->percent)
76 		return (0);
77 
78 	if (data->which == DROP_FIRST)
79 		pkt = TAILQ_FIRST(pktq);
80 	else if (data->which == DROP_LAST)
81 		pkt = TAILQ_LAST(pktq, pktq);
82 	else
83 		pkt = pktq_random(data->rnd, pktq);
84 
85 	TAILQ_REMOVE(pktq, pkt, pkt_next);
86 	pkt_free(pkt);
87 
88 	return (0);
89 }
90 
91 struct mod mod_drop = {
92 	"drop",					/* name */
93 	"drop first|last|random <prob-%>",	/* usage */
94 	drop_open,				/* open */
95 	drop_apply,				/* apply */
96 	drop_close				/* close */
97 };
98