trafgen: allow to schedule packets on specific CPUs
[netsniff-ng.git] / src / mops_tools.c
blob022f45b16913a799c3a608040681a310e2bac763
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008,2009 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
20 #include "mz.h"
21 #include "mops.h"
23 // Inserts value in 'flag' (up to 7 bits are useful) into the target
24 // with an optional left-shift. For example if flag contains a 4-bit value
25 // and should be placed within the target in bit positions 3-6 like:
26 //
27 // 7 6 5 4 3 2 1 0
28 // +--+--+--+--+--+--+--+--+
29 // | | FLAGS | | | |
30 // +--+--+--+--+--+--+--+--+
31 //
32 // then simply call:
33 //
34 // (void) mops_flags ( &target, &flag, 3 );
35 //
36 // Note that shift=0 means no shift.
37 inline void mops_flags (u_int8_t *target, u_int8_t *flag, int shift)
39 *target |= (*flag << shift);
44 inline void mops_hton2 (u_int16_t *host16, u_int8_t *net16)
46 char *x;
48 x = (char*) host16;
50 *(net16++) = *(x+1);
51 *net16 = *x;
55 inline void mops_hton4 (u_int32_t *host32, u_int8_t *net32)
57 char *x;
59 x = (char*) host32;
61 *(net32++) = *(x+3);
62 *(net32++) = *(x+2);
63 *(net32++) = *(x+1);
64 *(net32) = *x;
70 // returns new counter index for given packet
71 // or -1 if all counters used already
72 int mops_get_counter (struct mops *mp)
74 int i=0;
76 while (mp->counter[i].offset)
78 i++;
79 if (i==MAX_MOPS_COUNTERS_PER_PACKET) // exceeded range
80 return -1;
82 return i;
86 // Adds single byte to msg
87 int mops_msg_add_byte (struct mops *mp, u_int8_t data)
89 mp->msg[mp->msg_s++] = data;
90 return 0;
94 // Adds bit field in *previous* msg-byte using optional left-shift
95 int mops_msg_add_field (struct mops *mp, u_int8_t data, int shift)
97 mp->msg[mp->msg_s -1] |= (data << shift);
98 return 0;
102 // Adds two bytes in network byte order to msg
103 int mops_msg_add_2bytes (struct mops *mp, u_int16_t data)
105 char *x;
106 x = (char*) &data;
107 mp->msg[mp->msg_s++] = *(x+1);
108 mp->msg[mp->msg_s++] = *(x);
109 return 0;
113 // Adds four bytes in network byte order to msg
114 int mops_msg_add_4bytes (struct mops *mp, u_int32_t data)
116 char *x;
117 x = (char*) &data;
118 mp->msg[mp->msg_s++] = *(x+3);
119 mp->msg[mp->msg_s++] = *(x+2);
120 mp->msg[mp->msg_s++] = *(x+1);
121 mp->msg[mp->msg_s++] = *(x);
122 return 0;
125 // Adds string of bytes with lenght len
126 int mops_msg_add_string (struct mops *mp, u_int8_t *str, int len)
128 memcpy((void *) &mp->msg[mp->msg_s], (void *) str, len);
129 mp->msg_s += len;
131 return 0;
136 // Add counter to message
137 int mops_msg_add_counter (struct mops *mp,
138 int random, // 1=random, 0=use start/stop/step
139 u_int32_t start, // HOST BYTE ORDER
140 u_int32_t stop, // HOST BYTE ORDER
141 u_int32_t step, // HOST BYTE ORDER
142 int bytes // number of bytes used (1|2|4) - selects hton2 or hton4
146 int i;
148 // check if unsupported byte count
149 if ( (bytes!=1) &&
150 (bytes!=2) &&
151 (bytes!=4) )
152 return 1;
154 // get new counter
155 i = mops_get_counter(mp);
156 if (i==-1) return 1;
158 // configure counter values
159 mp->counter[i].offset = mp->msg_s;
160 mp->counter[i].random = random;
161 mp->counter[i].start = start;
162 mp->counter[i].stop = stop;
163 mp->counter[i].step = step;
164 mp->counter[i].bytes = bytes;
165 mp->counter[i].cur = start;
166 mp->counter[i].use = 1;
169 // configure first pointer value
170 switch (bytes)
172 case 1:
173 mops_msg_add_byte(mp, (u_int8_t) start);
174 break;
175 case 2:
176 mops_msg_add_2bytes(mp, (u_int16_t) start);
177 break;
178 case 4:
179 mops_msg_add_4bytes(mp, start);
180 break;
181 default: // never be reached
182 return 1;
185 return 0;
190 // Compares two IP addresses byte by byte
191 // returns 0 if identical, 1 if different
193 // Note that this works independent of endianess
194 // as long as both addresses have same endianess.
196 int compare_ip (u_int8_t *ip1, u_int8_t *ip2)
198 if (*ip1 != *ip2) return 1;
199 if (*(ip1+1) != *(ip2+1)) return 1;
200 if (*(ip1+2) != *(ip2+2)) return 1;
201 if (*(ip1+3) != *(ip2+3)) return 1;
203 return 0;
207 // Compares two MAC addresses byte by byte
208 // returns 0 if identical, 1 if different
209 int compare_mac (u_int8_t *mac1, u_int8_t *mac2)
211 if (*mac1 != *mac2) return 1;
212 if (*(mac1+1) != *(mac2+1)) return 1;
213 if (*(mac1+2) != *(mac2+2)) return 1;
214 if (*(mac1+3) != *(mac2+3)) return 1;
215 if (*(mac1+4) != *(mac2+4)) return 1;
216 if (*(mac1+5) != *(mac2+5)) return 1;
218 return 0;
222 // Converts a 'struct timespec' value into a human readable string
223 // This stringt is written into 'str' which must be at least a 32 byte
224 // array.
225 int timespec2str(struct timespec *t, char *str)
227 unsigned int d=0, h, m, s;
229 // zero delay
230 if ((t->tv_sec==0) && (t->tv_nsec==0)) {
231 sprintf(str, "(none)");
232 return 0;
235 h = t->tv_sec/3600;
236 m = (t->tv_sec - h*3600)/60;
237 s = t->tv_sec - h*3600 - m*60;
239 if (h>24) {
240 d = h/24;
241 h = h - d*24;
242 sprintf(str, "%u days %02u:%02u:%02u", d, h, m, s);
243 return 0;
246 if (h|m)
247 sprintf(str, "%02u:%02u:%02u", h, m, s); // ignore nanoseconds if delay is in order of hours
248 else if (s)
249 sprintf(str, "%u%s sec", s, (t->tv_nsec>1000000) ? "+" : "");
250 else if (t->tv_nsec>1000000)
251 sprintf(str, "%u msec", (unsigned int) t->tv_nsec/1000000);
252 else if (t->tv_nsec>1000)
253 sprintf(str, "%u usec", (unsigned int) t->tv_nsec/1000);
254 else
255 sprintf(str, "%lu nsec", t->tv_nsec);
257 return 0;