//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; }
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); }
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); }
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); }
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; }
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); }
// 消息线程处理:先接收网络协议的头,然后判断,如果头正确,则处理命令或继续接收命令参数后再处理 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; }
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; }
// 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; }
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__); } }
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(); }
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__); } }
static int cmd_net_debug(struct re_printf *pf, void *unused) { (void)unused; return net_debug(pf, baresip_network()); }