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; }
of_object_t * of_object_new_from_message_preallocated(of_object_storage_t *storage, uint8_t *buf, int len) { of_object_t *obj = &storage->obj; of_wire_buffer_t *wbuf = &storage->wbuf; of_message_t msg = buf; of_version_t version; of_object_id_t object_id; memset(storage, 0, sizeof(*storage)); version = of_message_version_get(msg); if (!OF_VERSION_OKAY(version)) { return NULL; } if (of_validate_message(msg, len) != 0) { LOCI_LOG_ERROR("message validation failed\n"); return NULL; } obj->version = version; obj->wbuf = wbuf; wbuf->buf = msg; wbuf->alloc_bytes = len; wbuf->current_bytes = len; of_header_wire_object_id_get(obj, &object_id); of_object_init_map[object_id](obj, version, len, 0); return obj; }
of_object_t * of_object_new_from_message(of_message_t msg, int len) { of_object_id_t object_id; of_object_t *obj; of_version_t version; version = of_message_version_get(msg); if (!OF_VERSION_OKAY(version)) { return NULL; } if (of_validate_message(msg, len) != 0) { LOCI_LOG_ERROR("message validation failed\n"); return NULL; } if ((obj = of_object_new(-1)) == NULL) { return NULL; } if (of_object_buffer_bind(obj, OF_MESSAGE_TO_BUFFER(msg), len, OF_MESSAGE_FREE_FUNCTION) < 0) { FREE(obj); return NULL; } obj->version = version; of_header_wire_object_id_get(obj, &object_id); of_object_init_map[object_id](obj, version, len, 0); return obj; }
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); }