blob: 2314d670303fa045854e5e6d1a2fcf75f1a83972 [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001:: # Copyright 2013, Big Switch Networks, Inc.
2:: #
3:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4:: # the following special exception:
5:: #
6:: # LOXI Exception
7:: #
8:: # As a special exception to the terms of the EPL, you may distribute libraries
9:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
11:: # from the LoxiGen Libraries and the notice provided below is (i) included in
12:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13:: # documentation for the LoxiGen Libraries, if distributed in binary form.
14:: #
15:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16:: #
17:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18:: # a copy of the EPL at:
19:: #
20:: # http://www.eclipse.org/legal/epl-v10.html
21:: #
22:: # Unless required by applicable law or agreed to in writing, software
23:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25:: # EPL for the specific language governing permissions and limitations
26:: # under the EPL.
27::
Rich Laned983aa52013-06-13 11:48:37 -070028:: include('_copyright.c')
Rich Lanea06d0c32013-03-25 08:52:03 -070029
30/****************************************************************
31 *
32 * Functions related to mapping wire values to object types
33 * and lengths
34 *
35 ****************************************************************/
36
37#include <loci/loci.h>
38#include <loci/of_message.h>
39
Rich Laneef7b9942013-11-18 16:29:28 -080040#define OF_INSTRUCTION_EXPERIMENTER_ID_OFFSET 4
41#define OF_INSTRUCTION_EXPERIMENTER_SUBTYPE_OFFSET 8
42
Rich Lanea06d0c32013-03-25 08:52:03 -070043/****************************************************************
44 * Top level OpenFlow message length functions
45 ****************************************************************/
46
47/**
48 * Get the length of a message object as reported on the wire
49 * @param obj The object to check
50 * @param bytes (out) Where the length is stored
51 * @returns OF_ERROR_ code
52 */
53void
54of_object_message_wire_length_get(of_object_t *obj, int *bytes)
55{
Rich Laneed79e0d2013-03-26 14:30:31 -070056 ASSERT(OF_OBJECT_TO_WBUF(obj) != NULL);
Rich Lanea06d0c32013-03-25 08:52:03 -070057 // ASSERT(obj is message)
58 *bytes = of_message_length_get(OF_OBJECT_TO_MESSAGE(obj));
59}
60
61/**
62 * Set the length of a message object as reported on the wire
63 * @param obj The object to check
64 * @param bytes The new length of the object
65 * @returns OF_ERROR_ code
66 */
67void
68of_object_message_wire_length_set(of_object_t *obj, int bytes)
69{
Rich Laneed79e0d2013-03-26 14:30:31 -070070 ASSERT(OF_OBJECT_TO_WBUF(obj) != NULL);
Rich Lanea06d0c32013-03-25 08:52:03 -070071 // ASSERT(obj is message)
72 of_message_length_set(OF_OBJECT_TO_MESSAGE(obj), bytes);
73}
74
75/****************************************************************
76 * TLV16 type/length functions
77 ****************************************************************/
78
79/**
80 * Many objects are TLVs and use uint16 for the type and length values
81 * stored on the wire at the beginning of the buffer.
82 */
83#define TLV16_WIRE_TYPE_OFFSET 0
84#define TLV16_WIRE_LENGTH_OFFSET 2
85
86/**
87 * Get the length field from the wire for a standard TLV
88 * object that uses uint16 for both type and length.
89 * @param obj The object being referenced
90 * @param bytes (out) Where to store the length
91 */
92
93void
94of_tlv16_wire_length_get(of_object_t *obj, int *bytes)
95{
96 uint16_t val16;
97 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
98 ASSERT(wbuf != NULL);
99
100 of_wire_buffer_u16_get(wbuf,
101 OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_LENGTH_OFFSET), &val16);
102 *bytes = val16;
103}
104
105/**
106 * Set the length field in the wire buffer for a standard TLV
107 * object that uses uint16 for both type and length.
108 * @param obj The object being referenced
109 * @param bytes The length value to use
110 */
111
112void
113of_tlv16_wire_length_set(of_object_t *obj, int bytes)
114{
115 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
116 ASSERT(wbuf != NULL);
117
118 of_wire_buffer_u16_set(wbuf,
119 OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_LENGTH_OFFSET), bytes);
120}
121
122/**
123 * Get the type field from the wire for a standard TLV object that uses
124 * uint16 for both type and length.
125 * @param obj The object being referenced
126 * @param wire_type (out) Where to store the type
127 */
128
129static void
130of_tlv16_wire_type_get(of_object_t *obj, int *wire_type)
131{
132 uint16_t val16;
133 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
134
135 of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj,
136 TLV16_WIRE_TYPE_OFFSET), &val16);
137
138 *wire_type = val16;
139}
140
141/**
142 * Set the object ID based on the wire buffer for any TLV object
143 * @param obj The object being referenced
144 * @param id The ID value representing what should be stored.
145 */
146
147void
148of_tlv16_wire_object_id_set(of_object_t *obj, of_object_id_t id)
149{
150 int wire_type;
151 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
152 ASSERT(wbuf != NULL);
153
154 wire_type = of_object_to_type_map[obj->version][id];
155 ASSERT(wire_type >= 0);
156
157 of_wire_buffer_u16_set(wbuf,
158 OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_TYPE_OFFSET), wire_type);
159
160 if (wire_type == OF_EXPERIMENTER_TYPE) {
161 of_extension_object_id_set(obj, id);
162 }
163}
164
165/**
166 * Get the object ID of an extended action
167 * @param obj The object being referenced
168 * @param id Where to store the object ID
169 * @fixme: This should be auto generated
170 *
171 * If unable to map to known extension, set id to generic "experimenter"
172 */
173
174#define OF_ACTION_EXPERIMENTER_ID_OFFSET 4
175#define OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET 8
176
177
178static void
179extension_action_object_id_get(of_object_t *obj, of_object_id_t *id)
180{
181 uint32_t exp_id;
182 uint8_t *buf;
183
184 *id = OF_ACTION_EXPERIMENTER;
185
186 buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
187
188 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
189
190 switch (exp_id) {
191 case OF_EXPERIMENTER_ID_BSN: {
192 uint32_t subtype;
193 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
194 switch (subtype) {
195 case 1: *id = OF_ACTION_BSN_MIRROR; break;
196 case 2: *id = OF_ACTION_BSN_SET_TUNNEL_DST; break;
197 }
198 break;
199 }
200 case OF_EXPERIMENTER_ID_NICIRA: {
201 uint16_t subtype;
202 buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
203 switch (subtype) {
204 case 18: *id = OF_ACTION_NICIRA_DEC_TTL; break;
205 }
206 break;
207 }
208 }
209}
210
211/**
212 * Set wire data for extension objects, not messages.
Rich Lanea06d0c32013-03-25 08:52:03 -0700213 */
214
215void
216of_extension_object_id_set(of_object_t *obj, of_object_id_t id)
217{
218 uint8_t *buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
219
220 switch (id) {
221 case OF_ACTION_BSN_MIRROR:
222 case OF_ACTION_ID_BSN_MIRROR:
223 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
224 OF_EXPERIMENTER_ID_BSN);
225 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 1);
226 break;
227 case OF_ACTION_BSN_SET_TUNNEL_DST:
228 case OF_ACTION_ID_BSN_SET_TUNNEL_DST:
229 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
230 OF_EXPERIMENTER_ID_BSN);
231 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 2);
232 break;
233 case OF_ACTION_NICIRA_DEC_TTL:
234 case OF_ACTION_ID_NICIRA_DEC_TTL:
235 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
236 OF_EXPERIMENTER_ID_NICIRA);
237 buf_u16_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 18);
238 break;
Rich Laneef7b9942013-11-18 16:29:28 -0800239 case OF_INSTRUCTION_BSN_DISABLE_SRC_MAC_CHECK:
240 buf_u32_set(buf + OF_INSTRUCTION_EXPERIMENTER_ID_OFFSET,
241 OF_EXPERIMENTER_ID_BSN);
242 buf_u32_set(buf + OF_INSTRUCTION_EXPERIMENTER_SUBTYPE_OFFSET, 0);
243 break;
Rich Lanea06d0c32013-03-25 08:52:03 -0700244 default:
245 break;
246 }
247}
248
249/**
250 * Get the object ID of an extended action
251 * @param obj The object being referenced
252 * @param id Where to store the object ID
253 * @fixme: This should be auto generated
254 *
255 * If unable to map to known extension, set id to generic "experimenter"
256 */
257
258static void
259extension_action_id_object_id_get(of_object_t *obj, of_object_id_t *id)
260{
261 uint32_t exp_id;
262 uint8_t *buf;
263
264 *id = OF_ACTION_ID_EXPERIMENTER;
265
266 buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
267
268 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
269
270 switch (exp_id) {
271 case OF_EXPERIMENTER_ID_BSN: {
272 uint32_t subtype;
273 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
274 switch (subtype) {
275 case 1: *id = OF_ACTION_ID_BSN_MIRROR; break;
276 case 2: *id = OF_ACTION_ID_BSN_SET_TUNNEL_DST; break;
277 }
278 break;
279 }
280 case OF_EXPERIMENTER_ID_NICIRA: {
281 uint16_t subtype;
282 buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
283 switch (subtype) {
284 case 18: *id = OF_ACTION_ID_NICIRA_DEC_TTL; break;
285 }
286 break;
287 }
288 }
289}
290
291
292/**
293 * Get the object ID based on the wire buffer for an action object
294 * @param obj The object being referenced
295 * @param id Where to store the object ID
296 */
297
298
299void
300of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
301{
302 int wire_type;
303
304 of_tlv16_wire_type_get(obj, &wire_type);
305 if (wire_type == OF_EXPERIMENTER_TYPE) {
306 extension_action_object_id_get(obj, id);
307 return;
308 }
309
310 ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ITEM_COUNT);
311
312 *id = of_action_type_to_id[obj->version][wire_type];
313 ASSERT(*id != OF_OBJECT_INVALID);
314}
315
316/**
317 * Get the object ID based on the wire buffer for an action ID object
318 * @param obj The object being referenced
319 * @param id Where to store the object ID
320 */
321
322
323void
324of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
325{
326 int wire_type;
327
328 of_tlv16_wire_type_get(obj, &wire_type);
329 if (wire_type == OF_EXPERIMENTER_TYPE) {
330 extension_action_id_object_id_get(obj, id);
331 return;
332 }
333
334 ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ID_ITEM_COUNT);
335
336 *id = of_action_id_type_to_id[obj->version][wire_type];
337 ASSERT(*id != OF_OBJECT_INVALID);
338}
339
340/**
341 * @fixme to do when we have instruction extensions
342 * See extension_action above
343 */
344
345static int
346extension_instruction_object_id_get(of_object_t *obj, of_object_id_t *id)
347{
Rich Laneef7b9942013-11-18 16:29:28 -0800348 uint32_t exp_id;
349 uint8_t *buf;
Rich Lanea06d0c32013-03-25 08:52:03 -0700350
351 *id = OF_INSTRUCTION_EXPERIMENTER;
352
Rich Laneef7b9942013-11-18 16:29:28 -0800353 buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
354
355 buf_u32_get(buf + OF_INSTRUCTION_EXPERIMENTER_ID_OFFSET, &exp_id);
356
357 switch (exp_id) {
358 case OF_EXPERIMENTER_ID_BSN: {
359 uint32_t subtype;
360 buf_u32_get(buf + OF_INSTRUCTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
361 switch (subtype) {
362 case 0: *id = OF_INSTRUCTION_BSN_DISABLE_SRC_MAC_CHECK; break;
363 }
364 break;
365 }
366 }
367
Rich Lanea06d0c32013-03-25 08:52:03 -0700368 return OF_ERROR_NONE;
369}
370
371/**
372 * Get the object ID based on the wire buffer for an instruction object
373 * @param obj The object being referenced
374 * @param id Where to store the object ID
375 */
376
377void
378of_instruction_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
379{
380 int wire_type;
381
382 of_tlv16_wire_type_get(obj, &wire_type);
383 if (wire_type == OF_EXPERIMENTER_TYPE) {
384 extension_instruction_object_id_get(obj, id);
385 return;
386 }
387
388 ASSERT(wire_type >= 0 && wire_type < OF_INSTRUCTION_ITEM_COUNT);
389
390 *id = of_instruction_type_to_id[obj->version][wire_type];
391 ASSERT(*id != OF_OBJECT_INVALID);
392}
393
394
395/**
396 * @fixme to do when we have queue_prop extensions
397 * See extension_action above
398 */
399
400static void
401extension_queue_prop_object_id_get(of_object_t *obj, of_object_id_t *id)
402{
403 (void)obj;
404
405 *id = OF_QUEUE_PROP_EXPERIMENTER;
406}
407
408/**
409 * Get the object ID based on the wire buffer for an queue_prop object
410 * @param obj The object being referenced
411 * @param id Where to store the object ID
412 */
413
414void
415of_queue_prop_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
416{
417 int wire_type;
418
419 of_tlv16_wire_type_get(obj, &wire_type);
420 if (wire_type == OF_EXPERIMENTER_TYPE) {
421 extension_queue_prop_object_id_get(obj, id);
422 return;
423 }
424
425 ASSERT(wire_type >= 0 && wire_type < OF_QUEUE_PROP_ITEM_COUNT);
426
427 *id = of_queue_prop_type_to_id[obj->version][wire_type];
428 ASSERT(*id != OF_OBJECT_INVALID);
429}
430
431
432/**
433 * @fixme to do when we have table_feature_prop extensions
434 * See extension_action above
435 */
436
437static void
438extension_table_feature_prop_object_id_get(of_object_t *obj, of_object_id_t *id)
439{
440 (void)obj;
441
442 *id = OF_TABLE_FEATURE_PROP_EXPERIMENTER;
443}
444
445/**
446 * Table feature property object ID determination
447 *
448 * @param obj The object being referenced
449 * @param id Where to store the object ID
450 */
451
452void
453of_table_feature_prop_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
454{
455 int wire_type;
456
457 of_tlv16_wire_type_get(obj, &wire_type);
458 if (wire_type == OF_EXPERIMENTER_TYPE) {
459 extension_table_feature_prop_object_id_get(obj, id);
460 return;
461 }
462
463 ASSERT(wire_type >= 0 && wire_type < OF_TABLE_FEATURE_PROP_ITEM_COUNT);
464
465 *id = of_table_feature_prop_type_to_id[obj->version][wire_type];
466 ASSERT(*id != OF_OBJECT_INVALID);
467}
468
469/**
470 * Get the object ID based on the wire buffer for meter_band object
471 * @param obj The object being referenced
472 * @param id Where to store the object ID
473 */
474
475void
476of_meter_band_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
477{
478 int wire_type;
479
480 of_tlv16_wire_type_get(obj, &wire_type);
481 if (wire_type == OF_EXPERIMENTER_TYPE) {
482 *id = OF_METER_BAND_EXPERIMENTER;
483 return;
484 }
485
486 ASSERT(wire_type >= 0 && wire_type < OF_METER_BAND_ITEM_COUNT);
487
488 *id = of_meter_band_type_to_id[obj->version][wire_type];
489 ASSERT(*id != OF_OBJECT_INVALID);
490}
491
492/**
493 * Get the object ID based on the wire buffer for a hello_elem object
494 * @param obj The object being referenced
495 * @param id Where to store the object ID
496 */
497
498void
499of_hello_elem_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
500{
501 int wire_type;
502
503 of_tlv16_wire_type_get(obj, &wire_type);
504 ASSERT(wire_type >= 0 && wire_type < OF_HELLO_ELEM_ITEM_COUNT);
505 *id = of_hello_elem_type_to_id[obj->version][wire_type];
506 ASSERT(*id != OF_OBJECT_INVALID);
507}
508
509/****************************************************************
510 * OXM type/length functions.
511 ****************************************************************/
512
513/* Where does the OXM type-length header lie in the buffer */
514#define OXM_HDR_OFFSET 0
515
516/**
517 * Get the OXM header (type-length fields) from the wire buffer
518 * associated with an OXM object
519 *
520 * Will return if error; set hdr to the OXM header
521 */
522
523#define _GET_OXM_TYPE_LEN(obj, tl_p, wbuf) do { \
524 wbuf = OF_OBJECT_TO_WBUF(obj); \
525 ASSERT(wbuf != NULL); \
526 of_wire_buffer_u32_get(wbuf, \
527 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), (tl_p)); \
528 } while (0)
529
530#define _SET_OXM_TYPE_LEN(obj, tl_p, wbuf) do { \
531 wbuf = OF_OBJECT_TO_WBUF(obj); \
532 ASSERT(wbuf != NULL); \
533 of_wire_buffer_u32_set(wbuf, \
534 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), (tl_p)); \
535 } while (0)
536
537/**
538 * Get the length of an OXM object from the wire buffer
539 * @param obj The object whose wire buffer is an OXM type
540 * @param bytes (out) Where length is stored
541 */
542
543void
544of_oxm_wire_length_get(of_object_t *obj, int *bytes)
545{
546 uint32_t type_len;
547 of_wire_buffer_t *wbuf;
548
549 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
550 *bytes = OF_OXM_LENGTH_GET(type_len);
551}
552
553/**
554 * Set the length of an OXM object in the wire buffer
555 * @param obj The object whose wire buffer is an OXM type
556 * @param bytes Value to store in wire buffer
557 */
558
559void
560of_oxm_wire_length_set(of_object_t *obj, int bytes)
561{
562 uint32_t type_len;
563 of_wire_buffer_t *wbuf;
564
565 ASSERT(bytes >= 0 && bytes < 256);
566
567 /* Read-modify-write */
568 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
569 OF_OXM_LENGTH_SET(type_len, bytes);
570 of_wire_buffer_u32_set(wbuf,
571 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), type_len);
572}
573
574/**
575 * Get the object ID of an OXM object based on the wire buffer type
576 * @param obj The object whose wire buffer is an OXM type
577 * @param id (out) Where the ID is stored
578 */
579
580void
581of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
582{
583 uint32_t type_len;
Rich Lanea06d0c32013-03-25 08:52:03 -0700584 of_wire_buffer_t *wbuf;
585
586 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
Rich Laned8d29c92013-09-24 13:46:42 -0700587 *id = of_oxm_to_object_id(type_len, obj->version);
Rich Lanea06d0c32013-03-25 08:52:03 -0700588}
589
590/**
591 * Set the wire type of an OXM object based on the object ID passed
592 * @param obj The object whose wire buffer is an OXM type
593 * @param id The object ID mapped to an OXM wire type which is stored
594 */
595
596void
597of_oxm_wire_object_id_set(of_object_t *obj, of_object_id_t id)
598{
599 uint32_t type_len;
600 int wire_type;
601 of_wire_buffer_t *wbuf;
602
603 ASSERT(OF_OXM_VALID_ID(id));
604
605 /* Read-modify-write */
606 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
Rich Laned8d29c92013-09-24 13:46:42 -0700607
608 switch (id) {
609 case OF_OXM_BSN_IN_PORTS_128:
610 type_len = 0x00030000 | (type_len & 0xff);
611 break;
612 case OF_OXM_BSN_IN_PORTS_128_MASKED:
613 type_len = 0x00030100 | (type_len & 0xff);
614 break;
Rich Lane61718362013-10-24 16:59:42 -0700615 case OF_OXM_BSN_LAG_ID:
616 type_len = 0x00030200 | (type_len & 0xff);
617 break;
618 case OF_OXM_BSN_LAG_ID_MASKED:
619 type_len = 0x00030300 | (type_len & 0xff);
620 break;
Rich Laneeb21c4f2013-10-28 17:34:41 -0700621 case OF_OXM_BSN_VRF:
622 type_len = 0x00030400 | (type_len & 0xff);
623 break;
624 case OF_OXM_BSN_VRF_MASKED:
625 type_len = 0x00030500 | (type_len & 0xff);
626 break;
627 case OF_OXM_BSN_GLOBAL_VRF_ALLOWED:
628 type_len = 0x00030600 | (type_len & 0xff);
629 break;
630 case OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED:
631 type_len = 0x00030700 | (type_len & 0xff);
632 break;
633 case OF_OXM_BSN_L3_INTERFACE_CLASS_ID:
634 type_len = 0x00030800 | (type_len & 0xff);
635 break;
636 case OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED:
637 type_len = 0x00030900 | (type_len & 0xff);
638 break;
639 case OF_OXM_BSN_L3_SRC_CLASS_ID:
640 type_len = 0x00030a00 | (type_len & 0xff);
641 break;
642 case OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED:
643 type_len = 0x00030b00 | (type_len & 0xff);
644 break;
645 case OF_OXM_BSN_L3_DST_CLASS_ID:
646 type_len = 0x00030c00 | (type_len & 0xff);
647 break;
648 case OF_OXM_BSN_L3_DST_CLASS_ID_MASKED:
649 type_len = 0x00030d00 | (type_len & 0xff);
650 break;
Rich Laned8d29c92013-09-24 13:46:42 -0700651 default:
652 wire_type = of_object_to_wire_type(id, obj->version);
653 ASSERT(wire_type >= 0);
654 type_len = 0x80000000 | (wire_type << 8) | (type_len & 0xff);
655 break;
656 }
657
Rich Lanea06d0c32013-03-25 08:52:03 -0700658 of_wire_buffer_u32_set(wbuf,
659 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), type_len);
660}
661
662
663
664#define OF_U16_LEN_LENGTH_OFFSET 0
665
666/**
667 * Get the wire length for an object with a uint16 length as first member
668 * @param obj The object being referenced
669 * @param bytes Pointer to location to store length
670 */
671void
672of_u16_len_wire_length_get(of_object_t *obj, int *bytes)
673{
674 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
675 uint16_t u16;
676
677 ASSERT(wbuf != NULL);
678
679 of_wire_buffer_u16_get(wbuf,
680 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_U16_LEN_LENGTH_OFFSET),
681 &u16);
682
683 *bytes = u16;
684}
685
686/**
687 * Set the wire length for an object with a uint16 length as first member
688 * @param obj The object being referenced
689 * @param bytes The length of the object
690 */
691
692void
693of_u16_len_wire_length_set(of_object_t *obj, int bytes)
694{
695 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
696 ASSERT(wbuf != NULL);
697
698 /* ASSERT(obj is u16-len entry) */
699
700 of_wire_buffer_u16_set(wbuf,
701 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_U16_LEN_LENGTH_OFFSET),
702 bytes);
703}
704
705
706#define OF_PACKET_QUEUE_LENGTH_OFFSET(ver) \
707 (((ver) >= OF_VERSION_1_2) ? 8 : 4)
708
709/**
710 * Get the wire length for a packet queue object
711 * @param obj The object being referenced
712 * @param bytes Pointer to location to store length
713 *
714 * The length is a uint16 at the offset indicated above
715 */
716void
717of_packet_queue_wire_length_get(of_object_t *obj, int *bytes)
718{
719 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
720 uint16_t u16;
721 int offset;
722
723 ASSERT(wbuf != NULL);
724
725 /* ASSERT(obj is packet queue obj) */
726 offset = OF_PACKET_QUEUE_LENGTH_OFFSET(obj->version);
727 of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, offset),
728 &u16);
729
730 *bytes = u16;
731}
732
733/**
734 * Set the wire length for a 1.2 packet queue object
735 * @param obj The object being referenced
736 * @param bytes The length of the object
737 *
738 * The length is a uint16 at the offset indicated above
739 */
740
741void
742of_packet_queue_wire_length_set(of_object_t *obj, int bytes)
743{
744 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
745 int offset;
746
747 ASSERT(wbuf != NULL);
748
749 /* ASSERT(obj is packet queue obj) */
750 offset = OF_PACKET_QUEUE_LENGTH_OFFSET(obj->version);
751 of_wire_buffer_u16_set(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, offset),
752 bytes);
753}
754
755/**
756 * Get the wire length for a meter band stats list
757 * @param obj The object being referenced
758 * @param bytes Pointer to location to store length
759 *
760 * Must a meter_stats object as a parent
761 */
762
763void
764of_list_meter_band_stats_wire_length_get(of_object_t *obj, int *bytes)
765{
766 ASSERT(obj->parent != NULL);
767 ASSERT(obj->parent->object_id == OF_METER_STATS);
768
769 /* We're counting on the parent being properly initialized already.
770 * The length is stored in a uint16 at offset 4 of the parent.
771 */
772 *bytes = obj->parent->length - OF_OBJECT_FIXED_LENGTH(obj->parent);
773}
774
775#define OF_METER_STATS_LENGTH_OFFSET 4
776
777/**
778 * Get/set the wire length for a meter stats object
779 * @param obj The object being referenced
780 * @param bytes Pointer to location to store length
781 *
782 * It's almost a TLV....
783 */
784
785void
786of_meter_stats_wire_length_get(of_object_t *obj, int *bytes)
787{
788 uint16_t val16;
789 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
790 ASSERT(wbuf != NULL);
791 of_wire_buffer_u16_get(wbuf,
792 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET),
793 &val16);
794 *bytes = val16;
795}
796
797void
798of_meter_stats_wire_length_set(of_object_t *obj, int bytes)
799{
800 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
801 ASSERT(wbuf != NULL);
802
803 of_wire_buffer_u16_set(wbuf,
804 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET), bytes);
805}
806
807/*
808 * Non-message extension push wire values
809 */
810
811int
812of_extension_object_wire_push(of_object_t *obj)
813{
814 of_action_bsn_mirror_t *action_mirror;
815 of_action_id_bsn_mirror_t *action_id_mirror;
816 of_action_bsn_set_tunnel_dst_t *action_set_tunnel_dst;
817 of_action_id_bsn_set_tunnel_dst_t *action_id_set_tunnel_dst;
818 of_action_nicira_dec_ttl_t *action_nicira_dec_ttl;
819 of_action_id_nicira_dec_ttl_t *action_id_nicira_dec_ttl;
820
821 /* Push exp type, subtype */
822 switch (obj->object_id) {
823 case OF_ACTION_BSN_MIRROR:
824 action_mirror = (of_action_bsn_mirror_t *)obj;
825 of_action_bsn_mirror_experimenter_set(action_mirror,
826 OF_EXPERIMENTER_ID_BSN);
827 of_action_bsn_mirror_subtype_set(action_mirror, 1);
828 break;
829 case OF_ACTION_ID_BSN_MIRROR:
830 action_id_mirror = (of_action_id_bsn_mirror_t *)obj;
831 of_action_id_bsn_mirror_experimenter_set(action_id_mirror,
832 OF_EXPERIMENTER_ID_BSN);
833 of_action_id_bsn_mirror_subtype_set(action_id_mirror, 1);
834 break;
835 case OF_ACTION_BSN_SET_TUNNEL_DST:
836 action_set_tunnel_dst = (of_action_bsn_set_tunnel_dst_t *)obj;
837 of_action_bsn_set_tunnel_dst_experimenter_set(action_set_tunnel_dst,
838 OF_EXPERIMENTER_ID_BSN);
839 of_action_bsn_set_tunnel_dst_subtype_set(action_set_tunnel_dst, 2);
840 break;
841 case OF_ACTION_ID_BSN_SET_TUNNEL_DST:
842 action_id_set_tunnel_dst = (of_action_id_bsn_set_tunnel_dst_t *)obj;
843 of_action_id_bsn_set_tunnel_dst_experimenter_set(action_id_set_tunnel_dst,
844 OF_EXPERIMENTER_ID_BSN);
845 of_action_id_bsn_set_tunnel_dst_subtype_set(action_id_set_tunnel_dst, 2);
846 break;
847 case OF_ACTION_NICIRA_DEC_TTL:
848 action_nicira_dec_ttl = (of_action_nicira_dec_ttl_t *)obj;
849 of_action_nicira_dec_ttl_experimenter_set(action_nicira_dec_ttl,
850 OF_EXPERIMENTER_ID_NICIRA);
851 of_action_nicira_dec_ttl_subtype_set(action_nicira_dec_ttl, 18);
852 break;
853 case OF_ACTION_ID_NICIRA_DEC_TTL:
854 action_id_nicira_dec_ttl = (of_action_id_nicira_dec_ttl_t *)obj;
855 of_action_id_nicira_dec_ttl_experimenter_set(action_id_nicira_dec_ttl,
856 OF_EXPERIMENTER_ID_NICIRA);
857 of_action_id_nicira_dec_ttl_subtype_set(action_id_nicira_dec_ttl, 18);
858 break;
859 default:
860 break;
861 }
862
863 return OF_ERROR_NONE;
864}
Rich Lane353a79f2013-11-13 10:39:56 -0800865
866int
867of_experimenter_stats_request_to_object_id(uint32_t experimenter, uint32_t subtype, int ver)
868{
869 switch (experimenter) {
870 case OF_EXPERIMENTER_ID_BSN:
871 switch (subtype) {
872 case 1: return OF_BSN_LACP_STATS_REQUEST;
Wilson Ng45386fb2013-12-03 13:46:42 -0800873 case 6: return OF_BSN_SWITCH_PIPELINE_STATS_REQUEST;
xinwu54ceaca2013-12-04 17:02:27 -0800874 case 8: return OF_BSN_PORT_COUNTER_STATS_REQUEST;
875 case 9: return OF_BSN_VLAN_COUNTER_STATS_REQUEST;
Rich Lane353a79f2013-11-13 10:39:56 -0800876 }
877 }
878 return OF_OBJECT_INVALID;
879}
880
881int
882of_experimenter_stats_reply_to_object_id(uint32_t experimenter, uint32_t subtype, int ver)
883{
884 switch (experimenter) {
885 case OF_EXPERIMENTER_ID_BSN:
886 switch (subtype) {
887 case 1: return OF_BSN_LACP_STATS_REPLY;
Wilson Ng45386fb2013-12-03 13:46:42 -0800888 case 6: return OF_BSN_SWITCH_PIPELINE_STATS_REPLY;
xinwu54ceaca2013-12-04 17:02:27 -0800889 case 8: return OF_BSN_PORT_COUNTER_STATS_REPLY;
890 case 9: return OF_BSN_VLAN_COUNTER_STATS_REPLY;
Rich Lane353a79f2013-11-13 10:39:56 -0800891 }
892 }
893 return OF_OBJECT_INVALID;
894}