GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/switchd/ofp.c Lines: 0 83 0.0 %
Date: 2017-11-13 Branches: 0 56 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ofp.c,v 1.18 2016/12/22 15:31:43 rzalamena Exp $	*/
2
3
/*
4
 * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/socket.h>
21
#include <sys/uio.h>
22
#include <sys/un.h>
23
#include <sys/queue.h>
24
25
#include <netinet/in.h>
26
#include <netinet/tcp.h>
27
#include <net/ofp.h>
28
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <string.h>
33
#include <fcntl.h>
34
#include <pwd.h>
35
#include <event.h>
36
37
#include "ofp10.h"
38
#include "switchd.h"
39
#include "ofp_map.h"
40
41
int	 ofp_dispatch_parent(int, struct privsep_proc *, struct imsg *);
42
int	 ofp_dispatch_control(int, struct privsep_proc *, struct imsg *);
43
void	 ofp_run(struct privsep *, struct privsep_proc *, void *);
44
int	 ofp_add_device(struct switchd *, int, const char *);
45
46
static struct privsep_proc procs[] = {
47
	{ "control",	PROC_CONTROL,	ofp_dispatch_control },
48
	{ "parent",	PROC_PARENT,	ofp_dispatch_parent }
49
};
50
51
void
52
ofp(struct privsep *ps, struct privsep_proc *p)
53
{
54
	ofrelay(ps, p);
55
	proc_run(ps, p, procs, nitems(procs), ofp_run, NULL);
56
}
57
58
void
59
ofp_run(struct privsep *ps, struct privsep_proc *p, void *arg)
60
{
61
	struct switchd	*sc = ps->ps_env;
62
63
	/*
64
	 * pledge in the ofp process:
65
 	 * stdio - for malloc and basic I/O including events.
66
	 * inet - for handling tcp connections with OpenFlow peers.
67
	 * recvfd - for receiving new sockets on reload.
68
	 */
69
	if (pledge("stdio inet recvfd flock rpath cpath wpath", NULL) == -1)
70
		fatal("pledge");
71
72
	TAILQ_INIT(&sc->sc_conns);
73
	sc->sc_tap = -1;
74
75
	ofrelay_run(ps, p, NULL);
76
}
77
78
int
79
ofp_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
80
{
81
	switch (imsg->hdr.type) {
82
	case IMSG_CTL_SHOW_SUM:
83
		return (switch_dispatch_control(fd, p, imsg));
84
	default:
85
		break;
86
	}
87
88
	return (-1);
89
}
90
91
int
92
ofp_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
93
{
94
	struct privsep			*ps = p->p_ps;
95
	struct switchd			*sc = ps->ps_env;
96
	struct switch_client		 swc;
97
	struct switch_connection	*con;
98
99
	switch (imsg->hdr.type) {
100
	case IMSG_TAPFD:
101
		if (sc->sc_tap != -1)
102
			close(sc->sc_tap);
103
		sc->sc_tap = imsg->fd;
104
		return (0);
105
	case IMSG_CTL_CONNECT:
106
	case IMSG_CTL_DISCONNECT:
107
		IMSG_SIZE_CHECK(imsg, &swc);
108
		memcpy(&swc, imsg->data, sizeof(swc));
109
110
		if (imsg->hdr.type == IMSG_CTL_CONNECT)
111
			ofrelay_attach(&sc->sc_server, imsg->fd,
112
			    (struct sockaddr *)&swc.swc_addr.swa_addr);
113
		else if ((con = switchd_connbyaddr(sc,
114
		    (struct sockaddr *)&swc.swc_addr.swa_addr)) != NULL)
115
			ofp_close(con);
116
		return (0);
117
	default:
118
		break;
119
	}
120
121
	return (-1);
122
}
123
124
int
125
ofp_input(struct switch_connection *con, struct ibuf *ibuf)
126
{
127
	struct switchd		*sc = con->con_sc;
128
	struct ofp_header	*oh;
129
130
	if ((oh = ibuf_seek(ibuf, 0, sizeof(*oh))) == NULL) {
131
		log_debug("short header");
132
		return (-1);
133
	}
134
135
	/* Check for message version match. */
136
	if (con->con_state > OFP_STATE_HELLO_WAIT &&
137
	    con->con_version != OFP_V_0 &&
138
	    oh->oh_version != con->con_version) {
139
		log_debug("wrong version %s, expected %s",
140
		    print_map(oh->oh_version, ofp_v_map),
141
		    print_map(con->con_version, ofp_v_map));
142
		return (-1);
143
	}
144
145
	/* Check the state machine to decide whether or not to allow. */
146
	if (con->con_state <= OFP_STATE_HELLO_WAIT &&
147
	    oh->oh_type > OFP_T_ERROR) {
148
		log_debug("expected hello, got %s",
149
		    print_map(oh->oh_type, ofp_t_map));
150
		return (-1);
151
	}
152
153
	switch (oh->oh_version) {
154
	case OFP_V_1_0:
155
		if (ofp10_input(sc, con, oh, ibuf) != 0)
156
			return (-1);
157
		break;
158
	case OFP_V_1_3:
159
		if (ofp13_input(sc, con, oh, ibuf) != 0)
160
			return (-1);
161
		break;
162
	case OFP_V_1_1:
163
	case OFP_V_1_2:
164
		/* FALLTHROUGH */
165
	default:
166
		(void)ofp10_validate(sc,
167
		    &con->con_peer, &con->con_local, oh, ibuf);
168
		ofp10_hello(sc, con, oh, ibuf);
169
		return (-1);
170
	}
171
172
	return (0);
173
}
174
175
int
176
ofp_open(struct privsep *ps, struct switch_connection *con)
177
{
178
	struct switch_control	*sw;
179
180
	/* Get associated switch, if it exists */
181
	sw = switch_get(con);
182
183
	log_info("%s: new connection %u.%u from switch %u",
184
	    __func__, con->con_id, con->con_instance,
185
	    sw == NULL ? 0 : sw->sw_id);
186
187
	/* Send the hello with the latest version we support. */
188
	if (ofp_send_hello(ps->ps_env, con, OFP_V_1_3) == -1)
189
		return (-1);
190
191
	if (ofp_nextstate(ps->ps_env, con, OFP_STATE_HELLO_WAIT) == -1)
192
		return (-1);
193
194
	return (0);
195
}
196
197
void
198
ofp_close(struct switch_connection *con)
199
{
200
	ofrelay_close(con);
201
}
202
203
int
204
ofp_nextstate(struct switchd *sc, struct switch_connection *con,
205
    enum ofp_state state)
206
{
207
	int		rv = 0;
208
209
	switch (con->con_state) {
210
	case OFP_STATE_CLOSED:
211
		if (state != OFP_STATE_HELLO_WAIT)
212
			return (-1);
213
214
		break;
215
216
	case OFP_STATE_HELLO_WAIT:
217
		if (state != OFP_STATE_FEATURE_WAIT)
218
			return (-1);
219
220
		rv = ofp_send_featuresrequest(sc, con);
221
		break;
222
223
	case OFP_STATE_FEATURE_WAIT:
224
		if (state != OFP_STATE_ESTABLISHED)
225
			return (-1);
226
227
		if (con->con_version != OFP_V_1_3)
228
			break;
229
230
#if 0
231
		/* Let's not ask this while we don't use it. */
232
		ofp13_flow_stats(sc, con, OFP_PORT_ANY, OFP_GROUP_ID_ANY,
233
		    OFP_TABLE_ID_ALL);
234
		ofp13_desc(sc, con);
235
#endif
236
		rv |= ofp13_table_features(sc, con, 0);
237
		rv |= ofp13_setconfig(sc, con, OFP_CONFIG_FRAG_NORMAL,
238
		    OFP_CONTROLLER_MAXLEN_NO_BUFFER);
239
		break;
240
241
242
	case OFP_STATE_ESTABLISHED:
243
		if (state != OFP_STATE_CLOSED)
244
			return (-1);
245
246
		break;
247
248
	default:
249
		return (-1);
250
	}
251
252
	/* Set the next state. */
253
	con->con_state = state;
254
255
	return (rv);
256
}