blob: fabd25f53eabc03689fbf87c0aa7c9291be2ea13 [file] [log] [blame]
:: # Copyright 2013, Big Switch Networks, Inc.
:: #
:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
:: # the following special exception:
:: #
:: # LOXI Exception
:: #
:: # As a special exception to the terms of the EPL, you may distribute libraries
:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
:: # from the LoxiGen Libraries and the notice provided below is (i) included in
:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
:: # documentation for the LoxiGen Libraries, if distributed in binary form.
:: #
:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
:: #
:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
:: # a copy of the EPL at:
:: #
:: # http://www.eclipse.org/legal/epl-v10.html
:: #
:: # Unless required by applicable law or agreed to in writing, software
:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
:: # EPL for the specific language governing permissions and limitations
:: # under the EPL.
::
:: include('_copyright.c')
/****************************************************************
*
* Functions related to mapping wire values to object types
* and lengths
*
****************************************************************/
#include <loci/loci.h>
#include <loci/of_message.h>
/****************************************************************
* Top level OpenFlow message length functions
****************************************************************/
/**
* Get the length of a message object as reported on the wire
* @param obj The object to check
* @param bytes (out) Where the length is stored
* @returns OF_ERROR_ code
*/
void
of_object_message_wire_length_get(of_object_t *obj, int *bytes)
{
ASSERT(OF_OBJECT_TO_WBUF(obj) != NULL);
// ASSERT(obj is message)
*bytes = of_message_length_get(OF_OBJECT_TO_MESSAGE(obj));
}
/**
* Set the length of a message object as reported on the wire
* @param obj The object to check
* @param bytes The new length of the object
* @returns OF_ERROR_ code
*/
void
of_object_message_wire_length_set(of_object_t *obj, int bytes)
{
ASSERT(OF_OBJECT_TO_WBUF(obj) != NULL);
// ASSERT(obj is message)
of_message_length_set(OF_OBJECT_TO_MESSAGE(obj), bytes);
}
/****************************************************************
* TLV16 type/length functions
****************************************************************/
/**
* Many objects are TLVs and use uint16 for the type and length values
* stored on the wire at the beginning of the buffer.
*/
#define TLV16_WIRE_TYPE_OFFSET 0
#define TLV16_WIRE_LENGTH_OFFSET 2
/**
* Get the length field from the wire for a standard TLV
* object that uses uint16 for both type and length.
* @param obj The object being referenced
* @param bytes (out) Where to store the length
*/
void
of_tlv16_wire_length_get(of_object_t *obj, int *bytes)
{
uint16_t val16;
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
ASSERT(wbuf != NULL);
of_wire_buffer_u16_get(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_LENGTH_OFFSET), &val16);
*bytes = val16;
}
/**
* Set the length field in the wire buffer for a standard TLV
* object that uses uint16 for both type and length.
* @param obj The object being referenced
* @param bytes The length value to use
*/
void
of_tlv16_wire_length_set(of_object_t *obj, int bytes)
{
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
ASSERT(wbuf != NULL);
of_wire_buffer_u16_set(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_LENGTH_OFFSET), bytes);
}
/**
* Get the type field from the wire for a standard TLV object that uses
* uint16 for both type and length.
* @param obj The object being referenced
* @param wire_type (out) Where to store the type
*/
static void
of_tlv16_wire_type_get(of_object_t *obj, int *wire_type)
{
uint16_t val16;
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj,
TLV16_WIRE_TYPE_OFFSET), &val16);
*wire_type = val16;
}
/**
* Set the object ID based on the wire buffer for any TLV object
* @param obj The object being referenced
* @param id The ID value representing what should be stored.
*/
void
of_tlv16_wire_object_id_set(of_object_t *obj, of_object_id_t id)
{
int wire_type;
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
ASSERT(wbuf != NULL);
wire_type = of_object_to_type_map[obj->version][id];
ASSERT(wire_type >= 0);
of_wire_buffer_u16_set(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, TLV16_WIRE_TYPE_OFFSET), wire_type);
if (wire_type == OF_EXPERIMENTER_TYPE) {
of_extension_object_id_set(obj, id);
}
}
/**
* Get the object ID of an extended action
* @param obj The object being referenced
* @param id Where to store the object ID
* @fixme: This should be auto generated
*
* If unable to map to known extension, set id to generic "experimenter"
*/
#define OF_ACTION_EXPERIMENTER_ID_OFFSET 4
#define OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET 8
static void
extension_action_object_id_get(of_object_t *obj, of_object_id_t *id)
{
uint32_t exp_id;
uint8_t *buf;
*id = OF_ACTION_EXPERIMENTER;
buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
switch (exp_id) {
case OF_EXPERIMENTER_ID_BSN: {
uint32_t subtype;
buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
switch (subtype) {
case 1: *id = OF_ACTION_BSN_MIRROR; break;
case 2: *id = OF_ACTION_BSN_SET_TUNNEL_DST; break;
}
break;
}
case OF_EXPERIMENTER_ID_NICIRA: {
uint16_t subtype;
buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
switch (subtype) {
case 18: *id = OF_ACTION_NICIRA_DEC_TTL; break;
}
break;
}
}
}
/**
* Set wire data for extension objects, not messages.
*
* Currently only handles BSN mirror; ignores all others
*/
void
of_extension_object_id_set(of_object_t *obj, of_object_id_t id)
{
uint8_t *buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
switch (id) {
case OF_ACTION_BSN_MIRROR:
case OF_ACTION_ID_BSN_MIRROR:
buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
OF_EXPERIMENTER_ID_BSN);
buf_u32_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 1);
break;
case OF_ACTION_BSN_SET_TUNNEL_DST:
case OF_ACTION_ID_BSN_SET_TUNNEL_DST:
buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
OF_EXPERIMENTER_ID_BSN);
buf_u32_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 2);
break;
case OF_ACTION_NICIRA_DEC_TTL:
case OF_ACTION_ID_NICIRA_DEC_TTL:
buf_u32_set(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET,
OF_EXPERIMENTER_ID_NICIRA);
buf_u16_set(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, 18);
break;
default:
break;
}
}
/**
* Get the object ID of an extended action
* @param obj The object being referenced
* @param id Where to store the object ID
* @fixme: This should be auto generated
*
* If unable to map to known extension, set id to generic "experimenter"
*/
static void
extension_action_id_object_id_get(of_object_t *obj, of_object_id_t *id)
{
uint32_t exp_id;
uint8_t *buf;
*id = OF_ACTION_ID_EXPERIMENTER;
buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
buf_u32_get(buf + OF_ACTION_EXPERIMENTER_ID_OFFSET, &exp_id);
switch (exp_id) {
case OF_EXPERIMENTER_ID_BSN: {
uint32_t subtype;
buf_u32_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
switch (subtype) {
case 1: *id = OF_ACTION_ID_BSN_MIRROR; break;
case 2: *id = OF_ACTION_ID_BSN_SET_TUNNEL_DST; break;
}
break;
}
case OF_EXPERIMENTER_ID_NICIRA: {
uint16_t subtype;
buf_u16_get(buf + OF_ACTION_EXPERIMENTER_SUBTYPE_OFFSET, &subtype);
switch (subtype) {
case 18: *id = OF_ACTION_ID_NICIRA_DEC_TTL; break;
}
break;
}
}
}
/**
* Get the object ID based on the wire buffer for an action object
* @param obj The object being referenced
* @param id Where to store the object ID
*/
void
of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
int wire_type;
of_tlv16_wire_type_get(obj, &wire_type);
if (wire_type == OF_EXPERIMENTER_TYPE) {
extension_action_object_id_get(obj, id);
return;
}
ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ITEM_COUNT);
*id = of_action_type_to_id[obj->version][wire_type];
ASSERT(*id != OF_OBJECT_INVALID);
}
/**
* Get the object ID based on the wire buffer for an action ID object
* @param obj The object being referenced
* @param id Where to store the object ID
*/
void
of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
int wire_type;
of_tlv16_wire_type_get(obj, &wire_type);
if (wire_type == OF_EXPERIMENTER_TYPE) {
extension_action_id_object_id_get(obj, id);
return;
}
ASSERT(wire_type >= 0 && wire_type < OF_ACTION_ID_ITEM_COUNT);
*id = of_action_id_type_to_id[obj->version][wire_type];
ASSERT(*id != OF_OBJECT_INVALID);
}
/**
* @fixme to do when we have instruction extensions
* See extension_action above
*/
static int
extension_instruction_object_id_get(of_object_t *obj, of_object_id_t *id)
{
(void)obj;
*id = OF_INSTRUCTION_EXPERIMENTER;
return OF_ERROR_NONE;
}
/**
* Get the object ID based on the wire buffer for an instruction object
* @param obj The object being referenced
* @param id Where to store the object ID
*/
void
of_instruction_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
int wire_type;
of_tlv16_wire_type_get(obj, &wire_type);
if (wire_type == OF_EXPERIMENTER_TYPE) {
extension_instruction_object_id_get(obj, id);
return;
}
ASSERT(wire_type >= 0 && wire_type < OF_INSTRUCTION_ITEM_COUNT);
*id = of_instruction_type_to_id[obj->version][wire_type];
ASSERT(*id != OF_OBJECT_INVALID);
}
/**
* @fixme to do when we have queue_prop extensions
* See extension_action above
*/
static void
extension_queue_prop_object_id_get(of_object_t *obj, of_object_id_t *id)
{
(void)obj;
*id = OF_QUEUE_PROP_EXPERIMENTER;
}
/**
* Get the object ID based on the wire buffer for an queue_prop object
* @param obj The object being referenced
* @param id Where to store the object ID
*/
void
of_queue_prop_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
int wire_type;
of_tlv16_wire_type_get(obj, &wire_type);
if (wire_type == OF_EXPERIMENTER_TYPE) {
extension_queue_prop_object_id_get(obj, id);
return;
}
ASSERT(wire_type >= 0 && wire_type < OF_QUEUE_PROP_ITEM_COUNT);
*id = of_queue_prop_type_to_id[obj->version][wire_type];
ASSERT(*id != OF_OBJECT_INVALID);
}
/**
* @fixme to do when we have table_feature_prop extensions
* See extension_action above
*/
static void
extension_table_feature_prop_object_id_get(of_object_t *obj, of_object_id_t *id)
{
(void)obj;
*id = OF_TABLE_FEATURE_PROP_EXPERIMENTER;
}
/**
* Table feature property object ID determination
*
* @param obj The object being referenced
* @param id Where to store the object ID
*/
void
of_table_feature_prop_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
int wire_type;
of_tlv16_wire_type_get(obj, &wire_type);
if (wire_type == OF_EXPERIMENTER_TYPE) {
extension_table_feature_prop_object_id_get(obj, id);
return;
}
ASSERT(wire_type >= 0 && wire_type < OF_TABLE_FEATURE_PROP_ITEM_COUNT);
*id = of_table_feature_prop_type_to_id[obj->version][wire_type];
ASSERT(*id != OF_OBJECT_INVALID);
}
/**
* Get the object ID based on the wire buffer for meter_band object
* @param obj The object being referenced
* @param id Where to store the object ID
*/
void
of_meter_band_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
int wire_type;
of_tlv16_wire_type_get(obj, &wire_type);
if (wire_type == OF_EXPERIMENTER_TYPE) {
*id = OF_METER_BAND_EXPERIMENTER;
return;
}
ASSERT(wire_type >= 0 && wire_type < OF_METER_BAND_ITEM_COUNT);
*id = of_meter_band_type_to_id[obj->version][wire_type];
ASSERT(*id != OF_OBJECT_INVALID);
}
/**
* Get the object ID based on the wire buffer for a hello_elem object
* @param obj The object being referenced
* @param id Where to store the object ID
*/
void
of_hello_elem_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
int wire_type;
of_tlv16_wire_type_get(obj, &wire_type);
ASSERT(wire_type >= 0 && wire_type < OF_HELLO_ELEM_ITEM_COUNT);
*id = of_hello_elem_type_to_id[obj->version][wire_type];
ASSERT(*id != OF_OBJECT_INVALID);
}
/****************************************************************
* OXM type/length functions.
****************************************************************/
/* Where does the OXM type-length header lie in the buffer */
#define OXM_HDR_OFFSET 0
/**
* Get the OXM header (type-length fields) from the wire buffer
* associated with an OXM object
*
* Will return if error; set hdr to the OXM header
*/
#define _GET_OXM_TYPE_LEN(obj, tl_p, wbuf) do { \
wbuf = OF_OBJECT_TO_WBUF(obj); \
ASSERT(wbuf != NULL); \
of_wire_buffer_u32_get(wbuf, \
OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), (tl_p)); \
} while (0)
#define _SET_OXM_TYPE_LEN(obj, tl_p, wbuf) do { \
wbuf = OF_OBJECT_TO_WBUF(obj); \
ASSERT(wbuf != NULL); \
of_wire_buffer_u32_set(wbuf, \
OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), (tl_p)); \
} while (0)
/**
* Get the length of an OXM object from the wire buffer
* @param obj The object whose wire buffer is an OXM type
* @param bytes (out) Where length is stored
*/
void
of_oxm_wire_length_get(of_object_t *obj, int *bytes)
{
uint32_t type_len;
of_wire_buffer_t *wbuf;
_GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
*bytes = OF_OXM_LENGTH_GET(type_len);
}
/**
* Set the length of an OXM object in the wire buffer
* @param obj The object whose wire buffer is an OXM type
* @param bytes Value to store in wire buffer
*/
void
of_oxm_wire_length_set(of_object_t *obj, int bytes)
{
uint32_t type_len;
of_wire_buffer_t *wbuf;
ASSERT(bytes >= 0 && bytes < 256);
/* Read-modify-write */
_GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
OF_OXM_LENGTH_SET(type_len, bytes);
of_wire_buffer_u32_set(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), type_len);
}
/**
* Get the object ID of an OXM object based on the wire buffer type
* @param obj The object whose wire buffer is an OXM type
* @param id (out) Where the ID is stored
*/
void
of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id)
{
uint32_t type_len;
of_wire_buffer_t *wbuf;
_GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
*id = of_oxm_to_object_id(type_len, obj->version);
}
/**
* Set the wire type of an OXM object based on the object ID passed
* @param obj The object whose wire buffer is an OXM type
* @param id The object ID mapped to an OXM wire type which is stored
*/
void
of_oxm_wire_object_id_set(of_object_t *obj, of_object_id_t id)
{
uint32_t type_len;
int wire_type;
of_wire_buffer_t *wbuf;
ASSERT(OF_OXM_VALID_ID(id));
/* Read-modify-write */
_GET_OXM_TYPE_LEN(obj, &type_len, wbuf);
switch (id) {
case OF_OXM_BSN_IN_PORTS_128:
type_len = 0x00030000 | (type_len & 0xff);
break;
case OF_OXM_BSN_IN_PORTS_128_MASKED:
type_len = 0x00030100 | (type_len & 0xff);
break;
case OF_OXM_BSN_LAG_ID:
type_len = 0x00030200 | (type_len & 0xff);
break;
case OF_OXM_BSN_LAG_ID_MASKED:
type_len = 0x00030300 | (type_len & 0xff);
break;
case OF_OXM_BSN_VRF:
type_len = 0x00030400 | (type_len & 0xff);
break;
case OF_OXM_BSN_VRF_MASKED:
type_len = 0x00030500 | (type_len & 0xff);
break;
case OF_OXM_BSN_GLOBAL_VRF_ALLOWED:
type_len = 0x00030600 | (type_len & 0xff);
break;
case OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED:
type_len = 0x00030700 | (type_len & 0xff);
break;
case OF_OXM_BSN_L3_INTERFACE_CLASS_ID:
type_len = 0x00030800 | (type_len & 0xff);
break;
case OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED:
type_len = 0x00030900 | (type_len & 0xff);
break;
case OF_OXM_BSN_L3_SRC_CLASS_ID:
type_len = 0x00030a00 | (type_len & 0xff);
break;
case OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED:
type_len = 0x00030b00 | (type_len & 0xff);
break;
case OF_OXM_BSN_L3_DST_CLASS_ID:
type_len = 0x00030c00 | (type_len & 0xff);
break;
case OF_OXM_BSN_L3_DST_CLASS_ID_MASKED:
type_len = 0x00030d00 | (type_len & 0xff);
break;
default:
wire_type = of_object_to_wire_type(id, obj->version);
ASSERT(wire_type >= 0);
type_len = 0x80000000 | (wire_type << 8) | (type_len & 0xff);
break;
}
of_wire_buffer_u32_set(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, OXM_HDR_OFFSET), type_len);
}
#define OF_U16_LEN_LENGTH_OFFSET 0
/**
* Get the wire length for an object with a uint16 length as first member
* @param obj The object being referenced
* @param bytes Pointer to location to store length
*/
void
of_u16_len_wire_length_get(of_object_t *obj, int *bytes)
{
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
uint16_t u16;
ASSERT(wbuf != NULL);
of_wire_buffer_u16_get(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_U16_LEN_LENGTH_OFFSET),
&u16);
*bytes = u16;
}
/**
* Set the wire length for an object with a uint16 length as first member
* @param obj The object being referenced
* @param bytes The length of the object
*/
void
of_u16_len_wire_length_set(of_object_t *obj, int bytes)
{
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
ASSERT(wbuf != NULL);
/* ASSERT(obj is u16-len entry) */
of_wire_buffer_u16_set(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_U16_LEN_LENGTH_OFFSET),
bytes);
}
#define OF_PACKET_QUEUE_LENGTH_OFFSET(ver) \
(((ver) >= OF_VERSION_1_2) ? 8 : 4)
/**
* Get the wire length for a packet queue object
* @param obj The object being referenced
* @param bytes Pointer to location to store length
*
* The length is a uint16 at the offset indicated above
*/
void
of_packet_queue_wire_length_get(of_object_t *obj, int *bytes)
{
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
uint16_t u16;
int offset;
ASSERT(wbuf != NULL);
/* ASSERT(obj is packet queue obj) */
offset = OF_PACKET_QUEUE_LENGTH_OFFSET(obj->version);
of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, offset),
&u16);
*bytes = u16;
}
/**
* Set the wire length for a 1.2 packet queue object
* @param obj The object being referenced
* @param bytes The length of the object
*
* The length is a uint16 at the offset indicated above
*/
void
of_packet_queue_wire_length_set(of_object_t *obj, int bytes)
{
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
int offset;
ASSERT(wbuf != NULL);
/* ASSERT(obj is packet queue obj) */
offset = OF_PACKET_QUEUE_LENGTH_OFFSET(obj->version);
of_wire_buffer_u16_set(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, offset),
bytes);
}
/**
* Get the wire length for a meter band stats list
* @param obj The object being referenced
* @param bytes Pointer to location to store length
*
* Must a meter_stats object as a parent
*/
void
of_list_meter_band_stats_wire_length_get(of_object_t *obj, int *bytes)
{
ASSERT(obj->parent != NULL);
ASSERT(obj->parent->object_id == OF_METER_STATS);
/* We're counting on the parent being properly initialized already.
* The length is stored in a uint16 at offset 4 of the parent.
*/
*bytes = obj->parent->length - OF_OBJECT_FIXED_LENGTH(obj->parent);
}
#define OF_METER_STATS_LENGTH_OFFSET 4
/**
* Get/set the wire length for a meter stats object
* @param obj The object being referenced
* @param bytes Pointer to location to store length
*
* It's almost a TLV....
*/
void
of_meter_stats_wire_length_get(of_object_t *obj, int *bytes)
{
uint16_t val16;
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
ASSERT(wbuf != NULL);
of_wire_buffer_u16_get(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET),
&val16);
*bytes = val16;
}
void
of_meter_stats_wire_length_set(of_object_t *obj, int bytes)
{
of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
ASSERT(wbuf != NULL);
of_wire_buffer_u16_set(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET), bytes);
}
/*
* Non-message extension push wire values
*/
int
of_extension_object_wire_push(of_object_t *obj)
{
of_action_bsn_mirror_t *action_mirror;
of_action_id_bsn_mirror_t *action_id_mirror;
of_action_bsn_set_tunnel_dst_t *action_set_tunnel_dst;
of_action_id_bsn_set_tunnel_dst_t *action_id_set_tunnel_dst;
of_action_nicira_dec_ttl_t *action_nicira_dec_ttl;
of_action_id_nicira_dec_ttl_t *action_id_nicira_dec_ttl;
/* Push exp type, subtype */
switch (obj->object_id) {
case OF_ACTION_BSN_MIRROR:
action_mirror = (of_action_bsn_mirror_t *)obj;
of_action_bsn_mirror_experimenter_set(action_mirror,
OF_EXPERIMENTER_ID_BSN);
of_action_bsn_mirror_subtype_set(action_mirror, 1);
break;
case OF_ACTION_ID_BSN_MIRROR:
action_id_mirror = (of_action_id_bsn_mirror_t *)obj;
of_action_id_bsn_mirror_experimenter_set(action_id_mirror,
OF_EXPERIMENTER_ID_BSN);
of_action_id_bsn_mirror_subtype_set(action_id_mirror, 1);
break;
case OF_ACTION_BSN_SET_TUNNEL_DST:
action_set_tunnel_dst = (of_action_bsn_set_tunnel_dst_t *)obj;
of_action_bsn_set_tunnel_dst_experimenter_set(action_set_tunnel_dst,
OF_EXPERIMENTER_ID_BSN);
of_action_bsn_set_tunnel_dst_subtype_set(action_set_tunnel_dst, 2);
break;
case OF_ACTION_ID_BSN_SET_TUNNEL_DST:
action_id_set_tunnel_dst = (of_action_id_bsn_set_tunnel_dst_t *)obj;
of_action_id_bsn_set_tunnel_dst_experimenter_set(action_id_set_tunnel_dst,
OF_EXPERIMENTER_ID_BSN);
of_action_id_bsn_set_tunnel_dst_subtype_set(action_id_set_tunnel_dst, 2);
break;
case OF_ACTION_NICIRA_DEC_TTL:
action_nicira_dec_ttl = (of_action_nicira_dec_ttl_t *)obj;
of_action_nicira_dec_ttl_experimenter_set(action_nicira_dec_ttl,
OF_EXPERIMENTER_ID_NICIRA);
of_action_nicira_dec_ttl_subtype_set(action_nicira_dec_ttl, 18);
break;
case OF_ACTION_ID_NICIRA_DEC_TTL:
action_id_nicira_dec_ttl = (of_action_id_nicira_dec_ttl_t *)obj;
of_action_id_nicira_dec_ttl_experimenter_set(action_id_nicira_dec_ttl,
OF_EXPERIMENTER_ID_NICIRA);
of_action_id_nicira_dec_ttl_subtype_set(action_id_nicira_dec_ttl, 18);
break;
default:
break;
}
return OF_ERROR_NONE;
}