summaryrefslogtreecommitdiffstats
path: root/usr.sbin/switchctl/ofpclient.c
diff options
context:
space:
mode:
authorreyk <reyk@openbsd.org>2016-11-24 09:23:11 +0000
committerreyk <reyk@openbsd.org>2016-11-24 09:23:11 +0000
commitb423f9d5571f6d10324c59d51a1c41277a699ef8 (patch)
tree16014384e6ba6168c076f488e0bb64fc234a068e /usr.sbin/switchctl/ofpclient.c
parentBetter cast for consistency (diff)
downloadwireguard-openbsd-b423f9d5571f6d10324c59d51a1c41277a699ef8.tar.xz
wireguard-openbsd-b423f9d5571f6d10324c59d51a1c41277a699ef8.zip
Add simple client to add flows from switchctl. Not finished yet, but
it is better for rzalamena and me to work on it in the tree. OK rzalamena@
Diffstat (limited to 'usr.sbin/switchctl/ofpclient.c')
-rw-r--r--usr.sbin/switchctl/ofpclient.c126
1 files changed, 98 insertions, 28 deletions
diff --git a/usr.sbin/switchctl/ofpclient.c b/usr.sbin/switchctl/ofpclient.c
index 2302355ebdd..179886c46ba 100644
--- a/usr.sbin/switchctl/ofpclient.c
+++ b/usr.sbin/switchctl/ofpclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofpclient.c,v 1.3 2016/11/18 22:15:52 tb Exp $ */
+/* $OpenBSD: ofpclient.c,v 1.4 2016/11/24 09:23:11 reyk Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include <stddef.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
@@ -45,17 +46,31 @@
#include "switchd.h"
#include "parser.h"
+void ofpclient_read(struct switch_connection *, int);
+int flowmod(struct switchd *, struct switch_connection *,
+ struct parse_result *);
+int flowmod_test(struct switchd *, struct switch_connection *);
+
void
ofpclient(struct parse_result *res, struct passwd *pw)
{
struct switch_connection con;
struct switchd sc;
struct ofp_header oh;
- int s;
+ int s, timeout;
memset(&sc, 0, sizeof(sc));
sc.sc_tap = -1;
+ /* If no uri has been specified, try to connect to localhost */
+ if (res->uri.swa_addr.ss_family == AF_UNSPEC) {
+ res->uri.swa_type = SWITCH_CONN_TCP;
+ if (parsehostport("127.0.0.1",
+ (struct sockaddr *)&res->uri.swa_addr,
+ sizeof(res->uri.swa_addr)) != 0)
+ fatal("could not parse address");
+ }
+
memset(&con, 0, sizeof(con));
memcpy(&con.con_peer, &res->uri.swa_addr, sizeof(res->uri.swa_addr));
con.con_sc = &sc;
@@ -87,15 +102,23 @@ ofpclient(struct parse_result *res, struct passwd *pw)
if (pledge("stdio", NULL) == -1)
err(1, "pledge");
- log_verbose(0);
+ /* Set a default read timeout */
+ timeout = 3 * 1000;
+
+ log_verbose(res->verbose);
oh.oh_version = OFP_V_1_3;
oh.oh_type = OFP_T_HELLO;
- oh.oh_length = 0;
- oh.oh_xid = 0;
- ofp13_hello(&sc, &con, &oh, NULL);
+ oh.oh_length = htons(sizeof(oh));
+ oh.oh_xid = htonl(1);
+ if (ofp_validate(&sc, &con.con_local, &con.con_peer, &oh,
+ NULL, oh.oh_version) != 0)
+ fatal("ofp_validate");
+ ofp_output(&con, &oh, NULL);
+
+ ofpclient_read(&con, timeout);
- log_verbose(res->quiet ? 0 : 2);
+ log_verbose(res->quiet ? res->verbose : 2);
switch (res->action) {
case DUMP_DESC:
@@ -106,24 +129,58 @@ ofpclient(struct parse_result *res, struct passwd *pw)
break;
case DUMP_FLOWS:
ofp13_flow_stats(&sc, &con, OFP_PORT_ANY, OFP_GROUP_ID_ANY,
- OFP_TABLE_ID_ALL);
+ res->table);
break;
case DUMP_TABLES:
- ofp13_table_features(&sc, &con, 0);
+ ofp13_table_features(&sc, &con, res->table);
break;
- default:
+ case FLOW_ADD:
+ case FLOW_DELETE:
+ case FLOW_MODIFY:
+ timeout = 0;
+ flowmod(&sc, &con, res);
break;
- }
+ default:
+ fatalx("unsupported action");
+ }
+
+ /* XXX */
+ ofpclient_read(&con, timeout);
}
-/*
- * stubs for ofp*.c
- */
+int
+flowmod(struct switchd *sc, struct switch_connection *con,
+ struct parse_result *res)
+{
+ struct ofp_header *oh;
+ struct ofp_flow_mod *fm;
+
+ if (oflowmod_iclose(&res->fctx) == -1)
+ goto err;
+ if (oflowmod_close(&res->fctx) == -1)
+ goto err;
+
+ fm = res->fctx.ctx_fm;
+ fm->fm_table_id = res->table;
+ oh = &fm->fm_oh;
+
+ if (ofp_validate(sc, &con->con_local, &con->con_peer,
+ oh, res->fbuf, oh->oh_version) != 0)
+ goto err;
+
+ ofrelay_write(con, res->fbuf);
+
+ return (0);
+
+ err:
+ (void)oflowmod_err(&res->fctx, __func__, __LINE__);
+ log_warnx("invalid flow");
+ return (-1);
+}
void
-ofrelay_write(struct switch_connection *con, struct ibuf *buf)
+ofpclient_read(struct switch_connection *con, int timeout)
{
- struct msgbuf msgbuf;
uint8_t rbuf[0xffff];
ssize_t rlen;
struct ofp_header *oh;
@@ -131,20 +188,17 @@ ofrelay_write(struct switch_connection *con, struct ibuf *buf)
struct pollfd pfd[1];
int nfds;
- msgbuf_init(&msgbuf);
- msgbuf.fd = con->con_fd;
-
- ibuf_close(&msgbuf, buf);
- ibuf_write(&msgbuf);
-
/* Wait for response */
pfd[0].fd = con->con_fd;
pfd[0].events = POLLIN;
- nfds = poll(pfd, 1, 3 * 1000);
+ nfds = poll(pfd, 1, timeout);
if (nfds == -1 || (pfd[0].revents & (POLLERR|POLLHUP|POLLNVAL)))
fatal("poll error");
- if (nfds == 0)
- fatal("time out");
+ if (nfds == 0) {
+ if (timeout)
+ fatal("time out");
+ return;
+ }
if ((rlen = read(con->con_fd, rbuf, sizeof(rbuf))) == -1)
fatal("read");
@@ -157,13 +211,29 @@ ofrelay_write(struct switch_connection *con, struct ibuf *buf)
if ((oh = ibuf_seek(ibuf, 0, sizeof(*oh))) == NULL)
fatal("short header");
- if (ofp13_validate(con->con_sc,
- &con->con_peer, &con->con_local, oh, ibuf) != 0)
- fatal("ofp13_validate");
+ if (ofp_validate(con->con_sc,
+ &con->con_peer, &con->con_local, oh, ibuf, oh->oh_version) != 0)
+ fatal("ofp_validate");
ibuf_free(ibuf);
}
+/*
+ * stubs for ofp*.c
+ */
+
+void
+ofrelay_write(struct switch_connection *con, struct ibuf *buf)
+{
+ struct msgbuf msgbuf;
+
+ msgbuf_init(&msgbuf);
+ msgbuf.fd = con->con_fd;
+
+ ibuf_close(&msgbuf, buf);
+ ibuf_write(&msgbuf);
+}
+
struct switch_control *
switch_add(struct switch_connection *con)
{