summaryrefslogtreecommitdiff
path: root/staging/mops_sequence.c
diff options
context:
space:
mode:
Diffstat (limited to 'staging/mops_sequence.c')
-rw-r--r--staging/mops_sequence.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/staging/mops_sequence.c b/staging/mops_sequence.c
new file mode 100644
index 0000000..32e7895
--- /dev/null
+++ b/staging/mops_sequence.c
@@ -0,0 +1,303 @@
+/*
+ * Mausezahn - A fast versatile traffic generator
+ * Copyright (C) 2010 Herbert Haas
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
+ *
+*/
+
+
+#include "mz.h"
+#include "cli.h"
+#include "mops.h"
+#include "llist.h"
+
+
+///////////////////// TOC /////////////////////
+//
+// int mops_delete_sequence (char *name)
+// struct mz_ll * mops_create_sequence (char *name)
+// int mops_dump_sequence (char* str)
+// int mops_add_packet_to_sequence (struct mz_ll *seq, struct mops *mp)
+// int mops_add_delay_to_sequence (struct mz_ll *seq, struct timespec *t)
+// int mops_delete_packet_from_pseq (struct mz_ll *seq, int index)
+// int stop_sequence (char *name)
+// int stop_all_sequences ()
+
+
+// delete one sequence element (from the global packet_sequence list)
+// which must be specified by its name
+//
+int mops_delete_sequence (char *name)
+{
+ struct mz_ll *v;
+
+ v = mz_ll_search_name (packet_sequences, name);
+ if (v==NULL) return 1; // name not found
+
+ if (v->state) return 2; // sequence is currently active!
+
+ if (mz_ll_delete_element (v))
+ return -1; // cannot delete head element!
+ return 0;
+}
+
+
+
+struct mz_ll * mops_create_sequence (char *name)
+{
+ struct mz_ll *cur;
+ struct pseq *seq;
+ int i;
+
+ cur = mz_ll_create_new_element(packet_sequences);
+ if (cur==NULL) return NULL;
+ strncpy(cur->name, name, MZ_LL_NAME_LEN);
+ // add data
+ cur->data = (struct pseq*) malloc (sizeof(struct pseq));
+ // initialize data
+ seq = (struct pseq*) cur->data;
+ seq->count = 0;
+ for (i=0; i<MAX_PACKET_SEQUENCE_LEN; i++) {
+ seq->packet[i] = NULL; // pointer to the packets
+ seq->gap[i].tv_sec = 0;
+ seq->gap[i].tv_nsec = 0;
+ }
+ return cur;
+}
+
+
+
+// PURPOSE: dumps all sequence objects line-by-line
+//
+// ARGUMENTS: Caller must provide a pointer to a string of size MZ_LL_NAME_LEN+(MAX_PACKET_SEQUENCE_LEN*6)
+// (recommendation: 512 bytes !)
+//
+// RETURN VALUE: 0 if list is finished, 1 otherwise
+//
+// EXAMPLE: char str[512];
+// while (mops_dump_sequence(str)
+// printf("%s\n", str);
+//
+int mops_dump_sequence (char* str)
+{
+ static int init=0;
+ static struct mz_ll *cur;
+ struct pseq *seq;
+ struct mops *pkt;
+
+ char tmp[256], t[16];
+ int i, c;
+
+ tmp[0]='\0';
+
+ if (init==-1) { // last turn said stop now!
+ init=0;
+ return 0;
+ }
+
+ if (init==0) {
+ cur=packet_sequences->next;
+ if (cur==NULL) {
+ str[0]='\0';
+ return 0;
+ }
+ init=1;
+ }
+
+ seq = (struct pseq*) cur->data;
+ if (seq==NULL) {
+ init=-1;
+ sprintf(str, "(no sequences found)");
+ return 1;
+ }
+
+ c = seq->count; // amount of currently stored packets in this sequence object
+
+ // create string with all packet IDs:
+ for (i=0; i<c; i++) {
+ pkt = seq->packet[i];
+ if (pkt == NULL) break;
+ snprintf(t, 15, "%i", pkt->id);
+ if (strnlen(tmp,256)>249) break;
+ strncat(tmp, t, 6);
+ if (i<c-1) strncat(tmp,", ", 2);
+ }
+
+ snprintf(str, 512, "%s {%s}", cur->name, tmp);
+
+ cur=cur->next;
+ if (cur==packet_sequences) init=-1; // stop next turn!
+ return 1;
+}
+
+
+// finds next free slot in sequence seq and adds packet mp
+//
+// RETURN VALUE: 0 upon success
+// -1 failure: array full
+// -2 failure: cannot add packets with infinite count
+//
+int mops_add_packet_to_sequence (struct mz_ll *seq, struct mops *mp)
+{
+ struct pseq *cur;
+ int i;
+
+ if (seq==NULL) return 1;
+
+ // don't add packets with count=0
+ if (mp->count==0) return -2;
+
+ cur = (struct pseq*) seq->data;
+ if (cur->count >= MAX_PACKET_SEQUENCE_LEN) return -1; // packet array full!
+ for (i=0; i<MAX_PACKET_SEQUENCE_LEN; i++) {
+ if (cur->packet[i]==NULL) { // found empty slot
+ cur->packet[i]=mp;
+ cur->count++;
+ return 0;
+ }
+ }
+ return 1; // never reach here
+}
+
+
+// adds the given delay 't' to the last packet in the sequence's pseq
+//
+// NOTE: return index number of pseq where delay had been added
+// or upon failure: -1 if there is no packet yet defined
+// -2 if array is full
+int mops_add_delay_to_sequence (struct mz_ll *seq, struct timespec *t)
+{
+ struct pseq *cur;
+ int i;
+
+ if (seq==NULL) return 1;
+
+ cur = (struct pseq*) seq->data;
+ i = cur->count;
+ if (i>= MAX_PACKET_SEQUENCE_LEN) return -2; // packet array full!
+
+ cur->gap[i-1].tv_sec = t->tv_sec;
+ cur->gap[i-1].tv_nsec = t->tv_nsec;
+
+ return i-1; // note: is -1 if there is no packet yet (count=0)
+}
+
+
+// Deletes packet and associated delay from a pseq for given index
+// If index == -1 then the last packet/delay is removed
+//
+// NOTE: index range is {1..count}
+//
+// RETURN VALUES: 0 upon success
+// 1 upon failure
+// 2 upon failure, index too big
+//
+int mops_delete_packet_from_pseq (struct mz_ll *seq, int index)
+{
+ struct pseq *cur;
+ int i;
+
+ if (seq==NULL) return 1;
+ cur = (struct pseq*) seq->data;
+ if (cur->count==0) return 1; // list is empty, nothing to delete
+ if (index>cur->count) return 2;
+ if ((index==0) || (index<-1)) return 1; // total invalid index values
+ if (index==-1) { // remove last element
+ cur->packet[cur->count-1]=NULL;
+ cur->gap[cur->count-1].tv_sec=0;
+ cur->gap[cur->count-1].tv_nsec=0;
+ } else {
+ for (i=index-1; i<(cur->count-1); i++) {
+ cur->packet[i] = cur->packet[i+1];
+ cur->gap[i].tv_sec = cur->gap[i+1].tv_sec;
+ cur->gap[i].tv_nsec=cur->gap[i+1].tv_nsec;
+ }
+ }
+ cur->count--;
+ return 0;
+}
+
+
+int mops_delete_all_packets_from_pseq (struct mz_ll *seq)
+{
+ struct pseq *cur;
+ int i;
+
+ if (seq==NULL) return 1;
+ cur = (struct pseq*) seq->data;
+ if (cur->count==0) return 1; // list is empty, nothing to delete
+ // DELETE ALL:
+ cur->count = 0;
+ for (i=0; i<MAX_PACKET_SEQUENCE_LEN; i++) {
+ cur->packet[i] = NULL; // pointer to the packets
+ cur->gap[i].tv_sec = 0;
+ cur->gap[i].tv_nsec = 0;
+ }
+ return 0;
+}
+
+
+
+// Stops an active sequence and sets all involved packets from state SEQACT to CONFIG.
+//
+// RETURN VALUE: 0 upon success
+// 1 if sequence does not exist
+// 2 if sequence is not actice
+int stop_sequence (char *name)
+{
+ struct mz_ll *v;
+ struct pseq *cur;
+ int i;
+
+ v = mz_ll_search_name (packet_sequences, name);
+ if (v==NULL) return 1; // name not found
+ if (!v->state) return 2; // sequence is not currently active!
+
+ // now stop thread:
+ pthread_cancel(v->sequence_thread);
+
+ // reset packet states:
+ cur = (struct pseq*) v->data;
+ for (i=0; i<cur->count; i++)
+ cur->packet[i]->state=MOPS_STATE_CONFIG;
+
+ // reset sequence state:
+ v->state = 0;
+ return 0;
+}
+
+
+// runs through 'packet_sequences' and cancels all active sequences
+// (i. e. stops threads and sets states appropriately)
+//
+// Comment: It might seem a bit inefficient to call 'stop_sequence' for the
+// detailed work, but this is the more safer way and it is fast enough.
+//
+// RETURN VALUE: Number of stopped sequences.
+//
+int stop_all_sequences ()
+{
+ struct mz_ll *cur=packet_sequences->next;
+ int i=0;
+
+ while (cur!=packet_sequences) {
+ if (cur!=packet_sequences) { // just for safety
+ if (stop_sequence(cur->name)==0) i++;
+ }
+ cur=cur->next;
+ }
+
+ return i;
+}
+