void ipv4_get_ff(struct fins_module *module) {
	struct finsFrame *ff;
	do {
		secure_sem_wait(module->event_sem);
		secure_sem_wait(module->input_sem);
		ff = read_queue(module->input_queue);
		sem_post(module->input_sem);
	} while (module->state == FMS_RUNNING && ff == NULL); //TODO change logic here, combine with switch_to_ipv4?

	if (module->state != FMS_RUNNING) {
		if (ff != NULL) {
			freeFinsFrame(ff);
		}
		return;
	}

	if (ff->metaData == NULL) {
		PRINT_ERROR("Error fcf.metadata==NULL");
		exit(-1);
	}

	if (ff->dataOrCtrl == FF_CONTROL) {
		ipv4_fcf(module, ff);
		PRINT_DEBUG("");
	} else if (ff->dataOrCtrl == FF_DATA) {
		if (ff->dataFrame.directionFlag == DIR_UP) {
			ipv4_in_fdf(module, ff);
			PRINT_DEBUG("");
		} else if (ff->dataFrame.directionFlag == DIR_DOWN) {
			ipv4_out_fdf(module, ff);
			PRINT_DEBUG("");
		} else {
			PRINT_ERROR("Error: Wrong value of fdf.directionFlag");
			exit(-1);
		}
	} else {
		PRINT_ERROR("Error: Wrong ff->dataOrCtrl value");
		exit(-1);
	}

}
void IP4_receive_fdf(void) {

	struct finsFrame* pff = NULL;
	uint32_t protocol;
	do {
		sem_wait(&Switch_to_IPv4_Qsem);
		pff = read_queue(Switch_to_IPv4_Queue);
		sem_post(&Switch_to_IPv4_Qsem);
	} while (ipv4_running && pff == NULL);

	if (!ipv4_running) {
		return;
	}

	if (pff->dataOrCtrl == CONTROL) {
		PRINT_DEBUG("Received frame: D/C: %d, DestID=%d, ff=%p, meta=%p", pff->dataOrCtrl, pff->destinationID.id, pff, pff->metaData);
		ipv4_fcf(pff);
	} else if (pff->dataOrCtrl == DATA) {
		PRINT_DEBUG("Received frame: D/C: %d, DestID=%d, ff=%p, meta=%p", pff->dataOrCtrl, pff->destinationID.id, pff, pff->metaData);
		PRINT_DEBUG("PDU Length: %d", pff->dataFrame.pduLength);
		PRINT_DEBUG("Data direction: %d", pff->dataFrame.directionFlag);
		PRINT_DEBUG("pdu=%p", pff->dataFrame.pdu);

		if (pff->dataFrame.directionFlag == UP) {
			PRINT_DEBUG("IP4_in");

			IP4_in(pff, (struct ip4_packet*) pff->dataFrame.pdu, pff->dataFrame.pduLength);

		} else if (pff->dataFrame.directionFlag == DOWN) {
			PRINT_DEBUG("IP4_out");

			metadata *params = pff->metaData;
			if (params == NULL) {
				PRINT_ERROR("todo error");
				freeFinsFrame(pff);
				return;
			}

			int ret = 0;
			ret += metadata_readFromElement(params, "send_protocol", &protocol) == META_FALSE;

			if (ret) {
				PRINT_ERROR("metadata read error: ret=%d", ret);
			}

			PRINT_DEBUG("%lu", my_ip_addr);
			PRINT_DEBUG("Transport protocol going out passed to IPv4: protocol=%u", protocol);
			switch (protocol) {
			case IP4_PT_ICMP:
				IP4_out(pff, pff->dataFrame.pduLength, my_ip_addr, IP4_PT_ICMP);
				break;
			case IP4_PT_TCP:
				IP4_out(pff, pff->dataFrame.pduLength, my_ip_addr, IP4_PT_TCP);
				break;
			case IP4_PT_UDP:
				IP4_out(pff, pff->dataFrame.pduLength, my_ip_addr, IP4_PT_UDP);
				break;
			default:
				PRINT_ERROR("invalid protocol: protocol=%u", protocol);
				/**
				 * TODO investigate why the freeFinsFrame below create segmentation fault
				 */
				freeFinsFrame(pff);
				break;
			}

		} else {
			PRINT_ERROR("Error: Wrong value of fdf.directionFlag");
			freeFinsFrame(pff);
		}
	} else {
		PRINT_ERROR("Error: Wrong pff->dataOrCtrl value");
		freeFinsFrame(pff);
	}

}