/** * 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; }
static int test_match_3(void) { of_match_t match1; of_match_t match2; int value = 1; of_octets_t octets; of_object_storage_t storage; memset(&storage, 0, sizeof(storage)); storage.obj.wbuf = &storage.wbuf; /* Serialize to version OF_VERSION_1_0 */ TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_0, value)) > 0); TEST_ASSERT(of_match_serialize(OF_VERSION_1_0, &match1, &octets) == OF_ERROR_NONE); storage.obj.wbuf->buf = octets.data; storage.obj.wbuf->alloc_bytes = octets.bytes; storage.obj.wbuf->current_bytes = octets.bytes; TEST_ASSERT(of_match_deserialize(OF_VERSION_1_0, &match2, &storage.obj, 0, octets.bytes) == OF_ERROR_NONE); TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0); FREE(octets.data); /* Serialize to version OF_VERSION_1_1 */ TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_1, value)) > 0); TEST_ASSERT(of_match_serialize(OF_VERSION_1_1, &match1, &octets) == OF_ERROR_NONE); storage.obj.wbuf->buf = octets.data; storage.obj.wbuf->alloc_bytes = octets.bytes; storage.obj.wbuf->current_bytes = octets.bytes; TEST_ASSERT(of_match_deserialize(OF_VERSION_1_1, &match2, &storage.obj, 0, octets.bytes) == OF_ERROR_NONE); TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0); FREE(octets.data); /* Serialize to version OF_VERSION_1_2 */ TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_2, value)) > 0); TEST_ASSERT(of_match_serialize(OF_VERSION_1_2, &match1, &octets) == OF_ERROR_NONE); storage.obj.wbuf->buf = octets.data; storage.obj.wbuf->alloc_bytes = octets.bytes; storage.obj.wbuf->current_bytes = octets.bytes; TEST_ASSERT(of_match_deserialize(OF_VERSION_1_2, &match2, &storage.obj, 0, octets.bytes) == OF_ERROR_NONE); TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0); FREE(octets.data); /* Serialize to version OF_VERSION_1_3 */ TEST_ASSERT((value = of_match_populate(&match1, OF_VERSION_1_3, value)) > 0); TEST_ASSERT(of_match_serialize(OF_VERSION_1_3, &match1, &octets) == OF_ERROR_NONE); storage.obj.wbuf->buf = octets.data; storage.obj.wbuf->alloc_bytes = octets.bytes; storage.obj.wbuf->current_bytes = octets.bytes; TEST_ASSERT(of_match_deserialize(OF_VERSION_1_3, &match2, &storage.obj, 0, octets.bytes) == OF_ERROR_NONE); TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0); FREE(octets.data); return TEST_PASS; }