コード例 #1
0
/**
 * Set match in an object of type of_flow_modify.
 * @param obj Pointer to an object of type of_flow_modify.
 * @param match Pointer to the child of type of_match_t.
 *
 * If the child's wire buffer is the same as the parent's, then
 * nothing is done as the changes have already been registered in the
 * parent.  Otherwise, the data in the child's wire buffer is inserted
 * into the parent's and the appropriate lengths are updated.
 */
int WARN_UNUSED_RESULT
of_flow_modify_match_set(
    of_flow_modify_t *obj,
    of_match_t *match)
{
    of_wire_buffer_t *wbuf;
    int offset = 0; /* Offset of value relative to the start obj */
    int abs_offset; /* Offset of value relative to start of wbuf */
    of_version_t ver;
    int cur_len = 0; /* Current length of object data */
    int new_len, delta; /* For set, need new length and delta */
    of_octets_t match_octets; /* Serialized string for match */

    ASSERT(IS_FLOW_MOD_SUBTYPE(obj->object_id));
    ver = obj->version;
    wbuf = OF_OBJECT_TO_WBUF(obj);
    ASSERT(wbuf != NULL);

    /* By version, determine offset and current length (where needed) */
    switch (ver) {
    case OF_VERSION_1_0:
        offset = 8;
        cur_len = _WIRE_MATCH_PADDED_LEN(obj, offset);
        break;
    case OF_VERSION_1_1:
        offset = 48;
        cur_len = _WIRE_MATCH_PADDED_LEN(obj, offset);
        break;
    case OF_VERSION_1_2:
    case OF_VERSION_1_3:
        offset = 48;
        cur_len = _WIRE_MATCH_PADDED_LEN(obj, offset);
        break;
    default:
        ASSERT(0);
    }

    abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, offset);
    ASSERT(abs_offset >= 0);
    ASSERT(cur_len >= 0 && cur_len < 64 * 1024);

    /* Match object */
    OF_TRY(of_match_serialize(ver, match, &match_octets));
    new_len = match_octets.bytes;
    of_wire_buffer_replace_data(wbuf, abs_offset, cur_len,
        match_octets.data, new_len);
    /* Free match serialized octets */
    FREE(match_octets.data);

    /* Not scalar, update lengths if needed */
    delta = new_len - cur_len;
    if (delta != 0) {
        /* Update parent(s) */
        of_object_parent_length_update((of_object_t *)obj, delta);
    }

    OF_LENGTH_CHECK_ASSERT(obj);

    return OF_ERROR_NONE;
}
コード例 #2
0
int
of_list_append_bind(of_object_t *parent, of_object_t *child)
{
    if (parent == NULL || child == NULL ||
           parent->wbuf == NULL) {
        return OF_ERROR_PARAM;
    }

    if (!of_object_can_grow(parent, parent->length + child->length)) {
        return OF_ERROR_RESOURCE;
    }

    object_child_attach(parent, child, parent->length, 
                        child->length);

    /* Update the wire length and type if needed */
    of_object_wire_length_set(child, child->length);
    of_object_wire_type_set(child);

    /* Update the parent's length */
    of_object_parent_length_update(parent, child->length);

    OF_LENGTH_CHECK_ASSERT(parent);

    return OF_ERROR_NONE;
}
コード例 #3
0
/**
 * Set data in an object of type of_packet_in.
 * @param obj Pointer to an object of type of_packet_in.
 * @param data The value to write into the object
 */
int WARN_UNUSED_RESULT
of_packet_in_data_set(
    of_packet_in_t *obj,
    of_octets_t *data)
{
    of_wire_buffer_t *wbuf;
    int offset = 0; /* Offset of value relative to the start obj */
    int abs_offset; /* Offset of value relative to start of wbuf */
    of_version_t ver;
    int cur_len = 0; /* Current length of object data */
    int new_len, delta; /* For set, need new length and delta */

    ASSERT(obj->object_id == OF_PACKET_IN);
    ver = obj->version;
    wbuf = OF_OBJECT_TO_WBUF(obj);
    ASSERT(wbuf != NULL);

    /* By version, determine offset and current length (where needed) */
    switch (ver) {
    case OF_VERSION_1_0:
        offset = 18;
        cur_len = _END_LEN(obj, offset);
        break;
    case OF_VERSION_1_1:
        offset = 24;
        cur_len = _END_LEN(obj, offset);
        break;
    case OF_VERSION_1_2:
    case OF_VERSION_1_3:
        offset = _PACKET_IN_DATA_OFFSET(obj);
        cur_len = _END_LEN(obj, offset);
        break;
    default:
        ASSERT(0);
    }

    abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, offset);
    ASSERT(abs_offset >= 0);
    ASSERT(cur_len >= 0 && cur_len < 64 * 1024);
    new_len = data->bytes;
    of_wire_buffer_grow(wbuf, abs_offset + (new_len - cur_len));
    of_wire_buffer_octets_data_set(wbuf, abs_offset, data, cur_len);

    /* Not scalar, update lengths if needed */
    delta = new_len - cur_len;
    if (delta != 0) {
        /* Update parent(s) */
        of_object_parent_length_update((of_object_t *)obj, delta);
    }

    OF_LENGTH_CHECK_ASSERT(obj);

    return OF_ERROR_NONE;
}
コード例 #4
0
static int
flow_removed_setup_from_flow_add_common(of_flow_removed_t *obj,
                                        of_flow_add_t *flow_add,
                                        int removed_match_offset,
                                        int add_match_offset)
{
    int add_len, removed_len;
    of_wire_buffer_t *wbuf;
    int abs_offset;
    int delta;
    uint16_t val16;
    uint64_t cookie;
    of_octets_t match_octets;

    /* Transfer the match underlying object from add to removed obj */
    wbuf = OF_OBJECT_TO_WBUF(obj);
    removed_len = _WIRE_MATCH_PADDED_LEN(obj, removed_match_offset);
    add_len = _WIRE_MATCH_PADDED_LEN(flow_add, add_match_offset);

    match_octets.bytes = add_len;
    match_octets.data = OF_OBJECT_BUFFER_INDEX(flow_add, add_match_offset);

    /* Copy data into flow removed */
    abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, removed_match_offset);
    of_wire_buffer_replace_data(wbuf, abs_offset, removed_len,
                                match_octets.data, add_len);

    /* Not scalar, update lengths if needed */
    delta = add_len - removed_len;
    if (delta != 0) {
        /* Update parent(s) */
        of_object_parent_length_update((of_object_t *)obj, delta);
    }

    of_flow_add_cookie_get(flow_add, &cookie);
    of_flow_removed_cookie_set(obj, cookie);

    of_flow_add_priority_get(flow_add, &val16);
    of_flow_removed_priority_set(obj, val16);

    of_flow_add_idle_timeout_get(flow_add, &val16);
    of_flow_removed_idle_timeout_set(obj, val16);

    if (obj->version >= OF_VERSION_1_2) {
        of_flow_add_hard_timeout_get(flow_add, &val16);
        of_flow_removed_hard_timeout_set(obj, val16);
    }

    return OF_ERROR_NONE;
}
コード例 #5
0
int
of_packet_in_setup_from_flow_add(of_packet_in_t *obj,
                                 of_flow_add_t *flow_add)
{
    int add_len, pkt_in_len;
    of_wire_buffer_t *wbuf;
    int abs_offset;
    int delta;
    const int pkt_in_match_offset = 16;
    const int add_match_offset = 48;
    of_octets_t match_octets;

    if (obj->version < OF_VERSION_1_2) {
        /* Nothing to be done before OF 1.2 */
        return OF_ERROR_NONE;
    }

    /* Transfer match struct from flow add to packet in object */
    wbuf = OF_OBJECT_TO_WBUF(obj);
    pkt_in_len = _WIRE_MATCH_PADDED_LEN(obj, pkt_in_match_offset);
    add_len = _WIRE_MATCH_PADDED_LEN(flow_add, add_match_offset);

    match_octets.bytes = add_len;
    match_octets.data = OF_OBJECT_BUFFER_INDEX(flow_add, add_match_offset);

    /* Copy data into pkt_in msg */
    abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, pkt_in_match_offset);
    of_wire_buffer_replace_data(wbuf, abs_offset, pkt_in_len,
                                match_octets.data, add_len);

    /* Not scalar, update lengths if needed */
    delta = add_len - pkt_in_len;
    if (delta != 0) {
        /* Update parent(s) */
        of_object_parent_length_update((of_object_t *)obj, delta);
    }

    return OF_ERROR_NONE;
}
コード例 #6
0
/**
 * Generic atomic list append operation
 * @param list The list to which an item is being appended
 * @param item THe item to append to the list
 *
 * The contents of the item are copied to the end of the list.
 * Currently assumes the list is at the end of its parent.
 */
int
of_list_append(of_object_t *list, of_object_t *item)
{
    int new_len;

    new_len = list->length + item->length;

    if (!of_object_can_grow(list, new_len)) {
        return OF_ERROR_RESOURCE;
    }

    of_wire_buffer_grow(list->wbuf,
                        OF_OBJECT_ABSOLUTE_OFFSET(list, new_len));

    MEMCPY(OF_OBJECT_BUFFER_INDEX(list, list->length),
           OF_OBJECT_BUFFER_INDEX(item, 0), item->length);

    /* Update the list's length */
    of_object_parent_length_update(list, item->length);

    OF_LENGTH_CHECK_ASSERT(list);

    return OF_ERROR_NONE;
}
コード例 #7
0
ファイル: of_hello.c プロジェクト: milouxk/loxigen-artifacts
/**
 * Set elements in an object of type of_hello.
 * @param obj Pointer to an object of type of_hello.
 * @param elements Pointer to the child of type of_list_hello_elem_t.
 *
 * If the child's wire buffer is the same as the parent's, then
 * nothing is done as the changes have already been registered in the
 * parent.  Otherwise, the data in the child's wire buffer is inserted
 * into the parent's and the appropriate lengths are updated.
 */
int WARN_UNUSED_RESULT
of_hello_elements_set(
    of_hello_t *obj,
    of_list_hello_elem_t *elements)
{
    of_wire_buffer_t *wbuf;
    int offset = 0; /* Offset of value relative to the start obj */
    int abs_offset; /* Offset of value relative to start of wbuf */
    of_version_t ver;
    int cur_len = 0; /* Current length of object data */
    int new_len, delta; /* For set, need new length and delta */

    ASSERT(obj->object_id == OF_HELLO);
    ver = obj->version;
    wbuf = OF_OBJECT_TO_WBUF(obj);
    ASSERT(wbuf != NULL);

    /* By version, determine offset and current length (where needed) */
    switch (ver) {
    case OF_VERSION_1_3:
        offset = 8;
        cur_len = _END_LEN(obj, offset);
        break;
    default:
        ASSERT(0);
    }

    abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, offset);
    ASSERT(abs_offset >= 0);
    ASSERT(cur_len >= 0 && cur_len < 64 * 1024);

    /* LOCI object type */
    new_len = elements->length;
    /* If underlying buffer already shared; nothing to do */
    if (obj->wire_object.wbuf == elements->wire_object.wbuf) {
        of_wire_buffer_grow(wbuf, abs_offset + new_len);
        /* Verify that the offsets are correct */
        ASSERT(abs_offset == OF_OBJECT_ABSOLUTE_OFFSET(elements, 0));
        /* ASSERT(new_len == cur_len); */ /* fixme: may fail for OXM lists */
        return OF_ERROR_NONE;
    }

    /* Otherwise, replace existing object in data buffer */
    of_wire_buffer_replace_data(wbuf, abs_offset, cur_len,
        OF_OBJECT_BUFFER_INDEX(elements, 0), new_len);

    /* @fixme Shouldn't this precede copying value's data to buffer? */
    if (elements->wire_length_set != NULL) {
        elements->wire_length_set((of_object_t *)elements, elements->length);
    }

    /* Not scalar, update lengths if needed */
    delta = new_len - cur_len;
    if (delta != 0) {
        /* Update parent(s) */
        of_object_parent_length_update((of_object_t *)obj, delta);
    }

    OF_LENGTH_CHECK_ASSERT(obj);

    return OF_ERROR_NONE;
}
コード例 #8
0
static int
flow_stats_entry_setup_from_flow_add_common(of_flow_stats_entry_t *obj,
                                            of_flow_add_t *flow_add,
                                            of_object_t *effects,
                                            int entry_match_offset,
                                            int add_match_offset)
{
    int entry_len, add_len;
    of_wire_buffer_t *wbuf;
    int abs_offset;
    int delta;
    uint16_t val16;
    uint64_t cookie;
    of_octets_t match_octets;

    /* Transfer the match underlying object from add to stats entry */
    wbuf = OF_OBJECT_TO_WBUF(obj);
    entry_len = _WIRE_MATCH_PADDED_LEN(obj, entry_match_offset);
    add_len = _WIRE_MATCH_PADDED_LEN(flow_add, add_match_offset);

    match_octets.bytes = add_len;
    match_octets.data = OF_OBJECT_BUFFER_INDEX(flow_add, add_match_offset);

    /* Copy data into flow entry */
    abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, entry_match_offset);
    of_wire_buffer_replace_data(wbuf, abs_offset, entry_len,
                                match_octets.data, add_len);

    /* Not scalar, update lengths if needed */
    delta = add_len - entry_len;
    if (delta != 0) {
        /* Update parent(s) */
        of_object_parent_length_update((of_object_t *)obj, delta);
    }

    of_flow_add_cookie_get(flow_add, &cookie);
    of_flow_stats_entry_cookie_set(obj, cookie);

    of_flow_add_priority_get(flow_add, &val16);
    of_flow_stats_entry_priority_set(obj, val16);

    of_flow_add_idle_timeout_get(flow_add, &val16);
    of_flow_stats_entry_idle_timeout_set(obj, val16);

    of_flow_add_hard_timeout_get(flow_add, &val16);
    of_flow_stats_entry_hard_timeout_set(obj, val16);

    /* Effects may come from different places */
    if (effects != NULL) {
        if (obj->version == OF_VERSION_1_0) {
            OF_TRY(of_flow_stats_entry_actions_set(obj,
                (of_list_action_t *)effects));
        } else {
            OF_TRY(of_flow_stats_entry_instructions_set(obj,
                (of_list_instruction_t *)effects));
        }
    } else {
        if (obj->version == OF_VERSION_1_0) {
            of_list_action_t actions;
            of_flow_add_actions_bind(flow_add, &actions);
            OF_TRY(of_flow_stats_entry_actions_set(obj, &actions));
        } else {
            of_list_instruction_t instructions;
            of_flow_add_instructions_bind(flow_add, &instructions);
            OF_TRY(of_flow_stats_entry_instructions_set(obj, &instructions));
        }
    }

    return OF_ERROR_NONE;
}
コード例 #9
0
/**
 * Set actions in an object of type of_packet_out.
 * @param obj Pointer to an object of type of_packet_out.
 * @param actions Pointer to the child of type of_list_action_t.
 *
 * If the child's wire buffer is the same as the parent's, then
 * nothing is done as the changes have already been registered in the
 * parent.  Otherwise, the data in the child's wire buffer is inserted
 * into the parent's and the appropriate lengths are updated.
 */
int WARN_UNUSED_RESULT
of_packet_out_actions_set(
    of_packet_out_t *obj,
    of_list_action_t *actions)
{
    of_wire_buffer_t *wbuf;
    int offset = 0; /* Offset of value relative to the start obj */
    int abs_offset; /* Offset of value relative to start of wbuf */
    of_version_t ver;
    int cur_len = 0; /* Current length of object data */
    int new_len, delta; /* For set, need new length and delta */

    ASSERT(obj->object_id == OF_PACKET_OUT);
    ver = obj->version;
    wbuf = OF_OBJECT_TO_WBUF(obj);
    ASSERT(wbuf != NULL);

    /* By version, determine offset and current length (where needed) */
    switch (ver) {
    case OF_VERSION_1_0:
        offset = 16;
        cur_len = _PACKET_OUT_ACTION_LEN(obj);
        break;
    case OF_VERSION_1_1:
    case OF_VERSION_1_2:
    case OF_VERSION_1_3:
        offset = 24;
        cur_len = _PACKET_OUT_ACTION_LEN(obj);
        break;
    default:
        ASSERT(0);
    }

    abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, offset);
    ASSERT(abs_offset >= 0);
    ASSERT(cur_len >= 0 && cur_len < 64 * 1024);

    /* LOCI object type */
    new_len = actions->length;
    /* If underlying buffer already shared; nothing to do */
    if (obj->wire_object.wbuf == actions->wire_object.wbuf) {
        of_wire_buffer_grow(wbuf, abs_offset + new_len);
        /* Verify that the offsets are correct */
        ASSERT(abs_offset == OF_OBJECT_ABSOLUTE_OFFSET(actions, 0));
        /* ASSERT(new_len == cur_len); */ /* fixme: may fail for OXM lists */
        return OF_ERROR_NONE;
    }

    /* Otherwise, replace existing object in data buffer */
    of_wire_buffer_replace_data(wbuf, abs_offset, cur_len,
        OF_OBJECT_BUFFER_INDEX(actions, 0), new_len);

    /* Special case for setting action lengths */
    _PACKET_OUT_ACTION_LEN_SET(obj, actions->length);

    /* Not scalar, update lengths if needed */
    delta = new_len - cur_len;
    if (delta != 0) {
        /* Update parent(s) */
        of_object_parent_length_update((of_object_t *)obj, delta);
    }

    OF_LENGTH_CHECK_ASSERT(obj);

    return OF_ERROR_NONE;
}