//mody by lv start add--------------------------------------------
int UDPNETSDK_Talk_Send(char *pBuf, int nLen)
{
	int ret = -1;
	NET_HEAD netHead;

		
	if (pBuf == NULL)
	{
		return -1;
	}
	if (nLen <= 0)
	{
		return -1;
	}
	if (g_server_info.hUdpListenSock <= 0)
	{
		return -1; 
	}

	netHead.nFlag = HDVS_FLAG;
	netHead.nCommand = NETCMD_TALK_DATA;
	netHead.nErrorCode = 0;
	netHead.nBufSize = nLen;
	netHead.nReserve = 0;

	printf("UDPNETSDK_Talk_Send ...\n");
	memcpy(g_talk_buffer, &netHead, sizeof(NET_HEAD));
	memcpy(g_talk_buffer+sizeof(NET_HEAD), pBuf, nLen);
	ret = sendto(g_server_info.hUdpListenSock, g_talk_buffer, nLen+sizeof(NET_HEAD), 0, (struct sockaddr*)&g_server_info.addr, sizeof(struct sockaddr));
	if (ret <= 0)
	{
		net_debug();
		return -1;
	}
	#if 0
	if(g_server_info.addr.sin_port > 0){
		ret = sendto(g_server_info.hUdpListenSock, g_talk_buffer, nLen+sizeof(NET_HEAD), 0, (struct sockaddr*)&g_server_info.addr, sizeof(struct sockaddr));
		if (ret <= 0)
		{
			net_debug();
			return -1;
		}
	}
	else{
		ret = send(g_server_info.hTalkbackSocket, g_talk_buffer, nLen+sizeof(NET_HEAD), 0);
		if (ret <= 0)
		{
			net_debug();
			return -1;
		}
	
	}
	#endif 
	
	return 0;
}
int NETSDK_Talk_Send(char *pBuf, int nLen)
{
	int ret = -1;
	NET_HEAD netHead;

	//printf("NETSDK_Talk_Send: %p %d %d\n", pBuf, nLen, g_server_info.hTalkbackSocket);

	if (pBuf == NULL)
	{
		return -1;
	}
	if (nLen <= 0)
	{
		return -1;
	}

	#if 0
	if (g_server_info.hTalkbackSocket <= 0 || g_server_info.hUdpListenSock <= 0)
	{
		return -1; 
	}
	#endif 
	

	netHead.nFlag = HDVS_FLAG;
	netHead.nCommand = NETCMD_TALK_DATA;
	netHead.nErrorCode = 0;
	netHead.nBufSize = nLen;
	netHead.nReserve = 0;

	memcpy(g_talk_buffer, &netHead, sizeof(NET_HEAD));
	memcpy(g_talk_buffer+sizeof(NET_HEAD), pBuf, nLen);
	
	if(g_server_info.nflag == TCP_FLAG){
		ret = send(g_server_info.hTalkbackSocket, g_talk_buffer, nLen+sizeof(NET_HEAD), 0);
		if (ret <= 0)
		{
			net_debug();
			return -1;
		}
	}
	else if(g_server_info.nflag == UDP_FLAG){
	ret = sendto(g_server_info.hUdpListenSock, g_talk_buffer, nLen+sizeof(NET_HEAD), 0, (struct sockaddr*)&g_server_info.addr, sizeof(struct sockaddr));
	if (ret <= 0)
	{
		net_debug();
		return -1;
	}
	}
	//mody by lv end add--------------------------------------------
	return 0;
}
int FreeAllClient()
{
	int nFreeNum = 0;
	CLIENT_INFO *pTmp = NULL;

	pthread_mutex_lock(&g_client_list.hClientMutex);
    
	while (g_client_list.pNext)
	{
		printf("Close TCP CMD Socket: %d<%d>\n", pTmp->hMsgSocket, __LINE__);

		pTmp = g_client_list.pNext;
		shutdown(pTmp->hMsgSocket, 2);
		close(pTmp->hMsgSocket);
		pTmp->hMsgSocket = -1;
		g_client_list.pNext = pTmp->pNext;
		free(pTmp);
		nFreeNum ++;
	}
	if (nFreeNum != g_client_list.nTotalNum)
	{
		net_debug();
	}

	g_client_list.nTotalNum = 0;
    
	pthread_mutex_unlock(&g_client_list.hClientMutex);
    
	return 0;
}
Example #4
0
void net_buffer_extract(struct net_buffer_t *buffer, struct net_msg_t *msg)
{
	struct net_t *net = buffer->net;
	struct net_node_t *node = buffer->node;

	assert(buffer->count >= msg->size);
	buffer->count -= msg->size;

	/* Extract message from list */
	if (!list_count(buffer->msg_list))
		panic("%s: empty message list", __FUNCTION__);
	if (list_dequeue(buffer->msg_list) != msg)
		panic("%s: message is not at buffer head", __FUNCTION__);

	/* Update occupancy stat */
	net_buffer_update_occupancy(buffer);

	/* Debug */
	net_debug("buf "
		"a=\"extract\" "
		"net=\"%s\" "
		"msg=%lld "
		"node=\"%s\" "
		"buf=\"%s\"\n",
		net->name,
		msg->id,
		node->name,
		buffer->name);

	/* Schedule events waiting for space in buffer. */
	net_buffer_wakeup(buffer);
}
Example #5
0
void net_buffer_insert(struct net_buffer_t *buffer, struct net_msg_t *msg)
{
	struct net_t *net = buffer->net;
	struct net_node_t *node = buffer->node;

	if (buffer->count + msg->size > buffer->size)
		panic("%s: not enough space in buffer", __FUNCTION__);
	buffer->count += msg->size;
	list_enqueue(buffer->msg_list, msg);

	/* Update occupancy stat */
	net_buffer_update_occupancy(buffer);

	/* Debug */
	net_debug("buf "
		"a=\"insert\" "
		"net=\"%s\" "
		"msg=%lld "
		"node=\"%s\" "
		"buf=\"%s\"\n",
		net->name,
		msg->id,
		node->name,
		buffer->name);
}
Example #6
0
void net_sim(char *debug_file_name) {
    struct net_t *net;
    double *inject_time; /* Next injection time (one per node) */

    /* Initialize */
    debug_init();
    esim_init();
    net_init();
    net_debug_category = debug_new_category(debug_file_name);

    /* Network to work with */
    if (!*net_sim_network_name) panic("%s: no network", __FUNCTION__);
    net = net_find(net_sim_network_name);
    if (!net) fatal("%s: network does not exist", net_sim_network_name);
    /* Initialize */
    inject_time = xcalloc(net->node_count, sizeof(double));

    /* FIXME: error for no dest node in network */

    /* Simulation loop */
    esim_process_events(TRUE);
    if (!strcmp(net_traffic_pattern, "") ||
            (!strcmp(net_traffic_pattern, "uniform"))) {
        net_traffic_uniform(net, inject_time);
    } else if (!strcmp(net_traffic_pattern, "command")) {
        while (1) {
            long long cycle;

            cycle = esim_domain_cycle(net_domain_index);
            if (cycle >= net_max_cycles) break;

            net_debug("___cycle %lld___ \n", cycle);
            esim_process_events(TRUE);
        }
    } else
        fatal("Network %s: unknown traffic pattern (%s). \n", net->name,
              net_traffic_pattern);

    /* Drain events */
    esim_process_all_events();

    /* Free */
    free(inject_time);

    /* Finalize */
    net_done();
    esim_done();
    debug_done();

    /* Finish program */
    mhandle_done();
    exit(0);
}
Example #7
0
static void net_traffic_uniform(struct net_t *net, double *inject_time)
{
	while (1)
	{
		struct net_node_t *node;
		struct net_node_t *dst_node;
		long long cycle;
		int i;

		/* Get current cycle */
		cycle = esim_domain_cycle(net_domain_index);
		if (cycle >= net_max_cycles)
			break;

		/* Inject messages */
		for (i = 0; i < net->node_count; i++)
		{
			/* Get end node */
			node = list_get(net->node_list, i);
			if (node->kind != net_node_end)
				continue;

			/* Turn for next injection? */
			if (inject_time[i] > cycle)
				continue;

			/* Get a random destination node */
			do
			{
				dst_node = list_get(net->node_list, random() %
						list_count(net->node_list));
			} while (dst_node->kind != net_node_end
					|| dst_node == node);

			/* Inject */
			while (inject_time[i] < cycle)
			{
				inject_time[i] += exp_random(net_injection_rate);
				if (net_can_send(net, node, dst_node, net_msg_size))
					net_send(net, node, dst_node, net_msg_size);
			}
		}
		/* Next cycle */
		net_debug("___ cycle %lld ___\n", cycle);
		esim_process_events(TRUE);
	}

}
// 退出UDP数据传输
BOOL ExistUdpUser(OPEN_CHANNEL openHead, unsigned long ip, unsigned long port)
{
	SEND_NODE *pNode = NULL;
	pthread_mutex_t hMutex;
    
	if (0 == openHead.nStreamType)
	{
		pNode = g_server_info.udpStreamSend1.pUdpSendList[openHead.nSerChn];
		hMutex = g_server_info.udpStreamSend1.hUdpSendListMutex[openHead.nSerChn];
	}
	else
	{
		pNode = g_server_info.udpStreamSend2.pUdpSendList[openHead.nSerChn];
		hMutex = g_server_info.udpStreamSend2.hUdpSendListMutex[openHead.nSerChn];
	}
    
	//net_debug();
    
	if (NULL == pNode)
	{
		return FALSE;
	}
        
	pthread_mutex_lock(&hMutex);
	pNode = pNode->pNext;
    
	while (pNode)
	{
		if ((pNode->nTcpCmdSock == openHead.nID) && (pNode->nUdpDataIP == ip) && (pNode->nUdpDataPort == port))
		{
			pthread_mutex_unlock(&hMutex);
			net_debug();
			return TRUE;
		}

		// Add the code by lvjh, 2008-04-17
		pNode = pNode->pNext;
	}
    
	pthread_mutex_unlock(&hMutex);

	//net_debug();
    
	return FALSE;
}
Example #9
0
void net_read_config(void) {
    struct config_t *config;
    struct list_t *net_name_list;
    char *section;
    int i;

    /* Configuration file */
    if (!*net_config_file_name) {
        net_domain_index = esim_new_domain(net_frequency);
        return;
    }

    /* Open network configuration file */
    config = config_create(net_config_file_name);
    if (*net_config_file_name) config_load(config);

    /* Section with generic configuration parameters */
    section = "General";

    /* Frequency */
    net_frequency = config_read_int(config, section, "Frequency", net_frequency);
    if (!IN_RANGE(net_frequency, 1, ESIM_MAX_FREQUENCY))
        fatal("%s: invalid value for 'Frequency'", net_config_file_name);

    /* Create frequency domain */
    net_domain_index = esim_new_domain(net_frequency);

    /* Create a temporary list of network names found in configuration
     * file */
    net_name_list = list_create();
    for (section = config_section_first(config); section;
            section = config_section_next(config)) {
        char *delim = ".";

        char section_str[MAX_STRING_SIZE];
        char *token;
        char *net_name;

        /* Create a copy of section name */
        snprintf(section_str, sizeof section_str, "%s", section);
        section = section_str;

        /* First token must be 'Network' */
        token = strtok(section, delim);
        if (strcasecmp(token, "Network")) continue;

        /* Second token is network name */
        net_name = strtok(NULL, delim);
        if (!net_name) continue;

        /* No third token */
        token = strtok(NULL, delim);
        if (token) continue;

        /* Insert new network name */
        net_name = xstrdup(net_name);
        list_add(net_name_list, net_name);
    }

    /* Print network names */
    net_debug("%s: loading network configuration file\n", net_config_file_name);
    net_debug("networks found:\n");
    for (i = 0; i < net_name_list->count; i++)
        net_debug("\t%s\n", (char *)list_get(net_name_list, i));
    net_debug("\n");

    /* Load networks */
    net_table = hash_table_create(0, 0);
    for (i = 0; i < net_name_list->count; i++) {
        struct net_t *network;
        char *net_name;

        net_name = list_get(net_name_list, i);
        network = net_create_from_config(config, net_name);

        hash_table_insert(net_table, net_name, network);
    }

    /* Free list of network names and configuration file */
    while (net_name_list->count) free(list_remove_at(net_name_list, 0));
    list_free(net_name_list);
    config_free(config);
}
Example #10
0
// 消息线程处理:先接收网络协议的头,然后判断,如果头正确,则处理命令或继续接收命令参数后再处理
int TcpMsgRecvThread()
{
	int ret = -1;
	char *recvBuf = NULL;
	NET_HEAD *netHead = NULL;
	char *pData = NULL;
	NET_HEAD keepalive;
	CLIENT_INFO *clientInfo = NULL;
	MSG_HEAD msgHead;
	int nRight = 0;

	fd_set fset;
	struct timeval to;

	pthread_detach(pthread_self());
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

	// 填充Keepalive数据
	keepalive.nFlag = HDVS_FLAG;
	keepalive.nCommand = NETCMD_KEEP_ALIVE;
	keepalive.nErrorCode = 0;
	keepalive.nBufSize = 0;
	keepalive.nReserve = 0;

	// 分配发送recvBuf
	recvBuf = (char *)malloc(NETCMD_MAX_SIZE);	// 100K
	if (recvBuf == NULL)
	{
		net_debug();
		restartSystem();
		return -1;
	}
	netHead = (NET_HEAD*)recvBuf;
	pData = recvBuf + sizeof(NET_HEAD);
	g_server_info.bServerExit = 0;

	while (!g_server_info.bServerExit)
	{
		pthread_mutex_lock(&g_server_info.msgThreadMutex);
		//printf("%s %d\n", __func__, __LINE__);
		// 等待用户登陆,加入命令线程池
		while (g_server_info.msgWaitThreadNum == 0) 
		{
			pthread_cond_wait(&g_server_info.msgThreadCond, &g_server_info.msgThreadMutex);
			if (g_server_info.bServerExit)
			{
				break;
			}
		}

		// 判断用户是否退出
		if (g_server_info.bServerExit)
		{
			pthread_mutex_unlock(&g_server_info.msgThreadMutex);
			continue;
		}
		
		// 查找已登陆的用户,但还未加入线程池
		clientInfo = FindWaitProccessClient();
		if ((clientInfo == NULL)||(clientInfo->nflag == UDP_FLAG))
		{
			pthread_mutex_unlock(&g_server_info.msgThreadMutex);
			printf("udp message quit!\n");
			break;
		}
		if (clientInfo->hMsgSocket <= 0)
		{
			continue;
		}
		
	
		// 更新用户线程池计数
		g_server_info.msgProcessThreadNum++;
		g_server_info.msgWaitThreadNum--;
		if (g_server_info.msgWaitThreadNum < 0)
		{
			g_server_info.msgWaitThreadNum = 0;
		}

		pthread_mutex_unlock(&g_server_info.msgThreadMutex);

		//
		FD_ZERO(&fset);
		memset(&to, 0, sizeof(to));

		clientInfo->nKeepAlive = 0;
		clientInfo->status = RUN;
		nRight = clientInfo->level;
		       
		while (STOP != clientInfo->status)
		{
			// 网络心跳
			clientInfo->nKeepAlive ++;
			if (clientInfo->nKeepAlive >= 10)
			{
				net_debug();
				printf("TCP_CMD_ERROR(%d): NOT KEEPALIVE!\n", clientInfo->hMsgSocket);
				break;
			}
					
			//接收网络协议的头
			ret = 0;
			ret = TcpReceive(clientInfo->hMsgSocket, (char *)netHead, sizeof(NET_HEAD));
			//ret = recv(clientInfo->hMsgSocket, (char *)netHead, sizeof(NET_HEAD), 0);
			if (ret < 0)
			{
				net_debug();
				printf("TCP_CMD_ERROR(%d): RECEIVE ERROR(NET_HEAD)!\n", clientInfo->hMsgSocket);
				break;
			}
			if (ret == 0)
			{
				printf("TCP_CMD_ERROR(%d): RECEIVE TIMEOUT(NET_HEAD)!\n", clientInfo->hMsgSocket);
				continue;
			}
			
			// 判断网络帧头是否正确
			if (netHead->nFlag != HDVS_FLAG)
			{
				printf("TCP_CMD_ERROR(%d): NET FLAG ERROR!\n", clientInfo->hMsgSocket);
				printf_bytes(recvBuf, 32);
				continue;
			}

			// 判断是否是心跳,如果是的话,则回复
			if (netHead->nCommand == NETCMD_KEEP_ALIVE)
			{
				//printf("NETCMD_KEEP_ALIVE(%d): %d\n", clientInfo->hMsgSocket, netHead->nReserve);

				clientInfo->nKeepAlive = 0;
				
				ret = send(clientInfo->hMsgSocket, &keepalive, sizeof(NET_HEAD), 0);
				if (ret < 0)
				{
					printf("TCP_CMD_ERROR(%d): SEND KEEPALIVE ERROR!\n", clientInfo->hMsgSocket);
					net_debug();
				}

				continue;
			}

			//printf("NetHead BufferSize: %d\n", netHead->nBufSize);

			// 接收网络命令参数
			if (netHead->nBufSize>0 && netHead->nBufSize<NETCMD_MAX_SIZE-sizeof(NET_HEAD))
			{
				ret = TcpReceive(clientInfo->hMsgSocket, pData, netHead->nBufSize);
				//ret = recv(clientInfo->hMsgSocket, pData, netHead->nBufSize, 0);
				if (ret < 0)
				{
					net_debug();
					printf("TCP_CMD_ERROR(%d): RECEIVE ERROR(CONTEXT)!\n", clientInfo->hMsgSocket);
					break;
				}
				if (ret == 0)
				{
					net_debug();
					printf("TCP_CMD_ERROR(%d): RECEIVE TIMEOUT(CONTEXT)!\n", clientInfo->hMsgSocket);
					continue;
				}
			}

			// 如果没有心跳,但有参数传过来,也可当心跳			
			clientInfo->nKeepAlive = 0;

			// 解析命令
			msgHead.nSock = clientInfo->hMsgSocket;
			msgHead.nCmd = netHead->nCommand;
			msgHead.nRight = nRight;
			msgHead.nErrorCode = 0;
			msgHead.nBufSize = netHead->nBufSize;
			msgHead.nflag = TCP_FLAG;
			g_server_info.nupdate_flag = TCP_FLAG;
			printf("%s %d %x\n", __func__, __LINE__, netHead->nCommand);
					

			ParseCommand(&msgHead, pData);
		}
		clientInfo->status = STOP;
		// 释放命令线程池的节点
		//printf("Cmd Exit(%d)!\n", clientInfo->hMsgSocket);

		StopUdpNode(clientInfo->hMsgSocket);
		StopTcpNode(clientInfo->hMsgSocket);
		pthread_cond_signal(&g_server_info.dataQuitThreadCond);
		WakeupStreamWait();
		usleep(1);

		// 刷新线程池的计数
		pthread_mutex_lock(&g_server_info.msgQuitThreadMutex);
		g_server_info.msgQuitThreadNum ++;
		g_server_info.msgProcessThreadNum --;
		if (g_server_info.msgProcessThreadNum < 0)
		{
			g_server_info.msgProcessThreadNum = 0;
		}
		pthread_mutex_unlock(&g_server_info.msgQuitThreadMutex);

		pthread_cond_signal(&g_server_info.msgQuitThreadCond);

	}
	
	g_server_info.nMsgThreadCount--;
	
	// 释放接收BUFFER
	if (recvBuf)
	{
		free(recvBuf);
		recvBuf = NULL;
	}
	
	return 0;
}
Example #11
0
int UdpReceive(int hSock, char *precvBuf, int nSize, struct sockaddr_in addr)
{
	int ret = 0;
	fd_set fset;
	struct timeval to;
	//struct sockaddr_in addr;
	int nLen = 0;
	int left = 0;
	int flag = 0;

	printf("UdpReceive ...\n");

	memset(&to, 0, sizeof(to));

	// 输入参数校验
	if (hSock<=0 || hSock>65535)
	{
		return -1;
	}
	if (precvBuf == NULL)
	{
		return -1;
	}
	if (nSize <= 0)
	{
		return -1;
	}

	while (left < nSize)
	{
		FD_ZERO(&fset);
		FD_SET(hSock, &fset);
		to.tv_sec = SOCK_TIME_OUT*2;
		to.tv_usec = 0;

		// SOCKET接收超时或错误,则退出
		ret = select(hSock+1, &fset, NULL, NULL, &to);
		if ( ret == 0)
		{
			net_debug();
			return 0;
		}
		if (ret<0 && errno==EINTR)
		{
			net_debug();
			return 0;
		}
		if (ret < 0)
		{
			net_debug();
			return -1;
		}

		if (!FD_ISSET(hSock, &fset))
		{
			net_debug();
			return -1;
		}
		
		// 接收数据
		nLen = sizeof(addr);
		//ret = recv(hSock, precvBuf + left, nSize - left, 0);
		ret = recvfrom(hSock, precvBuf + left, nSize - left, MSG_WAITALL, (struct sockaddr*)&addr, (socklen_t *)&nLen);
		
		// add the code by lvjh, 2009-08-06
		if (flag > 20)
		{
			net_debug();
			return -1;
		}
		
		if ( (ret < 0) && (errno == EAGAIN || errno == EINTR))
		{
			flag++;
			net_debug();
			continue;
		}
		if (ret == 0 && errno == 115)
		{
			flag++;
			net_debug();
			continue;
			//return -1;
		}

		//if (ret < 0)
		//{
		//	printf("Socket(%d): %s %d\n", hSock, __FILE__, __LINE__);
		//	net_debug();
		//	return -1;
		//}
		
		if (ret <= 0)
		{
			net_debug();
			return -1;
		}
		
		left += ret;
	}
	
	//printf("TcpReceive OK\n");

	return left;
}
Example #12
0
// UDP数据发送线程
int UdpSendThread(void *pPar)
{
	unsigned long lPar = 0;
	int channelNo = 0;
	int streamNo = 0;
	int opt;
	int ret;
	BOOL bRet;
	BOOL bMultiSend = FALSE;
	BOOL bFirstRead = TRUE;
	int hTcpDataSock = -1;

	int send_sample_size = 0;

	SEND_NODE *pHeadNode = NULL;
	SEND_NODE *pSendNode = NULL;

	pthread_mutex_t hNodeMutex;
    
	READ_POSITION	*pReadPos = NULL;
	CHANNEL_STREAM	*pStream = NULL;
	NET_DATA_PACKET  netDataPack;

	struct sockaddr_in addr;

	// Add the code by lvjh, 2008-02-29
	struct timeval tv;
	unsigned long long nStartTimeCount = 0;
	unsigned long long nCurTimeCount = 0;
	unsigned long nCount = 0;

	OPEN_CHANNEL closeHead;

	lPar = (unsigned long *)pPar;

	channelNo = LowWord(lPar);
	streamNo = HeightWord(lPar);

	pthread_detach(pthread_self());
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);

	bzero(&addr,sizeof(addr));
	bzero(&netDataPack,sizeof(NET_DATA_PACKET));

	// 判断是哪一种码流
	addr.sin_family = AF_INET; 
	if (0 == streamNo)
	{
		pHeadNode = g_server_info.udpStreamSend1.pUdpSendList[channelNo];
		hNodeMutex = g_server_info.udpStreamSend1.hUdpSendListMutex[channelNo];
	}
	else
	{
		pHeadNode = g_server_info.udpStreamSend2.pUdpSendList[channelNo];
		hNodeMutex = g_server_info.udpStreamSend2.hUdpSendListMutex[channelNo];
	}
    
	hTcpDataSock = socket(AF_INET, SOCK_DGRAM, 0);
	if (-1 == hTcpDataSock)
	{
		net_debug();
		return -1;
	}
    
	opt = SOCK_SNDRCV_LEN;
	setsockopt(hTcpDataSock, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
    
	if (0 == streamNo)
	{
		pStream = g_server_info.pChannelStream1[channelNo];
	}
	else
	{
		pStream = g_server_info.pChannelStream2[channelNo];
	}

	pReadPos = (READ_POSITION *)malloc(sizeof(READ_POSITION));
	bzero(pReadPos,sizeof(READ_POSITION));
	pthread_setspecific(g_server_info.hReadPosKey,pReadPos);
	pReadPos->nBegin = 0;
	pReadPos->nEnd = 1;
	pReadPos->bLost = FALSE;

	// Add the code by lvjh, 2008-02-29
	gettimeofday (&tv, NULL);

	while (!g_server_info.bServerExit)
	{
		// 等待用户连接数据通道
		pthread_mutex_lock(&pStream->hReadBlockMutex);

		while ((pReadPos->nBegin == pReadPos->nEnd) && (pReadPos->nBegin == pStream->nWritePos))
		{
			pthread_cond_wait(&pStream->hReadBlockCond,&pStream->hReadBlockMutex);
		}

		pthread_mutex_unlock(&pStream->hReadBlockMutex);

		if (g_server_info.bServerExit)
		{
			break;
		}
		
		if (0 == GetUdpRunNode(channelNo,streamNo))
		{
			usleep(100000);
			pReadPos->nBegin = pStream->nWritePos;
			pReadPos->nEnd = pStream->nWritePos;
			bFirstRead = TRUE;

			continue;
		}
        
		bMultiSend = FALSE;

		// 从码流BUFFER取数据包
		bRet = GetOnePacket(pStream, &netDataPack,pReadPos, bFirstRead);
		if (!bRet)
		{
			net_debug();
			usleep(40000);	// Add the code by lvjh, 2008-03-27
			printf("GetOnePacket(UDP): %d\n", bRet);
			continue;
		}

		bFirstRead = FALSE;

		// 开始处理码流传输
		pthread_mutex_lock(&hNodeMutex);
		pSendNode = pHeadNode->pNext;
        
		while (pSendNode)
		{
			addr.sin_family = AF_INET;
			addr.sin_addr.s_addr = pSendNode->nUdpDataIP;
			addr.sin_port = pSendNode->nUdpDataPort;

			if (pSendNode->nType == PROTOCOL_UDP)							// UDP传输
			{
			//	printf("g_server_info.hUdpListenSock  = %d :%s : %d\n",g_server_info.hUdpListenSock, pSendNode->nUdpDataIP, pSendNode->nUdpDataPort); 
				ret = sendto(g_server_info.hUdpListenSock, &netDataPack, netDataPack.packHead.nSize+sizeof(netDataPack.packHead), 0, (struct sockaddr *)&addr, sizeof(addr));
			//		ret = sendto(hTcpDataSock, &netDataPack, netDataPack.packHead.nSize+sizeof(netDataPack.packHead), 0, (struct sockaddr *)&addr, sizeof(addr));
			}
			else if (!bMultiSend &&(pSendNode->nType == PROTOCOL_MULTI))	// MULTI传输
			{
				ret = sendto(hTcpDataSock, &netDataPack, netDataPack.packHead.nSize+sizeof(netDataPack.packHead), 0, (struct sockaddr *)&addr, sizeof(addr));
			
				/*
				// Add the code by lvjh, 2008-05-12
				opt = inet_addr(g_wire_ip);
				ret = setsockopt(hTcpDataSock, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt));
				ret = sendto(hTcpDataSock, &netDataPack, netDataPack.packHead.nSize+sizeof(netDataPack.packHead), 0, (struct sockaddr *)&addr, sizeof(addr));
				
				opt = inet_addr(g_wireless_ip);
				ret = setsockopt(hTcpDataSock, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt));
				ret = sendto(hTcpDataSock, &netDataPack, netDataPack.packHead.nSize+sizeof(netDataPack.packHead), 0, (struct sockaddr *)&addr, sizeof(addr));
				*/
				bMultiSend = TRUE;
			}
			if (ret < 1)
			{
				net_debug();
			}   
             
			pSendNode = pSendNode->pNext;
		}
		pthread_mutex_unlock(&hNodeMutex);

		//usleep(10000);

		/*
		// Add the code by lvjh, 2008-02-29
		gettimeofday (&tv, NULL);
		nCurTimeCount = tv.tv_sec*1000000+tv.tv_usec;
		nCount = nCurTimeCount-nStartTimeCount;
		if (nCount < g_send_sleep)
		{
			usleep(g_send_sleep-nCount);
		}
		*/

	}
    
	return 0;
}
Example #13
0
void net_event_handler(int event, void *data)
{
	struct net_stack_t *stack = data;

	struct net_t *net = stack->net;
	struct net_routing_table_t *routing_table = net->routing_table;
	struct net_packet_t *pkt= stack->packet;

	struct net_node_t *src_node = pkt->msg->src_node;
	struct net_node_t *dst_node = pkt->msg->dst_node;

	struct net_node_t *node = pkt->node;
	struct net_buffer_t *buffer = pkt->buffer;

	long long cycle;

	/* Get current cycle */
	cycle = esim_domain_cycle(net_domain_index);

	if ((net_snap_period != 0) &&
	                (net->last_recorded_cycle < (cycle/net_snap_period )))
	        net_bandwidth_snapshot(net, cycle);

	if (event == EV_NET_SEND)
	{
		struct net_routing_table_entry_t *entry;
		struct net_buffer_t *output_buffer;

		if (net->magicNet)
		{
			/* Magic Net work-around */
			src_node->bytes_sent += pkt->size;
			src_node->msgs_sent++;
			dst_node->bytes_received += pkt->size;
			dst_node->msgs_received++;
			pkt->node = dst_node;
			esim_schedule_event(EV_NET_RECEIVE, stack,
				net->fixed_delay);
		}

		/* Get output buffer */
		entry = net_routing_table_lookup(routing_table, src_node,
				dst_node);
		output_buffer = entry->output_buffer;
		if (!output_buffer)
			fatal("%s: no route from %s to %s.\n%s", net->name,
					src_node->name, dst_node->name,
					net_err_no_route);

		if (pkt->msg->size > output_buffer->size)
			panic("%s: message does not fit in buffer.\n%s",
					__FUNCTION__, net_err_can_send);

		if (output_buffer->count + pkt->size > output_buffer->size)
			panic("%s: output buffer full.\n%s", __FUNCTION__,
					net_err_can_send);

		/* Insert in output buffer (1 cycle latency) */
		net_buffer_insert(output_buffer, pkt);
		output_buffer->write_busy = cycle;
		pkt->node = src_node;
		pkt->buffer = output_buffer;
		pkt->busy = cycle;

		/* Schedule next event */
		esim_schedule_event(EV_NET_OUTPUT_BUFFER, stack, 1);

	}

	else if (event == EV_NET_OUTPUT_BUFFER)
	{
		struct net_buffer_t *input_buffer;
		int lat;

		/* Debug */
		net_debug("msg "
				"a=\"obuf\" "
				"net=\"%s\" "
				"msg-->pkt=%lld-->%d "
				"node=\"%s\" "
				"buf=\"%s\"\n",
				net->name,
				pkt->msg->id,
				pkt->session_id,
				node->name,
				buffer->name);

		/* If message is not at buffer head, process later */
		assert(list_count(buffer->msg_list));

		if (list_get(buffer->msg_list, 0) != pkt)
		{
			net_buffer_wait(buffer, event, stack);
			net_debug("msg "
					"a=\"stall\" "
					"net=\"%s\" "
					"msg-->packet=%lld:%d "
					"why=\"not output buffer head\"\n",
					net->name,
					pkt->msg->id,
					pkt->session_id);
			return;
		}

		if (buffer->read_busy >= cycle)
		{
			esim_schedule_event(event, stack,
					buffer->read_busy - cycle + 1);
			net_debug("msg "
					"a=\"stall\" "
					"net=\"%s\" "
					"msg-->pkt=%lld:%d "
					"why=\"output buffer busy\" \n",
					net->name,
					pkt->msg->id,
					pkt->session_id);
			return;
		}

		/* If link is busy, wait */
		if (buffer->kind == net_buffer_link)
		{
			struct net_link_t *link;

			assert(buffer->link);
			link = buffer->link;
			if (link->busy >= cycle)
			{
				esim_schedule_event(event, stack,
						link->busy - cycle + 1);
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"link busy\"\n",
						net->name,
						pkt->msg->id,
						pkt->session_id);

				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:link_busy\" "
						"stg=\"LB\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);
				return;
			}

			/* If buffer contain the message but doesn't have the 
			 * shared link in control, wait */
			if (link->virtual_channel > 1)
			{
				struct net_buffer_t *temp_buffer;

				temp_buffer = net_link_arbitrator_vc(link, node);
				if (temp_buffer != buffer)
				{
					net_debug("msg "
							"a=\"stall\" "
							"net=\"%s\" "
							"msg-->pkt=%lld:%d "
							"why=\"arbitrator sched\"\n",
							net->name,
							pkt->msg->id,
							pkt->session_id);
					esim_schedule_event(event, stack, 1);

					net_trace("net.packet "
							"net=\"%s\" "
							"name=\"P-%lld:%d\" "
							"state=\"%s:%s:VC_arbitration_fail\" "
							"stg=\"VCA\"\n",
							net->name, pkt->msg->id,
							pkt->session_id,
							node->name,
							buffer->name);
					return;
				}
			}

			/* If destination input buffer is busy, wait */
			assert(buffer == link->src_buffer);
			input_buffer = link->dst_buffer;
			if (input_buffer->write_busy >= cycle)
			{
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"input buffer busy\"\n",
						net->name, pkt->msg->id,
						pkt->session_id);
				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:Dest_buffer_busy\" "
						"stg=\"DBB\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				esim_schedule_event(event, stack,
						input_buffer->write_busy - cycle + 1);
				return;
			}

			/* If destination input buffer is full, wait */
			if (pkt->size > input_buffer->size)
				fatal("%s: packet does not fit in buffer.\n%s",
						net->name, net_err_large_message);
			if (input_buffer->count + pkt->size >
			input_buffer->size)
			{
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"input buffer full\"\n",
						net->name, pkt->msg->id, pkt->session_id);
				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:Dest_buffer_full\" "
						"stg=\"DBF\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				net_buffer_wait(input_buffer, event, stack);
				return;
			}

			/* Calculate latency and occupy resources */
			lat = (pkt->size - 1) / link->bandwidth + 1;
			assert(lat > 0);
			buffer->read_busy = cycle + lat - 1;
			link->busy = cycle + lat - 1;
			input_buffer->write_busy = cycle + lat - 1;

			/* Transfer message to next input buffer */
			assert(pkt->busy < cycle);
			net_buffer_extract(buffer, pkt);
			net_buffer_insert(input_buffer, pkt);
			pkt->node = input_buffer->node;
			pkt->buffer = input_buffer;
			pkt->busy = cycle + lat - 1;

			/* Stats */
			link->busy_cycles += lat;
			link->transferred_bytes += pkt->size;
			link->transferred_msgs++;

			net->topology_util_bw += pkt->size;

			node->bytes_sent += pkt->size;
			node->msgs_sent++;
			input_buffer->node->bytes_received += pkt->size;
			input_buffer->node->msgs_received++;
			net_trace("net.link_transfer net=\"%s\" link=\"%s\" "
					"transB=%lld last_size=%d busy=%lld\n",
					net->name, link->name,
					link->transferred_bytes,
					pkt->size, link->busy);
		}
		else if (buffer->kind == net_buffer_bus)
		{
			struct net_bus_t *bus, *updated_bus;
			struct net_node_t *bus_node;

			assert(!buffer->link);
			assert(buffer->bus);
			bus = buffer->bus;
			bus_node = bus->node;

			/* before initiating bus transfer we have to figure out what is the
			 * next input buffer since it is not clear from the
			 * output buffer */
			int input_buffer_detection = 0;
			struct net_routing_table_entry_t *entry;

			entry = net_routing_table_lookup(routing_table,
					pkt->node, pkt->msg->dst_node);

			for (int i = 0; i < list_count(bus_node->dst_buffer_list); i++)
			{
				input_buffer = list_get(bus_node->dst_buffer_list, i);
				if (entry->next_node == input_buffer->node)
				{
					input_buffer_detection = 1;
					break;
				}
			}
			if (input_buffer_detection == 0)
				fatal("%s: Something went wrong so there is no appropriate input"
						"buffer for the route between %s and %s \n", net->name,
						pkt->node->name,entry->next_node->name);

			/* 1. Check the destination buffer is busy or not */
			if (input_buffer->write_busy >= cycle)
			{
				esim_schedule_event(event, stack,
						input_buffer->write_busy - cycle + 1);
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"input busy\"\n",
						net->name,
						pkt->msg->id,
						pkt->session_id);

				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:Dest_buffer_busy\" "
						"stg=\"DBB\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				return;
			}

			/* 2. Check the destination buffer is full or not */
			if (pkt->size > input_buffer->size)
				fatal("%s: packet  does not fit in buffer.\n%s",
						net->name, net_err_large_message);

			if (input_buffer->count + pkt->size > input_buffer->size)
			{
				net_buffer_wait(input_buffer, event, stack);
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"input full\"\n",
						net->name, pkt->msg->id,
						pkt->session_id);

				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:Dest_buffer_full\" "
						"stg=\"DBF\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				return;
			}

			/* 3. Make sure if any bus is available; return one
			 * that is available the fastest */
			updated_bus = net_bus_arbitration(bus_node, buffer);
			if (updated_bus == NULL)
			{
				esim_schedule_event(event, stack, 1);
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"bus arbiter\"\n",
						net->name, pkt->msg->id,
						pkt->session_id);
				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:BUS_arbit_fail\" "
						"stg=\"BA\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				return;
			}

			/* 4. assign the bus to the buffer. update the
			 * necessary data ; before here, the bus is not
			 * assign to anything and is not updated so it can be 
			 * assign to other buffers as well. If this certain
			 * buffer wins that specific bus_lane the appropriate
			 * fields will be updated. Contains: bus_lane
			 * cin_buffer and cout_buffer and busy time as well as
			 * buffer data itself */
			assert(updated_bus);
			buffer->bus = updated_bus;
			input_buffer->bus = updated_bus;
			bus = buffer->bus;
			assert(bus);


			/* Calculate latency and occupy resources */
			/* Wire delay is introduced when the packet is on transit */
			lat = bus->fix_delay + ((pkt->size - 1) / bus->bandwidth + 1) ;
			assert(lat > 0);
			buffer->read_busy = cycle + lat - 1;
			bus->busy = cycle + lat - 1;
			input_buffer->write_busy = cycle + lat - 1 ;

			/* Transfer message to next input buffer */
			assert(pkt->busy < cycle);
			net_buffer_extract(buffer, pkt);
			net_buffer_insert(input_buffer, pkt);
			pkt->node = input_buffer->node;
			pkt->buffer = input_buffer;
			pkt->busy = cycle + lat - 1;

			/* Stats */
			bus->busy_cycles += lat;
			bus->transferred_bytes += pkt->size;
			bus->transferred_msgs++;

                        net->topology_util_bw += pkt->size;

			node->bytes_sent += pkt->size;
			node->msgs_sent++;
			input_buffer->node->bytes_received += pkt->size;
			input_buffer->node->msgs_received++;
			net_trace("net.bus_transfer net=\"%s\" node=\"%s\" "
					"lane_index=%d transB=%lld last_size=%d busy=%lld\n",
					net->name, bus->node->name, bus->index,
					bus->transferred_bytes, pkt->size, bus->busy);
		}

		else if (buffer->kind == net_buffer_photonic)
		{
			struct net_bus_t *bus, *updated_bus;
			struct net_node_t *bus_node;

			assert(!buffer->link);
			assert(buffer->bus);
			bus = buffer->bus;
			bus_node = bus->node;

			/* before 1 and 2 we have to figure out what is the
			 * next input buffer since it is not clear from the
			 * output buffer */
			int input_buffer_detection = 0;
			struct net_routing_table_entry_t *entry;

			entry = net_routing_table_lookup(routing_table,
					pkt->node, pkt->msg->dst_node);

			for (int i = 0; i < list_count(bus_node->dst_buffer_list); i++)
			{
				input_buffer = list_get(bus_node->dst_buffer_list, i);
				if (entry->next_node == input_buffer->node)
				{
					input_buffer_detection = 1;
					break;
				}
			}
			if (input_buffer_detection == 0)
				fatal("%s: Something went wrong so there is no appropriate input"
						"buffer for the route between %s and %s \n", net->name,
						pkt->node->name,entry->next_node->name);

			/* 1. Check the destination buffer is busy or not */
			if (input_buffer->write_busy > cycle)
			{
				esim_schedule_event(event, stack,
						input_buffer->write_busy - cycle + 1);
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"input busy\"\n",
						net->name,
						pkt->msg->id,
						pkt->session_id);

				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:Dest_buffer_busy\" "
						"stg=\"DBB\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				return;
			}

			/* 2. Check the destination buffer is full or not */
			if (pkt->size > input_buffer->size)
				fatal("%s: message does not fit in buffer.\n%s",
						net->name, net_err_large_message);

			if (input_buffer->count + pkt->size > input_buffer->size)
			{
				net_buffer_wait(input_buffer, event, stack);
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"input full\"\n",
						net->name, pkt->msg->id,
						pkt->session_id);

				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:Dest_buffer_full\" "
						"stg=\"DBF\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				return;
			}


			/* 3. Make sure if any bus is available; return one
			 * that is available the fastest */
			updated_bus = net_photo_link_arbitration(bus_node, buffer);
			if (updated_bus == NULL)
			{
				esim_schedule_event(event, stack, 1);
				net_debug("msg "
						"a=\"stall\" "
						"net=\"%s\" "
						"msg-->pkt=%lld:%d "
						"why=\"bus arbiter\"\n",
						net->name, pkt->msg->id,
						pkt->session_id);

				net_trace("net.packet "
						"net=\"%s\" "
						"name=\"P-%lld:%d\" "
						"state=\"%s:%s:photonic_arbitration\" "
						"stg=\"BA\"\n",
						net->name, pkt->msg->id,
						pkt->session_id,
						node->name,
						buffer->name);

				return;
			}

			/* 4. assign the bus to the buffer. update the
			 * necessary data ; before here, the bus is not
			 * assign to anything and is not updated so it can be
			 * assign to other buffers as well. If this certain
			 * buffer wins that specific bus_lane the appropriate
			 * fields will be updated. Contains: bus_lane
			 * cin_buffer and cout_buffer and busy time as well as
			 * buffer data itself */
			assert(updated_bus);
			buffer->bus = updated_bus;
			input_buffer->bus = updated_bus;
			bus = buffer->bus;
			assert(bus);

			/* Calculate latency and occupy resources */
			lat = (pkt->size - 1) / bus->bandwidth + 1;
			assert(lat > 0);
			buffer->read_busy = cycle + lat - 1;
			bus->busy = cycle + lat - 1;
			input_buffer->write_busy = cycle + lat - 1;

			/* Transfer message to next input buffer */
			assert(pkt->busy < cycle);
			net_buffer_extract(buffer, pkt);
			net_buffer_insert(input_buffer, pkt);
			pkt->node = input_buffer->node;
			pkt->buffer = input_buffer;
			pkt->busy = cycle + lat - 1;

			/* Stats */
			bus->busy_cycles += lat;
			bus->transferred_bytes += pkt->size;
			bus->transferred_msgs++;

                        net->topology_util_bw += pkt->size;

			node->bytes_sent += pkt->size;
			node->msgs_sent++;
			input_buffer->node->bytes_received += pkt->size;
			input_buffer->node->msgs_received++;
			net_trace("net.photonic_transfer net=\"%s\" node=\"%s\" "
					"lane_index=%d transB=%lld last_size=%d busy=%lld\n",
					net->name, bus->node->name, bus->index,
					bus->transferred_bytes,pkt->size, bus->busy);
			net_debug("msg "
					"a=\"success photonic transmission\" "
					"net=\"%s\" "
					"msg-->pkt=%lld:%d "
					"through = \" %d\"\n",
					net->name, pkt->msg->id,
					pkt->session_id, updated_bus->index);
		}

		/* Schedule next event */
		esim_schedule_event(EV_NET_INPUT_BUFFER, stack, lat);
	}

	else if (event == EV_NET_INPUT_BUFFER)
	{
		struct net_routing_table_entry_t *entry;
		struct net_buffer_t *output_buffer;

		int lat;

		/* Debug */
		net_debug("msg "
				"a=\"ibuf\" "
				"net=\"%s\" "
				"msg-->pkt=%lld:%d "
				"node=\"%s\" "
				"buf=\"%s\"\n",
				net->name,
				pkt->msg->id,
				pkt->session_id,
				node->name,
				buffer->name);

		/* If message is not at buffer head, process later */
		assert(list_count(buffer->msg_list));
		if (list_get(buffer->msg_list, 0) != pkt)
		{
			net_debug("msg "
					"a=\"stall\" "
					"net=\"%s\" "
					"msg-->pkt=%lld:%d"
					"why=\"not-head\"\n",
					net->name, pkt->msg->id,
					pkt->session_id);
			net_buffer_wait(buffer, event, stack);
			return;
		}

		/* If this is the destination node, finish */
		if (node == pkt->msg->dst_node)
		{
			esim_schedule_event(EV_NET_RECEIVE, stack, 0);
			return;
		}

		/* If source input buffer is busy, wait */
		if (buffer->read_busy >= cycle)
		{
			net_debug("pkt"
					"a=\"stall\" "
					"net=\"%s\" "
					"msg-->pkt=%lld:%d "
					"why=\"src-busy\"\n",
					net->name,
					pkt->msg->id,
					pkt->session_id);

			esim_schedule_event(event, stack,
					buffer->read_busy - cycle + 1);
			return;
		}

		/* Get output buffer */
		entry = net_routing_table_lookup(routing_table, node,
				dst_node);
		output_buffer = entry->output_buffer;
		if (!output_buffer)
			fatal("%s: no route from %s to %s.\n%s", net->name,
					node->name, dst_node->name, net_err_no_route);

		/* If destination output buffer is busy, wait */
		if (output_buffer->write_busy >= cycle)
		{
			net_debug("pkt "
					"a=\"stall\" "
					"net=\"%s\" "
					"msg-->pkt=%lld:%d "
					"why=\"dst-busy\"\n",
					net->name,
					pkt->msg->id,
					pkt->session_id);
			net_trace("net.packet "
					"net=\"%s\" "
					"name=\"P-%lld:%d\" "
					"state=\"%s:%s:Dest_buffer_busy\" "
					"stg=\"DBB\"\n",
					net->name, pkt->msg->id,
					pkt->session_id,
					node->name,
					buffer->name);

			esim_schedule_event(event, stack,
					output_buffer->write_busy - cycle + 1);
			return;
		}

		/* If destination output buffer is full, wait */
		if (pkt->size > output_buffer->size)
			fatal("%s: packet does not fit in buffer.\n%s",
					net->name, net_err_large_message);


		if (output_buffer->count + pkt->size > output_buffer->size)
		{
			net_debug("pkt "
					"a=\"stall\" "
					"net=\"%s\" "
					"msg-->pkt=%lld:%d "
					"why=\"dst-full\"\n",
					net->name,
					pkt->msg->id,
					pkt->session_id);

			net_trace("net.packet "
					"net=\"%s\" "
					"name=\"P-%lld:%d\" "
					"state=\"%s:%s:Dest_buffer_full\" "
					"stg=\"DBF\"\n",
					net->name, pkt->msg->id,
					pkt->session_id,
					node->name,
					buffer->name);


			net_buffer_wait(output_buffer, event, stack);
			return;
		}

		/* If scheduler says that it is not our turn, try later */
		if (net_node_schedule(node, output_buffer) != buffer)
		{
			net_debug("pkt "
					"a=\"stall\" "
					"net=\"%s\" "
					"msg-->pkt=%lld:%d "
					"why=\"sched\"\n",
					net->name,
					pkt->msg->id,
					pkt->session_id);

			net_trace("net.packet "
					"net=\"%s\" "
					"name=\"P-%lld:%d\" "
					"state=\"%s:%s:switch_arbit_fail\" "
					"stg=\"SA\"\n",
					net->name, pkt->msg->id,
					pkt->session_id,
					node->name,
					buffer->name);

			esim_schedule_event(event, stack, 1);
			return;
		}

		/* Calculate latency and occupy resources */
		assert(node->kind != net_node_end);
		assert(node->bandwidth > 0);
		lat = (pkt->size - 1) / node->bandwidth + 1;
		assert(lat > 0);
		buffer->read_busy = cycle + lat - 1;
		output_buffer->write_busy = cycle + lat - 1;

		/* Transfer message to next output buffer */
		assert(pkt->busy < cycle);
		net_buffer_extract(buffer, pkt);
		net_buffer_insert(output_buffer, pkt);
		pkt->buffer = output_buffer;
		pkt->busy = cycle + lat - 1;

		/* Schedule next event */
		esim_schedule_event(EV_NET_OUTPUT_BUFFER, stack, lat);
	}

	else if (event == EV_NET_RECEIVE)
	{
		assert (pkt);
		struct net_msg_t *msg = pkt->msg;
		/* Debug */
		net_debug("pkt "
				"a=\"receive\" "
				"net=\"%s\" "
				"msg-->pkt=%lld:%d "
				"node=\"%s\"\n",
				net->name,
				pkt->msg->id,
				pkt->session_id,
				dst_node->name);

		if (net_depacketizer(net, node, pkt) == 1)
		{
			if (pkt->msg->packet_list_count > 1)
				net_trace("net.msg net=\"%s\" name=\"M-%lld\" "
						"state=\"%s:depacketize\"\n",
						net->name, msg->id, node->name);

			if (stack->ret_event == ESIM_EV_NONE)
			{
				assert (msg);
				net_receive(net, node, msg);

			}
			/* Finish */
			net_stack_return(stack);
		}
		else
			/* Freeing packet stack, not the message */
			free(stack);
	}

	else
	{
		panic("%s: unknown event", __FUNCTION__);
	}
}
Example #14
0
void net_sim(char *debug_file_name)
{
	struct net_t *net;
	double *inject_time;	/* Next injection time (one per node) */

	/* Initialize */
	debug_init();
	esim_init();
	net_init();
	net_debug_category = debug_new_category(debug_file_name);

	/* Network to work with */
	if (!*net_sim_network_name)
		panic("%s: no network", __FUNCTION__);
	net = net_find(net_sim_network_name);
	if (!net)
		fatal("%s: network does not exist", net_sim_network_name);
	/* Network Trace = Stand Alone */
        if (net_tracing())
        {
                /* Initialization of Trace */
                 net_trace_header("net.init version=\"%d.%d\"\n",
                                 NET_SYSTEM_TRACE_VERSION_MAJOR, NET_SYSTEM_TRACE_VERSION_MINOR);

                 /* Network Trace Header */
                 net_config_trace(net);
        }
	inject_time = xcalloc(net->node_count, sizeof(double));

	/* FIXME: error for no dest node in network */

	/* Simulation loop */
	esim_process_events(TRUE);
	if (!strcmp(net_traffic_pattern, "") ||
			(!strcmp(net_traffic_pattern, "uniform")))
	{
		net_traffic_uniform(net, inject_time);
	}
	else if (!strcmp(net_traffic_pattern, "command"))
	{
		while(1)
		{
			long long cycle;

			cycle = esim_domain_cycle(net_domain_index);
			if (cycle >= net_max_cycles)
				break;

			net_debug("___cycle %lld___ \n", cycle);
			esim_process_events(TRUE);
		}
	}
	else
		fatal("Network %s: unknown traffic pattern (%s). \n", net->name
				,net_traffic_pattern);


	/* Drain events */
	esim_process_all_events();

	/* Free */
	free(inject_time);

	/* Finalize */
	net_done();
	esim_done();
	trace_done();
	debug_done();
}
Example #15
0
void net_event_handler(int event, void *data)
{
	struct net_stack_t *stack = data;
	struct net_t *net = stack->net;
	struct net_routing_table_t *routing_table = net->routing_table;
	struct net_msg_t *msg = stack->msg;

	struct net_node_t *src_node = msg->src_node;
	struct net_node_t *dst_node = msg->dst_node;

	struct net_node_t *node = msg->node;
	struct net_buffer_t *buffer = msg->buffer;

	if (event == EV_NET_SEND)
	{
		struct net_routing_table_entry_t *entry;
		struct net_buffer_t *output_buffer;

		/* Debug */
		net_debug("msg "
			"a=\"send\" "
			"net=\"%s\" "
			"msg=%lld "
			"size=%d "
			"src=\"%s\" "
			"dst=\"%s\"\n",
			net->name,
			msg->id,
			msg->size,
			src_node->name,
			dst_node->name);

		/* Get output buffer */
		entry = net_routing_table_lookup(routing_table, src_node, dst_node);
		output_buffer = entry->output_buffer;
		if (!output_buffer)
			fatal("%s: no route from %s to %s.\n%s", net->name, src_node->name,
				dst_node->name, net_err_no_route);
		if (output_buffer->write_busy >= esim_cycle)
			panic("%s: output buffer busy.\n%s", __FUNCTION__, net_err_can_send);
		if (msg->size > output_buffer->size)
			panic("%s: message does not fit in buffer.\n%s", __FUNCTION__, net_err_can_send);
		if (output_buffer->count + msg->size > output_buffer->size)
			panic("%s: output buffer full.\n%s", __FUNCTION__, net_err_can_send);

		/* Insert in output buffer (1 cycle latency) */
		net_buffer_insert(output_buffer, msg);
		output_buffer->write_busy = esim_cycle;
		msg->node = src_node;
		msg->buffer = output_buffer;
		msg->busy = esim_cycle;

		/* Schedule next event */
		esim_schedule_event(EV_NET_OUTPUT_BUFFER, stack, 1);
	}

	else if (event == EV_NET_OUTPUT_BUFFER)
	{
		struct net_link_t *link;
		struct net_buffer_t *input_buffer;
		int lat;

		/* Debug */
		net_debug("msg "
			"a=\"obuf\" "
			"net=\"%s\" "
			"msg=%lld "
			"node=\"%s\" "
			"buf=\"%s\"\n",
			net->name,
			msg->id,
			node->name,
			buffer->name);

		/* If message is not at buffer head, process later */
		assert(list_count(buffer->msg_list));
		if (list_get(buffer->msg_list, 0) != msg)
		{
			net_buffer_wait(buffer, event, stack);
			return;
		}

		/* If source output buffer is busy, wait */
		if (buffer->read_busy >= esim_cycle)
		{
			esim_schedule_event(event, stack, buffer->read_busy - esim_cycle + 1);
			return;
		}
		
		/* If link is busy, wait */
		link = buffer->link;
		if (link->busy >= esim_cycle)
		{
			esim_schedule_event(event, stack, link->busy - esim_cycle + 1);
			return;
		}

		/* If buffer contain the message but doesn't have the shared link in control, wait*/
		if (link->virtual_channel > 1)
		{
			struct net_buffer_t *temp_buffer;
			temp_buffer = net_link_arbitrator_vc(link, node);
			if (temp_buffer != buffer)
			{
				net_debug("msg "
					"a=\"arbitrator stall\" "
					"net=\"%s\" "
					"msg=%lld "
					"why=\"sched\"\n",
					net->name,
					msg->id);
				esim_schedule_event(event, stack, 1);
				return;
			}
		}

		/* If destination input buffer is busy, wait */
		assert(buffer == link->src_buffer);
		input_buffer = link->dst_buffer;
		if (input_buffer->write_busy >= esim_cycle)
		{
			esim_schedule_event(event, stack, input_buffer->write_busy - esim_cycle + 1);
			return;
		}

		/* If destination input buffer is full, wait */
		if (msg->size > input_buffer->size)
			fatal("%s: message does not fit in buffer.\n%s",
				net->name, net_err_large_message);
		if (input_buffer->count + msg->size > input_buffer->size)
		{
			net_buffer_wait(input_buffer, event, stack);
			return;
		}

		/* Calculate latency and occupy resources */
		lat = (msg->size - 1) / link->bandwidth + 1;
		assert(lat > 0);
		buffer->read_busy = esim_cycle + lat - 1;
		link->busy = esim_cycle + lat - 1;
		input_buffer->write_busy = esim_cycle + lat - 1;

		/* Transfer message to next input buffer */
		assert(msg->busy < esim_cycle);
		net_buffer_extract(buffer, msg);
		net_buffer_insert(input_buffer, msg);
		msg->node = input_buffer->node;
		msg->buffer = input_buffer;
		msg->busy = esim_cycle + lat - 1;

		/* Stats */
		link->busy_cycles += lat;
		link->transferred_bytes += msg->size;
		link->transferred_msgs++;
		node->bytes_sent += msg->size;
		node->msgs_sent++;
		input_buffer->node->bytes_received += msg->size;
		input_buffer->node->msgs_received++;

		/* Schedule next event */
		esim_schedule_event(EV_NET_INPUT_BUFFER, stack, lat);
	}

	else if (event == EV_NET_INPUT_BUFFER)
	{
		struct net_routing_table_entry_t *entry;
		struct net_buffer_t *output_buffer;
		int lat;

		/* Debug */
		net_debug("msg "
			"a=\"ibuf\" "
			"net=\"%s\" "
			"msg=%lld "
			"node=\"%s\" "
			"buf=\"%s\"\n",
			net->name,
			msg->id,
			node->name,
			buffer->name);

		/* If message is not at buffer head, process later */
		assert(list_count(buffer->msg_list));
		if (list_get(buffer->msg_list, 0) != msg)
		{
			net_debug("msg "
				"a=\"stall\" "
				"net=\"%s\" "
				"msg=%lld "
				"why=\"not-head\"\n",
				net->name,
				msg->id);
			net_buffer_wait(buffer, event, stack);
			return;
		}
		
		/* If this is the destination node, finish */
		if (node == msg->dst_node)
		{
			esim_schedule_event(EV_NET_RECEIVE, stack, 0);
			return;
		}
		
		/* If source input buffer is busy, wait */
		if (buffer->read_busy >= esim_cycle)
		{
			net_debug("msg "
				"a=\"stall\" "
				"net=\"%s\" "
				"msg=%lld "
				"why=\"src-busy\"\n",
				net->name,
				msg->id);
			esim_schedule_event(event, stack, buffer->read_busy - esim_cycle + 1);
			return;
		}
		
		/* Get output buffer */
		entry = net_routing_table_lookup(routing_table, node, dst_node);
		output_buffer = entry->output_buffer;
		if (!output_buffer)
			fatal("%s: no route from %s to %s.\n%s", net->name,
				node->name, dst_node->name, net_err_no_route);
		
		/* If destination output buffer is busy, wait */
		if (output_buffer->write_busy >= esim_cycle)
		{
			net_debug("msg "
				"a=\"stall\" "
				"net=\"%s\" "
				"msg=%lld "
				"why=\"dst-busy\"\n",
				net->name,
				msg->id);
			esim_schedule_event(event, stack, output_buffer->write_busy - esim_cycle + 1);
			return;
		}

		/* If destination output buffer is full, wait */
		if (msg->size > output_buffer->size)
			fatal("%s: message does not fit in buffer.\n%s",
				net->name, net_err_large_message);
		if (output_buffer->count + msg->size > output_buffer->size)
		{
			net_debug("msg "
				"a=\"stall\" "
				"net=\"%s\" "
				"msg=%lld "
				"why=\"dst-full\"\n",
				net->name,
				msg->id);
			net_buffer_wait(output_buffer, event, stack);
			return;
		}

		/* If scheduler says that it is not our turn, try later */
		if (net_node_schedule(node, output_buffer) != buffer)
		{
			net_debug("msg "
				"a=\"stall\" "
				"net=\"%s\" "
				"msg=%lld "
				"why=\"sched\"\n",
				net->name,
				msg->id);
			esim_schedule_event(event, stack, 1);
			return;
		}

		/* Calculate latency and occupy resources */
		assert(node->kind != net_node_end);
		assert(node->bandwidth > 0);
		lat = (msg->size - 1) / node->bandwidth + 1;
		assert(lat > 0);
		buffer->read_busy = esim_cycle + lat - 1;
		output_buffer->write_busy = esim_cycle + lat - 1;

		/* Transfer message to next output buffer */
		assert(msg->busy < esim_cycle);
		net_buffer_extract(buffer, msg);
		net_buffer_insert(output_buffer, msg);
		msg->buffer = output_buffer;
		msg->busy = esim_cycle + lat - 1;

		/* Schedule next event */
		esim_schedule_event(EV_NET_OUTPUT_BUFFER, stack, lat);
	}

	else if (event == EV_NET_RECEIVE)
	{
		/* Debug */
		net_debug("msg "
			"a=\"receive\" "
			"net=\"%s\" "
			"msg=%lld "
			"node=\"%s\"\n",
			net->name,
			msg->id,
			dst_node->name);

		/* Stats */
		net->transfers++;
		net->lat_acc += esim_cycle - msg->send_cycle;
		net->msg_size_acc += msg->size;

		/* If not return event was specified, free message here */
		if (stack->ret_event == ESIM_EV_NONE)
			net_receive(net, node, msg);

		/* Finish */
		net_stack_return(stack);
	}

	else
	{
		panic("%s: unknown event", __FUNCTION__);
	}
}
Example #16
0
static int cmd_net_debug(struct re_printf *pf, void *unused)
{
	(void)unused;
	return net_debug(pf, baresip_network());
}