summaryrefslogtreecommitdiff
path: root/sys/net/ofp.h
blob: 0b844ef33d4e7d539ff096e4709ba2e8beab8fea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
/*	$OpenBSD: ofp.h,v 1.1 2016/09/01 10:06:33 goda Exp $	*/

/*
 * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
 * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _NET_OFP_H_
#define _NET_OFP_H_

#include <sys/types.h>
#include <sys/socket.h>

#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>

#define OFP_IFNAMSIZ	16	/* on-wire (not IF_NAMSIZE) */
#define OFP_ALIGNMENT	8	/* OFP alignment */
#define OFP_ALIGN(_x)	(((_x) + (OFP_ALIGNMENT - 1)) & ~(OFP_ALIGNMENT - 1))

struct ofp_header {
	uint8_t		 oh_version;		/* OpenFlow version */
	uint8_t		 oh_type;		/* message type */
	uint16_t	 oh_length;		/* message length */
	uint32_t	 oh_xid;		/* transaction Id */
} __packed;

/* OpenFlow version */
#define OFP_V_0				0x00	/* OpenFlow 0.0 */
#define OFP_V_1_0			0x01	/* OpenFlow 1.0 */
#define OFP_V_1_1			0x02	/* OpenFlow 1.1 */
#define OFP_V_1_2			0x03	/* OpenFlow 1.2 */
#define OFP_V_1_3			0x04	/* OpenFlow 1.3 */
#define OFP_V_1_4			0x05	/* OpenFlow 1.4 */
#define OFP_V_1_5			0x06	/* OpenFlow 1.5 */

/* OpenFlow message type */
#define OFP_T_HELLO			0	/* Hello */
#define OFP_T_ERROR			1	/* Error */
#define OFP_T_ECHO_REQUEST		2	/* Echo Request */
#define OFP_T_ECHO_REPLY		3	/* Echo Reply */
#define OFP_T_EXPERIMENTER		4	/* Vendor/Experimenter */
#define OFP_T_FEATURES_REQUEST		5	/* Features Request (switch) */
#define OFP_T_FEATURES_REPLY		6	/* Features Reply (switch) */
#define OFP_T_GET_CONFIG_REQUEST	7	/* Get Config Request (switch) */
#define OFP_T_GET_CONFIG_REPLY		8	/* Get Config Reply (switch) */
#define OFP_T_SET_CONFIG		9	/* Set Config (switch) */
#define OFP_T_PACKET_IN			10	/* Packet In (async) */
#define OFP_T_FLOW_REMOVED		11	/* Flow Removed (async) */
#define OFP_T_PORT_STATUS		12	/* Port Status (async) */
#define OFP_T_PACKET_OUT		13	/* Packet Out (controller) */
#define OFP_T_FLOW_MOD			14	/* Flow Mod (controller) */
#define OFP_T_GROUP_MOD			15	/* Group Mod (controller) */
#define OFP_T_PORT_MOD			16	/* Port Mod (controller) */
#define OFP_T_TABLE_MOD			17	/* Table Mod (controller) */
#define OFP_T_MULTIPART_REQUEST		18	/* Multipart Message Request */
#define OFP_T_MULTIPART_REPLY		19	/* Multipart Message Request */
#define OFP_T_BARRIER_REQUEST		20	/* Barrier Request */
#define OFP_T_BARRIER_REPLY		21	/* Barrier Reply */
#define OFP_T_QUEUE_GET_CONFIG_REQUEST	22	/* Queue Get Config Request */
#define OFP_T_QUEUE_GET_CONFIG_REPLY	23	/* Queue Get Config Reply */
#define OFP_T_ROLE_REQUEST		24	/* Role Request */
#define OFP_T_ROLE_REPLY		25	/* Role Reply */
#define OFP_T_GET_ASYNC_REQUEST		26	/* Get Async Request */
#define OFP_T_GET_ASYNC_REPLY		27	/* Get Async Reply */
#define OFP_T_SET_ASYNC			28	/* Set Async */
#define OFP_T_METER_MOD			29	/* Meter Mod */
#define OFP_T_TYPE_MAX			30

/* OpenFlow Hello Message */
struct ofp_hello_element_header {
	uint16_t	he_type;
	uint16_t	he_length;
};

#define OPF_HELLO_T_VERSION_BITMAP	1	/* Supported version bitmap */

struct ofp_hello_element_versionbitmap {
	uint16_t	hev_type;
	uint16_t	hev_length;
};

/* Ports */
#define OFP_PORT_MAX		0xffffff00	/* Maximum number of physical ports */
#define	OFP_PORT_INPUT		0xfffffff8 	/* Send back to input port */
#define OFP_PORT_FLOWTABLE	0xfffffff9	/* Perform actions in flow table */
#define OFP_PORT_NORMAL		0xfffffffa	/* Let switch decide */
#define OFP_PORT_FLOOD		0xfffffffb	/* All non-block ports except input */
#define OFP_PORT_ALL		0xfffffffc	/* All ports except input */
#define OFP_PORT_CONTROLLER	0xfffffffd	/* Send to controller */
#define OFP_PORT_LOCAL		0xfffffffe	/* Local virtual OpenFlow port */
#define OFP_PORT_ANY		0xffffffff	/* No port */

/* Switch Config Message (reply) */
struct ofp_switch_config {
	struct ofp_header	cfg_oh;		/* OpenFlow header */
	uint16_t		cfg_flags;	/* Configuration flags */
	uint16_t		cfg_miss_send_len; /* Max bytes from datapath */
} __packed;

/* Switch Config */
#define OFP_CONFIG_FRAG_NORMAL	0x0000		/* No special frag handling */
#define OFP_CONFIG_FRAG_DROP	0x0001		/* Drop fragments */
#define OFP_CONFIG_FRAG_REASM	0x0002		/* Reassemble fragments */
#define OFP_CONFIG_FRAG_MASK	0x0003		/* Fragment mask */

/* Switch port description */
struct ofp_switch_port {
	uint32_t	swp_number;		/* Switch port number */
	uint8_t		swp_pad[4];		/* Padding */
	uint8_t		swp_macaddr[ETHER_ADDR_LEN]; /* Port MAC address */
	uint8_t		swp_pad2[2];		/* Padding */
	char		swp_name[OFP_IFNAMSIZ];	/* Switch port name */
	uint32_t	swp_config;		/* Configuration flags */
	uint32_t	swp_state;		/* State flags */
	uint32_t	swp_cur;		/* Current features */
	uint32_t	swp_advertised;		/* Advertised by the port */
	uint32_t	swp_supported;		/* Supported by the port */
	uint32_t	swp_peer;		/* Advertised by peer */
	uint32_t	swp_cur_speed;		/* Current port speed in Kbps*/
	uint32_t	swp_max_speed;		/* Support port max speed in Kbps*/
};

/* Physical port configuration */
#define OFP_PORTCONFIG_PORT_DOWN	0x1	/* Port is down */
#define OFP_PORTCONFIG_NO_STP		0x2	/* Disable STP on port */
#define OFP_PORTCONFIG_NO_RECV		0x4	/* Drop everything except STP */
#define OFP_PORTCONFIG_NO_RECV_STP	0x8	/* Drop received STP */
#define OFP_PORTCONFIG_NO_FLOOD		0x10	/* Do not flood to this port */
#define OFP_PORTCONFIG_NO_FWD		0x20	/* Drop packets to port */
#define OFP_PORTCONFIG_NO_PACKET_IN	0x40	/* NO PACKET_IN on port */

/* Physical port state */
#define OFP_PORTSTATE_LINK_DOWN		0x1	/* Link not active */
#define OFP_PORTSTATE_STP_LISTEN	0x000	/* Not learning or forwarding */
#define OFP_PORTSTATE_STP_LEARN		0x100	/* Learning but not forwarding */
#define OFP_PORTSTATE_STP_FORWARD	0x200	/* Learning and forwarding */
#define OFP_PORTSTATE_STP_BLOCK		0x300	/* Not part of spanning tree */
#define OFP_PORTSTATE_STP_MASK		0x300	/* Spanning tree values */

/* Physical port media types */
#define OFP_PORTMEDIA_10MB_HD		0x1	/* 10 Mb half-duplex */
#define OFP_PORTMEDIA_10MB_FD		0x2	/* 10 Mb full-duplex */
#define OFP_PORTMEDIA_100MB_HD		0x4	/* 100 Mb half-duplex */
#define OFP_PORTMEDIA_100MB_FD		0x8	/* 100 Mb full-duplex */
#define OFP_PORTMEDIA_1GB_HD		0x10    /* 1 Gb half-duplex */
#define OFP_PORTMEDIA_1GB_FD		0x20    /* 1 Gb full-duplex */
#define OFP_PORTMEDIA_10GB_FD		0x40    /* 10 Gb full-duplex */
#define OFP_PORTMEDIA_COPPER		0x80    /* Copper */
#define OFP_PORTMEDIA_FIBER		0x100   /* Fiber */
#define OFP_PORTMEDIA_AUTONEG		0x200   /* Auto-negotiation */
#define OFP_PORTMEDIA_PAUSE		0x400   /* Pause */
#define OFP_PORTMEDIA_PAUSE_ASYM	0x800	/* Asymmetric pause */

/* Switch Features Message (reply) */
struct ofp_switch_features {
	struct ofp_header	swf_oh;		/* OpenFlow header */
	uint64_t		swf_datapath_id; /* Datapath unique ID */
	uint32_t		swf_nbuffers;	/* Max packets buffered */
	uint8_t			swf_ntables;	/* Number of supported tables */
	uint8_t			swf_aux_id;	/* Identify auxiliary connections */
	uint8_t			swf_pad[2];	/* Align to 64 bits */
	uint32_t		swf_capabilities; /* Capability flags */
	uint32_t		swf_actions;	/* Supported action flags */
};

/* Switch capabilities */
#define OFP_SWCAP_FLOW_STATS		0x1	/* Flow statistics */
#define OFP_SWCAP_TABLE_STATS  		0x2	/* Table statistics */
#define OFP_SWCAP_PORT_STATS   		0x4	/* Port statistics */
#define OFP_SWCAP_GROUP_STATS 		0x8	/* Group statistics */
#define OFP_SWCAP_IP_REASM		0x20	/* Can reassemble IP frags */
#define OFP_SWCAP_QUEUE_STATS		0x40	/* Queue statistics */
#define OFP_SWCAP_ARP_MATCH_IP		0x80	/* Match IP addresses in ARP pkts */
#define OFP_SWCAP_PORT_BLOCKED		0x100	/* Switch will block ports */

/* Flow matching */
struct ofp_match {
	uint16_t	om_type;
	uint16_t	om_length;
} __packed;

/* Flow matching type type */
#define OFP_MATCH_STANDARD		0	/* Standard match deprecated */
#define OFP_MATCH_OXM			1	/* OpenFlow Extensible Match */

/* Packet-In Message */
struct ofp_packet_in {
	struct ofp_header	pin_oh;		/* OpenFlow header */
	uint32_t		pin_buffer_id;
	uint16_t		pin_total_len;
	uint8_t			pin_reason;
	uint8_t			pin_table_id;
	uint64_t		pin_cookie;
	struct ofp_match	pin_match;
} __packed;

/* Reason */
#define	OFP_PKTIN_REASON_NO_MATCH	0	/* No matching flow */
#define	OFP_PKTIN_REASON_ACTION		1	/* Explicit output */
#define	OFP_PKTIN_REASON_TTL		2	/* Packet has invalid TTL */

/* Flow Instruction */
struct ofp_instruction {
	uint16_t	i_type;
	uint16_t	i_len;
};

/* Instruction types */
#define OFP_INSTRUCTION_T_GOTO_TABLE	1	/* Goto-Table */
#define OFP_INSTRUCTION_T_WRITE_META	2	/* Write-Metadata */
#define OFP_INSTRUCTION_T_WRITE_ACTIONS	3	/* Write-Actions */
#define OFP_INSTRUCTION_T_APPLY_ACTIONS	4	/* Apply-Actions */
#define OFP_INSTRUCTION_T_CLEAR_ACTIONS	5	/* Clear-Actions */
#define OFP_INSTRUCTION_T_METER		6	/* Meter */
#define OFP_INSTRUCTION_T_EXPERIMENTER	0xffff	/* Experimenter */

/* Write-Metadata instruction */
struct ofp_instruction_write_metadata {
	uint16_t	iwm_type;
	uint16_t	iwm_len;
	uint8_t		iwm_pad[4];
	uint64_t	iwm_metadata;
	uint64_t	iwm_metadata_mask;
};

/* Goto-Table instruction */
struct ofp_instruction_goto_table {
	uint16_t	igt_type;
	uint16_t	igt_len;
	uint8_t		igt_table_id;
	uint8_t		igt_pad[3];
};

/* Apply-Actions instruction */
struct ofp_instruction_actions {
	uint16_t	ia_type;
	uint16_t	ia_len;
	uint8_t		pad[4];
};

/* Meter instruction */
struct ofp_instruction_meter {
	uint16_t	im_type;
	uint16_t	im_len;
	uint32_t	im_meter_id;
};

/* Experimenter instruction */
struct ofp_instruction_experimenter {
	uint16_t	ie_type;
	uint16_t	ie_len;
	uint32_t	ie_experimenter;
};

/* Actions */
#define OFP_ACTION_OUTPUT		0	/* Output to switch port */
#define OFP_ACTION_COPY_TTL_OUT		11	/* ? */
#define OFP_ACTION_COPY_TTL_IN		12	/* ? */
#define OFP_ACTION_SET_MPLS_TTL		15	/* ? */
#define OFP_ACTION_DEC_MPLS_TTL		16	/* ? */
#define OFP_ACTION_PUSH_VLAN		17	/* ? */
#define OFP_ACTION_POP_VLAN		18	/* ? */
#define OFP_ACTION_PUSH_MPLS		19	/* ? */
#define OFP_ACTION_POP_MPLS		20	/* ? */
#define OFP_ACTION_SET_QUEUE		21	/* ? */
#define OFP_ACTION_GROUP		22	/* ? */
#define OFP_ACTION_SET_NW_TTL		23	/* ? */
#define OFP_ACTION_DEC_NW_TTL		24	/* ? */
#define OFP_ACTION_SET_FIELD		25	/* ? */
#define OFP_ACTION_PUSH_PBB		26	/* ? */
#define OFP_ACTION_POP_PBB		27	/* ? */
#define OFP_ACTION_EXPERIMENTER		0xffff	/* Vendor-specific action */

/* Action Header */
struct ofp_action_header {
	uint16_t	ah_type;
	uint16_t	ah_len;
	uint32_t	ah_pad;
} __packed;

#define OFP_CONTROLLER_MAXLEN_MAX	0xffe5
#define OFP_CONTROLLER_MAXLEN_NO_BUFFER	0xffff

/* Output Action */
struct ofp_action_output {
	uint16_t	ao_type;
	uint16_t	ao_len;
	uint32_t	ao_port;
	uint16_t	ao_max_len;
	uint8_t		ao_pad[6];
} __packed;

struct ofp_action_mpls_ttl {
	uint16_t	amt_type;
	uint16_t	amt_len;
	uint8_t		amt_ttl;
	uint8_t		amt_pad[3];
} __packed;

struct ofp_action_push {
	uint16_t	ap_type;
	uint16_t	ap_len;
	uint16_t 	ap_ethertype;
	uint8_t		pad[2];
} __packed;

struct ofp_action_pop_mpls {
	uint16_t	apm_type;
	uint16_t	apm_len;
	uint16_t	apm_ethertype;
	uint8_t		pad[2];
} __packed;

struct ofp_action_group {
	uint16_t	ag_type;
	uint16_t	ag_len;
	uint32_t	ag_group_id;
} __packed;

struct ofp_action_nw_ttl {
	uint16_t	ant_type;
	uint16_t	ant_len;
	uint8_t		ant_ttl;
	uint8_t		ant_pad[3];
} __packed;

struct ofp_action_set_field {
	uint16_t	asf_type;
	uint16_t	asf_len;
	uint8_t		asf_field[4];
} __packed;

/* Packet-Out Message */
struct ofp_packet_out {
	struct ofp_header	pout_oh;	/* OpenFlow header */
	uint32_t		pout_buffer_id;
	uint32_t		pout_in_port;
	uint16_t		pout_actions_len;
	uint8_t			pout_pad[6];
	struct ofp_action_header pout_actions[0];
	/* Followed by optional packet data if buffer_id == 0xffffffff */
} __packed;

/* Flow match fields for basic class */
#define OFP_XM_T_IN_PORT		0	/* ? */
#define OFP_XM_T_IN_PHY_PORT		1	/* ? */
#define OFP_XM_T_META			2	/* ? */
#define OFP_XM_T_ETH_DST		3	/* ? */
#define OFP_XM_T_ETH_SRC		4	/* ? */
#define OFP_XM_T_ETH_TYPE		5	/* ? */
#define OFP_XM_T_VLAN_VID		6	/* ? */
#define OFP_XM_T_VLAN_PCP		7	/* ? */
#define OFP_XM_T_IP_DSCP		8	/* ? */
#define OFP_XM_T_IP_ECN			9	/* ? */
#define OFP_XM_T_IP_PROTO		10	/* ? */
#define OFP_XM_T_IPV4_SRC		11	/* ? */
#define OFP_XM_T_IPV4_DST		12	/* ? */
#define OFP_XM_T_TCP_SRC		13	/* ? */
#define OFP_XM_T_TCP_DST		14	/* ? */
#define OFP_XM_T_UDP_SRC		15	/* ? */
#define OFP_XM_T_UDP_DST		16	/* ? */
#define OFP_XM_T_SCTP_SRC		17	/* ? */
#define OFP_XM_T_SCTP_DST		18	/* ? */
#define OFP_XM_T_ICMPV4_TYPE		19	/* ? */
#define OFP_XM_T_ICMPV4_CODE		20	/* ? */
#define OFP_XM_T_ARP_OP			21	/* ? */
#define OFP_XM_T_ARP_SPA		22	/* ? */
#define OFP_XM_T_ARP_TPA		23	/* ? */
#define OFP_XM_T_ARP_SHA		24	/* ? */
#define OFP_XM_T_ARP_THA		25	/* ? */
#define OFP_XM_T_IPV6_SRC		26	/* ? */
#define OFP_XM_T_IPV6_DST		27	/* ? */
#define OFP_XM_T_IPV6_FLABEL		28	/* ? */
#define OFP_XM_T_ICMPV6_TYPE		29	/* ? */
#define OFP_XM_T_ICMPV6_CODE		30	/* ? */
#define OFP_XM_T_IPV6_ND_TARGET		31	/* ? */
#define OFP_XM_T_IPV6_ND_SLL		32	/* ? */
#define OFP_XM_T_IPV6_ND_TLL		33	/* ? */
#define OFP_XM_T_MPLS_LABEL		34	/* ? */
#define OFP_XM_T_MPLS_TC		35	/* ? */
#define OFP_XM_T_MPLS_BOS		36	/* ? */
#define OFP_XM_T_PBB_ISID		37	/* ? */
#define OFP_XM_T_TUNNEL_ID		38	/* ? */
#define OFP_XM_T_IPV6_EXTHDR		39	/* ? */
#define OFP_XM_T_MAX			40	/* ? */

/* Flow match fields for nxm1 class */
#define OFP_XM_NXMT_TUNNEL_ID		38	/* ? */
#define OFP_XM_NXMT_TUNNEL_IPV4_SRC	31	/* ? */
#define OFP_XM_NXMT_TUNNEL_IPV4_DST	32	/* ? */
#define OFP_XM_NXMT_TUNNEL_IPV6_SRC	109	/* ? */
#define OFP_XM_NXMT_TUNNEL_IPV6_DST	110	/* ? */

/* OXM class */
#define OFP_OXM_C_NXM_0			0x0000	/* NXM 0 */
#define OFP_OXM_C_NXM_1			0x0001	/* NXM 1 */
#define OFP_OXM_C_OPENFLOW_BASIC	0x8000	/* OpenFlow Basic */
#define OFP_OXM_C_OPENFLOW_EXPERIMENTER	0xffff	/* OpenFlow Experimenter */

/* VLAN matching flag */
#define OFP_XM_VID_PRESENT		0x1000	/* VLAN ID present */
#define OFP_XM_VID_NONE			0x0000	/* No VLAN ID */

struct ofp_ox_match {
	uint16_t	oxm_class;
	uint8_t		oxm_fh;
	uint8_t		oxm_length;
};

#define OFP_OXM_GET_FIELD(o)	(((o)->oxm_fh) >> 1)
#define OFP_OXM_GET_HASMASK(o)	(((o)->oxm_fh) & 0x1)
#define OFP_OXM_SET_FIELD(o, t)	(((o)->oxm_fh) = ((t) << 1))
#define OFP_OXM_SET_HASMASK(o)	(((o)->oxm_fh) |= 0x1)

/* Flow modification commands */
#define OFP_FLOWCMD_ADD			0	/* Add new flow */
#define OFP_FLOWCMD_MODIFY		1	/* Modify flow */
#define OFP_FLOWCMD_MODIFY_STRICT	2	/* Modify flow w/o wildcard */
#define OFP_FLOWCMD_DELETE		3	/* Delete flow */
#define OFP_FLOWCMD_DELETE_STRICT	4	/* Delete flow w/o wildcard */

/* Flow modification flags */
#define OFP_FLOWFLAG_SEND_FLOW_REMOVED	0x01	/* Send flow removed message */
#define OFP_FLOWFLAG_CHECK_OVERLAP	0x02	/* Check flow overlap first */
#define OFP_FLOWFLAG_RESET_COUNTS	0x04	/* Reset flow packet and byte counters */
#define OFP_FLOWFLAG_NO_PACKET_COUNTS	0x08	/* Don't keep track of packet count */
#define OFP_FLOWFLAG_NO_BYTE_COUNTS	0x10	/* Don't keep track of byte count */

/* Flow modification message */
struct ofp_flow_mod {
	struct ofp_header	fm_oh;		/* OpenFlow header */
	uint64_t		fm_cookie;
	uint64_t		fm_cookie_mask;
	uint8_t			fm_table_id;
	uint8_t			fm_command;
	uint16_t		fm_idle_timeout;
	uint16_t		fm_hard_timeout;
	uint16_t		fm_priority;
	uint32_t		fm_buffer_id;
	uint32_t		fm_out_port;
	uint32_t		fm_out_group;
	uint16_t		fm_flags;
	uint8_t			fm_pad[2];
	struct ofp_match	fm_match;
} __packed;

/* Flow removed reasons */
#define OFP_FLOWREM_REASON_IDLE_TIMEOUT	0	/* Flow idle time exceeded idle_timeout */
#define OFP_FLOWREM_REASON_HARD_TIMEOUT	1	/* Time exceeded hard_timeout */
#define OFP_FLOWREM_REASON_DELETE	2	/* Evicted by a DELETE flow mod */
#define OFP_FLOWREM_REASON_GROUP_DELETE	3	/* Group was removed */

/* Flow removed message */
struct ofp_flow_removed {
	struct ofp_header	fr_oh;
	uint64_t		fr_cookie;
	uint16_t		fr_priority;
	uint8_t			fr_reason;
	uint8_t			fr_table_id;
	uint32_t		fr_duration_sec;
	uint32_t		fr_duration_nsec;
	uint16_t		fr_idle_timeout;
	uint16_t		fr_hard_timeout;
	uint64_t		fr_packet_count;
	uint64_t		fr_byte_count;
	struct ofp_match	fr_match;
} __packed;

/* Error message */
struct ofp_error {
	struct ofp_header	err_oh;
	uint16_t		err_type;
	uint16_t		err_code;
	uint8_t			err_data[0];
	/* Followed by optional data */
} __packed;
#define OFP_ERRDATA_MAX			64

/* Error types */
#define OFP_ERRTYPE_HELLO_FAILED	0	/* Hello protocol failed */
#define OFP_ERRTYPE_BAD_REQUEST		1	/* Request was not understood */
#define OFP_ERRTYPE_BAD_ACTION		2	/* Error in action */
#define OFP_ERRTYPE_BAD_INSTRUCTION	3	/* Error in instruction list */
#define OFP_ERRTYPE_BAD_MATCH		4	/* Error in match */
#define OFP_ERRTYPE_FLOW_MOD_FAILED	5	/* Problem modifying flow */
#define OFP_ERRTYPE_GROUP_MOD_FAILED	6	/* Problem modifying group */
#define OFP_ERRTYPE_PORT_MOD_FAILED	7	/* Port mod request failed */
#define OFP_ERRTYPE_TABLE_MOD_FAILED	8	/* Port mod request failed */
#define OFP_ERRTYPE_QUEUE_OP_FAILED	9	/* Queue operation failed */
#define OFP_ERRTYPE_SWITCH_CFG_FAILED	10	/* Switch Config request failed */
#define OFP_ERRTYPE_ROLE_REQUEST_FAILED	11	/* Controller role request failed */
#define OFP_ERRTYPE_METER_MOD_FAILED	12	/* Error in meter */
#define OFP_ERRTYPE_TABLE_FEATURES_FAILED 13	/* Setting table features failed */
#define OFP_ERRTYPE_EXPERIMENTER	0xffff	/* Experimenter error message */

/* HELLO error codes */
#define OFP_ERRHELLO_INCOMPATIBLE	0	/* No compatible version */
#define OFP_ERRHELLO_EPERM		1	/* Permissions error */

/* REQUEST error codes */
#define OFP_ERRREQ_VERSION		0	/* Version not supported  */
#define OFP_ERRREQ_TYPE			1	/* Type not supported  */
#define OFP_ERRREQ_MULTIPART		2	/* Multipart type not supported */
#define OFP_ERRREQ_EXPERIMENTER		3	/* Experimenter id not supported */
#define OFP_ERRREQ_EXP_TYPE		4	/* Experimenter type not supported  */
#define OFP_ERRREQ_EPERM		5	/* Permission error */
#define OFP_ERRREQ_LEN			6	/* Wrong request length for type */
#define OFP_ERRREQ_BUFFER_EMPTY		7	/* Specified buffer has already been used */
#define OFP_ERRREQ_BUFFER_UNKNOWN	8	/* Specified buffer does not exist */
#define OFP_ERRREQ_TABLE_ID		9	/* Specified table-id invalid or does not exit */
#define OFP_ERRREQ_IS_SLAVE		10	/* Denied because controller is slave */
#define OFP_ERRREQ_PORT			11	/* Invalid port */
#define OFP_ERRREQ_PACKET		12	/* Invalid packet in packet-out */
#define OFP_ERRREQ_MULTIPART_OVERFLOW	13	/* Multipart overflowed the assigned buffer */

/* ACTION error codes */
#define OFP_ERRACTION_TYPE		0	/* Unknown or unsupported action type */
#define OFP_ERRACTION_LEN		1	/* Length problem in actions */
#define OFP_ERRACTION_EXPERIMENTER	2	/* Unknown experimenter id specified */
#define OFP_ERRACTION_EXP_TYPE		3	/* Unknown action for experimenter id */
#define OFP_ERRACTION_OUT_PORT		4	/* Problem validating output port */
#define OFP_ERRACTION_ARGUMENT		5	/* Bad action argument  */
#define OFP_ERRACTION_EPERM		6	/* Permission error */
#define OFP_ERRACTION_TOO_MANY		7	/* Can't handle this many actions */
#define OFP_ERRACTION_BAD_QUEUE		8	/* Problem validating output queue */
#define OFP_ERRACTION_BAD_OUT_GROPU	9	/* Invalid group id in forward action */
#define OFP_ERRACTION_MATCH_INCONSIST	10	/* Action can't apply or Set-Field failed */
#define OFP_ERRACTION_UNSUPPORTED_ORDER	11	/* Action order is unsupported for Apply-Actions */
#define OFP_ERRACTION_TAG		12	/* Actions uses an unsupported tag/encap */
#define OFP_ERRACTION_SET_TYPE		13	/* Unsupported type in SET_FIELD action */
#define OFP_ERRACTION_SET_LEN		14	/* Length problem in SET_FIELD action */
#define OFP_ERRACTION_SET_ARGUMENT	15	/* Bad argument in SET_FIELD action */

/* INSTRUCTION error codes */
#define OFP_ERRINST_UNKNOWN_INST	0	/* Unknown instruction */
#define OFP_ERRINST_UNSUPPORTED_INST	1	/* Switch or table does not support */
#define OFP_ERRINST_TABLE_ID		2	/* Invalid Table-ID specified */
#define OFP_ERRINST_UNSUPP_META		3	/* Metadata value unsupported by datapath */
#define OFP_ERRINST_UNSUPP_META_MASK	4	/* Metadata mask value unsupported by datapath */
#define OFP_ERRINST_BAD_EXPERIMENTER	5	/* Unknown experimenter id specified */
#define OFP_ERRINST_BAD_EXPERIMENTER_TYPE 6	/* Unknown instruction for experimenter id */
#define OFP_ERRINST_BAD_LEN		7	/* Length problem in instructions */
#define OFP_ERRINST_EPERM		8	/* Permissions error */

/* MATCH error codes */
#define OFP_ERRMATCH_BAD_TYPE		0	/* Unsupported match type */
#define OFP_ERRMATCH_BAD_LEN		1	/* Length problem in match */
#define OFP_ERRMATCH_BAD_TAG		2	/* Match uses an unsupported tag/encap */
#define OFP_ERRMATCH_BAD_DL_ADDR_MASK	3	/* Unsupported datalink addr mask */
#define OFP_ERRMATCH_BAD_NW_ADDR_MASK	4	/* Unsupported network addr mask */
#define OFP_ERRMATCH_BAD_WILDCARDS	5	/* Unsupported combination of fields */
#define OFP_ERRMATCH_BAD_FIELD		6	/* Unsupported field type in the match */
#define OFP_ERRMATCH_BAD_VALUE		7	/* Unsupported value in a match field */
#define OFP_ERRMATCH_BAD_MASK		8	/* Unsupported mask specified in match */
#define OFP_ERRMATCH_BAD_PREREQ		9	/* A prerequisite was not met */
#define OFP_ERRMATCH_DUP_FIELD		10	/* A field type was duplicated */
#define OFP_ERRMATCH_EPERM		11	/* Permissions error */

/* FLOW MOD error codes */
#define OFP_ERRFLOWMOD_UNKNOWN		0	/* Unknown */
#define OFP_ERRFLOWMOD_ALL_TABLES_FULL	1	/* Not added, full tables */
#define OFP_ERRFLOWMOD_TABLE_ID		2	/* Invalid table id */
#define OFP_ERRFLOWMOD_OVERLAP		3	/* Overlapping flow */
#define OFP_ERRFLOWMOD_EPERM		4	/* Permissions error */
#define OFP_ERRFLOWMOD_BAD_TIMEOUT	5	/* non-zero idle/hard timeout */
#define OFP_ERRFLOWMOD_BAD_COMMAND	6	/* Unsupported or Unknown command */
#define OFP_ERRFLOWMOD_BAD_FLAGS	7	/* Unsupported or Unknown flags */

/* GROUP MOD error codes */
#define OFP_ERRGROUPMOD_GROUP_EXISTS	0	/* Already present group */
#define OFP_ERRGROUPMOD_INVALID_GROUP	1	/* Group specified is invalid */
#define OFP_ERRGROUPMOD_WEIGHT_UNSUPP	2	/* Switch does not support unequal load sharing */
#define OFP_ERRGROUPMOD_OUT_OF_GROUPS	3	/* The Group table is full */
#define OFP_ERRGROUPMOD_OUT_OF_BUCKETS	4	/* The maximum number of action buckets */
#define OFP_ERRGROUPMOD_CHAINING_UNSUPP	5	/* Switch does not support groups forwarding to groups */
#define OFP_ERRGROUPMOD_WATCH_UNSUPP	6	/* This group cannot watch the watch_port */
#define OFP_ERRGROUPMOD_LOOP		7	/* Group entry would cause a loop */
#define OFP_ERRGROUPMOD_UNKNOWN_GROUP	8	/* MODIFY attempted to modify a non-existent group */
#define OFP_ERRGROUPMOD_CHAINED_GROUP	9	/* Group not deleted because another group is forwarding to it */
#define OFP_ERRGROUPMOD_BAD_TYPE	10	/* Unsupported or unknown group type */
#define OFP_ERRGROUPMOD_BAD_COMMAND	11	/* Unsupported or unknown command */
#define OFP_ERRGROUPMOD_BAD_BUCKET	12	/* Error in bucket */
#define OFP_ERRGROUPMOD_BAD_WATCH	13	/* Error in watch port/group */
#define OFP_ERRGROUPMOD_EPERM		14	/* Permission error */

/* GROUP MOD message */
#define OFP_GROUPCMD_ADD		0	/* Add group */
#define OFP_GROUPCMD_MODIFY		1	/* Modify group */
#define OFP_GROUPCMD_DELETE		2	/* Delete group */

/* Group types */
#define OFP_GROUP_T_ALL			0
#define OFP_GROUP_T_SELECT		1
#define OFP_GROUP_T_INDIRECT		2
#define OFP_GROUP_T_FAST_FAILOVER	3

#define OFP_GROUP_MAX		0xffffff00
#define OFP_GROUP_ALL		0xfffffffc
#define OFP_GROUP_ANY		0xffffffff

struct ofp_bucket {
	uint16_t		b_len;
	uint16_t		b_weight;
	uint32_t		b_watch_port;
	uint32_t		b_watch_group;
	uint8_t			b_pad[4];
	struct ofp_action_header b_actions[0];
} __packed;

struct ofp_group_mod {
	struct ofp_header	gm_oh;
	uint16_t		gm_command;
	uint8_t			gm_type;
	uint8_t			gm_pad;
	uint32_t		gm_group_id;
	struct ofp_bucket	gm_buckets[0];
} __packed;

struct ofp_multipart {
	struct ofp_header	mp_oh;
	uint16_t		mp_type;
	uint16_t		mp_flags;
	uint8_t			mp_pad[4];
} __packed;

#define OFP_MP_FLAG_REQ_MORE		1
#define OFP_MP_FLAG_REPLY_MORE		1

/* Multipart types */
#define OFP_MP_T_DESC			0
#define OFP_MP_T_FLOW			1
#define OFP_MP_T_AGGREGATE		2
#define OFP_MP_T_TABLE			3
#define OFP_MP_T_PORT_STATS		4
#define OFP_MP_T_QUEUE			5
#define OFP_MP_T_GROUP			6
#define OFP_MP_T_GROUP_DESC		7
#define OFP_MP_T_GROUP_FEATURES		8
#define OFP_MP_T_METER			9
#define OFP_MP_T_METER_CONFIG		10
#define OFP_MP_T_METER_FEATURES		11
#define OFP_MP_T_TABLE_FEATURES		12
#define OFP_MP_T_PORT_DESC		13
#define OFP_MP_T_EXPERIMENTER		0xffff

#define OFP_DESC_STR_LEN		256
#define OFP_SERIAL_NUM_LEN		32

struct ofp_desc {
	char		d_mfr_desc[OFP_DESC_STR_LEN];
	char		d_hw_desc[OFP_DESC_STR_LEN];
	char		d_sw_desc[OFP_DESC_STR_LEN];
	char		d_serial_num[OFP_SERIAL_NUM_LEN];
	char		d_dp_desc[OFP_DESC_STR_LEN];
} __packed;

/* Flow stats request */
struct ofp_flow_stats_request {
	uint8_t			fsr_table_id;
	uint8_t			fsr_pad[3];
	uint32_t		fsr_out_port;
	uint32_t		fsr_out_group;
	uint8_t			fsr_pad2[4];
	uint64_t		fsr_cookie;
	uint64_t		fsr_cookie_mask;
	struct ofp_match	fsr_match;
} __packed;

/* Flow stats */
struct ofp_flow_stats {
	uint16_t		fs_length;
	uint8_t			fs_table_id;
	uint8_t			fs_pad;
	uint32_t		fs_duration_sec;
	uint32_t		fs_duration_nsec;
	uint16_t		fs_priority;
	uint16_t		fs_idle_timeout;
	uint16_t		fs_hard_timeout;
	uint16_t		fs_flags;
	uint8_t			fs_pad2[4];
	uint64_t		fs_cookie;
	uint64_t		fs_packet_count;
	uint64_t		fs_byte_count;
	struct ofp_match	fs_match;
} __packed;

/* Aggregate flow stats request */
struct ofp_aggregate_stats_request {
	uint8_t			asr_table_id;
	uint8_t			asr_pad[3];
	uint32_t		asr_out_port;
	uint32_t		asr_out_group;
	uint8_t			asr_pad2[4];
	uint64_t		asr_cookie;
	uint64_t		asr_cookie_mask;
	struct ofp_match	asr_match;
} __packed;

struct ofp_aggregate_stats {
	uint64_t	as_packet_count;
	uint64_t	as_byte_count;
	uint32_t	as_flow_count;
	uint8_t		as_pad[4];
} __packed;

#define OFP_TABLE_ID_MAX				0xfe
#define OFP_TABLE_ID_ALL				0xff

struct ofp_table_stats {
	uint8_t		ts_table_id;
	uint8_t		ts_pad[3];
	uint32_t	ts_active_count;
	uint64_t	ts_lookup_count;
	uint64_t	ts_matched_count;
} __packed;

/* Table features */
#define OFP_TABLE_FEATPROP_INSTRUCTION		0
#define OFP_TABLE_FEATPROP_INSTRUCTION_MISS	1
#define OFP_TABLE_FEATPROP_NEXT_TABLES		2
#define OFP_TABLE_FEATPROP_NEXT_TABLES_MISS	3
#define OFP_TABLE_FEATPROP_WRITE_ACTIONS	4
#define OFP_TABLE_FEATPROP_WRITE_ACTIONS_MISS	5
#define OFP_TABLE_FEATPROP_APPLY_ACTIONS	6
#define OFP_TABLE_FEATPROP_APPLY_ACTIONS_MISS	7
#define OFP_TABLE_FEATPROP_MATCH		8
#define OFP_TABLE_FEATPROP_WILDCARDS		10
#define OFP_TABLE_FEATPROP_WRITE_SETFIELD	12
#define OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS	13
#define OFP_TABLE_FEATPROP_APPLY_SETFIELD	14
#define OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS	15
#define OFP_TABLE_FEATPROP_EXPERIMENTER		0xfffe
#define OFP_TABLE_FEATPROP_EXPERIMENTER_MISS	0xffff

#define OFP_TABLE_MAX_NAME_LEN			32

struct ofp_table_features {
	uint16_t	tf_length;
	uint8_t		tf_tableid;
	uint8_t		tf_pad[5];
	char		tf_name[OFP_TABLE_MAX_NAME_LEN];
	uint64_t	tf_metadata_match;
	uint64_t	tf_metadata_write;
	uint32_t	tf_config;
	uint32_t	tf_max_entries;
} __packed;

struct ofp_table_feature_property {
	uint16_t	tp_type;
	uint16_t	tp_length;
} __packed;

struct ofp_table_feature_property_instruction {
	uint16_t		tpi_type;
	uint16_t		tpi_length;
	struct ofp_instruction	tpi_instructions[0];
} __packed;

struct ofp_table_feature_property_next_tables {
	uint16_t	tpnt_type;
	uint16_t	tpnt_length;
	uint8_t		tpnt_tables[0];
} __packed;

struct ofp_table_feature_property_actions {
	uint16_t			tpa_type;
	uint16_t			tpa_length;
	struct ofp_action_header	tpa_actions[0];
} __packed;

struct ofp_table_feature_property_oxm {
	uint16_t	tpoxm_type;
	uint16_t	tpoxm_length;
	uint32_t	tpoxm_oxm[0];
} __packed;

struct ofp_table_feature_property_experimenter {
	uint16_t	tfpexp_type;
	uint16_t	tfpexp_length;
	uint32_t	tfpexp_experimenter;
	uint32_t	tfpexp_exp_type;
	uint32_t	tfpexp_experimenter_data[0];
} __packed;

struct ofp_port_stats {
	uint32_t	pt_port_no;
	uint8_t		pt_pad[4];
	uint64_t	pt_rx_packets;
	uint64_t	pt_tx_packets;
	uint64_t	pt_rx_bytes;
	uint64_t	pt_tx_bytes;
	uint64_t	pt_rx_dropped;
	uint64_t	pt_tx_dropped;
	uint64_t	pt_rx_errors;
	uint64_t	pt_tx_errors;
	uint64_t	pt_rx_frame_err;
	uint64_t	pt_rx_over_err;
	uint64_t	pt_rx_crc_err;
	uint64_t	pt_collision;
	uint32_t	pt_duration_sec;
	uint32_t	pt_duration_nsec;
} __packed;

/* Groups stats request */
struct ofp_group_stats_request {
	uint32_t	gsr_group_id;
	uint8_t		gsr_pad[4];
} __packed;

struct ofp_bucket_counter {
	uint64_t	gs_packet_count;
	uint64_t	gs_byte_count;
} __packed;

/* Group stats */
struct ofp_group_stats {
	uint16_t		gs_length;
	uint8_t			gs_pad[2];
	uint32_t		gs_group_id;
	uint32_t		gs_ref_count;
	uint8_t			gs_pad2[4];
	uint64_t		gs_packet_count;
	uint64_t		gs_byte_count;
	uint32_t		gs_duration_sec;
	uint32_t		gs_duration_nsec;
	struct ofp_bucket_counter gs_bucket_stats[0];
} __packed;

/* Group description */
struct ofp_group_desc {
	uint16_t		gd_length;
	uint8_t			gd_type;
	uint8_t			gd_pad;
	uint32_t		gd_group_id;
	struct ofp_bucket	gd_buckets[0];
} __packed;

#endif /* _NET_OPF_H_ */