lib/type-props.h \
lib/util.c \
lib/util.h \
+ lib/vconn-fd.c \
lib/vconn-provider.h \
lib/vconn-ssl.h \
lib/vconn-stream.c \
rc->n_attempted_connections++;
retval = vconn_open(rc->name, OFP_VERSION, &rc->vconn);
if (!retval) {
+ if (!vconn_is_reconnectable(rc->vconn)) {
+ rc->reliable = false;
+ }
rc->backoff_deadline = time_now() + rc->backoff;
state_transition(rc, S_CONNECTING);
} else {
--- /dev/null
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#include <config.h>
+#include "vconn.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "util.h"
+#include "vconn-provider.h"
+#include "vconn-stream.h"
+
+#include "vlog.h"
+#define THIS_MODULE VLM_vconn_fd
+
+/* File descriptor. */
+
+static int
+fd_open(const char *name, char *suffix, struct vconn **vconnp)
+{
+ int fd = atoi(suffix);
+ struct stat s;
+
+ /* Check that 'fd' is really open and is really the right type of fd. */
+ if (fstat(fd, &s) < 0) {
+ VLOG_ERR("%s: failed to stat file descriptor %d: %s",
+ name, fd, strerror(errno));
+ return errno;
+ }
+ if (!S_ISSOCK(s.st_mode)) {
+ VLOG_ERR("%s: file descriptor %d is not a socket", name, fd);
+ return errno;
+ }
+
+ return new_stream_vconn(name, fd, 0, 0, false, vconnp);
+}
+
+struct vconn_class fd_vconn_class = {
+ "fd", /* name */
+ fd_open, /* open */
+ NULL, /* close */
+ NULL, /* connect */
+ NULL, /* recv */
+ NULL, /* send */
+ NULL, /* wait */
+};
}
netlink = xmalloc(sizeof *netlink);
- vconn_init(&netlink->vconn, &netlink_vconn_class, 0, 0, name);
+ vconn_init(&netlink->vconn, &netlink_vconn_class, 0, 0, name, true);
retval = dpif_open(subscribe ? dp_idx : -1, &netlink->dp);
netlink->dp_idx = dp_idx;
if (retval) {
int version;
uint32_t ip;
char *name;
+ bool reconnectable;
};
void vconn_init(struct vconn *, struct vconn_class *, int connect_status,
- uint32_t ip, const char *name);
+ uint32_t ip, const char *name, bool reconnectable);
static inline void vconn_assert_class(const struct vconn *vconn,
const struct vconn_class *class)
{
extern struct pvconn_class ptcp_pvconn_class;
extern struct vconn_class unix_vconn_class;
extern struct pvconn_class punix_pvconn_class;
+extern struct vconn_class fd_vconn_class;
#ifdef HAVE_OPENSSL
extern struct vconn_class ssl_vconn_class;
extern struct pvconn_class pssl_pvconn_class;
/* Create and return the ssl_vconn. */
sslv = xmalloc(sizeof *sslv);
vconn_init(&sslv->vconn, &ssl_vconn_class, EAGAIN, sin->sin_addr.s_addr,
- name);
+ name, true);
sslv->state = state;
sslv->type = type;
sslv->fd = fd;
int
new_stream_vconn(const char *name, int fd, int connect_status,
- uint32_t ip, struct vconn **vconnp)
+ uint32_t ip, bool reconnectable, struct vconn **vconnp)
{
struct stream_vconn *s;
s = xmalloc(sizeof *s);
- vconn_init(&s->vconn, &stream_vconn_class, connect_status, ip, name);
+ vconn_init(&s->vconn, &stream_vconn_class, connect_status, ip, name,
+ reconnectable);
s->fd = fd;
s->txbuf = NULL;
s->tx_waiter = NULL;
#ifndef VCONN_STREAM_H
#define VCONN_STREAM_H 1
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
struct sockaddr;
int new_stream_vconn(const char *name, int fd, int connect_status,
- uint32_t ip, struct vconn **vconnp);
+ uint32_t ip, bool reconnectable, struct vconn **vconnp);
int new_pstream_pvconn(const char *name, int fd,
int (*accept_cb)(int fd, const struct sockaddr *,
size_t sa_len, struct vconn **),
}
return new_stream_vconn(name, fd, connect_status, sin->sin_addr.s_addr,
- vconnp);
+ true, vconnp);
}
static int
}
return new_stream_vconn(name, fd, check_connection_completion(fd),
- 0, vconnp);
+ 0, true, vconnp);
}
struct vconn_class unix_vconn_class = {
} else {
strcpy(name, "unix");
}
- return new_stream_vconn(name, fd, 0, 0, vconnp);
+ return new_stream_vconn(name, fd, 0, 0, true, vconnp);
}
struct pvconn_class punix_pvconn_class = {
#ifdef HAVE_OPENSSL
&ssl_vconn_class,
#endif
+ &fd_vconn_class,
};
static struct pvconn_class *pvconn_classes[] = {
"SSL PORT (default: %d) on remote HOST\n", OFP_SSL_PORT);
#endif
printf(" unix:FILE Unix domain socket named FILE\n");
+ printf(" fd:N File descriptor N\n");
}
if (passive) {
return vconn->ip;
}
+/* Returns true if, when 'vconn' is closed, it is possible to try to reconnect
+ * to it using the name that was originally used. This is ordinarily the case.
+ *
+ * Returns false if reconnecting under the same name will never work in the way
+ * that you would expect. This is the case if 'vconn' represents a "fd:N" type
+ * vconn; one can never connect to such a vconn more than once, because closing
+ * it closes the file descriptor. */
+bool
+vconn_is_reconnectable(const struct vconn *vconn)
+{
+ return vconn->reconnectable;
+}
+
static void
vcs_connecting(struct vconn *vconn)
{
void
vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
- uint32_t ip, const char *name)
+ uint32_t ip, const char *name, bool reconnectable)
{
vconn->class = class;
vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING
vconn->min_version = -1;
vconn->ip = ip;
vconn->name = xstrdup(name);
+ vconn->reconnectable = reconnectable;
}
void
void vconn_close(struct vconn *);
const char *vconn_get_name(const struct vconn *);
uint32_t vconn_get_ip(const struct vconn *);
+bool vconn_is_reconnectable(const struct vconn *);
int vconn_connect(struct vconn *);
int vconn_recv(struct vconn *, struct ofpbuf **);
int vconn_send(struct vconn *, struct ofpbuf *);
VLOG_MODULE(switch)
VLOG_MODULE(terminal)
VLOG_MODULE(socket_util)
+VLOG_MODULE(vconn_fd)
VLOG_MODULE(vconn_netlink)
VLOG_MODULE(vconn_tcp)
VLOG_MODULE(vconn_ssl)