Commit 8a955c1c authored by Alessandro Rubini's avatar Alessandro Rubini

test/swflood: new dir, with code, cfg, results

parent eb4bb59d
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
CFLAGS = -Wall -O2 -ggdb
ALL = swflood multidump
all: $(ALL)
swflood: main.o parse.o commands.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
# build commands.o by various cmd-*.c using a linker script
CMD_C := $(wildcard cmd-*.c)
CMD_O := $(CMD_C:.c=.o)
commands.o: $(CMD_O)
$(LD) -r -T commands.lds $^ -o $@
clean:
rm -f $(ALL) *.o *~ core
repeat df r
repeat 1000 50
repeat 100 f
repeat 50 a
endr x
iface eth1 eth2 eth3 eth4
verbose 9 /dev/tty
send 0 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 1 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 2 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 3 20 00:00 +1 ff:ff:ff:ff:ff:ff
flush
repeat A 10
send 1 50 00:00 22:00:10:00:00:00
send 1 50 00:00 ff:ff:ff:ff:ff:ff
flush
endr A
#-*-shell-script-*-
flush
verbose 9 /dev/stdout
### I run this test with a 4-cable octopus
iface eth1 eth2 eth3 eth4
echo testing from 32 different senders plus another
send 0 32 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 32 32 32
send 1 32 00:00 22:00:10:00:00:00 +1
expect 32 0 0 0
echo testing from 64 different senders plus another
send 0 64 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 64 64 64
send 1 64 00:00 22:00:10:00:00:00 +1
expect 64 0 0 0
echo testing from 128 different senders plus another
send 0 128 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 128 128 128
send 1 128 00:00 22:00:10:00:00:00 +1
expect 128 0 0 0
echo testing from 256 different senders plus another
send 0 256 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 256 256 256
send 1 256 00:00 22:00:10:00:00:00 +1
expect 256 0 0 0
echo testing from 512 different senders plus another
send 0 512 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 512 512 512
send 1 512 00:00 22:00:10:00:00:00 +1
expect 512 0 0 0
echo testing from 1024 different senders plus another
send 0 1024 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 1024 1024 1024
send 1 1024 00:00 22:00:10:00:00:00 +1
expect 1024 0 0 0
echo testing from 2048 different senders plus another
send 0 2048 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 2048 2048 2048
send 1 2048 00:00 22:00:10:00:00:00 +1
expect 2048 0 0 0
echo testing from 4096 different senders plus another
send 0 4096 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 4096 4096 4096
send 1 4096 00:00 22:00:10:00:00:00 +1
expect 4096 0 0 0
echo testing from 8192 different senders plus another
send 0 8192 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 8192 8192 8192
send 1 8192 00:00 22:00:10:00:00:00 +1
expect 8192 0 0 0
echo testing from 16384 different senders plus another
send 0 16384 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 16384 16384 16384
send 1 16384 00:00 22:00:10:00:00:00 +1
expect 16384 0 0 0
iface br0 tap0 tap1 tap2 tap3
verbose 9 /dev/stdout
send 0 5 00:00 +1 ff:ff:ff:ff:ff:ff
flush
send 1 5 00:02 +0 ff:ff:ff:ff:ff:ff
flush
send 2 5 00:00 +0 ff:ff:ff:ff:ff:ff
flush
send 3 5 00:00 +0 ff:ff:ff:ff:ff:ff
flush
echo now repeating 10 times
repeat A 2
echo loop
send 1 5 00:00 22:00:10:00:00:00
flush
send 1 1 00:00 ff:ff:ff:ff:ff:ff
flush
send 2 5 00:20 22:00:11:00:00:00
flush
endr A
send 1 5 00:ff 22:00:12:00:00:20
flush
echo foreign
send 0 20 00:66 00:01:02:00:00:00 +1
flush
\ No newline at end of file
#-*-shell-script-*-
flush
verbose 9 /dev/stdout
### I run this test with a 4-cable octopus
iface tap1 tap2 tap3 tap4
echo testing from 32 different senders plus another
send 0 32 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 32 32 32
send 1 32 00:00 22:00:10:00:00:00 +1
expect 32 0 0 0
echo testing from 64 different senders plus another
send 0 64 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 64 64 64
send 1 64 00:00 22:00:10:00:00:00 +1
expect 64 0 0 0
echo testing from 128 different senders plus another
send 0 128 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 128 128 128
send 1 128 00:00 22:00:10:00:00:00 +1
expect 128 0 0 0
echo testing from 256 different senders plus another
send 0 256 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 256 256 256
send 1 256 00:00 22:00:10:00:00:00 +1
expect 256 0 0 0
echo testing from 512 different senders plus another
send 0 512 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 512 512 512
send 1 512 00:00 22:00:10:00:00:00 +1
expect 512 0 0 0
echo testing from 1024 different senders plus another
send 0 1024 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 1024 1024 1024
send 1 1024 00:00 22:00:10:00:00:00 +1
expect 1024 0 0 0
echo testing from 2048 different senders plus another
send 0 2048 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 2048 2048 2048
send 1 2048 00:00 22:00:10:00:00:00 +1
expect 2048 0 0 0
echo testing from 4096 different senders plus another
send 0 4096 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 4096 4096 4096
send 1 4096 00:00 22:00:10:00:00:00 +1
expect 4096 0 0 0
echo testing from 8192 different senders plus another
send 0 8192 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 8192 8192 8192
send 1 8192 00:00 22:00:10:00:00:00 +1
expect 8192 0 0 0
echo testing from 16384 different senders plus another
send 0 16384 00:00 +1 ff:ff:ff:ff:ff:ff
expect 0 16384 16384 16384
send 1 16384 00:00 22:00:10:00:00:00 +1
expect 16384 0 0 0
echo tsting repeat, expect 10 "loop" messages
repeat x 5
repeat y 2
repeat a 10000
endr a
echo loop
endr y
endr x
\ No newline at end of file
echo sleep 2s
sleep 2
echo sleep 2s
sleep 0 2000
repeat x 10
echo sleep .5s
sleep 0 500
endr x
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "swflood.h"
/*
* Loops are made of two commands: "repeat" and "endr"
*/
static int rep_verify(struct swf_line *line)
{
char *t;
int i, err = 0;
if (line->argc != 3) {
fprintf(stderr, "%s: wrong number of arguments\n",
line->argv[0]);
return -EINVAL;
}
if (strlen(line->argv[1]) != 1 || !isalpha(line->argv[1][0])) {
fprintf(stderr, "%s: not a letter \"%s\"\n",
line->argv[0], line->argv[1]);
err++;
}
i = strtol(line->argv[2], &t, 0);
if (t && *t) {
fprintf(stderr, "%s: not a number \"%s\"\n",
line->argv[0], line->argv[2]);
err++;
}
if (err)
return -EINVAL;
line->repcount = i;
return 0;
}
static struct swf_line *rep_execute(struct swf_line *line,
struct swf_status *status)
{
return line->next;
}
static struct swf_command cmd_repeat = {
.name = "repeat",
.verify = rep_verify,
.execute = rep_execute,
};
declare_command(cmd_repeat);
/* endr decrements and goes back or forward */
static int endr_verify(struct swf_line *line)
{
if (line->argc != 2) {
fprintf(stderr, "%s: wrong number of arguments\n",
line->argv[0]);
return -EINVAL;
}
if (strlen(line->argv[1]) != 1 || !isalpha(line->argv[1][0])) {
fprintf(stderr, "%s: not a letter \"%s\"\n",
line->argv[0], line->argv[1]);
return -EINVAL;
}
return 0;
}
static int endr_verify_late(struct swf_line *line)
{
/* Loop back looking for the letter */
struct swf_line *other;
int letter = line->argv[1][0];
for (other = line->prev; other; other = other->prev) {
if (other->cmd != &cmd_repeat)
continue;
if (other->argv[1][0] != letter)
continue;
line->data = other;
return 0;
}
fprintf(stderr, "%s: can't find matching '%c'\n",
line->argv[0], letter);
return -EINVAL;
}
static struct swf_line *endr_execute(struct swf_line *line,
struct swf_status *status)
{
struct swf_line *other = line->data;
/* The repcount field was 0 at allocate time */
if (!line->repcount) {
line->repcount = other->repcount;
}
line->repcount--;
if (line->repcount > 0)
return line->data;
return line->next;
}
static struct swf_command cmd_verbose = {
.name = "endr",
.verify = endr_verify,
.verify_late = endr_verify_late,
.execute = endr_execute,
};
declare_command(cmd_verbose);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include "swflood.h"
static int recv_and_send(struct swf_status *status, int sender,
unsigned char *packet, int plen);
/* Allocate a list of interfaces, with associated sockets */
static int iface_verify(struct swf_line *line)
{
struct ifreq ifr;
int i, sock, err = 0;
/* To verify the command we must ensure interfaces exist */
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock < 0) {
fprintf(stderr, "%s: socket: %s\n",
line->argv[0], strerror(errno));
return -errno;
}
for (i = 0; i < line->argc - 1; i++) {
memset (&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, line->argv[i+1], IF_NAMESIZE);
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
fprintf(stderr, "%s: no such interface \"%s\"\n",
line->argv[0], line->argv[i]);
err++;
}
}
if (err) return -EINVAL;
return 0;
}
static struct swf_line *iface_execute(struct swf_line *line,
struct swf_status *status)
{
struct ifreq ifr;
struct packet_mreq req;
struct swf_if *iface;
struct sockaddr_ll addr;
int i, sock;
/* We are sure interface names do exist */
for (i = 0; i < status->n_iface; i++) {
close(status->iface[i].socket);
}
if (status->iface)
free(status->iface);
iface = calloc(line->argc - 1, sizeof(*iface));
if (!iface) {
fprintf(stderr, "%s: out of memory\n", line->argv[0]);
return line->next;
}
status->iface = iface;
for (i = 0; i < line->argc - 1; i++, iface++) {
/* one socket per interface */
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock <= 0) {
fprintf(stderr, "%s: socket(): %s\n",
line->argv[0], strerror(errno));
return line->next;
}
/* one ifindex per inteface */
memset (&ifr, 0, sizeof(ifr));
iface->name = line->argv[i+1];
strncpy(ifr.ifr_name, iface->name, IF_NAMESIZE);
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
fprintf(stderr, "%s: getindex(%s): %s\n",
line->argv[0], iface->name, strerror(errno));
return line->next;
}
/* one promiscuous per inteface */
memset(&req, 0, sizeof(req));
req.mr_ifindex = ifr.ifr_ifindex;
req.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&req, sizeof(req)) < 0) {
fprintf(stderr, "%s: set_promiscuous(%s): %s\n",
line->argv[0], iface->name, strerror(errno));
return line->next;
}
/* one bind per inteface */
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_ifindex = ifr.ifr_ifindex;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
fprintf(stderr, "%s: bind(%s): %s\n",
line->argv[0], iface->name, strerror(errno));
return line->next;
}
iface->socket = sock;
}
status->n_iface = i;
return line->next;
}
static struct swf_command cmd_iface = {
.name = "iface",
.verify = iface_verify,
.execute = iface_execute,
};
declare_command(cmd_iface);
/* flush is trivial */
static int flush_verify(struct swf_line *line)
{
if (line->argc != 1) {
fprintf(stderr, "%s: wrong number of arguments\n",
line->argv[0]);
return -EINVAL;
}
return 0;
}
static struct swf_line *flush_execute(struct swf_line *line,
struct swf_status *status)
{
int i;
usleep(10*1000);
recv_and_send(status, 0, NULL, 0);
fprintf(status->logfile, "flush:");
for (i = 0; i < status->n_iface; i++) {
fprintf(status->logfile, " %i", status->iface[i].stat);
status->iface[i].stat = 0;
}
putc('\n', status->logfile);
return line->next;
}
static struct swf_command cmd_flush = {
.name = "flush",
.verify = flush_verify,
.execute = flush_execute,
};
declare_command(cmd_flush);
static int expect_verify(struct swf_line *line)
{
int i, j, err = 0;
char *t;
/* actually, we can't know, now, how many interfaces we have*/
for (i = 1; i < line->argc; i++) {
j = strtol(line->argv[i], &t, 10);
if (t && *t) {
fprintf(stderr, "%s: not a number \"%s\"\n",
line->argv[0], line->argv[i]);
err++;
}
}
if (err)
return -EINVAL;
return 0;
}
static struct swf_line *expect_execute(struct swf_line *line,
struct swf_status *status)
{
int i, j, error = 0;
usleep(10*1000);
recv_and_send(status, 0, NULL, 0);
if (line->argc != status->n_iface + 1) {
fprintf(stderr, "%s: wrong number of arguments "
"(expected %i numbers)\n", line->argv[0],
status->n_iface);
return line->next;
}
for (i = 0; i < status->n_iface; i++) {
j = strtol(line->argv[i+1], NULL, 10);
if (j != status->iface[i].stat)
error++;
}
if (error) {
/* loop again and print */
fprintf(stderr, "%s:%i: expect failed\n",
line->fname, line->lineno);
fprintf(status->logfile, "%s:%i: expect failed\n",
line->fname, line->lineno);
fprintf(status->logfile, "expected:");
for (i = 0; i < status->n_iface; i++)
fprintf(status->logfile, " %5li",
strtol(line->argv[i+1], NULL, 0));
fprintf(status->logfile, "\nreceived:");
for (i = 0; i < status->n_iface; i++)
fprintf(status->logfile, " %5i",
status->iface[i].stat);
putc('\n', status->logfile);
} else {
fprintf(status->logfile, "%s:%i: success\n", line->fname,
line->lineno);
}
/* zero stats in any case */
for (i = 0; i < status->n_iface; i++) {
status->iface[i].stat = 0;
}
return line->next;
}
static struct swf_command cmd_expect = {
.name = "expect",
.verify = expect_verify,
.execute = expect_execute,
};
declare_command(cmd_expect);
/* Send and sendas are handled by the same code, and helper function */
static int readhex(char *s, int nbyte, unsigned char *res)
{
int i, val;
char *t = s;
for (i = 0; i < nbyte; ) {
if (!s || !*s)
return -1;
val = strtol(s, &t, 16);
res[i++] = val;
if (!t || !*t)
break;
if (t && *t != ':')
return -1;
t++;
s = t;
}
if (i != nbyte)
return -1;
return 0;
}
static int readnr(char *name, char *s)
{
int i;
char *t;
i = strtol(s, &t, 10);
if (t && *t) {
fprintf(stderr, "%s: not a number \"%s\"\n", name, s);
return -1;
}
/* negative is considered and error, that's fine */
return i;
}
static int send_verify(struct swf_line *line)
{
int i = 1; /* arg being checked */
int err = 0;
unsigned char mac[6];
if (line->argc < 2) goto wna;
if (!strcmp(line->argv[0], "sendas")) {
/* as ifnum */
if (readnr(line->argv[0], line->argv[i]) < 0)
err++;
i++;
}
/* our ifnum */
if (line->argc < i+1) goto wna;
if (readnr(line->argv[0], line->argv[i]) < 0)
err++;
i++;
/* nr packets */
if (line->argc < i+1) goto wna;
if (readnr(line->argv[0], line->argv[i]) < 0)
err++;
i++;
/* sender addr */
if (line->argc < i+1) goto wna;
if (readhex(line->argv[i], 2, mac)) {
fprintf(stderr, "%s: expected \"xx:xx\" not \"%s\"\n",
line->argv[0], line->argv[i]);
err++;
}
i++;
/* incr */
if (line->argc < i+1) goto wna;
if (line->argv[i][0] == '+') {
if (readnr(line->argv[0], line->argv[i]+1) < 0)
err++;
i++;
}
/* dest addr */
if (line->argc < i+1) goto wna;
if (readhex(line->argv[i], 6, mac)) {
fprintf(stderr, "%s: expected MAC addr not \"%s\"\n",
line->argv[0], line->argv[i]);
err++;
}
i++;
/* incr */
if (line->argc == i+1 && line->argv[i][0] == '+') {
if (readnr(line->argv[0], line->argv[i]+1) < 0)
err++;
i++;
}
if (line->argc != i) goto wna;
if (err)
return -EINVAL;
return 0;
wna:
fprintf(stderr, "%s: too few arguments (checked %i)\n",
line->argv[0], i);
return -EINVAL;
}
static int recv_and_send(struct swf_status *status, int sender,
unsigned char *packet, int plen)
{
int i;
static uint32_t sequence;
unsigned char rcvp[32];
/* first receive whatever is pending on all interfaces */
for (i = 0; i < status->n_iface; i++) {
while (recv(status->iface[i].socket, rcvp, sizeof(rcvp),
MSG_DONTWAIT | MSG_TRUNC) != -1)
status->iface[i].stat++;
if (errno != EAGAIN) {
fprintf(stderr, "recv(if#%i): %s\n", i,
strerror(errno));
}
}
/* then send, adding a 32-bit sequence number, in net order */
if (!packet)
return 0;
if (plen >= 14+16) *(uint32_t *)(packet + 14+16-4) = htonl(sequence++);
send(status->iface[sender].socket, packet, plen, 0);
return 0;
}
static struct swf_line *send_execute(struct swf_line *line,
struct swf_status *status)
{
/* we must parse arguments anyways... */
unsigned char macsend[6] = {0x22, 0x00, 0x10, 0x00,};
unsigned char macrecv[6];
unsigned char packet[256] = {0,};
int senderif, sendermac = -1;
int incrsend = 0, incrrecv = 0;
int npacket, j, i = 1;
if (!strcmp(line->argv[0], "sendas")) {
/* as ifnum */
sendermac = readnr(line->argv[0], line->argv[i]);
i++;
}
/* our ifnum */
senderif = readnr(line->argv[0], line->argv[i]);
if (sendermac == -1) sendermac = senderif;
macsend[2] += sendermac;
i++;
/* nr packets */
npacket = readnr(line->argv[0], line->argv[i]);
i++;
/* sender addr */
readhex(line->argv[i], 2, macsend+4);
i++;
/* incr */
if (line->argv[i][0] == '+') {
incrsend = readnr(line->argv[0], line->argv[i]+1);
i++;
}
/* dest addr */
readhex(line->argv[i], 6, macrecv);
i++;
/* incr */
if (line->argc == i+1 && line->argv[i][0] == '+')
incrrecv = readnr(line->argv[0], line->argv[i]+1);
/* ok, now send and account */
for (i = 0; i < npacket; i++) {
memcpy(packet+0, macrecv, 6);
memcpy(packet+6, macsend, 6);
packet[12] = packet[13] = 0x66; /* fake protocol */
recv_and_send(status, senderif, packet, sizeof(packet));
j = ((macsend[4] << 8) | macsend[5]) + incrsend;
macsend[4] = j >> 8; macsend[5] = j;
j = ((macrecv[4] << 8) | macrecv[5]) + incrrecv;
macrecv[4] = j >> 8; macrecv[5] = j;
}
return line->next;
}
static struct swf_command cmd_send = {
.name = "send",
.verify = send_verify,
.execute = send_execute,
};
declare_command(cmd_send);
static struct swf_command cmd_sendas = {
.name = "sendas",
.verify = send_verify,
.execute = send_execute,
};
declare_command(cmd_sendas);
#if 0 /* not yet */
/* Expect some statistics */
static struct swf_command cmd_expect = {
.name = "expect",
.verify = expect_verify,
.execute = expect_execute,
};
declare_command(cmd_expect);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "swflood.h"
/* echo is always verified and is trivial to execute */
static int echo_verify(struct swf_line *line)
{
return 0;
}
static int do_echo(FILE *f, int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
fprintf(f, "%s%c", argv[i], i+1 == argc ? '\n' : ' ');
if (argc == 1)
putc('\n', f);
return 0;
}
static struct swf_line *echo_execute(struct swf_line *line,
struct swf_status *status)
{
do_echo(stdout, line->argc, line->argv);
fprintf(status->logfile, "# ");
do_echo(status->logfile, line->argc, line->argv);
return line->next;
}
static struct swf_command cmd_echo = {
.name = "echo",
.verify = echo_verify,
.execute = echo_execute,
};
declare_command(cmd_echo);
/* verbose sets status variables by possibly opening a file */
static int verbose_verify(struct swf_line *line)
{
char *t;
int i;
if (line->argc < 2 || line->argc > 3) {
fprintf(stderr, "%s: wrong number of arguments\n",
line->argv[0]);
return -EINVAL;
}
i = strtol(line->argv[1], &t, 0);
if (t && *t) {
fprintf(stderr, "%s: not a number \"%s\"\n",
line->argv[0], line->argv[1]);
return -EINVAL;
}
/* check of the file name is left to exectute time */
return 0;
}
static struct swf_line *verbose_execute(struct swf_line *line,
struct swf_status *status)
{
FILE *f;
status->verbose = atoi(line->argv[1]);
if (line->argc != 3)
return line->next;
f = fopen(line->argv[2], "a");
if (!f) {
fprintf(stderr, "%s: open(): %s\n",
line->argv[2], strerror(errno));
fprintf(status->logfile, "Error: %s: open(): %s\n",
line->argv[2], strerror(errno));
return line->next;
}
fclose(status->logfile);
status->logfile = f;
return line->next;
}
static struct swf_command cmd_verbose = {
.name = "verbose",
.verify = verbose_verify,
.execute = verbose_execute,
};
declare_command(cmd_verbose);
/* sleep seconds and/or milliseconds */
static int sleep_verify(struct swf_line *line)
{
char *t;
int i, err = 0;
if (line->argc != 2 && line->argc != 3) {
fprintf(stderr, "%s: wrong number of arguments\n",
line->argv[0]);
return -EINVAL;
}
i = strtol(line->argv[1], &t, 0);
if (t && *t) {
fprintf(stderr, "%s: not a number \"%s\"\n",
line->argv[0], line->argv[1]);
err++;
t = NULL;
}
if (line->argc == 3)
i = strtol(line->argv[1], &t, 0);
if (t && *t) {
fprintf(stderr, "%s: not a number \"%s\"\n",
line->argv[0], line->argv[2]);
err++;
}
if (err)
return -EINVAL;
return 0;
}
static struct swf_line *sleep_execute(struct swf_line *line,
struct swf_status *status)
{
int i;
i = strtol(line->argv[1], NULL, 0);
sleep(i);
if (line->argc == 3) {
i = strtol(line->argv[2], NULL, 0);
usleep(1000 * i);
}
return line->next;
}
static struct swf_command cmd_sleep = {
.name = "sleep",
.verify = sleep_verify,
.execute = sleep_execute,
};
declare_command(cmd_sleep);
SECTIONS
{
.data : {
. = ALIGN(4);
__cmd_start = .;
*(.commands);
__cmd_end = .;
}
}
/* Alessandro Rubini for CERN and White Rabbit, 2011 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "swflood.h"
static void swf_dump(struct swf_line *line)
{
int i;
fprintf(stderr, "%s:%i: (%i) =", line->fname, line->lineno,
line->argc);
for (i = 0; i < line->argc; i++)
fprintf(stderr, " \"%s\"", line->argv[i]);
putc('\n', stderr);
}
int main(int argc, char **argv)
{
struct swf_status *status;
struct swf_line *line, *lastline = NULL;
FILE *f;
char s[256];
int i, ret, lineno, err = 0;
status = calloc(1, sizeof(*status));
if (!status) {
fprintf(stderr, "%s: %s\n", argv[0], strerror(errno));
exit(1);
}
status->logfile = fopen("/dev/null", "w");
if (argc == 1) {
fprintf(stderr, "%s: Use \"%s <cfg> [<cfg> ...]\n",
argv[0], argv[0]);
exit(1);
}
/* Do the parsing */
for (i = 1; i < argc; i++) {
lineno = 0;
f = fopen(argv[i], "r");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i],
strerror(errno));
err++;
continue;
}
while (fgets(s, sizeof(s), f)) {
lineno++;
line = calloc(1, sizeof(*line));
if (!line) {
fprintf(stderr, "%s: %s\n", argv[0],
strerror(errno));
exit(1);
}
line->fname = argv[i];
line->lineno = lineno;
ret = swf_parse(s, line);
if (ret == -ENODATA) {
free(line);
continue;
}
if (ret < 0) {
fprintf(stderr, "%s:%i: %s in \"%s\"\n",
argv[i], lineno,
strerror(-ret), s);
err++;
continue;
}
/* enqueue this line */
if (lastline) {
lastline->next = line;
line->prev = lastline;
} else {
status->line = line;
}
lastline = line;
if (line->cmd->verify_late
&& line->cmd->verify_late(line)) {
err++;
continue;
}
if (getenv("VERBOSE"))
swf_dump(line);
}
}
if (err) exit(1);
/* Now run the commands */
for (line = status->line; line;
line = line->cmd->execute(line, status)) {
if (getenv("VERBOSE") && atoi(getenv("VERBOSE")) > 10)
fprintf(stderr, "run %-10s (%s:%i -- %i)\n",
line->argv[0], line->fname, line->lineno,
line->repcount);
}
/* done, it was easy, wasn't it? */
return 0;
}
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <sys/select.h>
#include <sys/time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <net/if_arp.h>
#include <netpacket/packet.h>
static int dumpone(char *name, struct timeval *tv,
unsigned char *packet, int plen)
{
int i;
static char sep[]="::::: ::::: . " "... ... ... ...\n";
char *s = sep;
printf("%-8s %li.%06li ", name, tv->tv_sec, tv->tv_usec);
for (i = 0; i < plen && *s; i++)
printf("%02x%c", packet[i], *(s++));
return 0;
}
int main(int argc, char **argv)
{
int i, len;
int sock = -1, *socks;
fd_set fullset, set;
struct ifreq ifr;
struct packet_mreq req;
struct sockaddr_ll addr;
unsigned char packet[128];
if (argc == 1) {
fprintf(stderr, "%s: pass a list of eth addresses\n",
argv[0]);
exit(1);
}
socks = malloc(sizeof(socks[0]) * (argc-1));
FD_ZERO(&fullset);
for (i = 0; i < argc-1; i++) {
/* one socket per interface */
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock < 0) {
fprintf(stderr, "%s: socket(): %s\n",
argv[0], strerror(errno));
exit(1);
}
/* one ifindex per inteface */
memset (&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, argv[i+1], IF_NAMESIZE);
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
fprintf(stderr, "%s: getindex(%s): %s\n",
argv[0], argv[i+1], strerror(errno));
exit(1);
}
/* one promiscuous per inteface */
memset(&req, 0, sizeof(req));
req.mr_ifindex = ifr.ifr_ifindex;
req.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&req, sizeof(req)) < 0) {
fprintf(stderr, "%s: set_promiscuous(%s): %s\n",
argv[0], argv[i+1], strerror(errno));
exit(1);
}
/* one bind per inteface */
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_ifindex = ifr.ifr_ifindex;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
fprintf(stderr, "%s: bind(%s): %s\n",
argv[0], argv[i+1], strerror(errno));
exit(1);
}
/* save for later */
socks[i] = sock;
FD_SET(sock, &fullset);
}
/* end of loop: "sock" is the largest one */
while(1) {
struct timeval tv;
set = fullset;
i = select(sock+1, &set, NULL, NULL, NULL);
gettimeofday(&tv, NULL);
if (i < 0 && errno == EINTR)
continue;
if (i <= 0)
exit(1);
/* retrieve data */
for (i = 0; i < argc-1; i++) {
if (!FD_ISSET(socks[i], &set))
continue;
while ( (len = recv(socks[i], packet, sizeof(packet),
MSG_DONTWAIT | MSG_TRUNC)) >= 0)
dumpone(argv[i+1], &tv, packet, len);
if (errno != EAGAIN) {
fprintf(stderr, "%s: revb(%s): %sn",
argv[0], argv[i+1], strerror(errno));
}
}
putchar('\n');
}
}
/* Alessandro Rubini for CERN and White Rabbit, 2011 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "swflood.h"
#define MAXARG 15 /* lazy me */
/*
* This can write to stderr and to the newly-allocated line.
* It returns -ENODATA if the line is empty, 0 on success, or
* other negative errors
*/
int swf_parse(char *s, struct swf_line *line)
{
int i;
struct swf_command **cmdp;
/* First trim any leading and trailing whitespace */
while (isspace(*s))
s++;
i = strlen(s);
while(i && isspace(s[i-1]))
s[--i] = '\0';
/* Now, if it's empty we are done */
if (!s[0] || s[0] == '#')
return -ENODATA;
/* Make a local copy for our argv, and allocate it */
s = strdup(s);
line->argv = malloc(sizeof(*line->argv) * (MAXARG + 1));
if (!s || !line->argv) {
free(s);
free(line->argv);
return -ENOMEM;
}
/* fill the argv */
i = 0;
while (1) {
line->argv[i++] = s;
while (*s && !isspace(*s))
s++;
if (!*s)
break;
*(s++) = '\0';
}
line->argc = i;
/* find the command */
for (cmdp = __cmd_start; cmdp < __cmd_end; cmdp++)
if (!strcmp(line->argv[0], (*cmdp)->name))
break;
if (cmdp == __cmd_end) {
fprintf(stderr, " invalid command \"%s\"\n",
line->argv[0]);
return -EINVAL;
}
/* and verify it */
line->cmd = *cmdp;
return line->cmd->verify(line);
return 0;
}
testing from 32 different senders plus another
# testing from 32 different senders plus another
cfg-test/tablesize-test:10: success
cfg-test/tablesize-test:12: success
testing from 64 different senders plus another
# testing from 64 different senders plus another
cfg-test/tablesize-test:16: success
cfg-test/tablesize-test:18: success
testing from 128 different senders plus another
# testing from 128 different senders plus another
cfg-test/tablesize-test:22: success
cfg-test/tablesize-test:24: success
testing from 256 different senders plus another
# testing from 256 different senders plus another
cfg-test/tablesize-test:28: success
cfg-test/tablesize-test:30: success
testing from 512 different senders plus another
# testing from 512 different senders plus another
cfg-test/tablesize-test:34: success
cfg-test/tablesize-test:36: success
testing from 1024 different senders plus another
# testing from 1024 different senders plus another
cfg-test/tablesize-test:40: success
cfg-test/tablesize-test:42: success
testing from 2048 different senders plus another
# testing from 2048 different senders plus another
cfg-test/tablesize-test:46: success
cfg-test/tablesize-test:48: expect failed
cfg-test/tablesize-test:48: expect failed
expected: 2048 0 0 0
received: 2048 0 1009 1009
testing from 4096 different senders plus another
# testing from 4096 different senders plus another
cfg-test/tablesize-test:52: success
cfg-test/tablesize-test:54: expect failed
cfg-test/tablesize-test:54: expect failed
expected: 4096 0 0 0
received: 4096 0 3057 3057
testing from 8192 different senders plus another
# testing from 8192 different senders plus another
cfg-test/tablesize-test:58: success
cfg-test/tablesize-test:60: expect failed
cfg-test/tablesize-test:60: expect failed
expected: 8192 0 0 0
received: 8192 0 7153 7153
testing from 16384 different senders plus another
# testing from 16384 different senders plus another
cfg-test/tablesize-test:64: success
cfg-test/tablesize-test:66: expect failed
cfg-test/tablesize-test:66: expect failed
expected: 16384 0 0 0
received: 16384 0 15345 15345
spusa$ sudo ./swflood cfg-test/tablesize-test
testing from 32 different senders plus another
# testing from 32 different senders plus another
cfg-test/tablesize-test:10: expect failed
cfg-test/tablesize-test:10: expect failed
expected: 0 32 32 32
received: 0 31 31 31
cfg-test/tablesize-test:12: expect failed
cfg-test/tablesize-test:12: expect failed
expected: 32 0 0 0
received: 31 0 0 0
testing from 64 different senders plus another
# testing from 64 different senders plus another
cfg-test/tablesize-test:16: success
cfg-test/tablesize-test:18: success
testing from 128 different senders plus another
# testing from 128 different senders plus another
cfg-test/tablesize-test:22: success
cfg-test/tablesize-test:24: success
testing from 256 different senders plus another
# testing from 256 different senders plus another
cfg-test/tablesize-test:28: success
cfg-test/tablesize-test:30: success
testing from 512 different senders plus another
# testing from 512 different senders plus another
cfg-test/tablesize-test:34: success
cfg-test/tablesize-test:36: success
testing from 1024 different senders plus another
# testing from 1024 different senders plus another
cfg-test/tablesize-test:40: success
cfg-test/tablesize-test:42: success
testing from 2048 different senders plus another
# testing from 2048 different senders plus another
cfg-test/tablesize-test:46: success
cfg-test/tablesize-test:48: expect failed
cfg-test/tablesize-test:48: expect failed
expected: 2048 0 0 0
received: 2048 0 1017 1017
testing from 4096 different senders plus another
# testing from 4096 different senders plus another
cfg-test/tablesize-test:52: success
cfg-test/tablesize-test:54: expect failed
cfg-test/tablesize-test:54: expect failed
expected: 4096 0 0 0
received: 4096 0 3065 3065
testing from 8192 different senders plus another
# testing from 8192 different senders plus another
cfg-test/tablesize-test:58: success
cfg-test/tablesize-test:60: expect failed
cfg-test/tablesize-test:60: expect failed
expected: 8192 0 0 0
received: 8192 0 7161 7161
testing from 16384 different senders plus another
# testing from 16384 different senders plus another
cfg-test/tablesize-test:64: success
cfg-test/tablesize-test:66: expect failed
cfg-test/tablesize-test:66: expect failed
expected: 16384 0 0 0
received: 16384 0 15353 15353
spusa$
sudo ./swflood cfg-test/tablesize-test
testing from 32 different senders plus another
# testing from 32 different senders plus another
cfg-test/tablesize-test:10: success
cfg-test/tablesize-test:12: success
testing from 64 different senders plus another
# testing from 64 different senders plus another
cfg-test/tablesize-test:16: success
cfg-test/tablesize-test:18: success
testing from 128 different senders plus another
# testing from 128 different senders plus another
cfg-test/tablesize-test:22: success
cfg-test/tablesize-test:24: success
testing from 256 different senders plus another
# testing from 256 different senders plus another
cfg-test/tablesize-test:28: success
cfg-test/tablesize-test:30: success
testing from 512 different senders plus another
# testing from 512 different senders plus another
cfg-test/tablesize-test:34: success
cfg-test/tablesize-test:36: success
testing from 1024 different senders plus another
# testing from 1024 different senders plus another
cfg-test/tablesize-test:40: success
cfg-test/tablesize-test:42: success
testing from 2048 different senders plus another
# testing from 2048 different senders plus another
cfg-test/tablesize-test:46: success
cfg-test/tablesize-test:48: success
testing from 4096 different senders plus another
# testing from 4096 different senders plus another
cfg-test/tablesize-test:52: success
cfg-test/tablesize-test:54: success
testing from 8192 different senders plus another
# testing from 8192 different senders plus another
cfg-test/tablesize-test:58: success
cfg-test/tablesize-test:60: expect failed
cfg-test/tablesize-test:60: expect failed
expected: 8192 0 0 0
received: 8192 0 2 2
testing from 16384 different senders plus another
# testing from 16384 different senders plus another
cfg-test/tablesize-test:64: success
cfg-test/tablesize-test:66: expect failed
cfg-test/tablesize-test:66: expect failed
expected: 16384 0 0 0
received: 16384 0 8194 8194
/* Prototypes and data structures for switch flooding */
#ifndef __SWFLOOD_H__
#define __SWFLOOD_H__
#include <linux/if_ether.h>
struct swf_if {
char *name;
int socket;
int stat;
int s_incr, d_incr;
unsigned char s_addr[ETH_ALEN], d_addr[ETH_ALEN];
};
struct swf_command;
struct swf_status;
struct swf_line {
struct swf_command *cmd;
int argc;
char **argv;
void *data;
char *fname;
int lineno;
int repcount;
struct swf_line *prev, *next;
};
struct swf_command {
char *name;
int (*verify)(struct swf_line *);
int (*verify_late)(struct swf_line *);
struct swf_line *(*execute)(struct swf_line *, struct swf_status *);
};
struct swf_status {
struct swf_line *line;
struct swf_if *iface;
int n_iface;
int verbose;
FILE *logfile;
int error;
};
/* each command */
#define declare_command(x) \
static struct swf_command * \
__attribute__((__used__)) \
__attribute__((section(".commands"))) \
__cmd_ptr_##x = &x
/* parse.c */
int swf_parse(char *s, struct swf_line *line);
/* commands.lds */
extern struct swf_command *__cmd_start[];
extern struct swf_command *__cmd_end[];
#endif /* __SWFLOOD_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment