1/* $OpenBSD: ofp.h,v 1.15 2023/04/11 00:45:09 jsg Exp $ */
2
3/*
4 * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2016 Kazuya GODA <goda@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#ifndef _NET_OFP_H_
21#define _NET_OFP_H_
22
23#include <sys/types.h>
24#include <sys/socket.h>
25
26#include <net/if.h>
27#include <netinet/in.h>
28#include <netinet/if_ether.h>
29
30#define OFP_IFNAMSIZ 16 /* on-wire (not IF_NAMSIZE) */
31#define OFP_ALIGNMENT 8 /* OFP alignment */
32#define OFP_ALIGN(_x) (((_x) + (OFP_ALIGNMENT - 1)) & ~(OFP_ALIGNMENT - 1))
33
34struct ofp_header {
35 uint8_t oh_version; /* OpenFlow version */
36 uint8_t oh_type; /* message type */
37 uint16_t oh_length; /* message length */
38 uint32_t oh_xid; /* transaction Id */
39} __packed;
40
41/* OpenFlow version */
42#define OFP_V_0 0x00 /* OpenFlow 0.0 */
43#define OFP_V_1_0 0x01 /* OpenFlow 1.0 */
44#define OFP_V_1_1 0x02 /* OpenFlow 1.1 */
45#define OFP_V_1_2 0x03 /* OpenFlow 1.2 */
46#define OFP_V_1_3 0x04 /* OpenFlow 1.3 */
47#define OFP_V_1_4 0x05 /* OpenFlow 1.4 */
48#define OFP_V_1_5 0x06 /* OpenFlow 1.5 */
49
50/* OpenFlow message type */
51#define OFP_T_HELLO 0 /* Hello */
52#define OFP_T_ERROR 1 /* Error */
53#define OFP_T_ECHO_REQUEST 2 /* Echo Request */
54#define OFP_T_ECHO_REPLY 3 /* Echo Reply */
55#define OFP_T_EXPERIMENTER 4 /* Vendor/Experimenter */
56#define OFP_T_FEATURES_REQUEST 5 /* Features Request (switch) */
57#define OFP_T_FEATURES_REPLY 6 /* Features Reply (switch) */
58#define OFP_T_GET_CONFIG_REQUEST 7 /* Get Config Request (switch) */
59#define OFP_T_GET_CONFIG_REPLY 8 /* Get Config Reply (switch) */
60#define OFP_T_SET_CONFIG 9 /* Set Config (switch) */
61#define OFP_T_PACKET_IN 10 /* Packet In (async) */
62#define OFP_T_FLOW_REMOVED 11 /* Flow Removed (async) */
63#define OFP_T_PORT_STATUS 12 /* Port Status (async) */
64#define OFP_T_PACKET_OUT 13 /* Packet Out (controller) */
65#define OFP_T_FLOW_MOD 14 /* Flow Mod (controller) */
66#define OFP_T_GROUP_MOD 15 /* Group Mod (controller) */
67#define OFP_T_PORT_MOD 16 /* Port Mod (controller) */
68#define OFP_T_TABLE_MOD 17 /* Table Mod (controller) */
69#define OFP_T_MULTIPART_REQUEST 18 /* Multipart Message Request */
70#define OFP_T_MULTIPART_REPLY 19 /* Multipart Message Request */
71#define OFP_T_BARRIER_REQUEST 20 /* Barrier Request */
72#define OFP_T_BARRIER_REPLY 21 /* Barrier Reply */
73#define OFP_T_QUEUE_GET_CONFIG_REQUEST 22 /* Queue Get Config Request */
74#define OFP_T_QUEUE_GET_CONFIG_REPLY 23 /* Queue Get Config Reply */
75#define OFP_T_ROLE_REQUEST 24 /* Role Request */
76#define OFP_T_ROLE_REPLY 25 /* Role Reply */
77#define OFP_T_GET_ASYNC_REQUEST 26 /* Get Async Request */
78#define OFP_T_GET_ASYNC_REPLY 27 /* Get Async Reply */
79#define OFP_T_SET_ASYNC 28 /* Set Async */
80#define OFP_T_METER_MOD 29 /* Meter Mod */
81#define OFP_T_TYPE_MAX 30
82
83/* OpenFlow Hello Message */
84struct ofp_hello_element_header {
85 uint16_t he_type;
86 uint16_t he_length;
87} __packed;
88
89#define OFP_HELLO_T_VERSION_BITMAP 1 /* Supported version bitmap */
90
91struct ofp_hello_element_versionbitmap {
92 uint16_t hev_type;
93 uint16_t hev_length;
94} __packed;
95
96/* Ports */
97#define OFP_PORT_MAX 0xffffff00 /* Maximum number of physical ports */
98#define OFP_PORT_INPUT 0xfffffff8 /* Send back to input port */
99#define OFP_PORT_FLOWTABLE 0xfffffff9 /* Perform actions in flow table */
100#define OFP_PORT_NORMAL 0xfffffffa /* Let switch decide */
101#define OFP_PORT_FLOOD 0xfffffffb /* All non-block ports except input */
102#define OFP_PORT_ALL 0xfffffffc /* All ports except input */
103#define OFP_PORT_CONTROLLER 0xfffffffd /* Send to controller */
104#define OFP_PORT_LOCAL 0xfffffffe /* Local virtual OpenFlow port */
105#define OFP_PORT_ANY 0xffffffff /* No port */
106
107/* Switch Config Message (reply) */
108struct ofp_switch_config {
109 struct ofp_header cfg_oh; /* OpenFlow header */
110 uint16_t cfg_flags; /* Configuration flags */
111 uint16_t cfg_miss_send_len; /* Max bytes from datapath */
112} __packed;
113
114/* Switch Config */
115#define OFP_CONFIG_FRAG_NORMAL 0x0000 /* No special frag handling */
116#define OFP_CONFIG_FRAG_DROP 0x0001 /* Drop fragments */
117#define OFP_CONFIG_FRAG_REASM 0x0002 /* Reassemble fragments */
118#define OFP_CONFIG_FRAG_MASK 0x0003 /* Fragment mask */
119
120/* Switch port description */
121struct ofp_switch_port {
122 uint32_t swp_number; /* Switch port number */
123 uint8_t swp_pad[4]; /* Padding */
124 uint8_t swp_macaddr[ETHER_ADDR_LEN]; /* Port MAC address */
125 uint8_t swp_pad2[2]; /* Padding */
126 char swp_name[OFP_IFNAMSIZ]; /* Switch port name */
127 uint32_t swp_config; /* Configuration flags */
128 uint32_t swp_state; /* State flags */
129 uint32_t swp_cur; /* Current features */
130 uint32_t swp_advertised; /* Advertised by the port */
131 uint32_t swp_supported; /* Supported by the port */
132 uint32_t swp_peer; /* Advertised by peer */
133 uint32_t swp_cur_speed; /* Current port speed in Kbps*/
134 uint32_t swp_max_speed; /* Support port max speed in Kbps*/
135} __packed;
136
137/* Physical port configuration */
138#define OFP_PORTCONFIG_PORT_DOWN 0x1 /* Port is down */
139#define OFP_PORTCONFIG_NO_STP 0x2 /* Disable STP on port */
140#define OFP_PORTCONFIG_NO_RECV 0x4 /* Drop everything except STP */
141#define OFP_PORTCONFIG_NO_RECV_STP 0x8 /* Drop received STP */
142#define OFP_PORTCONFIG_NO_FLOOD 0x10 /* Do not flood to this port */
143#define OFP_PORTCONFIG_NO_FWD 0x20 /* Drop packets to port */
144#define OFP_PORTCONFIG_NO_PACKET_IN 0x40 /* NO PACKET_IN on port */
145
146/* Physical port state */
147#define OFP_PORTSTATE_LINK_DOWN 0x1 /* Link not active */
148#define OFP_PORTSTATE_STP_LISTEN 0x000 /* Not learning or forwarding */
149#define OFP_PORTSTATE_STP_LEARN 0x100 /* Learning but not forwarding */
150#define OFP_PORTSTATE_STP_FORWARD 0x200 /* Learning and forwarding */
151#define OFP_PORTSTATE_STP_BLOCK 0x300 /* Not part of spanning tree */
152#define OFP_PORTSTATE_STP_MASK 0x300 /* Spanning tree values */
153
154/* Physical port media types */
155#define OFP_PORTMEDIA_10MB_HD 0x1 /* 10 Mb half-duplex */
156#define OFP_PORTMEDIA_10MB_FD 0x2 /* 10 Mb full-duplex */
157#define OFP_PORTMEDIA_100MB_HD 0x4 /* 100 Mb half-duplex */
158#define OFP_PORTMEDIA_100MB_FD 0x8 /* 100 Mb full-duplex */
159#define OFP_PORTMEDIA_1GB_HD 0x10 /* 1 Gb half-duplex */
160#define OFP_PORTMEDIA_1GB_FD 0x20 /* 1 Gb full-duplex */
161#define OFP_PORTMEDIA_10GB_FD 0x40 /* 10 Gb full-duplex */
162#define OFP_PORTMEDIA_COPPER 0x80 /* Copper */
163#define OFP_PORTMEDIA_FIBER 0x100 /* Fiber */
164#define OFP_PORTMEDIA_AUTONEG 0x200 /* Auto-negotiation */
165#define OFP_PORTMEDIA_PAUSE 0x400 /* Pause */
166#define OFP_PORTMEDIA_PAUSE_ASYM 0x800 /* Asymmetric pause */
167
168/* Switch Features Message (reply) */
169struct ofp_switch_features {
170 struct ofp_header swf_oh; /* OpenFlow header */
171 uint64_t swf_datapath_id; /* Datapath unique ID */
172 uint32_t swf_nbuffers; /* Max packets buffered */
173 uint8_t swf_ntables; /* Number of supported tables */
174 uint8_t swf_aux_id; /* Identify auxiliary connections */
175 uint8_t swf_pad[2]; /* Align to 64 bits */
176 uint32_t swf_capabilities; /* Capability flags */
177 uint32_t swf_actions; /* Supported action flags */
178} __packed;
179
180/* Switch capabilities */
181#define OFP_SWCAP_FLOW_STATS 0x1 /* Flow statistics */
182#define OFP_SWCAP_TABLE_STATS 0x2 /* Table statistics */
183#define OFP_SWCAP_PORT_STATS 0x4 /* Port statistics */
184#define OFP_SWCAP_GROUP_STATS 0x8 /* Group statistics */
185#define OFP_SWCAP_IP_REASM 0x20 /* Can reassemble IP frags */
186#define OFP_SWCAP_QUEUE_STATS 0x40 /* Queue statistics */
187#define OFP_SWCAP_ARP_MATCH_IP 0x80 /* Match IP addresses in ARP pkts */
188#define OFP_SWCAP_PORT_BLOCKED 0x100 /* Switch will block ports */
189
190/* Flow matching */
191struct ofp_match {
192 uint16_t om_type;
193 uint16_t om_length;
194} __packed;
195
196/* Flow matching type */
197#define OFP_MATCH_STANDARD 0 /* Standard match deprecated */
198#define OFP_MATCH_OXM 1 /* OpenFlow Extensible Match */
199
200/* Packet-In Message */
201struct ofp_packet_in {
202 struct ofp_header pin_oh; /* OpenFlow header */
203 uint32_t pin_buffer_id;
204 uint16_t pin_total_len;
205 uint8_t pin_reason;
206 uint8_t pin_table_id;
207 uint64_t pin_cookie;
208 struct ofp_match pin_match;
209} __packed;
210
211/* Reason */
212#define OFP_PKTIN_REASON_NO_MATCH 0 /* No matching flow */
213#define OFP_PKTIN_REASON_ACTION 1 /* Explicit output */
214#define OFP_PKTIN_REASON_TTL 2 /* Packet has invalid TTL */
215
216/* Flow Instruction */
217struct ofp_instruction {
218 uint16_t i_type;
219 uint16_t i_len;
220} __packed;
221
222/* Instruction types */
223#define OFP_INSTRUCTION_T_GOTO_TABLE 1 /* Goto-Table */
224#define OFP_INSTRUCTION_T_WRITE_META 2 /* Write-Metadata */
225#define OFP_INSTRUCTION_T_WRITE_ACTIONS 3 /* Write-Actions */
226#define OFP_INSTRUCTION_T_APPLY_ACTIONS 4 /* Apply-Actions */
227#define OFP_INSTRUCTION_T_CLEAR_ACTIONS 5 /* Clear-Actions */
228#define OFP_INSTRUCTION_T_METER 6 /* Meter */
229#define OFP_INSTRUCTION_T_EXPERIMENTER 0xffff /* Experimenter */
230
231/* Write-Metadata instruction */
232struct ofp_instruction_write_metadata {
233 uint16_t iwm_type;
234 uint16_t iwm_len;
235 uint8_t iwm_pad[4];
236 uint64_t iwm_metadata;
237 uint64_t iwm_metadata_mask;
238} __packed;
239
240/* Goto-Table instruction */
241struct ofp_instruction_goto_table {
242 uint16_t igt_type;
243 uint16_t igt_len;
244 uint8_t igt_table_id;
245 uint8_t igt_pad[3];
246} __packed;
247
248/* Apply-Actions instruction */
249struct ofp_instruction_actions {
250 uint16_t ia_type;
251 uint16_t ia_len;
252 uint8_t ia_pad[4];
253} __packed;
254
255/* Meter instruction */
256struct ofp_instruction_meter {
257 uint16_t im_type;
258 uint16_t im_len;
259 uint32_t im_meter_id;
260} __packed;
261
262/* Experimenter instruction */
263struct ofp_instruction_experimenter {
264 uint16_t ie_type;
265 uint16_t ie_len;
266 uint32_t ie_experimenter;
267} __packed;
268
269/* Actions */
270#define OFP_ACTION_OUTPUT 0 /* Output to switch port */
271#define OFP_ACTION_COPY_TTL_OUT 11 /* Copy TTL outwards */
272#define OFP_ACTION_COPY_TTL_IN 12 /* Copy TTL inwards */
273#define OFP_ACTION_SET_MPLS_TTL 15 /* MPLS TTL */
274#define OFP_ACTION_DEC_MPLS_TTL 16 /* Decrement MPLS TTL */
275#define OFP_ACTION_PUSH_VLAN 17 /* Push a new VLAN tag */
276#define OFP_ACTION_POP_VLAN 18 /* Pop the outer VLAN tag */
277#define OFP_ACTION_PUSH_MPLS 19 /* Push a new MPLS tag */
278#define OFP_ACTION_POP_MPLS 20 /* Pop the outer MPLS tag */
279#define OFP_ACTION_SET_QUEUE 21 /* Set queue id when outputting to a port */
280#define OFP_ACTION_GROUP 22 /* Apply group */
281#define OFP_ACTION_SET_NW_TTL 23 /* Set IP TTL */
282#define OFP_ACTION_DEC_NW_TTL 24 /* Decrement IP TTL */
283#define OFP_ACTION_SET_FIELD 25 /* Set a header field using OXM TLV format */
284#define OFP_ACTION_PUSH_PBB 26 /* Push a new PBB service tag (I-TAG) */
285#define OFP_ACTION_POP_PBB 27 /* Pop the outer PBB service tag (I-TAG) */
286#define OFP_ACTION_EXPERIMENTER 0xffff /* Vendor-specific action */
287
288/* Action Header */
289struct ofp_action_header {
290 uint16_t ah_type;
291 uint16_t ah_len;
292 uint32_t ah_pad;
293} __packed;
294
295/* Output Action */
296struct ofp_action_output {
297 uint16_t ao_type;
298 uint16_t ao_len;
299 uint32_t ao_port;
300 uint16_t ao_max_len;
301 uint8_t ao_pad[6];
302} __packed;
303
304/* Buffer configuration */
305#define OFP_CONTROLLER_MAXLEN_MAX 0xffe5 /* maximum buffer length */
306#define OFP_CONTROLLER_MAXLEN_NO_BUFFER 0xffff /* don't do any buffering */
307
308struct ofp_action_mpls_ttl {
309 uint16_t amt_type;
310 uint16_t amt_len;
311 uint8_t amt_ttl;
312 uint8_t amt_pad[3];
313} __packed;
314
315struct ofp_action_push {
316 uint16_t ap_type;
317 uint16_t ap_len;
318 uint16_t ap_ethertype;
319 uint8_t ap_pad[2];
320} __packed;
321
322struct ofp_action_pop_mpls {
323 uint16_t apm_type;
324 uint16_t apm_len;
325 uint16_t apm_ethertype;
326 uint8_t apm_pad[2];
327} __packed;
328
329struct ofp_action_group {
330 uint16_t ag_type;
331 uint16_t ag_len;
332 uint32_t ag_group_id;
333} __packed;
334
335struct ofp_action_nw_ttl {
336 uint16_t ant_type;
337 uint16_t ant_len;
338 uint8_t ant_ttl;
339 uint8_t ant_pad[3];
340} __packed;
341
342struct ofp_action_set_field {
343 uint16_t asf_type;
344 uint16_t asf_len;
345 uint8_t asf_field[4];
346} __packed;
347
348struct ofp_action_set_queue {
349 uint16_t asq_type;
350 uint16_t asq_len;
351 uint32_t asq_queue_id;
352} __packed;
353
354/* Packet-Out Message */
355struct ofp_packet_out {
356 struct ofp_header pout_oh; /* OpenFlow header */
357 uint32_t pout_buffer_id;
358 uint32_t pout_in_port;
359 uint16_t pout_actions_len;
360 uint8_t pout_pad[6];
361 struct ofp_action_header pout_actions[0];
362 /* Followed by optional packet data if buffer_id == 0xffffffff */
363} __packed;
364
365/* Special buffer id */
366#define OFP_PKTOUT_NO_BUFFER 0xffffffff /* No buffer id */
367
368/* Flow match fields for basic class */
369#define OFP_XM_T_IN_PORT 0 /* Switch input port */
370#define OFP_XM_T_IN_PHY_PORT 1 /* Switch physical input port */
371#define OFP_XM_T_META 2 /* Metadata passed between tables */
372#define OFP_XM_T_ETH_DST 3 /* Ethernet destination address */
373#define OFP_XM_T_ETH_SRC 4 /* Ethernet source address */
374#define OFP_XM_T_ETH_TYPE 5 /* Ethernet frame type */
375#define OFP_XM_T_VLAN_VID 6 /* VLAN id */
376#define OFP_XM_T_VLAN_PCP 7 /* VLAN priority */
377#define OFP_XM_T_IP_DSCP 8 /* IP DSCP (6 bits in ToS field) */
378#define OFP_XM_T_IP_ECN 9 /* IP ECN (2 bits in ToS field) */
379#define OFP_XM_T_IP_PROTO 10 /* IP protocol */
380#define OFP_XM_T_IPV4_SRC 11 /* IPv4 source address */
381#define OFP_XM_T_IPV4_DST 12 /* IPv4 destination address */
382#define OFP_XM_T_TCP_SRC 13 /* TCP source port */
383#define OFP_XM_T_TCP_DST 14 /* TCP destination port */
384#define OFP_XM_T_UDP_SRC 15 /* UDP source port */
385#define OFP_XM_T_UDP_DST 16 /* UDP destination port */
386#define OFP_XM_T_SCTP_SRC 17 /* SCTP source port */
387#define OFP_XM_T_SCTP_DST 18 /* SCTP destination port */
388#define OFP_XM_T_ICMPV4_TYPE 19 /* ICMP type */
389#define OFP_XM_T_ICMPV4_CODE 20 /* ICMP code */
390#define OFP_XM_T_ARP_OP 21 /* ARP opcode */
391#define OFP_XM_T_ARP_SPA 22 /* ARP source IPv4 address */
392#define OFP_XM_T_ARP_TPA 23 /* ARP target IPv4 address */
393#define OFP_XM_T_ARP_SHA 24 /* ARP source hardware address */
394#define OFP_XM_T_ARP_THA 25 /* ARP target hardware address */
395#define OFP_XM_T_IPV6_SRC 26 /* IPv6 source address */
396#define OFP_XM_T_IPV6_DST 27 /* IPv6 destination address */
397#define OFP_XM_T_IPV6_FLABEL 28 /* IPv6 Flow Label */
398#define OFP_XM_T_ICMPV6_TYPE 29 /* ICMPv6 type */
399#define OFP_XM_T_ICMPV6_CODE 30 /* ICMPv6 code */
400#define OFP_XM_T_IPV6_ND_TARGET 31 /* Target address for ND */
401#define OFP_XM_T_IPV6_ND_SLL 32 /* Source link-layer for ND */
402#define OFP_XM_T_IPV6_ND_TLL 33 /* Target link-layer for ND */
403#define OFP_XM_T_MPLS_LABEL 34 /* MPLS label */
404#define OFP_XM_T_MPLS_TC 35 /* MPLS TC */
405#define OFP_XM_T_MPLS_BOS 36 /* MPLS BoS bit */
406#define OFP_XM_T_PBB_ISID 37 /* PBB I-SID */
407#define OFP_XM_T_TUNNEL_ID 38 /* Logical Port Metadata */
408#define OFP_XM_T_IPV6_EXTHDR 39 /* IPv6 Extension Header pseudo-field */
409#define OFP_XM_T_MAX 40
410
411/* Flow match fields for nxm1 class */
412#define OFP_XM_NXMT_TUNNEL_ID 38 /* Tunnel Logical Port Metadata */
413#define OFP_XM_NXMT_TUNNEL_IPV4_SRC 31 /* Tunnel IPv4 source address */
414#define OFP_XM_NXMT_TUNNEL_IPV4_DST 32 /* Tunnel IPv4 destination address */
415#define OFP_XM_NXMT_TUNNEL_IPV6_SRC 109 /* Tunnel IPv6 source address */
416#define OFP_XM_NXMT_TUNNEL_IPV6_DST 110 /* Tunnel IPv6 destination address */
417
418/* OXM class */
419#define OFP_OXM_C_NXM_0 0x0000 /* NXM 0 */
420#define OFP_OXM_C_NXM_1 0x0001 /* NXM 1 */
421#define OFP_OXM_C_OPENFLOW_BASIC 0x8000 /* OpenFlow Basic */
422#define OFP_OXM_C_OPENFLOW_EXPERIMENTER 0xffff /* OpenFlow Experimenter */
423
424/* VLAN matching flag */
425#define OFP_XM_VID_PRESENT 0x1000 /* VLAN ID present */
426#define OFP_XM_VID_NONE 0x0000 /* No VLAN ID */
427
428/* IPv6 Extension header pseudo-field flags */
429#define OFP_XM_IPV6_EXTHDR_NONEXT 0x0001 /* "No next header" encountered */
430#define OFP_XM_IPV6_EXTHDR_ESP 0x0002 /* Encrypted Sec Payload header present */
431#define OFP_XM_IPV6_EXTHDR_AUTH 0x0004 /* Authentication header present. */
432#define OFP_XM_IPV6_EXTHDR_DEST 0x0008 /* 1 or 2 dest headers present. */
433#define OFP_XM_IPV6_EXTHDR_FRAG 0x0010 /* Fragment header present. */
434#define OFP_XM_IPV6_EXTHDR_ROUTER 0x0020 /* Router header present. */
435#define OFP_XM_IPV6_EXTHDR_HOP 0x0040 /* Hop-by-hop header present. */
436#define OFP_XM_IPV6_EXTHDR_UNREP 0x0080 /* Unexpected repeats encountered. */
437#define OFP_XM_IPV6_EXTHDR_UNSEQ 0x0100 /* Unexpected sequencing encountered. */
438
439struct ofp_ox_match {
440 uint16_t oxm_class;
441 uint8_t oxm_fh;
442 uint8_t oxm_length;
443 uint8_t oxm_value[0];
444} __packed;
445
446#define OFP_OXM_GET_FIELD(o) (((o)->oxm_fh) >> 1)
447#define OFP_OXM_GET_HASMASK(o) (((o)->oxm_fh) & 0x1)
448#define OFP_OXM_SET_FIELD(o, t) (((o)->oxm_fh) = ((t) << 1))
449#define OFP_OXM_SET_HASMASK(o) (((o)->oxm_fh) |= 0x1)
450
451/* Flow modification commands */
452#define OFP_FLOWCMD_ADD 0 /* Add new flow */
453#define OFP_FLOWCMD_MODIFY 1 /* Modify flow */
454#define OFP_FLOWCMD_MODIFY_STRICT 2 /* Modify flow w/o wildcard */
455#define OFP_FLOWCMD_DELETE 3 /* Delete flow */
456#define OFP_FLOWCMD_DELETE_STRICT 4 /* Delete flow w/o wildcard */
457
458/* Flow modification flags */
459#define OFP_FLOWFLAG_SEND_FLOW_REMOVED 0x0001 /* Send flow removed message */
460#define OFP_FLOWFLAG_CHECK_OVERLAP 0x0002 /* Check flow overlap first */
461#define OFP_FLOWFLAG_RESET_COUNTS 0x0004 /* Reset flow packet and byte counters */
462#define OFP_FLOWFLAG_NO_PACKET_COUNTS 0x0008 /* Don't keep track of packet count */
463#define OFP_FLOWFLAG_NO_BYTE_COUNTS 0x0010 /* Don't keep track of byte count */
464
465/* Flow modification message */
466struct ofp_flow_mod {
467 struct ofp_header fm_oh; /* OpenFlow header */
468 uint64_t fm_cookie;
469 uint64_t fm_cookie_mask;
470 uint8_t fm_table_id;
471 uint8_t fm_command;
472 uint16_t fm_idle_timeout;
473 uint16_t fm_hard_timeout;
474 uint16_t fm_priority;
475 uint32_t fm_buffer_id;
476 uint32_t fm_out_port;
477 uint32_t fm_out_group;
478 uint16_t fm_flags;
479 uint8_t fm_pad[2];
480 struct ofp_match fm_match;
481} __packed;
482
483/* Flow removed reasons */
484#define OFP_FLOWREM_REASON_IDLE_TIMEOUT 0 /* Flow idle time exceeded idle_timeout */
485#define OFP_FLOWREM_REASON_HARD_TIMEOUT 1 /* Time exceeded hard_timeout */
486#define OFP_FLOWREM_REASON_DELETE 2 /* Evicted by a DELETE flow mod */
487#define OFP_FLOWREM_REASON_GROUP_DELETE 3 /* Group was removed */
488
489/* Flow removed message */
490struct ofp_flow_removed {
491 struct ofp_header fr_oh;
492 uint64_t fr_cookie;
493 uint16_t fr_priority;
494 uint8_t fr_reason;
495 uint8_t fr_table_id;
496 uint32_t fr_duration_sec;
497 uint32_t fr_duration_nsec;
498 uint16_t fr_idle_timeout;
499 uint16_t fr_hard_timeout;
500 uint64_t fr_packet_count;
501 uint64_t fr_byte_count;
502 struct ofp_match fr_match;
503} __packed;
504
505/* Error message */
506struct ofp_error {
507 struct ofp_header err_oh;
508 uint16_t err_type;
509 uint16_t err_code;
510 uint8_t err_data[0];
511 /* Followed by optional data */
512} __packed;
513#define OFP_ERRDATA_MAX 64
514
515/* Error types */
516#define OFP_ERRTYPE_HELLO_FAILED 0 /* Hello protocol failed */
517#define OFP_ERRTYPE_BAD_REQUEST 1 /* Request was not understood */
518#define OFP_ERRTYPE_BAD_ACTION 2 /* Error in action */
519#define OFP_ERRTYPE_BAD_INSTRUCTION 3 /* Error in instruction list */
520#define OFP_ERRTYPE_BAD_MATCH 4 /* Error in match */
521#define OFP_ERRTYPE_FLOW_MOD_FAILED 5 /* Problem modifying flow */
522#define OFP_ERRTYPE_GROUP_MOD_FAILED 6 /* Problem modifying group */
523#define OFP_ERRTYPE_PORT_MOD_FAILED 7 /* Port mod request failed */
524#define OFP_ERRTYPE_TABLE_MOD_FAILED 8 /* Port mod request failed */
525#define OFP_ERRTYPE_QUEUE_OP_FAILED 9 /* Queue operation failed */
526#define OFP_ERRTYPE_SWITCH_CFG_FAILED 10 /* Switch Config request failed */
527#define OFP_ERRTYPE_ROLE_REQUEST_FAILED 11 /* Controller role request failed */
528#define OFP_ERRTYPE_METER_MOD_FAILED 12 /* Error in meter */
529#define OFP_ERRTYPE_TABLE_FEATURES_FAILED 13 /* Setting table features failed */
530#define OFP_ERRTYPE_EXPERIMENTER 0xffff /* Experimenter error message */
531
532/* HELLO error codes */
533#define OFP_ERRHELLO_INCOMPATIBLE 0 /* No compatible version */
534#define OFP_ERRHELLO_EPERM 1 /* Permissions error */
535
536/* REQUEST error codes */
537#define OFP_ERRREQ_VERSION 0 /* Version not supported */
538#define OFP_ERRREQ_TYPE 1 /* Type not supported */
539#define OFP_ERRREQ_MULTIPART 2 /* Multipart type not supported */
540#define OFP_ERRREQ_EXPERIMENTER 3 /* Experimenter id not supported */
541#define OFP_ERRREQ_EXP_TYPE 4 /* Experimenter type not supported */
542#define OFP_ERRREQ_EPERM 5 /* Permission error */
543#define OFP_ERRREQ_BAD_LEN 6 /* Wrong request length for type */
544#define OFP_ERRREQ_BUFFER_EMPTY 7 /* Specified buffer has already been used */
545#define OFP_ERRREQ_BUFFER_UNKNOWN 8 /* Specified buffer does not exist */
546#define OFP_ERRREQ_TABLE_ID 9 /* Specified table-id invalid or does not exit */
547#define OFP_ERRREQ_IS_SLAVE 10 /* Denied because controller is slave */
548#define OFP_ERRREQ_PORT 11 /* Invalid port */
549#define OFP_ERRREQ_PACKET 12 /* Invalid packet in packet-out */
550#define OFP_ERRREQ_MULTIPART_OVERFLOW 13 /* Multipart overflowed the assigned buffer */
551
552/* ACTION error codes */
553#define OFP_ERRACTION_TYPE 0 /* Unknown or unsupported action type */
554#define OFP_ERRACTION_LEN 1 /* Length problem in actions */
555#define OFP_ERRACTION_EXPERIMENTER 2 /* Unknown experimenter id specified */
556#define OFP_ERRACTION_EXP_TYPE 3 /* Unknown action for experimenter id */
557#define OFP_ERRACTION_OUT_PORT 4 /* Problem validating output port */
558#define OFP_ERRACTION_ARGUMENT 5 /* Bad action argument */
559#define OFP_ERRACTION_EPERM 6 /* Permission error */
560#define OFP_ERRACTION_TOO_MANY 7 /* Can't handle this many actions */
561#define OFP_ERRACTION_BAD_QUEUE 8 /* Problem validating output queue */
562#define OFP_ERRACTION_BAD_OUT_GROUP 9 /* Invalid group id in forward action */
563#define OFP_ERRACTION_MATCH_INCONSISTENT 10 /* Action can't apply or Set-Field failed */
564#define OFP_ERRACTION_UNSUPPORTED_ORDER 11 /* Action order is unsupported for Apply-Actions */
565#define OFP_ERRACTION_TAG 12 /* Actions uses an unsupported tag/encap */
566#define OFP_ERRACTION_SET_TYPE 13 /* Unsupported type in SET_FIELD action */
567#define OFP_ERRACTION_SET_LEN 14 /* Length problem in SET_FIELD action */
568#define OFP_ERRACTION_SET_ARGUMENT 15 /* Bad argument in SET_FIELD action */
569
570/* INSTRUCTION error codes */
571#define OFP_ERRINST_UNKNOWN_INST 0 /* Unknown instruction */
572#define OFP_ERRINST_UNSUPPORTED_INST 1 /* Switch or table does not support */
573#define OFP_ERRINST_TABLE_ID 2 /* Invalid Table-ID specified */
574#define OFP_ERRINST_UNSUPP_META 3 /* Metadata value unsupported by datapath */
575#define OFP_ERRINST_UNSUPP_META_MASK 4 /* Metadata mask value unsupported by datapath */
576#define OFP_ERRINST_BAD_EXPERIMENTER 5 /* Unknown experimenter id specified */
577#define OFP_ERRINST_BAD_EXPERIMENTER_TYPE 6 /* Unknown instruction for experimenter id */
578#define OFP_ERRINST_BAD_LEN 7 /* Length problem in instructions */
579#define OFP_ERRINST_EPERM 8 /* Permissions error */
580
581/* MATCH error codes */
582#define OFP_ERRMATCH_BAD_TYPE 0 /* Unsupported match type */
583#define OFP_ERRMATCH_BAD_LEN 1 /* Length problem in match */
584#define OFP_ERRMATCH_BAD_TAG 2 /* Match uses an unsupported tag/encap */
585#define OFP_ERRMATCH_BAD_DL_ADDR_MASK 3 /* Unsupported datalink addr mask */
586#define OFP_ERRMATCH_BAD_NW_ADDR_MASK 4 /* Unsupported network addr mask */
587#define OFP_ERRMATCH_BAD_WILDCARDS 5 /* Unsupported combination of fields */
588#define OFP_ERRMATCH_BAD_FIELD 6 /* Unsupported field type in the match */
589#define OFP_ERRMATCH_BAD_VALUE 7 /* Unsupported value in a match field */
590#define OFP_ERRMATCH_BAD_MASK 8 /* Unsupported mask specified in match */
591#define OFP_ERRMATCH_BAD_PREREQ 9 /* A prerequisite was not met */
592#define OFP_ERRMATCH_DUP_FIELD 10 /* A field type was duplicated */
593#define OFP_ERRMATCH_EPERM 11 /* Permissions error */
594
595/* FLOW MOD error codes */
596#define OFP_ERRFLOWMOD_UNKNOWN 0 /* Unknown */
597#define OFP_ERRFLOWMOD_TABLE_FULL 1 /* Table is full */
598#define OFP_ERRFLOWMOD_TABLE_ID 2 /* Invalid table id */
599#define OFP_ERRFLOWMOD_OVERLAP 3 /* Overlapping flow */
600#define OFP_ERRFLOWMOD_EPERM 4 /* Permissions error */
601#define OFP_ERRFLOWMOD_BAD_TIMEOUT 5 /* non-zero idle/hard timeout */
602#define OFP_ERRFLOWMOD_BAD_COMMAND 6 /* Unsupported or Unknown command */
603#define OFP_ERRFLOWMOD_BAD_FLAGS 7 /* Unsupported or Unknown flags */
604
605/* GROUP MOD error codes */
606#define OFP_ERRGROUPMOD_GROUP_EXISTS 0 /* Already present group */
607#define OFP_ERRGROUPMOD_INVALID_GROUP 1 /* Group specified is invalid */
608#define OFP_ERRGROUPMOD_WEIGHT_UNSUPP 2 /* Switch does not support unequal load sharing */
609#define OFP_ERRGROUPMOD_OUT_OF_GROUPS 3 /* The Group table is full */
610#define OFP_ERRGROUPMOD_OUT_OF_BUCKETS 4 /* The maximum number of action buckets */
611#define OFP_ERRGROUPMOD_CHAINING_UNSUPP 5 /* Switch does not support groups forwarding to groups */
612#define OFP_ERRGROUPMOD_WATCH_UNSUPP 6 /* This group cannot watch the watch_port */
613#define OFP_ERRGROUPMOD_LOOP 7 /* Group entry would cause a loop */
614#define OFP_ERRGROUPMOD_UNKNOWN_GROUP 8 /* MODIFY attempted to modify a non-existent group */
615#define OFP_ERRGROUPMOD_CHAINED_GROUP 9 /* Group not deleted because another group is forwarding to it */
616#define OFP_ERRGROUPMOD_BAD_TYPE 10 /* Unsupported or unknown group type */
617#define OFP_ERRGROUPMOD_BAD_COMMAND 11 /* Unsupported or unknown command */
618#define OFP_ERRGROUPMOD_BAD_BUCKET 12 /* Error in bucket */
619#define OFP_ERRGROUPMOD_BAD_WATCH 13 /* Error in watch port/group */
620#define OFP_ERRGROUPMOD_EPERM 14 /* Permission error */
621
622/* GROUP MOD message */
623#define OFP_GROUPCMD_ADD 0 /* Add group */
624#define OFP_GROUPCMD_MODIFY 1 /* Modify group */
625#define OFP_GROUPCMD_DELETE 2 /* Delete group */
626
627/* Group types */
628#define OFP_GROUP_T_ALL 0 /* All (multicast/broadcast) group */
629#define OFP_GROUP_T_SELECT 1 /* Select group */
630#define OFP_GROUP_T_INDIRECT 2 /* Indirect group */
631#define OFP_GROUP_T_FAST_FAILOVER 3 /* Fast failover group */
632
633/* Special group identifiers */
634#define OFP_GROUP_ID_MAX 0xffffff00 /* Last usable group number */
635#define OFP_GROUP_ID_ALL 0xfffffffc /* Represents all groups for delete command */
636#define OFP_GROUP_ID_ANY 0xffffffff /* Special wildcard: no group specified */
637
638struct ofp_bucket {
639 uint16_t b_len;
640 uint16_t b_weight;
641 uint32_t b_watch_port;
642 uint32_t b_watch_group;
643 uint8_t b_pad[4];
644 struct ofp_action_header b_actions[0];
645} __packed;
646
647struct ofp_group_mod {
648 struct ofp_header gm_oh;
649 uint16_t gm_command;
650 uint8_t gm_type;
651 uint8_t gm_pad;
652 uint32_t gm_group_id;
653 struct ofp_bucket gm_buckets[0];
654} __packed;
655
656struct ofp_multipart {
657 struct ofp_header mp_oh;
658 uint16_t mp_type;
659 uint16_t mp_flags;
660 uint8_t mp_pad[4];
661} __packed;
662
663#define OFP_MP_FLAG_REQ_MORE 1 /* More requests to follow */
664#define OFP_MP_FLAG_REPLY_MORE 1 /* More replies to follow */
665
666/* Multipart types */
667#define OFP_MP_T_DESC 0 /* Description of the switch */
668#define OFP_MP_T_FLOW 1 /* Individual flow statistics */
669#define OFP_MP_T_AGGREGATE 2 /* Aggregate flow statistics */
670#define OFP_MP_T_TABLE 3 /* Flow table statistics */
671#define OFP_MP_T_PORT_STATS 4 /* Port statistics */
672#define OFP_MP_T_QUEUE 5 /* Queue statistics for a port */
673#define OFP_MP_T_GROUP 6 /* Group counter statistics */
674#define OFP_MP_T_GROUP_DESC 7 /* Group description */
675#define OFP_MP_T_GROUP_FEATURES 8 /* Group features */
676#define OFP_MP_T_METER 9 /* Meter statistics */
677#define OFP_MP_T_METER_CONFIG 10 /* Meter configuration */
678#define OFP_MP_T_METER_FEATURES 11 /* Meter features */
679#define OFP_MP_T_TABLE_FEATURES 12 /* Table features */
680#define OFP_MP_T_PORT_DESC 13 /* Port description */
681#define OFP_MP_T_EXPERIMENTER 0xffff /* Experimenter extension */
682
683#define OFP_DESC_STR_LEN 256
684#define OFP_SERIAL_NUM_LEN 32
685
686struct ofp_desc {
687 char d_mfr_desc[OFP_DESC_STR_LEN];
688 char d_hw_desc[OFP_DESC_STR_LEN];
689 char d_sw_desc[OFP_DESC_STR_LEN];
690 char d_serial_num[OFP_SERIAL_NUM_LEN];
691 char d_dp_desc[OFP_DESC_STR_LEN];
692} __packed;
693
694/* Flow stats request */
695struct ofp_flow_stats_request {
696 uint8_t fsr_table_id;
697 uint8_t fsr_pad[3];
698 uint32_t fsr_out_port;
699 uint32_t fsr_out_group;
700 uint8_t fsr_pad2[4];
701 uint64_t fsr_cookie;
702 uint64_t fsr_cookie_mask;
703 struct ofp_match fsr_match;
704} __packed;
705
706/* Flow stats */
707struct ofp_flow_stats {
708 uint16_t fs_length;
709 uint8_t fs_table_id;
710 uint8_t fs_pad;
711 uint32_t fs_duration_sec;
712 uint32_t fs_duration_nsec;
713 uint16_t fs_priority;
714 uint16_t fs_idle_timeout;
715 uint16_t fs_hard_timeout;
716 uint16_t fs_flags;
717 uint8_t fs_pad2[4];
718 uint64_t fs_cookie;
719 uint64_t fs_packet_count;
720 uint64_t fs_byte_count;
721 struct ofp_match fs_match;
722} __packed;
723
724/* Aggregate flow stats request */
725struct ofp_aggregate_stats_request {
726 uint8_t asr_table_id;
727 uint8_t asr_pad[3];
728 uint32_t asr_out_port;
729 uint32_t asr_out_group;
730 uint8_t asr_pad2[4];
731 uint64_t asr_cookie;
732 uint64_t asr_cookie_mask;
733 struct ofp_match asr_match;
734} __packed;
735
736struct ofp_aggregate_stats {
737 uint64_t as_packet_count;
738 uint64_t as_byte_count;
739 uint32_t as_flow_count;
740 uint8_t as_pad[4];
741} __packed;
742
743/* Special table id */
744#define OFP_TABLE_ID_MAX 0xfe /* Last usable table */
745#define OFP_TABLE_ID_ALL 0xff /* Wildcard table */
746
747struct ofp_table_stats {
748 uint8_t ts_table_id;
749 uint8_t ts_pad[3];
750 uint32_t ts_active_count;
751 uint64_t ts_lookup_count;
752 uint64_t ts_matched_count;
753} __packed;
754
755/* Table features */
756#define OFP_TABLE_FEATPROP_INSTRUCTION 0 /* Instruction property */
757#define OFP_TABLE_FEATPROP_INSTRUCTION_MISS 1 /* Instruction for table-miss */
758#define OFP_TABLE_FEATPROP_NEXT_TABLES 2 /* Next table property */
759#define OFP_TABLE_FEATPROP_NEXT_TABLES_MISS 3 /* Next table for table-miss */
760#define OFP_TABLE_FEATPROP_WRITE_ACTIONS 4 /* Write actions property */
761#define OFP_TABLE_FEATPROP_WRITE_ACTIONS_MISS 5 /* Write actions for table-miss */
762#define OFP_TABLE_FEATPROP_APPLY_ACTIONS 6 /* Apply actions property */
763#define OFP_TABLE_FEATPROP_APPLY_ACTIONS_MISS 7 /* Apply actions for table-miss */
764#define OFP_TABLE_FEATPROP_MATCH 8 /* Match property */
765#define OFP_TABLE_FEATPROP_WILDCARDS 10 /* Wildcards property */
766#define OFP_TABLE_FEATPROP_WRITE_SETFIELD 12 /* Write set-field property */
767#define OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS 13 /* Write set-field for table-miss */
768#define OFP_TABLE_FEATPROP_APPLY_SETFIELD 14 /* Apply set-field property */
769#define OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS 15 /* Apply set-field for table-miss */
770#define OFP_TABLE_FEATPROP_EXPERIMENTER 0xfffe /* Experimenter property */
771#define OFP_TABLE_FEATPROP_EXPERIMENTER_MISS 0xffff /* Experimenter for table-miss */
772
773#define OFP_TABLE_MAX_NAME_LEN 32
774
775struct ofp_table_features {
776 uint16_t tf_length;
777 uint8_t tf_tableid;
778 uint8_t tf_pad[5];
779 char tf_name[OFP_TABLE_MAX_NAME_LEN];
780 uint64_t tf_metadata_match;
781 uint64_t tf_metadata_write;
782 uint32_t tf_config;
783 uint32_t tf_max_entries;
784} __packed;
785
786struct ofp_table_feature_property {
787 uint16_t tp_type;
788 uint16_t tp_length;
789} __packed;
790
791struct ofp_table_feature_property_instruction {
792 uint16_t tpi_type;
793 uint16_t tpi_length;
794 struct ofp_instruction tpi_instructions[0];
795} __packed;
796
797struct ofp_table_feature_property_next_tables {
798 uint16_t tpnt_type;
799 uint16_t tpnt_length;
800 uint8_t tpnt_tables[0];
801} __packed;
802
803struct ofp_table_feature_property_actions {
804 uint16_t tpa_type;
805 uint16_t tpa_length;
806 struct ofp_action_header tpa_actions[0];
807} __packed;
808
809struct ofp_table_feature_property_oxm {
810 uint16_t tpoxm_type;
811 uint16_t tpoxm_length;
812 uint32_t tpoxm_oxm[0];
813} __packed;
814
815struct ofp_table_feature_property_experimenter {
816 uint16_t tfpexp_type;
817 uint16_t tfpexp_length;
818 uint32_t tfpexp_experimenter;
819 uint32_t tfpexp_exp_type;
820 uint32_t tfpexp_experimenter_data[0];
821} __packed;
822
823struct ofp_port_stats {
824 uint32_t pt_port_no;
825 uint8_t pt_pad[4];
826 uint64_t pt_rx_packets;
827 uint64_t pt_tx_packets;
828 uint64_t pt_rx_bytes;
829 uint64_t pt_tx_bytes;
830 uint64_t pt_rx_dropped;
831 uint64_t pt_tx_dropped;
832 uint64_t pt_rx_errors;
833 uint64_t pt_tx_errors;
834 uint64_t pt_rx_frame_err;
835 uint64_t pt_rx_over_err;
836 uint64_t pt_rx_crc_err;
837 uint64_t pt_collision;
838 uint32_t pt_duration_sec;
839 uint32_t pt_duration_nsec;
840} __packed;
841
842/* Groups stats request */
843struct ofp_group_stats_request {
844 uint32_t gsr_group_id;
845 uint8_t gsr_pad[4];
846} __packed;
847
848struct ofp_bucket_counter {
849 uint64_t gs_packet_count;
850 uint64_t gs_byte_count;
851} __packed;
852
853/* Group stats */
854struct ofp_group_stats {
855 uint16_t gs_length;
856 uint8_t gs_pad[2];
857 uint32_t gs_group_id;
858 uint32_t gs_ref_count;
859 uint8_t gs_pad2[4];
860 uint64_t gs_packet_count;
861 uint64_t gs_byte_count;
862 uint32_t gs_duration_sec;
863 uint32_t gs_duration_nsec;
864 struct ofp_bucket_counter gs_bucket_stats[0];
865} __packed;
866
867/* Group description */
868struct ofp_group_desc {
869 uint16_t gd_length;
870 uint8_t gd_type;
871 uint8_t gd_pad;
872 uint32_t gd_group_id;
873 struct ofp_bucket gd_buckets[0];
874} __packed;
875
876/*
877 * Implementation-specific definitions that are not part of the spec
878 */
879
880/* OpenFlow finite state machine */
881enum ofp_state {
882 OFP_STATE_CLOSED,
883 OFP_STATE_HELLO_WAIT,
884 OFP_STATE_FEATURE_WAIT,
885 OFP_STATE_ESTABLISHED
886};
887
888/* Used by the bpf for DLT_OPENFLOW */
889struct dlt_openflow_hdr {
890 uint32_t of_direction;
891 uint64_t of_datapath_id;
892} __packed;
893
894#define DLT_OPENFLOW_TO_SWITCH 1
895#define DLT_OPENFLOW_TO_CONTROLLER 2
896
897#endif /* _NET_OFP_H_ */