f6636b13aa08f1c8840812488331cfa8e81bab08
[dragonfly.git] / tools / tools / netrate / pktgenctl / pktgenctl.c
1 /*
2  * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Sepherosa Ziehau <sepherosa@gmail.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/tools/tools/netrate/pktgenctl/pktgenctl.c,v 1.1 2008/03/26 13:53:14 sephe Exp $
35  */
36
37 #include <sys/types.h>
38 #include <sys/ioctl.h>
39 #include <sys/stat.h>
40 #include <sys/socket.h>
41
42 #include <arpa/inet.h>
43 #include <netinet/in.h>
44 #include <net/if.h>
45 #include <net/if_dl.h>
46 #include <net/ethernet.h>
47
48 #include <err.h>
49 #include <fcntl.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54
55 #include "pktgen/pktgen.h"
56
57 #define PKTGEN_DEVPATH  "/dev/pktg0"
58
59 #define DEFAULT_SPORT   3001
60 #define DEFAULT_DPORT   3000
61
62 #define INDST_MASK      0x1
63 #define INSRC_MASK      0x2
64 #define EADDR_MASK      0x4
65 #define IFACE_MASK      0x8
66 #define DATALEN_MASK    0x10
67 #define SPORT_MASK      0x20
68 #define DPORT_MASK      0x40
69 #define CPUID_MASK      0x80
70 #define DURATION_MASK   0x100
71 #define YIELD_MASK      0x200
72
73 #define MASK_NEEDED     (INDST_MASK | INSRC_MASK | EADDR_MASK | IFACE_MASK)
74
75 static void
76 usage(void)
77 {
78         fprintf(stderr, "pktgenctl -d dst_inaddr -s src_inaddr "
79                         "-e (gw_eaddr|dst_eaddr) -i iface "
80                         "[-p src_port] [-P dst_port] "
81                         "[-m data_len] [-c cpuid] [-l duration] [-y yield]\n");
82         exit(1);
83 }
84
85 int
86 main(int argc, char *argv[])
87 {
88         struct pktgen_conf conf;
89         struct sockaddr *sa;
90         struct sockaddr_in *dst_sin, *src_sin;
91         struct sockaddr_dl sdl;
92         char eaddr_str[32];
93         uint32_t arg_mask = 0;
94         int fd, c, n;
95
96         memset(&conf, 0, sizeof(conf));
97
98         conf.pc_cpuid = 0;
99         conf.pc_duration = 10;
100         conf.pc_datalen = 10;
101
102         sa = &conf.pc_dst_lladdr;
103         sa->sa_family = AF_LINK;
104         sa->sa_len = ETHER_ADDR_LEN;
105
106         dst_sin = &conf.pc_dst;
107         dst_sin->sin_family = AF_INET;
108         dst_sin->sin_port = htons(DEFAULT_DPORT);
109
110         src_sin = &conf.pc_src;
111         src_sin->sin_family = AF_INET;
112         src_sin->sin_port = htons(DEFAULT_SPORT);
113
114         while ((c = getopt(argc, argv, "d:s:e:i:p:P:m:c:l:y:")) != -1) {
115                 switch (c) {
116                 case 'd':
117                         n = inet_pton(AF_INET, optarg,
118                                       &dst_sin->sin_addr.s_addr);
119                         if (n == 0)
120                                 errx(1, "-d: invalid inet address");
121                         else if (n < 0)
122                                 err(1, "-d");
123                         arg_mask |= INDST_MASK;
124                         break;
125
126                 case 's':
127                         n = inet_pton(AF_INET, optarg,
128                                       &src_sin->sin_addr.s_addr);
129                         if (n == 0)
130                                 errx(1, "-s: invalid inet address");
131                         else if (n < 0)
132                                 err(1, "-s");
133                         arg_mask |= INSRC_MASK;
134                         break;
135
136                 case 'e':
137                         strcpy(eaddr_str, "if0.");
138                         strlcpy(&eaddr_str[strlen("if0.")], optarg,
139                                 sizeof(eaddr_str) - strlen("if0."));
140
141                         memset(&sdl, 0, sizeof(sdl));
142                         sdl.sdl_len = sizeof(sdl);
143                         if (ascii2addr(AF_LINK, eaddr_str, &sdl) < 0)
144                                 errx(1, "-e: invalid ethernet address");
145                         bcopy(LLADDR(&sdl), sa->sa_data, ETHER_ADDR_LEN);
146                         arg_mask |= EADDR_MASK;
147                         for (n = 0; n < ETHER_ADDR_LEN; ++n)
148                                 fprintf(stderr, "%02x ", (u_char)sa->sa_data[n]);
149                         fprintf(stderr, "\n");
150                         break;
151
152                 case 'i':
153                         strlcpy(conf.pc_ifname, optarg, sizeof(conf.pc_ifname));
154                         arg_mask |= IFACE_MASK;
155                         break;
156
157                 case 'p':
158                         src_sin->sin_port = htons(atoi(optarg));
159                         arg_mask |= SPORT_MASK;
160                         break;
161
162                 case 'P':
163                         dst_sin->sin_port = htons(atoi(optarg));
164                         arg_mask |= DPORT_MASK;
165                         break;
166
167                 case 'm':
168                         conf.pc_datalen = atoi(optarg);
169                         arg_mask |= DATALEN_MASK;
170                         break;
171
172                 case 'c':
173                         conf.pc_cpuid = atoi(optarg);
174                         arg_mask |= CPUID_MASK;
175                         break;
176
177                 case 'l':
178                         conf.pc_duration = atoi(optarg);
179                         arg_mask |= DURATION_MASK;
180                         break;
181
182                 case 'y':
183                         conf.pc_yield = atoi(optarg);
184                         arg_mask |= YIELD_MASK;
185                         break;
186                 }
187         }
188
189         if ((arg_mask & MASK_NEEDED) != MASK_NEEDED)
190                 usage();
191
192         fd = open(PKTGEN_DEVPATH, O_RDONLY);
193         if (fd < 0)
194                 err(1, "open(" PKTGEN_DEVPATH ")");
195
196         if (ioctl(fd, PKTGENSCONF, &conf) < 0)
197                 err(1, "ioctl(PKTGENSCONF)");
198
199         if (ioctl(fd, PKTGENSTART) < 0)
200                 err(1, "ioctl(PKTGENSTART)");
201
202         close(fd);
203         exit(0);
204 }