2 * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/param.h>
36 #include <sys/endian.h>
37 #include <sys/socket.h>
38 #include <sys/linker.h>
39 #include <sys/module.h>
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
42 #include <arpa/inet.h>
56 #include <geom/gate/g_gate.h>
60 int g_gate_devfd
= -1;
61 int g_gate_verbose
= 0;
65 g_gate_vlog(int priority
, const char *message
, va_list ap
)
91 printf("%s: ", prefix
);
95 if (priority
!= LOG_DEBUG
)
96 vsyslog(priority
, message
, ap
);
101 g_gate_log(int priority
, const char *message
, ...)
105 va_start(ap
, message
);
106 g_gate_vlog(priority
, message
, ap
);
111 g_gate_xvlog(const char *message
, va_list ap
)
114 g_gate_vlog(LOG_ERR
, message
, ap
);
115 g_gate_vlog(LOG_ERR
, "Exiting.", ap
);
120 g_gate_xlog(const char *message
, ...)
124 va_start(ap
, message
);
125 g_gate_xvlog(message
, ap
);
132 g_gate_mediasize(int fd
)
137 if (fstat(fd
, &sb
) == -1)
138 g_gate_xlog("fstat(): %s.", strerror(errno
));
139 if (S_ISCHR(sb
.st_mode
)) {
140 if (ioctl(fd
, DIOCGMEDIASIZE
, &mediasize
) == -1) {
141 g_gate_xlog("Can't get media size: %s.",
144 } else if (S_ISREG(sb
.st_mode
)) {
145 mediasize
= sb
.st_size
;
147 g_gate_xlog("Unsupported file system object.");
153 g_gate_sectorsize(int fd
)
158 if (fstat(fd
, &sb
) == -1)
159 g_gate_xlog("fstat(): %s.", strerror(errno
));
160 if (S_ISCHR(sb
.st_mode
)) {
161 if (ioctl(fd
, DIOCGSECTORSIZE
, &secsize
) == -1) {
162 g_gate_xlog("Can't get sector size: %s.",
165 } else if (S_ISREG(sb
.st_mode
)) {
168 g_gate_xlog("Unsupported file system object.");
174 g_gate_open_device(void)
177 g_gate_devfd
= open("/dev/" G_GATE_CTL_NAME
, O_RDWR
);
178 if (g_gate_devfd
== -1)
179 err(EXIT_FAILURE
, "open(/dev/%s)", G_GATE_CTL_NAME
);
183 g_gate_close_device(void)
190 g_gate_ioctl(unsigned long req
, void *data
)
193 if (ioctl(g_gate_devfd
, req
, data
) == -1) {
194 g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
195 G_GATE_CTL_NAME
, strerror(errno
));
200 g_gate_destroy(int unit
, int force
)
202 struct g_gate_ctl_destroy ggio
;
204 ggio
.gctl_version
= G_GATE_VERSION
;
205 ggio
.gctl_unit
= unit
;
206 ggio
.gctl_force
= force
;
207 g_gate_ioctl(G_GATE_CMD_DESTROY
, &ggio
);
211 g_gate_load_module(void)
214 if (modfind("g_gate") == -1) {
215 /* Not present in kernel, try loading it. */
216 if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) {
217 if (errno
!= EEXIST
) {
219 "geom_gate module not available!");
226 * When we send from ggatec packets larger than 32kB, performance drops
227 * significantly (eg. to 256kB/s over 1Gbit/s link). This is not a problem
228 * when data is send from ggated. I don't know why, so for now I limit
229 * size of packets send from ggatec to 32kB by defining MAX_SEND_SIZE
230 * in ggatec Makefile.
232 #ifndef MAX_SEND_SIZE
233 #define MAX_SEND_SIZE MAXPHYS
236 g_gate_send(int s
, const void *buf
, size_t len
, int flags
)
238 ssize_t done
= 0, done2
;
239 const unsigned char *p
= buf
;
242 done2
= send(s
, p
, MIN(len
, MAX_SEND_SIZE
), flags
);
245 else if (done2
== -1) {
246 if (errno
== EAGAIN
) {
247 printf("%s: EAGAIN\n", __func__
);
261 g_gate_recv(int s
, void *buf
, size_t len
, int flags
)
266 done
= recv(s
, buf
, len
, flags
);
267 } while (done
== -1 && errno
== EAGAIN
);
272 unsigned rcvbuf
= G_GATE_RCVBUF
;
273 unsigned sndbuf
= G_GATE_SNDBUF
;
276 g_gate_socket_settings(int sfd
)
281 /* Socket settings. */
284 if (setsockopt(sfd
, IPPROTO_TCP
, TCP_NODELAY
, &on
,
286 g_gate_xlog("setsockopt() error: %s.", strerror(errno
));
289 if (setsockopt(sfd
, SOL_SOCKET
, SO_REUSEADDR
, &on
, sizeof(on
)) == -1)
290 g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno
));
292 if (setsockopt(sfd
, SOL_SOCKET
, SO_RCVBUF
, &bsize
, sizeof(bsize
)) == -1)
293 g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno
));
295 if (setsockopt(sfd
, SOL_SOCKET
, SO_SNDBUF
, &bsize
, sizeof(bsize
)) == -1)
296 g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno
));
299 if (setsockopt(sfd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
)) == -1) {
300 g_gate_log(LOG_ERR
, "setsockopt(SO_SNDTIMEO) error: %s.",
303 if (setsockopt(sfd
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
)) == -1) {
304 g_gate_log(LOG_ERR
, "setsockopt(SO_RCVTIMEO) error: %s.",
310 static struct gclass
*
311 find_class(struct gmesh
*mesh
, const char *name
)
313 struct gclass
*class;
315 LIST_FOREACH(class, &mesh
->lg_class
, lg_class
) {
316 if (strcmp(class->lg_name
, name
) == 0)
323 get_conf(struct ggeom
*gp
, const char *name
)
325 struct gconfig
*conf
;
327 LIST_FOREACH(conf
, &gp
->lg_config
, lg_config
) {
328 if (strcmp(conf
->lg_name
, name
) == 0)
329 return (conf
->lg_val
);
335 show_config(struct ggeom
*gp
, int verbose
)
337 struct gprovider
*pp
;
340 pp
= LIST_FIRST(&gp
->lg_provider
);
344 printf("%s\n", pp
->lg_name
);
347 printf(" NAME: %s\n", pp
->lg_name
);
348 printf(" info: %s\n", get_conf(gp
, "info"));
349 printf(" access: %s\n", get_conf(gp
, "access"));
350 printf(" timeout: %s\n", get_conf(gp
, "timeout"));
351 printf("queue_count: %s\n", get_conf(gp
, "queue_count"));
352 printf(" queue_size: %s\n", get_conf(gp
, "queue_size"));
353 printf(" references: %s\n", get_conf(gp
, "ref"));
354 humanize_number(buf
, sizeof(buf
), (int64_t)pp
->lg_mediasize
, "",
355 HN_AUTOSCALE
, HN_B
| HN_NOSPACE
| HN_DECIMAL
);
356 printf(" mediasize: %jd (%s)\n", (intmax_t)pp
->lg_mediasize
, buf
);
357 printf(" sectorsize: %u\n", pp
->lg_sectorsize
);
358 printf(" mode: %s\n", pp
->lg_mode
);
363 g_gate_list(int unit
, int verbose
)
366 struct gclass
*class;
371 error
= geom_gettree(&mesh
);
374 class = find_class(&mesh
, G_GATE_CLASS_NAME
);
376 geom_deletetree(&mesh
);
380 snprintf(name
, sizeof(name
), "%s%d", G_GATE_PROVIDER_NAME
,
383 LIST_FOREACH(gp
, &class->lg_geom
, lg_geom
) {
384 if (unit
!= -1 && strcmp(gp
->lg_name
, name
) != 0)
386 show_config(gp
, verbose
);
388 geom_deletetree(&mesh
);
394 g_gate_str2ip(const char *str
)
400 if (ip
!= INADDR_NONE
) {
401 /* It is a valid IP address. */
404 /* Check if it is a valid host name. */
405 hp
= gethostbyname(str
);
407 return (INADDR_NONE
);
408 return (((struct in_addr
*)(void *)hp
->h_addr
)->s_addr
);