2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2010 Herbert Haas
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.
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
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
26 ///////////////////// TOC /////////////////////
28 // int mops_delete_sequence (char *name)
29 // struct mz_ll * mops_create_sequence (char *name)
30 // int mops_dump_sequence (char* str)
31 // int mops_add_packet_to_sequence (struct mz_ll *seq, struct mops *mp)
32 // int mops_add_delay_to_sequence (struct mz_ll *seq, struct timespec *t)
33 // int mops_delete_packet_from_pseq (struct mz_ll *seq, int index)
34 // int stop_sequence (char *name)
35 // int stop_all_sequences ()
38 // delete one sequence element (from the global packet_sequence list)
39 // which must be specified by its name
41 int mops_delete_sequence (char *name
)
45 v
= mz_ll_search_name (packet_sequences
, name
);
46 if (v
==NULL
) return 1; // name not found
48 if (v
->state
) return 2; // sequence is currently active!
50 if (mz_ll_delete_element (v
))
51 return -1; // cannot delete head element!
57 struct mz_ll
* mops_create_sequence (char *name
)
63 cur
= mz_ll_create_new_element(packet_sequences
);
64 if (cur
==NULL
) return NULL
;
65 strncpy(cur
->name
, name
, MZ_LL_NAME_LEN
);
67 cur
->data
= (struct pseq
*) malloc (sizeof(struct pseq
));
69 seq
= (struct pseq
*) cur
->data
;
71 for (i
=0; i
<MAX_PACKET_SEQUENCE_LEN
; i
++) {
72 seq
->packet
[i
] = NULL
; // pointer to the packets
73 seq
->gap
[i
].tv_sec
= 0;
74 seq
->gap
[i
].tv_nsec
= 0;
81 // PURPOSE: dumps all sequence objects line-by-line
83 // ARGUMENTS: Caller must provide a pointer to a string of size MZ_LL_NAME_LEN+(MAX_PACKET_SEQUENCE_LEN*6)
84 // (recommendation: 512 bytes !)
86 // RETURN VALUE: 0 if list is finished, 1 otherwise
88 // EXAMPLE: char str[512];
89 // while (mops_dump_sequence(str)
90 // printf("%s\n", str);
92 int mops_dump_sequence (char* str
)
95 static struct mz_ll
*cur
;
104 if (init
==-1) { // last turn said stop now!
110 cur
=packet_sequences
->next
;
118 seq
= (struct pseq
*) cur
->data
;
121 sprintf(str
, "(no sequences found)");
125 c
= seq
->count
; // amount of currently stored packets in this sequence object
127 // create string with all packet IDs:
128 for (i
=0; i
<c
; i
++) {
129 pkt
= seq
->packet
[i
];
130 if (pkt
== NULL
) break;
131 snprintf(t
, 15, "%i", pkt
->id
);
132 if (strnlen(tmp
,256)>249) break;
134 if (i
<c
-1) strncat(tmp
,", ", 2);
137 snprintf(str
, 512, "%s {%s}", cur
->name
, tmp
);
140 if (cur
==packet_sequences
) init
=-1; // stop next turn!
145 // finds next free slot in sequence seq and adds packet mp
147 // RETURN VALUE: 0 upon success
148 // -1 failure: array full
149 // -2 failure: cannot add packets with infinite count
151 int mops_add_packet_to_sequence (struct mz_ll
*seq
, struct mops
*mp
)
156 if (seq
==NULL
) return 1;
158 // don't add packets with count=0
159 if (mp
->count
==0) return -2;
161 cur
= (struct pseq
*) seq
->data
;
162 if (cur
->count
>= MAX_PACKET_SEQUENCE_LEN
) return -1; // packet array full!
163 for (i
=0; i
<MAX_PACKET_SEQUENCE_LEN
; i
++) {
164 if (cur
->packet
[i
]==NULL
) { // found empty slot
170 return 1; // never reach here
174 // adds the given delay 't' to the last packet in the sequence's pseq
176 // NOTE: return index number of pseq where delay had been added
177 // or upon failure: -1 if there is no packet yet defined
178 // -2 if array is full
179 int mops_add_delay_to_sequence (struct mz_ll
*seq
, struct timespec
*t
)
184 if (seq
==NULL
) return 1;
186 cur
= (struct pseq
*) seq
->data
;
188 if (i
>= MAX_PACKET_SEQUENCE_LEN
) return -2; // packet array full!
190 cur
->gap
[i
-1].tv_sec
= t
->tv_sec
;
191 cur
->gap
[i
-1].tv_nsec
= t
->tv_nsec
;
193 return i
-1; // note: is -1 if there is no packet yet (count=0)
197 // Deletes packet and associated delay from a pseq for given index
198 // If index == -1 then the last packet/delay is removed
200 // NOTE: index range is {1..count}
202 // RETURN VALUES: 0 upon success
204 // 2 upon failure, index too big
206 int mops_delete_packet_from_pseq (struct mz_ll
*seq
, int index
)
211 if (seq
==NULL
) return 1;
212 cur
= (struct pseq
*) seq
->data
;
213 if (cur
->count
==0) return 1; // list is empty, nothing to delete
214 if (index
>cur
->count
) return 2;
215 if ((index
==0) || (index
<-1)) return 1; // total invalid index values
216 if (index
==-1) { // remove last element
217 cur
->packet
[cur
->count
-1]=NULL
;
218 cur
->gap
[cur
->count
-1].tv_sec
=0;
219 cur
->gap
[cur
->count
-1].tv_nsec
=0;
221 for (i
=index
-1; i
<(cur
->count
-1); i
++) {
222 cur
->packet
[i
] = cur
->packet
[i
+1];
223 cur
->gap
[i
].tv_sec
= cur
->gap
[i
+1].tv_sec
;
224 cur
->gap
[i
].tv_nsec
=cur
->gap
[i
+1].tv_nsec
;
232 int mops_delete_all_packets_from_pseq (struct mz_ll
*seq
)
237 if (seq
==NULL
) return 1;
238 cur
= (struct pseq
*) seq
->data
;
239 if (cur
->count
==0) return 1; // list is empty, nothing to delete
242 for (i
=0; i
<MAX_PACKET_SEQUENCE_LEN
; i
++) {
243 cur
->packet
[i
] = NULL
; // pointer to the packets
244 cur
->gap
[i
].tv_sec
= 0;
245 cur
->gap
[i
].tv_nsec
= 0;
252 // Stops an active sequence and sets all involved packets from state SEQACT to CONFIG.
254 // RETURN VALUE: 0 upon success
255 // 1 if sequence does not exist
256 // 2 if sequence is not actice
257 int stop_sequence (char *name
)
263 v
= mz_ll_search_name (packet_sequences
, name
);
264 if (v
==NULL
) return 1; // name not found
265 if (!v
->state
) return 2; // sequence is not currently active!
268 pthread_cancel(v
->sequence_thread
);
270 // reset packet states:
271 cur
= (struct pseq
*) v
->data
;
272 for (i
=0; i
<cur
->count
; i
++)
273 cur
->packet
[i
]->state
=MOPS_STATE_CONFIG
;
275 // reset sequence state:
281 // runs through 'packet_sequences' and cancels all active sequences
282 // (i. e. stops threads and sets states appropriately)
284 // Comment: It might seem a bit inefficient to call 'stop_sequence' for the
285 // detailed work, but this is the more safer way and it is fast enough.
287 // RETURN VALUE: Number of stopped sequences.
289 int stop_all_sequences(void)
291 struct mz_ll
*cur
=packet_sequences
->next
;
294 while (cur
!=packet_sequences
) {
295 if (cur
!=packet_sequences
) { // just for safety
296 if (stop_sequence(cur
->name
)==0) i
++;