:: import of_g :: from loxi_utils import loxi_utils :: from loxi_front_end import type_maps /** * Test message validator * * Run the message validator on corrupt messages to ensure it catches them. */ #include "loci_log.h" #include <locitest/test_common.h> #include <loci/loci_validator.h> static int test_validate_fixed_length(void) { of_table_stats_request_t *obj = of_table_stats_request_new(OF_VERSION_1_0); of_message_t msg = OF_OBJECT_TO_MESSAGE(obj); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == 0); of_message_length_set(msg, of_message_length_get(msg) - 1); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == -1); of_table_stats_request_delete(obj); return TEST_PASS; }
static int test_validate_tlv16_list(void) { of_flow_modify_t *obj = of_flow_modify_new(OF_VERSION_1_0); of_list_action_t list; of_action_set_tp_dst_t element1; of_action_output_t element2; of_message_t msg; of_flow_modify_actions_bind(obj, &list); of_action_set_tp_dst_init(&element1, OF_VERSION_1_0, -1, 1); of_list_action_append_bind(&list, (of_action_t *)&element1); of_action_output_init(&element2, OF_VERSION_1_0, -1, 1); of_list_action_append_bind(&list, (of_action_t *)&element2); msg = OF_OBJECT_TO_MESSAGE(obj); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == 0); of_message_length_set(msg, of_message_length_get(msg) - 1); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == -1); of_message_length_set(msg, of_message_length_get(msg) + 2); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == -1); of_flow_modify_delete(obj); return TEST_PASS; }
static int test_validate_fixed_length(void) { of_table_stats_request_t *obj = of_table_stats_request_new(OF_VERSION_1_0); of_message_t msg = OF_OBJECT_TO_MESSAGE(obj); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == 0); of_message_length_set(msg, of_message_length_get(msg) - 1); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == -1); of_table_stats_request_delete(obj); return TEST_PASS; }
of_hello_t * of_hello_new_from_message(of_message_t msg) { of_hello_t *obj = NULL; of_version_t version; int length; if (msg == NULL) return NULL; version = of_message_version_get(msg); if (!OF_VERSION_OKAY(version)) return NULL; length = of_message_length_get(msg); if ((obj = (of_hello_t *)of_object_new(-1)) == NULL) { return NULL; } of_hello_init(obj, version, 0, 0); if ((of_object_buffer_bind((of_object_t *)obj, OF_MESSAGE_TO_BUFFER(msg), length, OF_MESSAGE_FREE_FUNCTION)) < 0) { FREE(obj); return NULL; } obj->length = length; obj->version = version; return obj; }
/** * 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)); }
void ind_cxn_bundle_add_handle(connection_t *cxn, of_object_t *obj) { uint32_t bundle_id; uint16_t flags; of_octets_t data; of_bundle_add_msg_bundle_id_get(obj, &bundle_id); of_bundle_add_msg_flags_get(obj, &flags); of_bundle_add_msg_data_get(obj, &data); bundle_t *bundle = find_bundle(cxn, bundle_id); if (bundle == NULL) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_BAD_ID); return; } /* Validate length */ if (data.bytes < OF_MESSAGE_HEADER_LENGTH || data.bytes != of_message_length_get(data.data)) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_MSG_BAD_LEN); AIM_LOG_WARN("Inconsistent bundled message length", bundle->id); return; } /* Limit number of messages in the bundle */ if (bundle->count >= OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_MSGS) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_MSG_TOO_MANY); AIM_LOG_WARN("Exceeded maximum number (%u) of messages in bundle %u", OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_MSGS, bundle->id); return; } /* Limit amount of memory used by the bundle */ if ((bundle->bytes + data.bytes) > OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_BYTES) { indigo_cxn_send_error_reply( cxn->cxn_id, obj, OF_ERROR_TYPE_BUNDLE_FAILED, OFPBFC_MSG_TOO_MANY); AIM_LOG_WARN("Exceeded maximum size (%u bytes) of messages in bundle %u", OFCONNECTIONMANAGER_CONFIG_MAX_BUNDLE_BYTES, bundle->id); return; } if (bundle->count == bundle->allocated) { /* Resize array */ uint32_t new_allocated = (bundle->allocated == 0 ? 1 : bundle->allocated * 2); bundle->msgs = aim_realloc(bundle->msgs, sizeof(*bundle->msgs) * new_allocated); bundle->allocated = new_allocated; } bundle->msgs[bundle->count++] = aim_memdup(data.data, data.bytes); bundle->bytes += data.bytes; }
static int test_validate_fixed_length_list(void) { of_table_stats_reply_t *obj = of_table_stats_reply_new(OF_VERSION_1_0); of_list_table_stats_entry_t list; of_table_stats_entry_t element; of_message_t msg; of_table_stats_reply_entries_bind(obj, &list); of_table_stats_entry_init(&element, OF_VERSION_1_0, -1, 1); of_list_table_stats_entry_append_bind(&list, &element); of_list_table_stats_entry_append_bind(&list, &element); msg = OF_OBJECT_TO_MESSAGE(obj); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == 0); of_message_length_set(msg, of_message_length_get(msg) - 1); TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == -1); of_table_stats_reply_delete(obj); return TEST_PASS; }
SwitchConnectionUtil::HandshakeResult SwitchConnectionUtil::attemptHandshake( std::shared_ptr<Poco::Net::SocketStream> socket, const of_version_t openFlowVersion) { uint8_t* receiveBuffer = new uint8_t[65536]; bool ioSuccess; // Do handshake - send an OpenFlow hello message to the switch of_hello_t* hello = of_hello_new(openFlowVersion); ioSuccess = SwitchConnectionUtil::writeOpenFlowToSocket(*socket, hello); of_hello_delete(hello); if (ioSuccess) { socket->flush(); ioSuccess = socket->good(); } if (!ioSuccess) { delete[] receiveBuffer; return HandshakeResult(HandshakeResult::HELLO_FAILED, OF_VERSION_UNKNOWN, 0); } ioSuccess = SwitchConnectionUtil::parseOpenFlowFromSocketToBuffer(receiveBuffer, *socket); if (!ioSuccess) { delete[] receiveBuffer; return HandshakeResult(HandshakeResult::HELLO_FAILED, OF_VERSION_UNKNOWN, 0); } if (of_message_type_get(receiveBuffer) != OF_OBJ_TYPE_HELLO) { delete[] receiveBuffer; return HandshakeResult(HandshakeResult::HELLO_FAILED, OF_VERSION_UNKNOWN, 0); } of_version_t switchVersion = of_message_version_get(receiveBuffer); if (switchVersion != openFlowVersion) { // send ERROR message to switch of_hello_failed_error_msg_t* errorMsg = of_hello_failed_error_msg_new(openFlowVersion); SwitchConnectionUtil::writeOpenFlowToSocket(*socket, errorMsg); of_hello_failed_error_msg_delete(errorMsg); delete[] receiveBuffer; return HandshakeResult(HandshakeResult::WRONG_OPENFLOW_VERSION, switchVersion, 0); } // now we send a feature request so we know the Switch id (DPID) of the switch that just connected. of_features_request_t* featReq = of_features_request_new(openFlowVersion); ioSuccess = SwitchConnectionUtil::writeOpenFlowToSocket(*socket, featReq); of_features_request_delete(featReq); if (ioSuccess) { socket->flush(); ioSuccess = socket->good(); } if (!ioSuccess) { delete[] receiveBuffer; return HandshakeResult(HandshakeResult::FEATURE_REQUEST_FAILED, switchVersion, 0); } // receive featureReply ioSuccess = SwitchConnectionUtil::parseOpenFlowFromSocketToBuffer(receiveBuffer, *socket); if (!ioSuccess) { delete[] receiveBuffer; return HandshakeResult(HandshakeResult::FEATURE_REQUEST_FAILED, switchVersion, 0); } if (of_message_type_get(receiveBuffer) != OF_OBJ_TYPE_FEATURES_REPLY) { delete[] receiveBuffer; return HandshakeResult(HandshakeResult::FEATURE_REQUEST_FAILED, switchVersion, 0); } uint64_t switchId; of_features_reply_t* featRep = of_object_new_from_message(receiveBuffer, of_message_length_get(receiveBuffer)); of_features_reply_datapath_id_get(featRep, &switchId); of_object_wire_buffer_steal(featRep, &receiveBuffer); of_features_reply_delete(featRep); delete[] receiveBuffer; return HandshakeResult(HandshakeResult::SUCCESS, switchVersion, switchId); }
static of_object_t * parse_message(uint8_t *data, of_object_storage_t *storage) { int len = of_message_length_get(data); return of_object_new_from_message_preallocated(storage, data, len); }