// 这个函数连接到节点ID比自己小的所有邻居. // 在所有外出连接都建立后, 返回1, 否则返回-1. int connectNbrs() { printf("neighbornum is %d\n",topology_getNbrNum()); int i; for (i = 0; i < topology_getNbrNum(); i++){ if(nt[i].nodeID < topology_getMyNodeID()){ int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; if (sockfd < 0){ printf("Create Socket Wrong !!!!!!!\n"); return -1; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CONNECTION_PORT); addr.sin_addr.s_addr = nt[i].nodeIP; if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0){ printf("Connect the Socket Wring !!!!!!!!\n"); return -1; } nt[i].conn = sockfd; printf("connectNbrs:connect success %d\n", nt[i].nodeID); } } return 1; }
// 这个函数连接到节点ID比自己小的所有邻居. // 在所有外出连接都建立后, 返回1, 否则返回-1. int connectNbrs() { int i = 0; for(i = 0;i < topology_getNbrNum();i++) { if(nt[i].nodeID < topology_getMyNodeID()) { struct sockaddr_in servaddr; int sockfd = socket(AF_INET, SOCK_STREAM, 0); //AF_INET for ipv4; SOCK_STREAM for byte stream if(sockfd < 0) { printf("Socket error!\n"); return 0; } memset(&servaddr, 0, sizeof(struct sockaddr_in)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = nt[i].nodeIP; printf("IP :%d\n",servaddr.sin_addr.s_addr); servaddr.sin_port = htons(CONNECTION_PORT); //connect to the server if(connect(sockfd, (struct sockaddr* )&servaddr, sizeof(servaddr)) < 0) {//创建套接字连接服务器 printf("Link Wrong!\n"); //exit(1); return -1; } else { printf("%d Link Success!\n",nt[i].nodeID); nt[i].conn = sockfd; } } } //你需要编写这里的代码. return 1; }
//这个线程每隔ROUTEUPDATE_INTERVAL时间发送路由更新报文.路由更新报文包含这个节点 //的距离矢量.广播是通过设置SIP报文头中的dest_NodeID为BROADCAST_NODEID,并通过son_sendpkt()发送报文来完成的. void* routeupdate_daemon(void* arg) { int node_num = topology_getNodeNum(); int nbr_num = topology_getNbrNum(); pkt_routeupdate_t routemsg; while(1){ sleep(ROUTEUPDATE_INTERVAL); sip_pkt_t sendbuf; memset(&sendbuf, 0, sizeof sendbuf); sendbuf.header.type = ROUTE_UPDATE; sendbuf.header.dest_nodeID = BROADCAST_NODEID; sendbuf.header.src_nodeID = topology_getMyNodeID(); sendbuf.header.length = sizeof(pkt_routeupdate_t); //add the content of route update packet int i = 0; routemsg.entryNum = node_num; pthread_mutex_lock(dv_mutex); for(i = 0; i < node_num; i++){ //dv[nbr_num] is the node itself's distance vector routemsg.entry[i].nodeID = dv[nbr_num].dvEntry[i].nodeID; routemsg.entry[i].cost = dv[nbr_num].dvEntry[i].cost; } pthread_mutex_unlock(dv_mutex); memcpy(sendbuf.data, &routemsg, sizeof routemsg); if(son_sendpkt(BROADCAST_NODEID, &sendbuf, son_conn) == -1){ printf("sip: can't send routeupdate msg\n"); // break; } } pthread_exit(NULL); }
//This function creates a routing table dynamically. //All the entries in the table are initialized to NULL pointers. //Then for all the neighbors with a direct link, create a routing entry using the neighbor itself as the //next hop node, and insert this routing entry into the routing table. //The dynamically created routing table structure is returned. routingtable_t* routingtable_create() { routingtable_t *routingTable = malloc(sizeof(routingtable_entry_t *)*MAX_ROUTINGTABLE_SLOTS); memset(routingTable, 0, sizeof(routingtable_entry_t *)*MAX_ROUTINGTABLE_SLOTS); //initialize all hash entries to NULL for (int i = 0; i < MAX_ROUTINGTABLE_SLOTS; i++) { routingTable->hash[i] = NULL; } //initialize neighbors int* nbrArray = topology_getNbrArray(); int numNbrs = topology_getNbrNum(); for (int j = 0; j < numNbrs; j++){ routingtable_entry_t *temp = malloc(sizeof(routingtable_entry_t)); temp->destNodeID = nbrArray[j]; temp->nextNodeID = nbrArray[j]; temp->next = NULL; int tempHash = makehash(nbrArray[j]); if (routingTable->hash[tempHash] == NULL) { routingTable->hash[tempHash] = temp; } else { routingtable_entry_t *tempEntry = routingTable->hash[tempHash]; while (tempEntry->next != NULL) { tempEntry = tempEntry->next; } tempEntry->next = temp; } } //routingtable_print(routingTable); free(nbrArray); return routingTable; }
//这个函数解析保存在文件topology.dat中的拓扑信息. //返回一个动态分配的数组, 它包含所有邻居的节点ID. int* topology_getNbrArray(){ char buf[MAX_LENGTH]; char *p,*q; FILE *file = fopen("../topology/topology.dat", "r"); if(file == NULL){ return -1; } char hostname[MAX_LENGTH]; gethostname(hostname, MAX_LENGTH); int num = topology_getNbrNum(); int *nodeID = (int *)malloc(sizeof(int)*num); memset(nodeID, 0, sizeof(int)*num); int i = 0; while( fgets(buf, MAX_LENGTH, file) ){ p = strtok(buf, "\t\b\n\v\r "); q = strtok(NULL, "\t\b\n\v\r "); if(strcmp(p,hostname)==0) nodeID[i++] = topology_getNodeIDfromname(q); if(strcmp(q,hostname)==0) nodeID[i++] = topology_getNodeIDfromname(p); p = strtok(NULL,"\t\b\n\v\r "); } fclose(file); return nodeID; }
// 这个线程打开TCP端口CONNECTION_PORT, 等待节点ID比自己大的所有邻居的进入连接, // 在所有进入连接都建立后, 这个线程终止. void* waitNbrs(void* arg) { int nbrNum = topology_getNbrNum(); //你需要编写这里的代码. int total=0; int thisID=topology_getMyNodeID(); for (int i=0;i<nbrNum;i++) if (thisID<nt[i].nodeID) total++; int listenfd=0; struct sockaddr_in servaddr,cliaddr; socklen_t clilen; if ((listenfd=socket(AF_INET, SOCK_STREAM,0))<0) { puts("create socket error!"); } servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_ANY); servaddr.sin_port=htons(CONNECTION_PORT); const int on = 1; setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); bind(listenfd,(struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd,total); printf("Wait For %d Neighbor Init Success!\n",total); while (total>0) { int conn=accept(listenfd,(struct sockaddr *)&cliaddr,&clilen); int nodeID=topology_getNodeIDfromip(&cliaddr.sin_addr); printf("%d Accept %d connection\n",thisID,nodeID); if (nt_addconn(nt,nodeID,conn)<0) puts("Add Connection Error!"); total--; } return 0; }
// 这个函数连接到节点ID比自己小的所有邻居. // 在所有外出连接都建立后, 返回1, 否则返回-1. int connectNbrs() { int nbr_num = topology_getNbrNum(); int local_id = topology_getMyNodeID(); int i; for (i = 0; i < nbr_num; i++){ if (nt[i].nodeID < local_id){ struct sockaddr_in servaddr; int sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(CONNECTION_PORT); servaddr.sin_addr.s_addr = nt[i].nodeIP; if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){ printf("error when connect %d\n", nt[i].nodeID); return -1; } else { if (nt_addconn(nt, nt[i].nodeID, sockfd) == -1) { printf("error when addconn %d\n", nt[i].nodeID); close(sockfd); return -1; } } } } return 1; }
// 这个函数连接到节点ID比自己小的所有邻居. // 在所有外出连接都建立后, 返回1, 否则返回-1. int connectNbrs() { int mynode= topology_getMyNodeID(); int mynbrnum = topology_getNbrNum(); int *nbrlist = topology_getNbrArray(); int i=0; for(i=0; i<mynbrnum; i++) { if(nbrlist[i] < mynode) { int sockfd; struct sockaddr_in serv_addr; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <0) { perror("Error create socket!\n"); return -1; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = topology_getfromIDtoIP(nbrlist[i]); serv_addr.sin_port = htons(CONNECTION_PORT); if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))<0) { perror("Error connect\n"); return -1; } nt_addconn(nt, nbrlist[i], sockfd); } } return 1; }
// 这个函数连接到节点ID比自己小的所有邻居. // 在所有外出连接都建立后, 返回1, 否则返回-1. int connectNbrs() { //你需要编写这里的代码. int nbrNum = topology_getNbrNum(); int thisID=topology_getMyNodeID(); printf("%d neighbors %d thisID\n",nbrNum,thisID); for (int i=0;i<nbrNum;i++) if (thisID>nt[i].nodeID) { int sockfd; struct sockaddr_in serv_addr; if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0) { perror("socket error"); return -1; } memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(CONNECTION_PORT); memcpy(&serv_addr.sin_addr,&nt[i].nodeIP,sizeof(in_addr_t)); if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) { perror("connect error"); return -1; } else { printf("%d node connected to %d node\n",thisID,nt[i].nodeID); if (nt_addconn(nt,nt[i].nodeID,sockfd)<0) puts("Add Connection Error!"); } } return 1; }
//这个函数动态创建距离矢量表. //距离矢量表包含n+1个条目, 其中n是这个节点的邻居数,剩下1个是这个节点本身. //距离矢量表中的每个条目是一个dv_t结构,它包含一个源节点ID和一个有N个dv_entry_t结构的数组, 其中N是重叠网络中节点总数. //每个dv_entry_t包含一个目的节点地址和从该源节点到该目的节点的链路代价. //距离矢量表也在这个函数中初始化.从这个节点到其邻居的链路代价使用提取自topology.dat文件中的直接链路代价初始化. //其他链路代价被初始化为INFINITE_COST. //该函数返回动态创建的距离矢量表. dv_t* dvtable_create() { int nbr_count = topology_getNbrNum(); int * nbr_array = topology_getNbrArray(); int node_count = topology_getNodeNum(); int * node_array = topology_getNodeArray(); dv_t * dvtable = (dv_t *)malloc( sizeof(dv_t) * (nbr_count + 1) ); memset(dvtable, 0, sizeof(dv_t) * (nbr_count+1) ); int i, j; // the first dv_t has nodeID of itself. dvtable[0].nodeID = topology_getMyNodeID(); dvtable[0].dvEntry = (dv_entry_t *)malloc(sizeof(dv_entry_t)*(node_count)); memset(dvtable[0].dvEntry, 0, sizeof(dv_entry_t)*(node_count)); for (j = 0; j < node_count; ++j) { dvtable[0].dvEntry[j].nodeID = node_array[j]; dvtable[0].dvEntry[j].cost = topology_getCost(dvtable[0].nodeID, node_array[j]); if (dvtable[0].nodeID == dvtable[0].dvEntry[j].nodeID) dvtable[0].dvEntry[j].cost = 0; } for (i = 1; i < nbr_count+1; ++i) { dvtable[i].nodeID = nbr_array[i-1]; dvtable[i].dvEntry = (dv_entry_t *)malloc( sizeof(dv_entry_t)*node_count); memset(dvtable[i].dvEntry, 0, sizeof(dv_entry_t)*node_count); for (j = 0; j < node_count; ++j) { dvtable[i].dvEntry[j].nodeID = node_array[j]; dvtable[i].dvEntry[j].cost = INFINITE_COST; } } return dvtable; }
//这个函数打印邻居代价表的内容. void nbrcosttable_print(nbr_cost_entry_t* nct) { int num_nbr = topology_getNbrNum(); int i = 0; for(i=0;i<num_nbr;i++) printf("nodeID: %d, and the cost: %d\n",nct[i].nodeID,nct[i].cost); return; }
int getConnByNode(int id){ int ct = topology_getNbrNum(); int i; for (i = 0; i < ct; i++) if (nt[i].nodeID == id) return nt[i].conn; print_pos(); printf("ERROR: no such node, return conn = -1\n"); return -1; }
// 这个线程打开TCP端口CONNECTION_PORT, 等待节点ID比自己大的所有邻居的进入连接, // 在所有进入连接都建立后, 这个线程终止. in_addr_t getIPByNode(int id){ int ct = topology_getNbrNum(); int i; for (i = 0; i < ct; i ++) if (nt[i].nodeID == id) return nt[i].nodeIP; print_pos(); printf("ERROR: no such node, return ip = 0\n"); return 0; }
//这个函数删除一个邻居表. 它关闭所有连接, 释放所有动态分配的内存. void nt_destroy(nbr_entry_t* nt) { int nbrNum = topology_getNbrNum(); int i; for (i = 0; i < nbrNum; i ++) { close(nt[i].conn); } free(nt); }
//这个函数删除距离矢量表. //它释放所有为距离矢量表动态分配的内存. void dvtable_destroy(dv_t* dvtable) { int i; int nbr_count = topology_getNbrNum(); for (i = 0; i < nbr_count + 1; ++i) { free(dvtable[i].dvEntry); } free(dvtable); return; }
//这个函数删除一个邻居表. 它关闭所有连接, 释放所有动态分配的内存. void nt_destroy(nbr_entry_t* nt){ int nbr_ct = topology_getNbrNum(); int i; for (i = 0; i < nbr_ct; i ++){ if (nt[i].conn != -1){ close(nt[i].conn); nt[i].conn = -1; } } free(nt); }
static bool exist_id(nbr_entry_t *nt, int id){ int nbr_num = topology_getNbrNum(); int i; for(i = 0; i < nbr_num; i++){ if (nt[i].nodeID == id) return true; } return false; }
//这个函数用于获取邻居的直接链路代价. //如果邻居节点在表中发现,就返回直接链路代价.否则返回INFINITE_COST. unsigned int nbrcosttable_getcost(nbr_cost_entry_t* nct, int nodeID) { int num_nbr = topology_getNbrNum(); int i = 0; for(i=0;i<num_nbr;i++) { if(nct[i].nodeID==nodeID) return nct[i].cost; } return INFINITE_COST; }
static int getConnByID(int id){ int nbr_num = topology_getNbrNum(); int i ; for(i = 0; i < nbr_num; i++){ if(nt[i].nodeID == id) return nt[i].conn; } return -1; }
void* waitNbrs(void* arg) { int listenfd, connfd; int option = 1; struct sockaddr_in caddr, saddr; if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("Listen is Wrong !!!!!!!\n"); exit(2); } if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0){ printf("Error!!!!!\n"); exit(2); } memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(CONNECTION_PORT); bind(listenfd, (struct sockaddr*)&saddr, sizeof(saddr)); listen(listenfd, 2); socklen_t len = sizeof(caddr); int i; for (i = 0; i < topology_getNbrNum(); i++){ if(nt[i].nodeID > topology_getMyNodeID()){ connfd = accept(listenfd, (struct sockaddr*)&caddr, &len); if(connfd <= 0) printf("Accept the Socket Wrong !!!!!!!!\n"); printf("*****************success %d******************\n",i); inet_ntoa(*(struct in_addr *)&caddr.sin_addr.s_addr); int t=0; for(t=0; t < topology_getNbrNum(); t++){ if((nt[t]).nodeIP == caddr.sin_addr.s_addr){ (nt[t]).conn = connfd; printf("waitNbrs:connect success %d\n",nt[t].nodeID); break; } } } } pthread_exit(NULL); }
//这个函数删除一个邻居表. 它关闭所有连接 //动态分配的表在外面销毁,为了让监听线程可以读取套接字 void nt_destroy(nbr_entry_t *table) { int n = topology_getNbrNum(); for (int i = 0; i < n; i++) { log("Disconnect to neighbor ID %d", table[i].nodeID); shutdown(table[i].conn, SHUT_RDWR); if (table[i].conn != -1) { close(table[i].conn); } } return; }
int debugTopology() { topology_analysis(); printf("nbr :%d node %d \n", topology_getNbrNum(), topology_getNodeNum()); int i = 0; for(i = 0; i < nbrNum; i++) printf("%d ", nbrIDArray[i]); printf("\n"); for(i = 0; i < nodeNum; i++) printf("%d ", nodeArray[i]); printf("\n"); }
//这个函数首先动态创建一个邻居表. 然后解析文件topology/topology.dat, 填充所有条目中的nodeID和nodeIP字段, 将conn字段初始化为-1. //返回创建的邻居表. nbr_entry_t* nt_create() { int i; int num_nbr = topology_getNbrNum();//获取邻居节点数 nbr_entry_t* nt = (nbr_entry_t*)malloc(num_nbr * sizeof(struct neighborentry));//创建邻居表空间 int* temp = topology_getNbrArray();//获取邻居节点ID数组 for (i = 0; i < num_nbr; i++) { nt[i].nodeID = temp[i];///////////////// nt[i].nodeIP = (0x72D4BE << 8) + temp[i]; nt[i].conn = -1; } return nt; }
//This function destroys a neighbortable. It closes all the connections and frees all the dynamically // allocated memory. void nt_destroy(nbr_entry_t* nt) { int i; int nbrNum = topology_getNbrNum(); for (i = 0; i < nbrNum; i++) { if (nt[i].conn != -1) { close(nt[i].conn); printf("Closed connection to neighbor with nodeID %d (conn %d).\n", nt[i].nodeID, nt[i].conn); } } free(nt); printf("Successfully destroyed neighbor table!\n"); }
int main() { //启动重叠网络初始化工作 printf("Overlay network: Node %d initializing...\n",topology_getMyNodeID()); //创建一个邻居表 nt = nt_create(); //将sip_conn初始化为-1, 即还未与SIP进程连接 sip_conn = -1; //注册一个信号句柄, 用于终止进程 signal(SIGINT, son_stop); //打印所有邻居 int nbrNum = topology_getNbrNum(); int i; for(i=0;i<nbrNum;i++) { printf("Overlay network: neighbor %d:%d\n",i+1,nt[i].nodeID); } //启动waitNbrs线程, 等待节点ID比自己大的所有邻居的进入连接 pthread_t waitNbrs_thread; pthread_create(&waitNbrs_thread,NULL,waitNbrs,(void*)0); //等待其他节点启动 sleep(SON_START_DELAY); //连接到节点ID比自己小的所有邻居 connectNbrs(); //等待waitNbrs线程返回 pthread_join(waitNbrs_thread,NULL); //此时, 所有与邻居之间的连接都建立好了 for (i = 0; i < nbrNum; i++){ printf("id:%d, socket:%d\n", nt[i].nodeID, nt[i].conn); } //创建线程监听所有邻居 for(i=0;i<nbrNum;i++) { int* idx = (int*)malloc(sizeof(int)); *idx = i; pthread_t nbr_listen_thread; pthread_create(&nbr_listen_thread,NULL,listen_to_neighbor,(void*)idx); } printf("Overlay network: node initialized...\n"); printf("Overlay network: waiting for connection from SIP process...\n"); //等待来自SIP进程的连接 waitSIP(); }
//这个函数动态创建距离矢量表. //距离矢量表包含n+1个条目, 其中n是这个节点的邻居数,剩下1个是这个节点本身. //距离矢量表中的每个条目是一个dv_t结构,它包含一个源节点ID和一个有N个dv_entry_t结构的数组, 其中N是重叠网络中节点总数. //每个dv_entry_t包含一个目的节点地址和从该源节点到该目的节点的链路代价. //距离矢量表也在这个函数中初始化.从这个节点到其邻居的链路代价使用提取自topology.dat文件中的直接链路代价初始化. //其他链路代价被初始化为INFINITE_COST. //该函数返回动态创建的距离矢量表. dv_t* dvtable_create() { getTopoData(); nbn=topology_getNbrNum(); int *nbList=topology_getNbrArray(); int *costList=topology_getNbrCost(); alln=topology_getNodeNum(); int *allList=topology_getNodeArray(); dv_t *dvList=malloc((nbn+1)*sizeof(dv_t)); if(dvList==NULL)exit(-1); int i=0; //init nerghbor for(;i<nbn;i++) { dvList[i].nodeID=nbList[i]; dvList[i].dvEntry=malloc(alln*sizeof(dv_entry_t)); int j=0; for(;j<alln;j++) { dvList[i].dvEntry[j].nodeID=allList[j]; dvList[i].dvEntry[j].cost=INFINITE_COST; } } //init this node dvList[nbn].nodeID=topology_getMyNodeID(); dvList[nbn].dvEntry=malloc(alln*sizeof(dv_entry_t)); for(i=0;i<alln;i++) { dvList[nbn].dvEntry[i].nodeID=allList[i]; if(allList[i]==dvList[nbn].nodeID) { dvList[nbn].dvEntry[i].cost=0; continue; } int j=0; for(;j<nbn;j++) { if(allList[i]==nbList[j]) { dvList[nbn].dvEntry[i].cost=costList[j]; break; } } if(j==nbn) dvList[nbn].dvEntry[i].cost=INFINITE_COST; } return dvList; }
//这个函数停止重叠网络, 当接收到信号SIGINT时, 该函数被调用. //它关闭所有的连接, 释放所有动态分配的内存. void son_stop() { int nbr_num = topology_getNbrNum(); int i; for(i = 0; i < nbr_num; i++){ if (nt[i].conn >= 0) close(nt[i].conn); } close(sip_conn); free(nt); printf("son exit\n"); exit(0); }
//这个函数为邻居表中指定的邻居节点条目分配一个TCP连接. 如果分配成功, 返回1, 否则返回-1. int nt_addconn(nbr_entry_t* nt, int nodeID, int conn) { int nbrNum = topology_getNbrNum(); int i; for (i = 0; i < nbrNum; i ++) { if (nt[i].nodeID == nodeID) { nt[i].conn = conn; return 1; } } return -1; }
//这个函数动态创建邻居代价表并使用邻居节点ID和直接链路代价初始化该表. //邻居的节点ID和直接链路代价提取自文件topology.dat. nbr_cost_entry_t* nbrcosttable_create() { int nbrnum = topology_getNbrNum(); nbr_cost_entry_t *nbr_table = (nbr_cost_entry_t*)malloc(sizeof(nbr_cost_entry_t)); int* nbrlist = topology_getNbrArray(); int mynode = topology_getMyNodeID(); int i = 0; for(i = 0; i<nbrnum; i++) { nbr_table[i].nodeID = nbrlist[i]; nbr_table[i].cost = topology_getCost(mynode, nbrlist[i]); nbr_table[i].flag = 0; pthread_mutex_init(&nbr_table[i].flag_mutex, NULL); } return nbr_table; }
//这个函数动态创建路由表.表中的所有条目都被初始化为NULL指针. //然后对有直接链路的邻居,使用邻居本身作为下一跳节点创建路由条目,并插入到路由表中. //该函数返回动态创建的路由表结构. routingtable_t* routingtable_create() { routingtable_t * my_route = (routingtable_t *)malloc(sizeof(routingtable_t)); int i = 0; for(i=0; i<MAX_ROUTINGTABLE_SLOTS; i++) { my_route->hash[i] = NULL; } int nbrnum = topology_getNbrNum(); int *nbrlist = topology_getNbrArray(); int j; for( j=0; j<nbrnum; j++) { routingtable_setnextnode(my_route, nbrlist[j], nbrlist[j]); } return my_route; }