Flowgrind
Advanced TCP traffic generator
fg_math.c
Go to the documentation of this file.
1 
6 /*
7  * Copyright (C) 2010-2013 Christian Samsel <christian.samsel@rwth-aachen.de>
8  *
9  * This file is part of Flowgrind.
10  *
11  * Flowgrind is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * Flowgrind is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Flowgrind. If not, see <http://www.gnu.org/licenses/>.
23  *
24  */
25 
26 #ifndef HAVE_CONFIG_H
27 #include "config.h"
28 #endif /* HAVE_CONFIG_H */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <math.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <syslog.h>
41 #include <float.h>
42 #include <fenv.h>
43 
44 #include "debug.h"
45 #include "fg_math.h"
46 #include "fg_error.h"
47 #include "fg_definitions.h"
48 
49 #ifdef HAVE_LIBGSL
50 #include <gsl/gsl_rng.h>
51 #include <gsl/gsl_randist.h>
52 #include <gsl/gsl_cdf.h>
53 #include <gsl/gsl_sf_gamma.h>
54 #include <gsl/gsl_math.h>
55 #include <gsl/gsl_errno.h>
56 #endif /* HAVE_LIBGSL */
57 
58 extern void init_math_functions (struct flow *flow, unsigned long seed)
59 {
60  int rc;
61 #ifndef HAVE_LIBGSL
62  UNUSED_ARGUMENT(flow);
63 #endif /* HAVE_LIBGSL */
64  /* set rounding */
65  fesetround(FE_TONEAREST);
66 
67  /* initalize rng */
68 #ifdef HAVE_LIBGSL
69  const gsl_rng_type * T;
70  gsl_rng_env_setup();
71  T = gsl_rng_default;
72  flow->r = gsl_rng_alloc (T);
73 #endif /* HAVE_LIBGSL */
74 
75  if (!seed) {
76  /* if no seed supplied use urandom */
77  DEBUG_MSG(LOG_WARNING, "client did not supply random seed value");
78  int data = open("/dev/urandom", O_RDONLY);
79  rc = read(data, &seed, sizeof (long) );
80  close(data);
81  if(rc == -1)
82  crit("read /dev/urandom failed");
83  }
84 
85 #ifdef HAVE_LIBGSL
86  gsl_rng_set (flow->r, seed);
87  DEBUG_MSG(LOG_WARNING, "initalized local libgsl random functions for "
88  "flow %d with seed %lu, gsl generator is: %s",
89  flow->id,seed,gsl_rng_name (flow->r));
90 #else /* HAVE_LIBGSL */
91  srand((unsigned)seed);
92  DEBUG_MSG(LOG_WARNING, "initalized posix random functions with seed "
93  "%u", (unsigned)seed);
94 #endif /* HAVE_LIBGSL */
95 }
96 
97 extern void free_math_functions (struct flow *flow)
98 {
99 #ifdef HAVE_LIBGSL
100  gsl_rng_free(flow->r);
101 #else /* HAVE_LIBGSL */
102  UNUSED_ARGUMENT(flow);
103 #endif /* HAVE_LIBGSL */
104 }
105 
106 #ifndef HAVE_LIBGSL
107 static inline double rn_uniform(void)
108 {
109  return (double)rand();
110 }
111 
112 static inline double rn_uniform_zero_to_one(void)
113 {
114  return (rn_uniform()/(RAND_MAX + 1.0));
115 }
116 
117 static inline double rn_uniform_minusone_to_one(void)
118 {
119  return (rn_uniform()/(RAND_MAX/2.0) - 1.0);
120 }
121 #endif /* HAVE_LIBGSL */
122 
123 extern double dist_exponential(struct flow *flow, const double mu)
124 {
125 #ifdef HAVE_LIBGSL
126  gsl_rng * r = flow->r;
127  return gsl_ran_exponential(r, mu);
128 #else /* HAVE_LIBGSL */
129  UNUSED_ARGUMENT(flow);
130  return -log(rn_uniform())+mu;
131 #endif /* HAVE_LIBGSL */
132 }
133 
134 /* source for naive implementation english wikipedia articles */
135 
136 extern double dist_uniform(struct flow *flow, const double minval,
137  const double maxval)
138 {
139 #ifdef HAVE_LIBGSL
140  gsl_rng * r = flow->r;
141  return gsl_ran_flat(r, minval, maxval);
142 #else /* HAVE_LIBGSL */
143  UNUSED_ARGUMENT(flow);
144  const double x = rn_uniform_zero_to_one();
145  return ((maxval-minval) * x) + minval;
146 #endif /* HAVE_LIBGSL */
147 }
148 
149 extern double dist_normal(struct flow *flow, const double mu,
150  const double sigma_square)
151 {
152 #ifdef HAVE_LIBGSL
153  const gsl_rng * r = flow->r;
154  return gsl_ran_gaussian (r, sigma_square) + mu;
155 #else /* HAVE_LIBGSL */
156  UNUSED_ARGUMENT(flow);
157  const double x = rn_uniform_minusone_to_one();
158  return (1.0 / sqrt(2.0*M_PI*sigma_square)) *
159  exp((-pow ((x-mu),2)) / (2 * sigma_square));
160 #endif /* HAVE_LIBGSL */
161 }
162 
163 extern double dist_lognormal(struct flow *flow, const double zeta,
164  const double sigma)
165 {
166 #ifdef HAVE_LIBGSL
167  gsl_rng * r = flow->r;
168  return gsl_ran_lognormal (r, zeta, sigma);
169 #else /* HAVE_LIBGSL */
170  /* not implemented */
171  UNUSED_ARGUMENT(flow);
172  UNUSED_ARGUMENT(zeta);
173  UNUSED_ARGUMENT(sigma);
174  return 0;
175 #endif /* HAVE_LIBGSL */
176 }
177 
178 
179 extern int dist_bernoulli(struct flow *flow, const double p)
180 {
181 #ifdef HAVE_LIBGSL
182  gsl_rng * r = flow->r;
183  return gsl_ran_bernoulli (r, p);
184 #else /* HAVE_LIBGSL */
185  UNUSED_ARGUMENT(flow);
186  return rn_uniform_zero_to_one() <= p;
187 #endif /* HAVE_LIBGSL */
188 }
189 
190 extern double dist_pareto (struct flow *flow, const double k,
191  const double x_min)
192 {
193 #ifdef HAVE_LIBGSL
194  gsl_rng * r = flow->r;
195  return gsl_ran_pareto (r, k, x_min);
196 #else /* HAVE_LIBGSL */
197  UNUSED_ARGUMENT(flow);
198  const double x = rn_uniform();
199  if (x < x_min)
200  return 0;
201  else
202  return (k/x_min) * pow (x_min/x,k+1);
203 #endif /* HAVE_LIBGSL */
204 }
205 
206 extern double dist_weibull (struct flow *flow, const double alpha,
207  const double beta)
208 {
209 #ifdef HAVE_LIBGSL
210  gsl_rng * r = flow->r;
211  return gsl_ran_weibull (r, alpha, beta);
212 #else /* HAVE_LIBGSL */
213  UNUSED_ARGUMENT(flow);
214  const double x = rn_uniform_zero_to_one();
215  return alpha * beta * pow (x,beta-1.0) * exp(-alpha * pow(x,beta));
216 #endif /* HAVE_LIBGSL */
217 }
218 
219 extern double dist_chisq (struct flow *flow, const double nu)
220 {
221 #ifdef HAVE_LIBGSL
222  gsl_rng * r = flow->r;
223  return gsl_ran_chisq(r, nu);
224 #else /* HAVE_LIBGSL */
225  /* not implemented */
226  UNUSED_ARGUMENT(flow);
227  UNUSED_ARGUMENT(nu);
228  return 0;
229 #endif /* HAVE_LIBGSL */
230 }
231 
Debugging routines for Flowgrind controller and daemon.
double dist_uniform(struct flow *flow, const double minval, const double maxval)
Definition: fg_math.c:136
Routines for statistics and advanced traffic generation.
Error-reporting routines used by Flowgrind.
gsl_rng * r
Definition: daemon.h:167
double dist_exponential(struct flow *flow, const double mu)
Definition: fg_math.c:123
#define DEBUG_MSG(LVL, MSG,...)
Print debug message to standard error.
Definition: debug.h:49
void * data
Pointer to user defined data stored with this node.
Definition: fg_list.h:38
double dist_weibull(struct flow *flow, const double alpha, const double beta)
Definition: fg_math.c:206
#define UNUSED_ARGUMENT(x)
Suppress warning for unused argument.
double dist_pareto(struct flow *flow, const double k, const double x_min)
Definition: fg_math.c:190
double dist_lognormal(struct flow *flow, const double zeta, const double sigma)
Definition: fg_math.c:163
#define crit(...)
To report an critical error w/ the corresponding system error message.
Definition: fg_error.h:36
double dist_chisq(struct flow *flow, const double nu)
Definition: fg_math.c:219
void init_math_functions(struct flow *flow, unsigned long seed)
Definition: fg_math.c:58
Common definitions used by the Flowgrind daemon, controller, and libs.
int dist_bernoulli(struct flow *flow, const double p)
Definition: fg_math.c:179
Definition: daemon.h:73
void free_math_functions(struct flow *flow)
Definition: fg_math.c:97
int id
Definition: daemon.h:75
double dist_normal(struct flow *flow, const double mu, const double sigma_square)
Definition: fg_math.c:149