blob: 67c353555baa98cc35b3570671dbe692c9c47eb2 [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
40/****************************************************************
41 * Top level OpenFlow message length functions
42 ****************************************************************/
43
44/**
45 * Get the length of a message object as reported on the wire
46 * @param obj The object to check
47 * @param bytes (out) Where the length is stored
48 * @returns OF_ERROR_ code
49 */
50void
51of_object_message_wire_length_get(of_object_t *obj, int *bytes)
52{
Rich Laneed79e0d2013-03-26 14:30:31 -070053 ASSERT(OF_OBJECT_TO_WBUF(obj) != NULL);
Rich Lanea06d0c32013-03-25 08:52:03 -070054 // ASSERT(obj is message)
55 *bytes = of_message_length_get(OF_OBJECT_TO_MESSAGE(obj));
56}
57
58/**
59 * Set the length of a message object as reported on the wire
60 * @param obj The object to check
61 * @param bytes The new length of the object
62 * @returns OF_ERROR_ code
63 */
64void
65of_object_message_wire_length_set(of_object_t *obj, int bytes)
66{
Rich Laneed79e0d2013-03-26 14:30:31 -070067 ASSERT(OF_OBJECT_TO_WBUF(obj) != NULL);
Rich Lanea06d0c32013-03-25 08:52:03 -070068 // ASSERT(obj is message)
69 of_message_length_set(OF_OBJECT_TO_MESSAGE(obj), bytes);
70}
71
72/****************************************************************
73 * TLV16 type/length functions
74 ****************************************************************/
75
76/**
77 * Many objects are TLVs and use uint16 for the type and length values
78 * stored on the wire at the beginning of the buffer.
79 */
80#define TLV16_WIRE_TYPE_OFFSET 0
81#define TLV16_WIRE_LENGTH_OFFSET 2
82
83/**
84 * Get the length field from the wire for a standard TLV
85 * object that uses uint16 for both type and length.
86 * @param obj The object being referenced
87 * @param bytes (out) Where to store the length
88 */
89
90void
91of_tlv16_wire_length_get(of_object_t *obj, int *bytes)
92{
93 uint16_t val16;
94 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
95 ASSERT(wbuf != NULL);
96
97 of_wire_buffer_u16_get(wbuf,
98 OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_LENGTH_OFFSET), &val16);
99 *bytes = val16;
100}
101
102/**
103 * Set the length field in the wire buffer for a standard TLV
104 * object that uses uint16 for both type and length.
105 * @param obj The object being referenced
106 * @param bytes The length value to use
107 */
108
109void
110of_tlv16_wire_length_set(of_object_t *obj, int bytes)
111{
112 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
113 ASSERT(wbuf != NULL);
114
115 of_wire_buffer_u16_set(wbuf,
116 OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_LENGTH_OFFSET), bytes);
117}
118
119/**
120 * Get the type field from the wire for a standard TLV object that uses
121 * uint16 for both type and length.
122 * @param obj The object being referenced
123 * @param wire_type (out) Where to store the type
124 */
125
126static void
127of_tlv16_wire_type_get(of_object_t *obj, int *wire_type)
128{
129 uint16_t val16;
130 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
131
132 of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj,
133 TLV16_WIRE_TYPE_OFFSET), &val16);
134
135 *wire_type = val16;
136}
137
138/**
139 * Set the object ID based on the wire buffer for any TLV object
140 * @param obj The object being referenced
141 * @param id The ID value representing what should be stored.
142 */
143
144void
145of_tlv16_wire_object_id_set(of_object_t *obj, of_object_id_t id)
146{
147 int wire_type;
148 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
149 ASSERT(wbuf != NULL);
150
151 wire_type = of_object_to_type_map[obj->version][id];
152 ASSERT(wire_type >= 0);
153
154 of_wire_buffer_u16_set(wbuf,
155 OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_TYPE_OFFSET), wire_type);
156
157 if (wire_type == OF_EXPERIMENTER_TYPE) {
158 of_extension_object_id_set(obj, id);
159 }
160}
161
162/**
163 * Get the object ID of an extended action
164 * @param obj The object being referenced
165 * @param id Where to store the object ID
166 * @fixme: This should be auto generated
167 *
168 * If unable to map to known extension, set id to generic "experimenter"
169 */
170
171#define OF_ACTION_EXPERIMENTER_ID_OFFSET 4
172#define OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET 8
173
174
175static void
176extension_action_object_id_get(of_object_t *obj, of_object_id_t *id)
177{
178 uint32_t exp_id;
179 uint8_t *buf;
180
181 *id = OF_ACTION_EXPERIMENTER;
182
183 buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
184
185 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
186
187 switch (exp_id) {
188 case OF_EXPERIMENTER_ID_BSN: {
189 uint32_t subtype;
190 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
191 switch (subtype) {
192 case 1: *id = OF_ACTION_BSN_MIRROR; break;
193 case 2: *id = OF_ACTION_BSN_SET_TUNNEL_DST; break;
194 }
195 break;
196 }
197 case OF_EXPERIMENTER_ID_NICIRA: {
198 uint16_t subtype;
199 buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
200 switch (subtype) {
201 case 18: *id = OF_ACTION_NICIRA_DEC_TTL; break;
202 }
203 break;
204 }
205 }
206}
207
208/**
209 * Set wire data for extension objects, not messages.
210 *
211 * Currently only handles BSN mirror; ignores all others
212 */
213
214void
215of_extension_object_id_set(of_object_t *obj, of_object_id_t id)
216{
217 uint8_t *buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
218
219 switch (id) {
220 case OF_ACTION_BSN_MIRROR:
221 case OF_ACTION_ID_BSN_MIRROR:
222 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
223 OF_EXPERIMENTER_ID_BSN);
224 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 1);
225 break;
226 case OF_ACTION_BSN_SET_TUNNEL_DST:
227 case OF_ACTION_ID_BSN_SET_TUNNEL_DST:
228 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
229 OF_EXPERIMENTER_ID_BSN);
230 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 2);
231 break;
232 case OF_ACTION_NICIRA_DEC_TTL:
233 case OF_ACTION_ID_NICIRA_DEC_TTL:
234 buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
235 OF_EXPERIMENTER_ID_NICIRA);
236 buf_u16_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 18);
237 break;
238 default:
239 break;
240 }
241}
242
243/**
244 * Get the object ID of an extended action
245 * @param obj The object being referenced
246 * @param id Where to store the object ID
247 * @fixme: This should be auto generated
248 *
249 * If unable to map to known extension, set id to generic "experimenter"
250 */
251
252static void
253extension_action_id_object_id_get(of_object_t *obj, of_object_id_t *id)
254{
255 uint32_t exp_id;
256 uint8_t *buf;
257
258 *id = OF_ACTION_ID_EXPERIMENTER;
259
260 buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
261
262 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
263
264 switch (exp_id) {
265 case OF_EXPERIMENTER_ID_BSN: {
266 uint32_t subtype;
267 buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
268 switch (subtype) {
269 case 1: *id = OF_ACTION_ID_BSN_MIRROR; break;
270 case 2: *id = OF_ACTION_ID_BSN_SET_TUNNEL_DST; break;
271 }
272 break;
273 }
274 case OF_EXPERIMENTER_ID_NICIRA: {
275 uint16_t subtype;
276 buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
277 switch (subtype) {
278 case 18: *id = OF_ACTION_ID_NICIRA_DEC_TTL; break;
279 }
280 break;
281 }
282 }
283}
284
285
286/**
287 * Get the object ID based on the wire buffer for an action object
288 * @param obj The object being referenced
289 * @param id Where to store the object ID
290 */
291
292
293void
294of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
295{
296 int wire_type;
297
298 of_tlv16_wire_type_get(obj, &wire_type);
299 if (wire_type == OF_EXPERIMENTER_TYPE) {
300 extension_action_object_id_get(obj, id);
301 return;
302 }
303
304 ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ITEM_COUNT);
305
306 *id = of_action_type_to_id[obj->version][wire_type];
307 ASSERT(*id != OF_OBJECT_INVALID);
308}
309
310/**
311 * Get the object ID based on the wire buffer for an action ID object
312 * @param obj The object being referenced
313 * @param id Where to store the object ID
314 */
315
316
317void
318of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
319{
320 int wire_type;
321
322 of_tlv16_wire_type_get(obj, &wire_type);
323 if (wire_type == OF_EXPERIMENTER_TYPE) {
324 extension_action_id_object_id_get(obj, id);
325 return;
326 }
327
328 ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ID_ITEM_COUNT);
329
330 *id = of_action_id_type_to_id[obj->version][wire_type];
331 ASSERT(*id != OF_OBJECT_INVALID);
332}
333
334/**
335 * @fixme to do when we have instruction extensions
336 * See extension_action above
337 */
338
339static int
340extension_instruction_object_id_get(of_object_t *obj, of_object_id_t *id)
341{
342 (void)obj;
343
344 *id = OF_INSTRUCTION_EXPERIMENTER;
345
346 return OF_ERROR_NONE;
347}
348
349/**
350 * Get the object ID based on the wire buffer for an instruction object
351 * @param obj The object being referenced
352 * @param id Where to store the object ID
353 */
354
355void
356of_instruction_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
357{
358 int wire_type;
359
360 of_tlv16_wire_type_get(obj, &wire_type);
361 if (wire_type == OF_EXPERIMENTER_TYPE) {
362 extension_instruction_object_id_get(obj, id);
363 return;
364 }
365
366 ASSERT(wire_type >= 0 && wire_type < OF_INSTRUCTION_ITEM_COUNT);
367
368 *id = of_instruction_type_to_id[obj->version][wire_type];
369 ASSERT(*id != OF_OBJECT_INVALID);
370}
371
372
373/**
374 * @fixme to do when we have queue_prop extensions
375 * See extension_action above
376 */
377
378static void
379extension_queue_prop_object_id_get(of_object_t *obj, of_object_id_t *id)
380{
381 (void)obj;
382
383 *id = OF_QUEUE_PROP_EXPERIMENTER;
384}
385
386/**
387 * Get the object ID based on the wire buffer for an queue_prop object
388 * @param obj The object being referenced
389 * @param id Where to store the object ID
390 */
391
392void
393of_queue_prop_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
394{
395 int wire_type;
396
397 of_tlv16_wire_type_get(obj, &wire_type);
398 if (wire_type == OF_EXPERIMENTER_TYPE) {
399 extension_queue_prop_object_id_get(obj, id);
400 return;
401 }
402
403 ASSERT(wire_type >= 0 && wire_type < OF_QUEUE_PROP_ITEM_COUNT);
404
405 *id = of_queue_prop_type_to_id[obj->version][wire_type];
406 ASSERT(*id != OF_OBJECT_INVALID);
407}
408
409
410/**
411 * @fixme to do when we have table_feature_prop extensions
412 * See extension_action above
413 */
414
415static void
416extension_table_feature_prop_object_id_get(of_object_t *obj, of_object_id_t *id)
417{
418 (void)obj;
419
420 *id = OF_TABLE_FEATURE_PROP_EXPERIMENTER;
421}
422
423/**
424 * Table feature property object ID determination
425 *
426 * @param obj The object being referenced
427 * @param id Where to store the object ID
428 */
429
430void
431of_table_feature_prop_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
432{
433 int wire_type;
434
435 of_tlv16_wire_type_get(obj, &wire_type);
436 if (wire_type == OF_EXPERIMENTER_TYPE) {
437 extension_table_feature_prop_object_id_get(obj, id);
438 return;
439 }
440
441 ASSERT(wire_type >= 0 && wire_type < OF_TABLE_FEATURE_PROP_ITEM_COUNT);
442
443 *id = of_table_feature_prop_type_to_id[obj->version][wire_type];
444 ASSERT(*id != OF_OBJECT_INVALID);
445}
446
447/**
448 * Get the object ID based on the wire buffer for meter_band object
449 * @param obj The object being referenced
450 * @param id Where to store the object ID
451 */
452
453void
454of_meter_band_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
455{
456 int wire_type;
457
458 of_tlv16_wire_type_get(obj, &wire_type);
459 if (wire_type == OF_EXPERIMENTER_TYPE) {
460 *id = OF_METER_BAND_EXPERIMENTER;
461 return;
462 }
463
464 ASSERT(wire_type >= 0 && wire_type < OF_METER_BAND_ITEM_COUNT);
465
466 *id = of_meter_band_type_to_id[obj->version][wire_type];
467 ASSERT(*id != OF_OBJECT_INVALID);
468}
469
470/**
471 * Get the object ID based on the wire buffer for a hello_elem object
472 * @param obj The object being referenced
473 * @param id Where to store the object ID
474 */
475
476void
477of_hello_elem_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
478{
479 int wire_type;
480
481 of_tlv16_wire_type_get(obj, &wire_type);
482 ASSERT(wire_type >= 0 && wire_type < OF_HELLO_ELEM_ITEM_COUNT);
483 *id = of_hello_elem_type_to_id[obj->version][wire_type];
484 ASSERT(*id != OF_OBJECT_INVALID);
485}
486
487/****************************************************************
488 * OXM type/length functions.
489 ****************************************************************/
490
491/* Where does the OXM type-length header lie in the buffer */
492#define OXM_HDR_OFFSET 0
493
494/**
495 * Get the OXM header (type-length fields) from the wire buffer
496 * associated with an OXM object
497 *
498 * Will return if error; set hdr to the OXM header
499 */
500
501#define _GET_OXM_TYPE_LEN(obj, tl_p, wbuf) do { \
502 wbuf = OF_OBJECT_TO_WBUF(obj); \
503 ASSERT(wbuf != NULL); \
504 of_wire_buffer_u32_get(wbuf, \
505 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), (tl_p)); \
506 } while (0)
507
508#define _SET_OXM_TYPE_LEN(obj, tl_p, wbuf) do { \
509 wbuf = OF_OBJECT_TO_WBUF(obj); \
510 ASSERT(wbuf != NULL); \
511 of_wire_buffer_u32_set(wbuf, \
512 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), (tl_p)); \
513 } while (0)
514
515/**
516 * Get the length of an OXM object from the wire buffer
517 * @param obj The object whose wire buffer is an OXM type
518 * @param bytes (out) Where length is stored
519 */
520
521void
522of_oxm_wire_length_get(of_object_t *obj, int *bytes)
523{
524 uint32_t type_len;
525 of_wire_buffer_t *wbuf;
526
527 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
528 *bytes = OF_OXM_LENGTH_GET(type_len);
529}
530
531/**
532 * Set the length of an OXM object in the wire buffer
533 * @param obj The object whose wire buffer is an OXM type
534 * @param bytes Value to store in wire buffer
535 */
536
537void
538of_oxm_wire_length_set(of_object_t *obj, int bytes)
539{
540 uint32_t type_len;
541 of_wire_buffer_t *wbuf;
542
543 ASSERT(bytes >= 0 && bytes < 256);
544
545 /* Read-modify-write */
546 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
547 OF_OXM_LENGTH_SET(type_len, bytes);
548 of_wire_buffer_u32_set(wbuf,
549 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), type_len);
550}
551
552/**
553 * Get the object ID of an OXM object based on the wire buffer type
554 * @param obj The object whose wire buffer is an OXM type
555 * @param id (out) Where the ID is stored
556 */
557
558void
559of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
560{
561 uint32_t type_len;
Rich Lanea06d0c32013-03-25 08:52:03 -0700562 of_wire_buffer_t *wbuf;
563
564 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
Rich Laned8d29c92013-09-24 13:46:42 -0700565 *id = of_oxm_to_object_id(type_len, obj->version);
Rich Lanea06d0c32013-03-25 08:52:03 -0700566}
567
568/**
569 * Set the wire type of an OXM object based on the object ID passed
570 * @param obj The object whose wire buffer is an OXM type
571 * @param id The object ID mapped to an OXM wire type which is stored
572 */
573
574void
575of_oxm_wire_object_id_set(of_object_t *obj, of_object_id_t id)
576{
577 uint32_t type_len;
578 int wire_type;
579 of_wire_buffer_t *wbuf;
580
581 ASSERT(OF_OXM_VALID_ID(id));
582
583 /* Read-modify-write */
584 _GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
Rich Laned8d29c92013-09-24 13:46:42 -0700585
586 switch (id) {
587 case OF_OXM_BSN_IN_PORTS_128:
588 type_len = 0x00030000 | (type_len & 0xff);
589 break;
590 case OF_OXM_BSN_IN_PORTS_128_MASKED:
591 type_len = 0x00030100 | (type_len & 0xff);
592 break;
593 default:
594 wire_type = of_object_to_wire_type(id, obj->version);
595 ASSERT(wire_type >= 0);
596 type_len = 0x80000000 | (wire_type << 8) | (type_len & 0xff);
597 break;
598 }
599
Rich Lanea06d0c32013-03-25 08:52:03 -0700600 of_wire_buffer_u32_set(wbuf,
601 OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), type_len);
602}
603
604
605
606#define OF_U16_LEN_LENGTH_OFFSET 0
607
608/**
609 * Get the wire length for an object with a uint16 length as first member
610 * @param obj The object being referenced
611 * @param bytes Pointer to location to store length
612 */
613void
614of_u16_len_wire_length_get(of_object_t *obj, int *bytes)
615{
616 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
617 uint16_t u16;
618
619 ASSERT(wbuf != NULL);
620
621 of_wire_buffer_u16_get(wbuf,
622 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_U16_LEN_LENGTH_OFFSET),
623 &u16);
624
625 *bytes = u16;
626}
627
628/**
629 * Set the wire length for an object with a uint16 length as first member
630 * @param obj The object being referenced
631 * @param bytes The length of the object
632 */
633
634void
635of_u16_len_wire_length_set(of_object_t *obj, int bytes)
636{
637 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
638 ASSERT(wbuf != NULL);
639
640 /* ASSERT(obj is u16-len entry) */
641
642 of_wire_buffer_u16_set(wbuf,
643 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_U16_LEN_LENGTH_OFFSET),
644 bytes);
645}
646
647
648#define OF_PACKET_QUEUE_LENGTH_OFFSET(ver) \
649 (((ver) >= OF_VERSION_1_2) ? 8 : 4)
650
651/**
652 * Get the wire length for a packet queue object
653 * @param obj The object being referenced
654 * @param bytes Pointer to location to store length
655 *
656 * The length is a uint16 at the offset indicated above
657 */
658void
659of_packet_queue_wire_length_get(of_object_t *obj, int *bytes)
660{
661 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
662 uint16_t u16;
663 int offset;
664
665 ASSERT(wbuf != NULL);
666
667 /* ASSERT(obj is packet queue obj) */
668 offset = OF_PACKET_QUEUE_LENGTH_OFFSET(obj->version);
669 of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, offset),
670 &u16);
671
672 *bytes = u16;
673}
674
675/**
676 * Set the wire length for a 1.2 packet queue object
677 * @param obj The object being referenced
678 * @param bytes The length of the object
679 *
680 * The length is a uint16 at the offset indicated above
681 */
682
683void
684of_packet_queue_wire_length_set(of_object_t *obj, int bytes)
685{
686 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
687 int offset;
688
689 ASSERT(wbuf != NULL);
690
691 /* ASSERT(obj is packet queue obj) */
692 offset = OF_PACKET_QUEUE_LENGTH_OFFSET(obj->version);
693 of_wire_buffer_u16_set(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, offset),
694 bytes);
695}
696
697/**
698 * Get the wire length for a meter band stats list
699 * @param obj The object being referenced
700 * @param bytes Pointer to location to store length
701 *
702 * Must a meter_stats object as a parent
703 */
704
705void
706of_list_meter_band_stats_wire_length_get(of_object_t *obj, int *bytes)
707{
708 ASSERT(obj->parent != NULL);
709 ASSERT(obj->parent->object_id == OF_METER_STATS);
710
711 /* We're counting on the parent being properly initialized already.
712 * The length is stored in a uint16 at offset 4 of the parent.
713 */
714 *bytes = obj->parent->length - OF_OBJECT_FIXED_LENGTH(obj->parent);
715}
716
717#define OF_METER_STATS_LENGTH_OFFSET 4
718
719/**
720 * Get/set the wire length for a meter stats object
721 * @param obj The object being referenced
722 * @param bytes Pointer to location to store length
723 *
724 * It's almost a TLV....
725 */
726
727void
728of_meter_stats_wire_length_get(of_object_t *obj, int *bytes)
729{
730 uint16_t val16;
731 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
732 ASSERT(wbuf != NULL);
733 of_wire_buffer_u16_get(wbuf,
734 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET),
735 &val16);
736 *bytes = val16;
737}
738
739void
740of_meter_stats_wire_length_set(of_object_t *obj, int bytes)
741{
742 of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
743 ASSERT(wbuf != NULL);
744
745 of_wire_buffer_u16_set(wbuf,
746 OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET), bytes);
747}
748
749/*
750 * Non-message extension push wire values
751 */
752
753int
754of_extension_object_wire_push(of_object_t *obj)
755{
756 of_action_bsn_mirror_t *action_mirror;
757 of_action_id_bsn_mirror_t *action_id_mirror;
758 of_action_bsn_set_tunnel_dst_t *action_set_tunnel_dst;
759 of_action_id_bsn_set_tunnel_dst_t *action_id_set_tunnel_dst;
760 of_action_nicira_dec_ttl_t *action_nicira_dec_ttl;
761 of_action_id_nicira_dec_ttl_t *action_id_nicira_dec_ttl;
762
763 /* Push exp type, subtype */
764 switch (obj->object_id) {
765 case OF_ACTION_BSN_MIRROR:
766 action_mirror = (of_action_bsn_mirror_t *)obj;
767 of_action_bsn_mirror_experimenter_set(action_mirror,
768 OF_EXPERIMENTER_ID_BSN);
769 of_action_bsn_mirror_subtype_set(action_mirror, 1);
770 break;
771 case OF_ACTION_ID_BSN_MIRROR:
772 action_id_mirror = (of_action_id_bsn_mirror_t *)obj;
773 of_action_id_bsn_mirror_experimenter_set(action_id_mirror,
774 OF_EXPERIMENTER_ID_BSN);
775 of_action_id_bsn_mirror_subtype_set(action_id_mirror, 1);
776 break;
777 case OF_ACTION_BSN_SET_TUNNEL_DST:
778 action_set_tunnel_dst = (of_action_bsn_set_tunnel_dst_t *)obj;
779 of_action_bsn_set_tunnel_dst_experimenter_set(action_set_tunnel_dst,
780 OF_EXPERIMENTER_ID_BSN);
781 of_action_bsn_set_tunnel_dst_subtype_set(action_set_tunnel_dst, 2);
782 break;
783 case OF_ACTION_ID_BSN_SET_TUNNEL_DST:
784 action_id_set_tunnel_dst = (of_action_id_bsn_set_tunnel_dst_t *)obj;
785 of_action_id_bsn_set_tunnel_dst_experimenter_set(action_id_set_tunnel_dst,
786 OF_EXPERIMENTER_ID_BSN);
787 of_action_id_bsn_set_tunnel_dst_subtype_set(action_id_set_tunnel_dst, 2);
788 break;
789 case OF_ACTION_NICIRA_DEC_TTL:
790 action_nicira_dec_ttl = (of_action_nicira_dec_ttl_t *)obj;
791 of_action_nicira_dec_ttl_experimenter_set(action_nicira_dec_ttl,
792 OF_EXPERIMENTER_ID_NICIRA);
793 of_action_nicira_dec_ttl_subtype_set(action_nicira_dec_ttl, 18);
794 break;
795 case OF_ACTION_ID_NICIRA_DEC_TTL:
796 action_id_nicira_dec_ttl = (of_action_id_nicira_dec_ttl_t *)obj;
797 of_action_id_nicira_dec_ttl_experimenter_set(action_id_nicira_dec_ttl,
798 OF_EXPERIMENTER_ID_NICIRA);
799 of_action_id_nicira_dec_ttl_subtype_set(action_id_nicira_dec_ttl, 18);
800 break;
801 default:
802 break;
803 }
804
805 return OF_ERROR_NONE;
806}