GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/switchctl/../switchd/ofp_common.c Lines: 0 512 0.0 %
Date: 2017-11-07 Branches: 0 295 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ofp_common.c,v 1.10 2016/12/22 15:31:43 rzalamena Exp $	*/
2
3
/*
4
 * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
5
 * Copyright (c) 2016 Rafael Zalamena <rzalamena@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <sys/queue.h>
22
#include <sys/socket.h>
23
24
#include <net/if.h>
25
#include <net/if_arp.h>
26
#include <net/ofp.h>
27
28
#include <netinet/in.h>
29
#include <netinet/if_ether.h>
30
#include <netinet/tcp.h>
31
#include <netmpls/mpls.h>
32
33
#include <endian.h>
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <stddef.h>
37
#include <unistd.h>
38
#include <string.h>
39
#include <fcntl.h>
40
#include <imsg.h>
41
#include <event.h>
42
43
#include "switchd.h"
44
#include "ofp_map.h"
45
46
int		ofp_setversion(struct switch_connection *, int);
47
48
int
49
ofp_validate_header(struct switchd *sc,
50
    struct sockaddr_storage *src, struct sockaddr_storage *dst,
51
    struct ofp_header *oh, uint8_t version)
52
{
53
	struct constmap	*tmap;
54
55
	/* For debug, don't verify the header if the version is unset */
56
	if (version != OFP_V_0 &&
57
	    (oh->oh_version != version ||
58
	    oh->oh_type >= OFP_T_TYPE_MAX))
59
		return (-1);
60
61
	switch (version) {
62
	case OFP_V_1_0:
63
	case OFP_V_1_1:
64
		tmap = ofp10_t_map;
65
		break;
66
	case OFP_V_1_3:
67
	default:
68
		tmap = ofp_t_map;
69
		break;
70
	}
71
72
	log_debug("%s > %s: version %s type %s length %u xid %u",
73
	    print_host(src, NULL, 0),
74
	    print_host(dst, NULL, 0),
75
	    print_map(oh->oh_version, ofp_v_map),
76
	    print_map(oh->oh_type, tmap),
77
	    ntohs(oh->oh_length), ntohl(oh->oh_xid));
78
79
	return (0);
80
}
81
82
int
83
ofp_validate(struct switchd *sc,
84
    struct sockaddr_storage *src, struct sockaddr_storage *dst,
85
    struct ofp_header *oh, struct ibuf *ibuf, uint8_t version)
86
{
87
	switch (version) {
88
	case OFP_V_1_0:
89
		return (ofp10_validate(sc, src, dst, oh, ibuf));
90
	case OFP_V_1_3:
91
		return (ofp13_validate(sc, src, dst, oh, ibuf));
92
	default:
93
		return (-1);
94
	}
95
96
	/* NOTREACHED */
97
}
98
99
int
100
ofp_output(struct switch_connection *con, struct ofp_header *oh,
101
    struct ibuf *obuf)
102
{
103
	struct ibuf	*buf;
104
105
	if ((buf = ibuf_static()) == NULL)
106
		return (-1);
107
	if ((oh != NULL) &&
108
	    (ibuf_add(buf, oh, sizeof(*oh)) == -1)) {
109
		ibuf_release(buf);
110
		return (-1);
111
	}
112
	if ((obuf != NULL) &&
113
	    (ibuf_cat(buf, obuf) == -1)) {
114
		ibuf_release(buf);
115
		return (-1);
116
	}
117
118
	ofrelay_write(con, buf);
119
120
	return (0);
121
}
122
123
int
124
ofp_send_hello(struct switchd *sc, struct switch_connection *con, int version)
125
{
126
	struct ofp_hello_element_header	*he;
127
	struct ofp_header		*oh;
128
	struct ibuf			*ibuf;
129
	size_t				 hstart, hend;
130
	uint32_t			*bmp;
131
	int				 rv = -1;
132
133
	if ((ibuf = ibuf_static()) == NULL ||
134
	    (oh = ibuf_advance(ibuf, sizeof(*oh))) == NULL ||
135
	    (he = ibuf_advance(ibuf, sizeof(*he))) == NULL)
136
		goto done;
137
138
	/* Write down all versions we support. */
139
	hstart = ibuf->wpos;
140
	if ((bmp = ibuf_advance(ibuf, sizeof(*bmp))) == NULL)
141
		goto done;
142
143
	*bmp = htonl((1 << OFP_V_1_0) | (1 << OFP_V_1_3));
144
	hend = ibuf->wpos;
145
146
	/* Fill the headers. */
147
	oh->oh_version = version;
148
	oh->oh_type = OFP_T_HELLO;
149
	oh->oh_length = htons(ibuf_length(ibuf));
150
	oh->oh_xid = htonl(con->con_xidnxt++);
151
	he->he_type = htons(OFP_HELLO_T_VERSION_BITMAP);
152
	he->he_length = htons(sizeof(*he) + (hend - hstart));
153
154
	if (ofp_validate(sc, &con->con_local, &con->con_peer, oh, ibuf,
155
	    version) != 0)
156
		goto done;
157
158
	rv = ofp_output(con, NULL, ibuf);
159
160
 done:
161
	ibuf_free(ibuf);
162
	return (rv);
163
}
164
165
int
166
ofp_validate_hello(struct switchd *sc,
167
    struct sockaddr_storage *src, struct sockaddr_storage *dst,
168
    struct ofp_header *oh, struct ibuf *ibuf)
169
{
170
	struct ofp_hello_element_header	*he;
171
	uint32_t			*bmp;
172
	off_t				 poff;
173
	int				 helen, i, ver;
174
175
	/* No extra element headers. */
176
	if (ntohs(oh->oh_length) == sizeof(*oh))
177
		return (0);
178
179
	/* Test for supported element headers. */
180
	if ((he = ibuf_seek(ibuf, sizeof(*oh), sizeof(*he))) == NULL)
181
		return (-1);
182
	if (he->he_type != htons(OFP_HELLO_T_VERSION_BITMAP))
183
		return (-1);
184
185
	log_debug("\tversion bitmap:");
186
187
	/* Validate header sizes. */
188
	helen = ntohs(he->he_length);
189
	if (helen < (int)sizeof(*he))
190
		return (-1);
191
	else if (helen == sizeof(*he))
192
		return (0);
193
194
	helen -= sizeof(*he);
195
	/* Invalid bitmap size. */
196
	if ((helen % sizeof(*bmp)) != 0)
197
		return (-1);
198
199
	ver = 0;
200
	poff = sizeof(*oh) + sizeof(*he);
201
	while (helen > 0) {
202
		if ((bmp = ibuf_seek(ibuf, poff, sizeof(*bmp))) == NULL)
203
			return (-1);
204
205
		for (i = 0; i < 32; i++, ver++) {
206
			if ((ntohl(*bmp) & (1 << i)) == 0)
207
				continue;
208
209
			log_debug("\t\tversion %s",
210
			    print_map(ver, ofp_v_map));
211
		}
212
213
		helen -= sizeof(*bmp);
214
		poff += sizeof(*bmp);
215
	}
216
217
	return (0);
218
}
219
220
int
221
ofp_setversion(struct switch_connection *con, int version)
222
{
223
	switch (version) {
224
	case OFP_V_1_0:
225
	case OFP_V_1_3:
226
		con->con_version = version;
227
		return (0);
228
229
	default:
230
		return (-1);
231
	}
232
}
233
234
int
235
ofp_recv_hello(struct switchd *sc, struct switch_connection *con,
236
    struct ofp_header *oh, struct ibuf *ibuf)
237
{
238
	struct ofp_hello_element_header	*he;
239
	uint32_t			*bmp;
240
	off_t				 poff;
241
	int				 helen, i, ver;
242
243
	/* No extra element headers, just use the header version. */
244
	if (ntohs(oh->oh_length) == sizeof(*oh))
245
		return (ofp_setversion(con, oh->oh_version));
246
247
	/* Read the element header. */
248
	if ((he = ibuf_seek(ibuf, sizeof(*oh), sizeof(*he))) == NULL)
249
		return (-1);
250
251
	/* We don't support anything else than the version bitmap. */
252
	if (he->he_type != htons(OFP_HELLO_T_VERSION_BITMAP))
253
		return (-1);
254
255
	/* Validate header sizes. */
256
	helen = ntohs(he->he_length);
257
	if (helen < (int)sizeof(*he))
258
		return (-1);
259
	else if (helen == sizeof(*he))
260
		return (ofp_setversion(con, oh->oh_version));
261
262
	helen -= sizeof(*he);
263
	/* Invalid bitmap size. */
264
	if ((helen % sizeof(*bmp)) != 0)
265
		return (-1);
266
267
	ver = 0;
268
	poff = sizeof(*oh) + sizeof(*he);
269
270
	/* Loop through the bitmaps and choose the higher version. */
271
	while (helen > 0) {
272
		if ((bmp = ibuf_seek(ibuf, poff, sizeof(*bmp))) == NULL)
273
			return (-1);
274
275
		for (i = 0; i < 32; i++, ver++) {
276
			if ((ntohl(*bmp) & (1 << i)) == 0)
277
				continue;
278
279
			ofp_setversion(con, ver);
280
		}
281
282
		helen -= sizeof(*bmp);
283
		poff += sizeof(*bmp);
284
	}
285
286
	/* Check if we have set any version, otherwise fallback. */
287
	if (con->con_version == OFP_V_0)
288
		return (ofp_setversion(con, oh->oh_version));
289
290
	return (0);
291
}
292
293
int
294
ofp_send_featuresrequest(struct switchd *sc, struct switch_connection *con)
295
{
296
	struct ofp_header	*oh;
297
	struct ibuf		*ibuf;
298
	int			 rv = -1;
299
300
	if ((ibuf = ibuf_static()) == NULL ||
301
	    (oh = ibuf_advance(ibuf, sizeof(*oh))) == NULL)
302
		return (-1);
303
304
	oh->oh_version = con->con_version;
305
	oh->oh_type = OFP_T_FEATURES_REQUEST;
306
	oh->oh_length = htons(ibuf_length(ibuf));
307
	oh->oh_xid = htonl(con->con_xidnxt++);
308
	if (ofp_validate(sc, &con->con_local, &con->con_peer, oh, ibuf,
309
	    con->con_version) != 0)
310
		goto done;
311
312
	rv = ofp_output(con, NULL, ibuf);
313
314
 done:
315
	ibuf_free(ibuf);
316
	return (rv);
317
}
318
319
/* Appends an action with just the generic header. */
320
int
321
action_new(struct ibuf *ibuf, uint16_t type)
322
{
323
	struct ofp_action_header	*ah;
324
325
	if ((ah = ibuf_advance(ibuf, sizeof(*ah))) == NULL)
326
		return (-1);
327
328
	ah->ah_type = htons(type);
329
	ah->ah_len = htons(sizeof(*ah));
330
	return (0);
331
}
332
333
int
334
action_group(struct ibuf *ibuf, uint32_t group)
335
{
336
	struct ofp_action_group		*ag;
337
338
	if ((ag = ibuf_advance(ibuf, sizeof(*ag))) == NULL)
339
		return (-1);
340
341
	ag->ag_type = htons(OFP_ACTION_GROUP);
342
	ag->ag_len = sizeof(*ag);
343
	ag->ag_group_id = htonl(group);
344
	return (0);
345
}
346
347
int
348
action_output(struct ibuf *ibuf, uint32_t port, uint16_t maxlen)
349
{
350
	struct ofp_action_output	*ao;
351
352
	if ((ao = ibuf_advance(ibuf, sizeof(*ao))) == NULL)
353
		return (-1);
354
355
	ao->ao_type = htons(OFP_ACTION_OUTPUT);
356
	ao->ao_len = htons(sizeof(*ao));
357
	ao->ao_port = htonl(port);
358
	ao->ao_max_len = htons(maxlen);
359
	return (0);
360
}
361
362
/*
363
 * This action pushes VLAN/MPLS/PBB tags into the outermost part of the
364
 * packet. When the type is X ethertype must be Y:
365
 * - OFP_ACTION_PUSH_VLAN: ETHERTYPE_VLAN or ETHERTYPE_QINQ.
366
 * - OFP_ACTION_PUSH_MPLS: ETHERTYPE_MPLS or ETHERTYPE_MPLSCAST.
367
 * - OFP_ACTION_PUSH_PBB: ETHERTYPE_??? (0x88E7).
368
 */
369
int
370
action_push(struct ibuf *ibuf, uint16_t type, uint16_t ethertype)
371
{
372
	struct ofp_action_push		*ap;
373
374
	if ((ap = ibuf_advance(ibuf, sizeof(*ap))) == NULL)
375
		return (-1);
376
377
	ap->ap_type = htons(type);
378
	ap->ap_len = htons(sizeof(*ap));
379
	ap->ap_ethertype = htons(ethertype);
380
	return (0);
381
}
382
383
/*
384
 * This action only pops the outermost VLAN tag and only one at a time,
385
 * you can only pop multiple VLANs with an action list that is only
386
 * availiable for OFP_INSTRUCTION_T_APPLY_ACTIONS.
387
 */
388
int
389
action_pop_vlan(struct ibuf *ibuf)
390
{
391
	return (action_new(ibuf, OFP_ACTION_POP_VLAN));
392
}
393
394
/*
395
 * Use this with caution since this will pop MPLS shim regardless of the
396
 * BoS bit state.
397
 */
398
int
399
action_pop_mpls(struct ibuf *ibuf, uint16_t ethertype)
400
{
401
	struct ofp_action_pop_mpls	*apm;
402
403
	if ((apm = ibuf_advance(ibuf, sizeof(*apm))) == NULL)
404
		return (-1);
405
406
	apm->apm_type = htons(OFP_ACTION_POP_MPLS);
407
	apm->apm_len = htons(sizeof(*apm));
408
	apm->apm_ethertype = htons(ethertype);
409
	return (0);
410
}
411
412
int
413
action_copyttlout(struct ibuf *ibuf)
414
{
415
	return (action_new(ibuf, OFP_ACTION_COPY_TTL_OUT));
416
}
417
418
int
419
action_copyttlin(struct ibuf *ibuf)
420
{
421
	return (action_new(ibuf, OFP_ACTION_COPY_TTL_IN));
422
}
423
424
int
425
action_decnwttl(struct ibuf *ibuf)
426
{
427
	return (action_new(ibuf, OFP_ACTION_DEC_NW_TTL));
428
}
429
430
/*
431
 * This function should be used with the oxm_*() family.
432
 *
433
 * After filling the action_setfield() with oxms you have to set the
434
 * asf_len with htons(size_of_oxms).
435
 */
436
struct ofp_action_set_field *
437
action_setfield(struct ibuf *ibuf)
438
{
439
	struct ofp_action_set_field	*asf;
440
441
	if ((asf = ibuf_advance(ibuf, sizeof(*asf))) == NULL)
442
		return (NULL);
443
444
	asf->asf_type = htons(OFP_ACTION_SET_FIELD);
445
	return (asf);
446
}
447
448
struct ofp_ox_match *
449
oxm_get(struct ibuf *ibuf, uint16_t field, int hasmask, uint8_t len)
450
{
451
	struct ofp_ox_match	*oxm;
452
	size_t			 oxmlen;
453
454
	/*
455
	 * When the mask is used we must always reserve double the space,
456
	 * because the mask field is the same size of the value.
457
	 */
458
	if (hasmask)
459
		len = len * 2;
460
461
	oxmlen = sizeof(*oxm) + len;
462
	if ((oxm = ibuf_advance(ibuf, oxmlen)) == NULL)
463
		return (NULL);
464
465
	oxm->oxm_class = htons(OFP_OXM_C_OPENFLOW_BASIC);
466
	oxm->oxm_length = len;
467
	OFP_OXM_SET_FIELD(oxm, field);
468
	if (hasmask)
469
		OFP_OXM_SET_HASMASK(oxm);
470
471
	return (oxm);
472
}
473
474
/*
475
 * OpenFlow port where the packet where received.
476
 * May be a physical port, a logical port or the reserved port OFPP_LOCAL.
477
 */
478
int
479
oxm_inport(struct ibuf *ibuf, uint32_t in_port)
480
{
481
	struct ofp_ox_match	*oxm;
482
483
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IN_PORT, 0,
484
	    sizeof(in_port))) == NULL)
485
		return (-1);
486
487
	in_port = htonl(in_port);
488
	memcpy(oxm->oxm_value, &in_port, sizeof(in_port));
489
	return (0);
490
}
491
492
/*
493
 * Physical port on which the packet was received.
494
 * Requires: oxm_inport.
495
 */
496
int
497
oxm_inphyport(struct ibuf *ibuf, uint32_t in_phy_port)
498
{
499
	struct ofp_ox_match	*oxm;
500
501
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IN_PHY_PORT, 0,
502
	    sizeof(in_phy_port))) == NULL)
503
		return (-1);
504
505
	in_phy_port = htonl(in_phy_port);
506
	memcpy(oxm->oxm_value, &in_phy_port, sizeof(in_phy_port));
507
	return (0);
508
}
509
510
/* Table metadata. */
511
int
512
oxm_metadata(struct ibuf *ibuf, int hasmask, uint64_t metadata, uint64_t mask)
513
{
514
	struct ofp_ox_match	*oxm;
515
516
	if ((oxm = oxm_get(ibuf, OFP_XM_T_META, hasmask,
517
	    sizeof(metadata))) == NULL)
518
		return (-1);
519
520
	metadata = htobe64(metadata);
521
	memcpy(oxm->oxm_value, &metadata, sizeof(metadata));
522
	if (hasmask) {
523
		mask = htobe64(mask);
524
		memcpy(oxm->oxm_value + sizeof(metadata), &mask, sizeof(mask));
525
	}
526
527
	return (0);
528
}
529
530
int
531
oxm_etheraddr(struct ibuf *ibuf, int issrc, uint8_t *addr, uint8_t *mask)
532
{
533
	struct ofp_ox_match	*oxm;
534
	int			 type;
535
	int			 hasmask = (mask != NULL);
536
537
	type = issrc ? OFP_XM_T_ETH_SRC : OFP_XM_T_ETH_DST;
538
	if ((oxm = oxm_get(ibuf, type, hasmask, ETHER_ADDR_LEN)) == NULL)
539
		return (-1);
540
541
	memcpy(oxm->oxm_value, addr, ETHER_ADDR_LEN);
542
	if (hasmask)
543
		memcpy(oxm->oxm_value + ETHER_ADDR_LEN, mask, ETHER_ADDR_LEN);
544
545
	return (0);
546
}
547
548
int
549
oxm_ethertype(struct ibuf *ibuf, uint16_t type)
550
{
551
	struct ofp_ox_match	*oxm;
552
553
	if ((oxm = oxm_get(ibuf, OFP_XM_T_ETH_TYPE, 0, sizeof(type))) == NULL)
554
		return (-1);
555
556
	type = htons(type);
557
	memcpy(oxm->oxm_value, &type, sizeof(type));
558
	return (0);
559
}
560
561
int
562
oxm_vlanvid(struct ibuf *ibuf, int hasmask, uint16_t vid, uint16_t mask)
563
{
564
	struct ofp_ox_match	*oxm;
565
566
	if ((oxm = oxm_get(ibuf, OFP_XM_T_VLAN_VID, hasmask,
567
	    sizeof(vid))) == NULL)
568
		return (-1);
569
570
	/* VID uses only the 13 least significant bits. */
571
	vid &= 0x1fff;
572
	vid = htons(vid);
573
	memcpy(oxm->oxm_value, &vid, sizeof(vid));
574
	if (hasmask) {
575
		mask &= 0x1fff;
576
		mask = htons(mask);
577
		memcpy(oxm->oxm_value + sizeof(vid), &mask, sizeof(mask));
578
	}
579
580
	return (0);
581
}
582
583
/*
584
 * 802.1Q Prio from the outermost tag.
585
 *
586
 * Requires: oxm_vlanvid.
587
 */
588
int
589
oxm_vlanpcp(struct ibuf *ibuf, uint8_t pcp)
590
{
591
	struct ofp_ox_match	*oxm;
592
593
	if ((oxm = oxm_get(ibuf, OFP_XM_T_VLAN_PCP, 0, sizeof(pcp))) == NULL)
594
		return (-1);
595
596
	/* PCP only uses the lower 3 bits. */
597
	pcp &= 0x07;
598
	memcpy(oxm->oxm_value, &pcp, sizeof(pcp));
599
	return (0);
600
}
601
602
/*
603
 * The Diff Serv Code Point (DSCP) bits avaliable in IPv4 ToS field or
604
 * IPv6 Traffic Class field.
605
 *
606
 * Requires: oxm_ethertype(ETHERTYPE_IP) or oxm_ethertype(ETHERTYPE_IPV6).
607
 */
608
int
609
oxm_ipdscp(struct ibuf *ibuf, uint8_t dscp)
610
{
611
	struct ofp_ox_match	*oxm;
612
613
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IP_DSCP, 0, sizeof(dscp))) == NULL)
614
		return (-1);
615
616
	/* Only the 6 lower bits have meaning. */
617
	dscp &= 0x3F;
618
	memcpy(oxm->oxm_value, &dscp, sizeof(dscp));
619
	return (0);
620
}
621
622
/*
623
 * The ECN (Explicit Congestion Notification) bits of IP headers.
624
 *
625
 * Requires: oxm_ethertype(ETHERTYPE_IP) or oxm_ethertype(ETHERTYPE_IPV6).
626
 */
627
int
628
oxm_ipecn(struct ibuf *ibuf, uint8_t ecn)
629
{
630
	struct ofp_ox_match	*oxm;
631
632
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IP_ECN, 0, sizeof(ecn))) == NULL)
633
		return (-1);
634
635
	/* Only the 2 most significant bits have meaning. */
636
	ecn &= 0x03;
637
	memcpy(oxm->oxm_value, &ecn, sizeof(ecn));
638
	return (0);
639
}
640
641
/*
642
 * The IP protocol byte.
643
 *
644
 * Requires: oxm_ethertype(ETHERTYPE_IP) or oxm_ethertype(ETHERTYPE_IPV6).
645
 */
646
int
647
oxm_ipproto(struct ibuf *ibuf, uint8_t proto)
648
{
649
	struct ofp_ox_match	*oxm;
650
651
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IP_PROTO, 0, sizeof(proto))) == NULL)
652
		return (-1);
653
654
	memcpy(oxm->oxm_value, &proto, sizeof(proto));
655
	return (0);
656
}
657
658
/*
659
 * The IPv4 address source/destination.
660
 *
661
 * Requires: oxm_ethertype(ETHERTYPE_IP).
662
 */
663
int
664
oxm_ipaddr(struct ibuf *ibuf, int issrc, int hasmask, uint32_t addr,
665
    uint32_t mask)
666
{
667
	struct ofp_ox_match	*oxm;
668
	int			 type;
669
670
	type = issrc ? OFP_XM_T_IPV4_SRC : OFP_XM_T_IPV4_DST;
671
	if ((oxm = oxm_get(ibuf, type, hasmask, sizeof(addr))) == NULL)
672
		return (-1);
673
674
	addr = htonl(addr);
675
	memcpy(oxm->oxm_value, &addr, sizeof(addr));
676
	if (hasmask) {
677
		mask = htonl(mask);
678
		memcpy(oxm->oxm_value + sizeof(addr), &mask, sizeof(mask));
679
	}
680
681
	return (0);
682
}
683
684
/*
685
 * The TCP source/destination port.
686
 *
687
 * Requirements: oxm_ethertype(ETHERTYPE_IP) or oxm_ethertype(ETHERTYPE_IPV6)
688
 * and oxm_ipproto(IPPROTO_TCP).
689
 */
690
int
691
oxm_tcpport(struct ibuf *ibuf, int issrc, uint16_t port)
692
{
693
	struct ofp_ox_match	*oxm;
694
	int			 type;
695
696
	type = issrc ? OFP_XM_T_TCP_SRC : OFP_XM_T_TCP_DST;
697
	if ((oxm = oxm_get(ibuf, type, 0, sizeof(port))) == NULL)
698
		return (-1);
699
700
	port = htons(port);
701
	memcpy(oxm->oxm_value, &port, sizeof(port));
702
	return (0);
703
}
704
705
/*
706
 * The UDP source/destination port.
707
 *
708
 * Requirements: oxm_ethertype(ETHERTYPE_IP) or oxm_ethertype(ETHERTYPE_IPV6)
709
 * and oxm_ipproto(IPPROTO_UDP).
710
 */
711
int
712
oxm_udpport(struct ibuf *ibuf, int issrc, uint16_t port)
713
{
714
	struct ofp_ox_match	*oxm;
715
	int			 type;
716
717
	type = issrc ? OFP_XM_T_UDP_SRC : OFP_XM_T_UDP_DST;
718
	if ((oxm = oxm_get(ibuf, type, 0, sizeof(port))) == NULL)
719
		return (-1);
720
721
	port = htons(port);
722
	memcpy(oxm->oxm_value, &port, sizeof(port));
723
	return (0);
724
}
725
726
/*
727
 * The SCTP source/destination port.
728
 *
729
 * Requirements: oxm_ethertype(ETHERTYPE_IP) or oxm_ethertype(ETHERTYPE_IPV6)
730
 * and oxm_ipproto(IPPROTO_??? -- 132).
731
 */
732
int
733
oxm_sctpport(struct ibuf *ibuf, int issrc, uint16_t port)
734
{
735
	struct ofp_ox_match	*oxm;
736
	int			 type;
737
738
	type = issrc ? OFP_XM_T_SCTP_SRC : OFP_XM_T_SCTP_DST;
739
	if ((oxm = oxm_get(ibuf, type, 0, sizeof(port))) == NULL)
740
		return (-1);
741
742
	port = htons(port);
743
	memcpy(oxm->oxm_value, &port, sizeof(port));
744
	return (0);
745
}
746
747
/*
748
 * The ICMPv4 type in the ICMP header.
749
 *
750
 * Requires: oxm_ethertype(ETHERTYPE_IP) and oxm_ipproto(IPPROTO_ICMP).
751
 */
752
int
753
oxm_icmpv4type(struct ibuf *ibuf, uint8_t type)
754
{
755
	struct ofp_ox_match	*oxm;
756
757
	if ((oxm = oxm_get(ibuf, OFP_XM_T_ICMPV4_TYPE, 0,
758
	    sizeof(type))) == NULL)
759
		return (-1);
760
761
	memcpy(oxm->oxm_value, &type, sizeof(type));
762
	return (0);
763
}
764
765
/*
766
 * The ICMPv4 code in the ICMP header.
767
 *
768
 * Requires: oxm_ethertype(ETHERTYPE_IP) and oxm_ipproto(IPPROTO_ICMP).
769
 */
770
int
771
oxm_icmpv4code(struct ibuf *ibuf, uint8_t code)
772
{
773
	struct ofp_ox_match	*oxm;
774
775
	if ((oxm = oxm_get(ibuf, OFP_XM_T_ICMPV4_CODE, 0,
776
	    sizeof(code))) == NULL)
777
		return (-1);
778
779
	memcpy(oxm->oxm_value, &code, sizeof(code));
780
	return (0);
781
}
782
783
/*
784
 * ARP opcode.
785
 *
786
 * Requires: oxm_ethertype(ETHERTYPE_ARP).
787
 */
788
int
789
oxm_arpop(struct ibuf *ibuf, uint16_t op)
790
{
791
	struct ofp_ox_match	*oxm;
792
793
	if ((oxm = oxm_get(ibuf, OFP_XM_T_ARP_OP, 0, sizeof(op))) == NULL)
794
		return (-1);
795
796
	op = htons(op);
797
	memcpy(oxm->oxm_value, &op, sizeof(op));
798
	return (0);
799
}
800
801
/*
802
 * ARP source/target protocol address.
803
 *
804
 * Requires: oxm_ethertype(ETHERTYPE_ARP).
805
 */
806
int
807
oxm_arpaddr(struct ibuf *ibuf, int issrc, int hasmask, uint32_t addr,
808
    uint32_t mask)
809
{
810
	struct ofp_ox_match	*oxm;
811
	int			 type;
812
813
	type = issrc ? OFP_XM_T_ARP_SPA : OFP_XM_T_ARP_TPA;
814
	if ((oxm = oxm_get(ibuf, type, hasmask, sizeof(addr))) == NULL)
815
		return (-1);
816
817
	addr = htonl(addr);
818
	memcpy(oxm->oxm_value, &addr, sizeof(addr));
819
	if (hasmask) {
820
		mask = htonl(mask);
821
		memcpy(oxm->oxm_value + sizeof(addr), &mask, sizeof(mask));
822
	}
823
824
	return (0);
825
}
826
827
/*
828
 * ARP source/target hardware address.
829
 *
830
 * Requires: oxm_ethertype(ETHERTYPE_ARP).
831
 */
832
int
833
oxm_arphaddr(struct ibuf *ibuf, int issrc, uint8_t *addr, uint8_t *mask)
834
{
835
	struct ofp_ox_match	*oxm;
836
	int			 type;
837
	int			 hasmask = (mask != NULL);
838
839
	type = issrc ? OFP_XM_T_ARP_SHA : OFP_XM_T_ARP_THA;
840
	if ((oxm = oxm_get(ibuf, type, hasmask, ETHER_ADDR_LEN)) == NULL)
841
		return (-1);
842
843
	memcpy(oxm->oxm_value, addr, ETHER_ADDR_LEN);
844
	if (hasmask)
845
		memcpy(oxm->oxm_value + ETHER_ADDR_LEN, mask, ETHER_ADDR_LEN);
846
847
	return (0);
848
}
849
850
/*
851
 * The source or destination of the IPv6 address.
852
 *
853
 * Requirements: oxm_ethertype(ETHERTYPE_IPV6).
854
 */
855
int
856
oxm_ipv6addr(struct ibuf *ibuf, int issrc, struct in6_addr *addr,
857
    struct in6_addr *mask)
858
{
859
	struct ofp_ox_match	*oxm;
860
	int			 type;
861
	int			 hasmask = (mask != NULL);
862
863
	type = issrc ? OFP_XM_T_IPV6_SRC : OFP_XM_T_IPV6_DST;
864
	if ((oxm = oxm_get(ibuf, type, hasmask, sizeof(*addr))) == NULL)
865
		return (-1);
866
867
	memcpy(oxm->oxm_value, addr, sizeof(*addr));
868
	if (hasmask)
869
		memcpy(oxm->oxm_value + sizeof(*addr), mask, sizeof(*mask));
870
871
	return (0);
872
}
873
874
/*
875
 * The IPv6 flow label field.
876
 *
877
 * Requirements: oxm_ethertype(ETHERTYPE_IPV6).
878
 */
879
int
880
oxm_ipv6flowlabel(struct ibuf *ibuf, int hasmask, uint32_t flowlabel,
881
    uint32_t mask)
882
{
883
	struct ofp_ox_match	*oxm;
884
885
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IPV6_FLABEL, hasmask,
886
	    sizeof(flowlabel))) == NULL)
887
		return (-1);
888
889
	/*
890
         * 12 most significants bits forced to 0 and only the 20 lowers
891
         * bits have meaning.
892
	 */
893
	flowlabel &= 0x000FFFFFU;
894
	flowlabel = htonl(flowlabel);
895
	memcpy(oxm->oxm_value, &flowlabel, sizeof(flowlabel));
896
	if (hasmask) {
897
		mask &= 0x000FFFFFU;
898
		mask = htonl(mask);
899
		memcpy(oxm->oxm_value + sizeof(flowlabel), &mask, sizeof(mask));
900
	}
901
902
	return (0);
903
}
904
905
/*
906
 * The ICMPv6 type in ICMP header.
907
 *
908
 * Requirements: oxm_ethertype(ETHERTYPE_IPV6) and oxm_ipproto(IPPROTO_ICMPV6).
909
 */
910
int
911
oxm_icmpv6type(struct ibuf *ibuf, uint8_t type)
912
{
913
	struct ofp_ox_match	*oxm;
914
915
	if ((oxm = oxm_get(ibuf, OFP_XM_T_ICMPV6_TYPE, 0,
916
	    sizeof(type))) == NULL)
917
		return (-1);
918
919
	memcpy(oxm->oxm_value, &type, sizeof(type));
920
	return (0);
921
}
922
923
/*
924
 * The ICMPv6 code in ICMP header.
925
 *
926
 * Requirements: oxm_ethertype(ETHERTYPE_IPV6) and oxm_ipproto(IPPROTO_ICMPV6).
927
 */
928
int
929
oxm_icmpv6code(struct ibuf *ibuf, uint8_t code)
930
{
931
	struct ofp_ox_match	*oxm;
932
933
	if ((oxm = oxm_get(ibuf, OFP_XM_T_ICMPV6_CODE, 0,
934
	    sizeof(code))) == NULL)
935
		return (-1);
936
937
	memcpy(oxm->oxm_value, &code, sizeof(code));
938
	return (0);
939
}
940
941
/*
942
 * The target address in neighbour discovery message.
943
 *
944
 * Requirements: oxm_ethertype(ETHERTYPE_IPV6), oxm_ipproto(IPPROTO_ICMPV6)
945
 * and oxm_icmpv6type(ND_NEIGHBOR_SOLICIT) or
946
 * oxm_icmpv6type(ND_NEIGHBOR_ADVERT).
947
 */
948
int
949
oxm_ipv6ndtarget(struct ibuf *ibuf, struct in6_addr *addr)
950
{
951
	struct ofp_ox_match	*oxm;
952
953
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IPV6_ND_TARGET, 0,
954
	    sizeof(*addr))) == NULL)
955
		return (-1);
956
957
	memcpy(oxm->oxm_value, addr, sizeof(*addr));
958
	return (0);
959
}
960
961
/*
962
 * The source link-layer address in an IPv6 Neighbour discovery.
963
 *
964
 * Requirements: oxm_ethertype(ETHERTYPE_IPV6), oxm_ipproto(IPPROTO_ICMPV6)
965
 * and oxm_icmpv6type(ND_NEIGHBOR_SOLICIT).
966
 */
967
int
968
oxm_ipv6ndlinkaddr(struct ibuf *ibuf, int issrc, uint8_t *addr)
969
{
970
	struct ofp_ox_match	*oxm;
971
	int			 type;
972
973
	type = issrc ? OFP_XM_T_IPV6_ND_SLL : OFP_XM_T_IPV6_ND_TLL;
974
	if ((oxm = oxm_get(ibuf, type, 0, ETHER_ADDR_LEN)) == NULL)
975
		return (-1);
976
977
	memcpy(oxm->oxm_value, addr, ETHER_ADDR_LEN);
978
	return (0);
979
}
980
981
/*
982
 * The label in the MPLS shim.
983
 *
984
 * Requirements: oxm_ethertype(ETHERTYPE_MPLS) or
985
 * oxm_ethertype(ETHERTYPE_MPLS_MCAST).
986
 */
987
int
988
oxm_mplslabel(struct ibuf *ibuf, uint32_t label)
989
{
990
	struct ofp_ox_match	*oxm;
991
992
	if ((oxm = oxm_get(ibuf, OFP_XM_T_MPLS_LABEL, 0,
993
	    sizeof(label))) == NULL)
994
		return (-1);
995
996
	label &= MPLS_LABEL_MASK;
997
	label = htonl(label);
998
	memcpy(oxm->oxm_value, &label, sizeof(label));
999
	return (0);
1000
}
1001
1002
/*
1003
 * The TC in the first MPLS shim.
1004
 *
1005
 * Requirements: oxm_ethertype(ETHERTYPE_MPLS) or
1006
 * oxm_ethertype(ETHERTYPE_MPLS_MCAST).
1007
 */
1008
int
1009
oxm_mplstc(struct ibuf *ibuf, uint8_t tc)
1010
{
1011
	struct ofp_ox_match	*oxm;
1012
1013
	if ((oxm = oxm_get(ibuf, OFP_XM_T_MPLS_TC, 0, sizeof(tc))) == NULL)
1014
		return (-1);
1015
1016
	tc &= 0x07;
1017
	memcpy(oxm->oxm_value, &tc, sizeof(tc));
1018
	return (0);
1019
}
1020
1021
/*
1022
 * The BoS bit in the first MPLS shim.
1023
 *
1024
 * Requirements: oxm_ethertype(ETHERTYPE_MPLS) or
1025
 * oxm_ethertype(ETHERTYPE_MPLS_MCAST).
1026
 */
1027
int
1028
oxm_mplsbos(struct ibuf *ibuf, uint8_t bos)
1029
{
1030
	struct ofp_ox_match	*oxm;
1031
1032
	if ((oxm = oxm_get(ibuf, OFP_XM_T_MPLS_BOS, 0, sizeof(bos))) == NULL)
1033
		return (-1);
1034
1035
	bos &= 0x01;
1036
	memcpy(oxm->oxm_value, &bos, sizeof(bos));
1037
	return (0);
1038
}
1039
1040
/*
1041
 * Comment shamelessly taken from OpenFlow 1.3.5 specification.
1042
 *
1043
 * Metadata associated with a logical port.
1044
 *
1045
 * If the logical port performs encapsulation and decapsulation, this
1046
 * is the demultiplexing field from the encapsulation header.
1047
 * For example, for a packet received via GRE tunnel including a (32-bit) key,
1048
 * the key is stored in the low 32-bits and the high bits are zeroed.
1049
 * For a MPLS logical port, the low 20 bits represent the MPLS Label.
1050
 * For a VxLAN logical port, the low 24 bits represent the VNI.
1051
 * If the packet is not received through a logical port, the value is 0.
1052
 */
1053
int
1054
oxm_tunnelid(struct ibuf *ibuf, int hasmask, uint64_t id, uint64_t mask)
1055
{
1056
	struct ofp_ox_match	*oxm;
1057
1058
	if ((oxm = oxm_get(ibuf, OFP_XM_T_TUNNEL_ID, hasmask,
1059
	    sizeof(id))) == NULL)
1060
		return (-1);
1061
1062
	id = htobe64(id);
1063
	memcpy(oxm->oxm_value, &id, sizeof(id));
1064
	if (hasmask) {
1065
		mask = htobe64(mask);
1066
		memcpy(oxm->oxm_value + sizeof(id), &mask, sizeof(mask));
1067
	}
1068
	return (0);
1069
}
1070
1071
/*
1072
 * The IPv6 extension header.
1073
 *
1074
 * Tip: use the OFP_XM_IPV6_EXTHDR_* macros.
1075
 *
1076
 * Requirements: oxm_ethertype(ETHERTYPE_IPV6).
1077
 */
1078
int
1079
oxm_ipv6exthdr(struct ibuf *ibuf, int hasmask, uint16_t exthdr, uint16_t mask)
1080
{
1081
	struct ofp_ox_match	*oxm;
1082
1083
	if ((oxm = oxm_get(ibuf, OFP_XM_T_IPV6_EXTHDR, hasmask,
1084
	    sizeof(exthdr))) == NULL)
1085
		return (-1);
1086
1087
	/* Only the lower 9 bits have meaning. */
1088
	exthdr &= 0x01FF;
1089
	exthdr = htons(exthdr);
1090
	memcpy(oxm->oxm_value, &exthdr, sizeof(exthdr));
1091
	if (hasmask) {
1092
		mask &= 0x01FF;
1093
		mask = htons(mask);
1094
		memcpy(oxm->oxm_value + sizeof(exthdr), &mask, sizeof(mask));
1095
	}
1096
	return (0);
1097
}
1098
1099
/*
1100
 * Appends a new instruction with hlen size.
1101
 *
1102
 * Remember to set the instruction length (i->i_len) if it has more data,
1103
 * like ofp_instruction_actions, ofp_instruction_goto_table etc...
1104
 */
1105
struct ofp_instruction *
1106
ofp_instruction(struct ibuf *ibuf, uint16_t type, uint16_t hlen)
1107
{
1108
	struct ofp_instruction	*oi;
1109
1110
	if ((oi = ibuf_advance(ibuf, hlen)) == NULL)
1111
		return (NULL);
1112
1113
	oi->i_type = htons(type);
1114
	oi->i_len = htons(hlen);
1115
	return (oi);
1116
}
1117
1118
struct multipart_message *
1119
ofp_multipart_lookup(struct switch_connection *con, uint32_t xid)
1120
{
1121
	struct multipart_message	*mm;
1122
1123
	SLIST_FOREACH(mm, &con->con_mmlist, mm_entry) {
1124
		if (mm->mm_xid != xid)
1125
			continue;
1126
1127
		return (mm);
1128
	}
1129
1130
	return (NULL);
1131
}
1132
1133
int
1134
ofp_multipart_add(struct switch_connection *con, uint32_t xid, uint8_t type)
1135
{
1136
	struct multipart_message	*mm;
1137
1138
	if ((mm = ofp_multipart_lookup(con, xid)) != NULL) {
1139
		/*
1140
		 * A multipart reply has the same xid and type, otherwise
1141
		 * something went wrong.
1142
		 */
1143
		if (mm->mm_type != type)
1144
			return (-1);
1145
1146
		return (0);
1147
	}
1148
1149
	if ((mm = calloc(1, sizeof(*mm))) == NULL)
1150
		return (-1);
1151
1152
	mm->mm_xid = xid;
1153
	mm->mm_type = type;
1154
	SLIST_INSERT_HEAD(&con->con_mmlist, mm, mm_entry);
1155
	return (0);
1156
}
1157
1158
void
1159
ofp_multipart_del(struct switch_connection *con, uint32_t xid)
1160
{
1161
	struct multipart_message	*mm;
1162
1163
	SLIST_FOREACH(mm, &con->con_mmlist, mm_entry)
1164
		if (mm->mm_xid == xid)
1165
			break;
1166
1167
	if (mm == NULL)
1168
		return;
1169
1170
	ofp_multipart_free(con, mm);
1171
}
1172
1173
void
1174
ofp_multipart_free(struct switch_connection *con,
1175
    struct multipart_message *mm)
1176
{
1177
	SLIST_REMOVE(&con->con_mmlist, mm, multipart_message, mm_entry);
1178
	free(mm);
1179
}
1180
1181
void
1182
ofp_multipart_clear(struct switch_connection *con)
1183
{
1184
	struct multipart_message	*mm;
1185
1186
	while (!SLIST_EMPTY(&con->con_mmlist)) {
1187
		mm = SLIST_FIRST(&con->con_mmlist);
1188
		ofp_multipart_free(con, mm);
1189
	}
1190
}
1191
1192
struct switch_table *
1193
switch_tablelookup(struct switch_connection *con, int table)
1194
{
1195
	struct switch_table		*st;
1196
1197
	TAILQ_FOREACH(st, &con->con_stlist, st_entry) {
1198
		if (st->st_table == table)
1199
			return (st);
1200
	}
1201
1202
	return (NULL);
1203
}
1204
1205
struct switch_table *
1206
switch_newtable(struct switch_connection *con, int table)
1207
{
1208
	struct switch_table		*st;
1209
1210
	if ((st = calloc(1, sizeof(*st))) == NULL)
1211
		return (NULL);
1212
1213
	st->st_table = table;
1214
	TAILQ_INSERT_TAIL(&con->con_stlist, st, st_entry);
1215
1216
	return (st);
1217
}
1218
1219
void
1220
switch_deltable(struct switch_connection *con, struct switch_table *st)
1221
{
1222
	TAILQ_REMOVE(&con->con_stlist, st, st_entry);
1223
	free(st);
1224
}
1225
1226
void
1227
switch_freetables(struct switch_connection *con)
1228
{
1229
	struct switch_table		*st;
1230
1231
	while (!TAILQ_EMPTY(&con->con_stlist)) {
1232
		st = TAILQ_FIRST(&con->con_stlist);
1233
		switch_deltable(con, st);
1234
	}
1235
}
1236
1237
int
1238
oflowmod_state(struct oflowmod_ctx *ctx, unsigned int old, unsigned int new)
1239
{
1240
	if (ctx->ctx_state != old)
1241
		return (-1);
1242
	ctx->ctx_state = new;
1243
	return (0);
1244
}
1245
1246
int
1247
oflowmod_err(struct oflowmod_ctx *ctx, const char *func, int line)
1248
{
1249
	log_debug("%s: function %s line %d state %d",
1250
	    __func__, func, line, ctx->ctx_state);
1251
1252
	if (ctx->ctx_state >= OFMCTX_ERR)
1253
		return (-1);
1254
	if (ctx->ctx_flags & OFMCTX_IBUF)
1255
		ibuf_release(ctx->ctx_ibuf);
1256
	ctx->ctx_state = OFMCTX_ERR;
1257
	return (-1);
1258
}
1259
1260
struct ibuf *
1261
oflowmod_open(struct oflowmod_ctx *ctx, struct switch_connection *con,
1262
    struct ibuf *ibuf, uint8_t version)
1263
{
1264
	struct ofp_flow_mod	*fm;
1265
	struct switch_connection conb;
1266
1267
	switch (version) {
1268
	case OFP_V_0:
1269
	case OFP_V_1_3:
1270
		version = OFP_V_1_3;
1271
		break;
1272
	default:
1273
		log_warnx("%s: unsupported version 0x%02x", __func__, version);
1274
		return (NULL);
1275
	}
1276
1277
	memset(ctx, 0, sizeof(*ctx));
1278
1279
	if (oflowmod_state(ctx, OFMCTX_INIT, OFMCTX_OPEN) == -1)
1280
		goto err;
1281
1282
	if (ibuf == NULL) {
1283
		ctx->ctx_flags |= OFMCTX_IBUF;
1284
		if ((ibuf = ibuf_static()) == NULL)
1285
			goto err;
1286
	}
1287
1288
	ctx->ctx_ibuf = ibuf;
1289
	ctx->ctx_start = ibuf->wpos;
1290
1291
	/*
1292
	 * The connection is not strictly required and might not be
1293
	 * available in other places;  just default to an xid 0.
1294
	 */
1295
	if (con == NULL) {
1296
		con = &conb;
1297
		memset(con, 0, sizeof(*con));
1298
	}
1299
1300
	/* uses defaults, can be changed by accessing fm later */
1301
	if ((fm = ofp13_flowmod(con, ibuf,
1302
	    OFP_FLOWCMD_ADD, 0, 0, 0, 0)) == NULL)
1303
		goto err;
1304
1305
	ctx->ctx_fm = fm;
1306
1307
	return (ctx->ctx_ibuf);
1308
1309
 err:
1310
	(void)oflowmod_err(ctx, __func__, __LINE__);
1311
	return (NULL);
1312
}
1313
1314
int
1315
oflowmod_mopen(struct oflowmod_ctx *ctx)
1316
{
1317
	if (oflowmod_state(ctx, OFMCTX_OPEN, OFMCTX_MOPEN) == -1)
1318
		return (oflowmod_err(ctx, __func__, __LINE__));
1319
1320
	ctx->ctx_ostart = ctx->ctx_start +
1321
	    offsetof(struct ofp_flow_mod, fm_match);
1322
1323
	return (0);
1324
}
1325
1326
int
1327
oflowmod_mclose(struct oflowmod_ctx *ctx)
1328
{
1329
	struct ibuf		*ibuf = ctx->ctx_ibuf;
1330
	struct ofp_flow_mod	*fm = ctx->ctx_fm;
1331
	size_t			 omlen, padding;
1332
1333
	if (oflowmod_state(ctx, OFMCTX_MOPEN, OFMCTX_MCLOSE) == -1)
1334
		return (oflowmod_err(ctx, __func__, __LINE__));
1335
1336
	ctx->ctx_oend = ibuf->wpos;
1337
	omlen = ctx->ctx_oend - ctx->ctx_ostart;
1338
1339
	/* Update match length */
1340
	fm->fm_match.om_length = htons(omlen);
1341
1342
	padding = OFP_ALIGN(omlen) - omlen;
1343
	if (padding) {
1344
		ctx->ctx_oend += padding;
1345
		if (ibuf_advance(ibuf, padding) == NULL)
1346
			return (oflowmod_err(ctx, __func__, __LINE__));
1347
	}
1348
1349
	return (0);
1350
}
1351
1352
int
1353
oflowmod_iopen(struct oflowmod_ctx *ctx)
1354
{
1355
	struct ibuf		*ibuf = ctx->ctx_ibuf;
1356
1357
	if (ctx->ctx_state < OFMCTX_MOPEN &&
1358
	    (oflowmod_mopen(ctx) == -1))
1359
		return (oflowmod_err(ctx, __func__, __LINE__));
1360
	if (ctx->ctx_state < OFMCTX_MCLOSE &&
1361
	    (oflowmod_mclose(ctx) == -1))
1362
		return (oflowmod_err(ctx, __func__, __LINE__));
1363
1364
	if (oflowmod_state(ctx, OFMCTX_MCLOSE, OFMCTX_IOPEN) == -1)
1365
		return (oflowmod_err(ctx, __func__, __LINE__));
1366
1367
	ctx->ctx_istart = ibuf->wpos;
1368
1369
	return (0);
1370
}
1371
1372
int
1373
oflowmod_instruction(struct oflowmod_ctx *ctx, unsigned int type)
1374
{
1375
	struct ibuf		*ibuf = ctx->ctx_ibuf;
1376
	struct ofp_instruction	*oi;
1377
	size_t			 len;
1378
1379
	if (ctx->ctx_state < OFMCTX_IOPEN &&
1380
	    (oflowmod_iopen(ctx) == -1))
1381
		return (oflowmod_err(ctx, __func__, __LINE__));
1382
1383
	if (oflowmod_state(ctx, OFMCTX_IOPEN, OFMCTX_IOPEN) == -1)
1384
		return (oflowmod_err(ctx, __func__, __LINE__));
1385
1386
	if (ctx->ctx_oi != NULL && oflowmod_instructionclose(ctx) == -1)
1387
		return (oflowmod_err(ctx, __func__, __LINE__));
1388
1389
	ctx->ctx_oioff = ibuf->wpos;
1390
1391
	switch (type) {
1392
	case OFP_INSTRUCTION_T_GOTO_TABLE:
1393
		len = sizeof(struct ofp_instruction_goto_table);
1394
		break;
1395
	case OFP_INSTRUCTION_T_WRITE_META:
1396
		len = sizeof(struct ofp_instruction_write_metadata);
1397
		break;
1398
	case OFP_INSTRUCTION_T_WRITE_ACTIONS:
1399
	case OFP_INSTRUCTION_T_APPLY_ACTIONS:
1400
	case OFP_INSTRUCTION_T_CLEAR_ACTIONS:
1401
		len = sizeof(struct ofp_instruction_actions);
1402
		break;
1403
	case OFP_INSTRUCTION_T_METER:
1404
		len = sizeof(struct ofp_instruction_meter);
1405
		break;
1406
	case OFP_INSTRUCTION_T_EXPERIMENTER:
1407
		len = sizeof(struct ofp_instruction_experimenter);
1408
		break;
1409
	default:
1410
		return (oflowmod_err(ctx, __func__, __LINE__));
1411
	}
1412
1413
	if ((oi = ofp_instruction(ibuf, type, len)) == NULL)
1414
		return (oflowmod_err(ctx, __func__, __LINE__));
1415
1416
	ctx->ctx_oi = oi;
1417
1418
	return (0);
1419
}
1420
1421
int
1422
oflowmod_instructionclose(struct oflowmod_ctx *ctx)
1423
{
1424
	struct ibuf		*ibuf = ctx->ctx_ibuf;
1425
	struct ofp_instruction	*oi = ctx->ctx_oi;
1426
	size_t			 oilen;
1427
1428
	if (ctx->ctx_state < OFMCTX_IOPEN || oi == NULL)
1429
		return (oflowmod_err(ctx, __func__, __LINE__));
1430
1431
	oilen = ibuf->wpos - ctx->ctx_oioff;
1432
1433
	if (oilen > UINT16_MAX)
1434
		return (oflowmod_err(ctx, __func__, __LINE__));
1435
1436
	oi->i_len = htons(oilen);
1437
	ctx->ctx_oi = NULL;
1438
1439
	return (0);
1440
}
1441
1442
int
1443
oflowmod_iclose(struct oflowmod_ctx *ctx)
1444
{
1445
	struct ibuf		*ibuf = ctx->ctx_ibuf;
1446
1447
	if (oflowmod_state(ctx, OFMCTX_IOPEN, OFMCTX_ICLOSE) == -1)
1448
		return (oflowmod_err(ctx, __func__, __LINE__));
1449
1450
	if (ctx->ctx_oi != NULL && oflowmod_instructionclose(ctx) == -1)
1451
		return (-1);
1452
1453
	ctx->ctx_iend = ibuf->wpos;
1454
1455
	return (0);
1456
}
1457
1458
int
1459
oflowmod_close(struct oflowmod_ctx *ctx)
1460
{
1461
	struct ofp_flow_mod	*fm = ctx->ctx_fm;
1462
	struct ibuf		*ibuf = ctx->ctx_ibuf;
1463
	size_t			 len;
1464
1465
	/* No matches, calculate default */
1466
	if (ctx->ctx_state < OFMCTX_MOPEN &&
1467
	    (oflowmod_mopen(ctx) == -1 ||
1468
	    oflowmod_mclose(ctx) == -1))
1469
		goto err;
1470
1471
	/* No instructions, calculate default */
1472
	if (ctx->ctx_state < OFMCTX_IOPEN &&
1473
	    (oflowmod_iopen(ctx) == -1 ||
1474
	    oflowmod_iclose(ctx) == -1))
1475
		goto err;
1476
1477
	if (oflowmod_state(ctx, OFMCTX_ICLOSE, OFMCTX_CLOSE) == -1)
1478
		goto err;
1479
1480
	/* Update length */
1481
	len = ibuf->wpos - ctx->ctx_start;
1482
	fm->fm_oh.oh_length = htons(len);
1483
1484
	return (0);
1485
1486
 err:
1487
	return (oflowmod_err(ctx, __func__, __LINE__));
1488
1489
}