📄 sim.c
字号:
char *msgbuf; char *text_msg; switch(type) { char tcl_command[80]; case SIM_HELLO: hello = (SimHello *)msg; // Start the node, reassigning simnode class restart_node(node, hello->rtrid, fd, ntoh16(hello->myport)); break; case SIM_TICK_RESPONSE: NodeStats *statentry; dbstats = (DBStats *)msg; node->got_tick = true; statentry = (NodeStats *) stats.find((byte *)dbstats, sizeof(DBStats)); if (statentry && statentry == node->dbstats) break; if (node->dbstats && --(node->dbstats->refct) == 0) { stats.remove(node->dbstats); delete node->dbstats; } if (!statentry) { statentry = new NodeStats(dbstats); stats.add(statentry); } node->dbstats = statentry; statentry->refct++; break; case SIM_LOGMSG: msgbuf = (char *)msg; msgbuf[nbytes-1] = '\0'; addr.s_addr = hton32(node->id()); printf("%d:%03d (%s) OSPF.%03d: %s\n", sim->elapsed_seconds(), sim->elapsed_milliseconds(), inet_ntoa(addr), subtype, msgbuf); fflush(stdout); break; case SIM_ECHO_REPLY: EchoReplyMsg *em; em = (EchoReplyMsg *)msg; addr.s_addr = hton32(em->src); sprintf(tcl_command, "ping_reply %d %s %d %d %d", subtype, inet_ntoa(addr), em->icmp_seq, em->ttl, em->msd); if (Tcl_VarEval(sim->interp, tcl_command, 0) != TCL_OK) printf("ping_reply: %s\n", sim->interp->result); break; case SIM_ICMP_ERROR: IcmpErrMsg *errmsg; errmsg = (IcmpErrMsg *)msg; addr.s_addr = hton32(errmsg->src); sprintf(tcl_command, "icmp_error %d %s %d %d %d", subtype, inet_ntoa(addr), errmsg->type, errmsg->code, errmsg->msd); if (Tcl_VarEval(sim->interp, tcl_command, 0) != TCL_OK) printf("icmp_error: %s\n", sim->interp->result); break; case SIM_TRACEROUTE_TTL: TrTtlMsg *ttlm; ttlm = (TrTtlMsg *)msg; sprintf(tcl_command, "traceroute_ttl %d %d", subtype, ttlm->ttl); if (Tcl_VarEval(sim->interp, tcl_command, 0) != TCL_OK) printf("traceroute_ttl: %s\n", sim->interp->result); break; case SIM_TRACEROUTE_TMO: sprintf(tcl_command, "print_session %d \"* \"", subtype); if (Tcl_VarEval(sim->interp, tcl_command, 0) != TCL_OK) printf("print_session: %s\n", sim->interp->result); break; case SIM_PRINT_SESSION: text_msg=(char *)msg; sprintf(tcl_command, "print_session %d \"%s\"", subtype,text_msg); if (Tcl_VarEval(sim->interp, tcl_command, 0) != TCL_OK) printf("print_session: %s\n", sim->interp->result); break; default: addr.s_addr = node->id(); printf("Bad type %d from %s", type, inet_ntoa(addr)); break; } }}/* (Re)start a router. */void SimCtl::restart_node(SimNode *node, InAddr id, int fd, uns16 home_port){ in_addr addr; TickBody tm; SimNode *newnode; newnode = new SimNode(id, fd); sim->simnodes.add(newnode); newnode->home_port = home_port; addr.s_addr = hton32(newnode->id()); newnode->color = SimNode::WHITE; if (Tcl_VarEval(sim->interp, "color_router ", inet_ntoa(addr), " white", 0) != TCL_OK) printf("color_router: %s\n", sim->interp->result); // If the router has already been running, tell it to restart if (node->id() != 0) newnode->pktdata.queue_xpkt(NULL, SIM_RESTART, 0, 0); // Initialize its idea of time tm.tick = sim->n_ticks; newnode->pktdata.queue_xpkt(&tm, SIM_FIRST_TICK, 0, sizeof(tm)); // Send address to port maps send_addrmap(newnode); send_addrmap_increment(0, newnode); // Download node's configuration addr.s_addr = hton32(newnode->id()); if (Tcl_VarEval(sim->interp,"sendcfg ", inet_ntoa(addr),0) != TCL_OK) printf("sendcfg: %s\n", sim->interp->result); // Delete previous router // Also frees message space delete node;}/* Construct a node statistics entry. */NodeStats::NodeStats(DBStats *d){ dbstats = *d; key = (byte *) &dbstats; keylen = sizeof(dbstats); refct = 0;}/* Send the current address to port map to a particular * router. */void SimCtl::send_addrmap(SimNode *node){ byte *msg; AVLsearch iter(&ifmaps); int size; IfMap *map; AddrMap *addrmap; if (!(size = (ifmaps.size() * sizeof(*addrmap)))) return; msg = new byte[size]; addrmap = (AddrMap *) msg; for (size = 0; (map = (IfMap *) iter.next()); ) { SimNode *home; if (!(home = (SimNode *) simnodes.find(map->owner, 0))) continue; addrmap->addr = map->index1(); addrmap->port = home->home_port; addrmap->home = home->id(); addrmap++; size += sizeof(*addrmap); } node->pktdata.queue_xpkt(msg, SIM_ADDRMAP, 0, size); delete [] msg;}/* Send a new router's interfaces to all existing routers. */void SimCtl::send_addrmap_increment(IfMap *newmap, SimNode *newnode){ byte *msg; AVLsearch iter(&ifmaps); int size; IfMap *map; AddrMap *addrmap; AVLsearch niter(&sim->simnodes); SimNode *node; SimNode *home; if (!running) return; if (newmap) size = sizeof(*addrmap); else size = ifmaps.size() * sizeof(*addrmap); if (size == 0) return; msg = new byte[size]; addrmap = (AddrMap *) msg; size = 0; if (newmap) { home = (SimNode *) simnodes.find(newmap->owner, 0); if (home) { addrmap->addr = newmap->index1(); addrmap->port = home->home_port; addrmap->home = home->id(); addrmap++; size += sizeof(*addrmap); } } else { while ((map = (IfMap *) iter.next())) { home = (SimNode *) simnodes.find(map->owner, 0); if (home != newnode) continue; addrmap->addr = map->index1(); addrmap->port = home->home_port; addrmap->home = home->id(); addrmap++; size += sizeof(*addrmap); } } while ((node = (SimNode *)niter.next())) { if (!newmap && node == newnode) continue; node->pktdata.queue_xpkt(msg, SIM_ADDRMAP, 0, size); } delete [] msg;}/* Create a simulated router. * Give it the benefit of the doubt on the first tick. */SimNode::SimNode(uns32 id, int file) : AVLitem(id, 0), pktdata(file){ fd = file; got_tick = true; home_port = 0; awaiting_htl_restart = false; dbstats = 0; sim->nodes[fd] = this; sim->maxfd = MAX(file, sim->maxfd); color = RED;}/* Delete a simulated router. */void SimCtl::delete_router(SimNode *node){ if (node->id()) { in_addr addr; close(node->fd); node->home_port = 0; send_addrmap_increment(0, node); addr.s_addr = hton32(node->id()); if (Tcl_VarEval(interp, "color_router ", inet_ntoa(addr), " red", 0) != TCL_OK) printf("color_router: %s\n", interp->result); if (node->dbstats && --(node->dbstats->refct) == 0) { stats.remove(node->dbstats); delete node->dbstats; } simnodes.remove(node); } sim->nodes[node->fd] = 0; delete node;}/* Toggle the operation state of a simulated router. */int ToggleRouter(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr id; SimNode *node; id = ntoh32(inet_addr(argv[1])); if (!(node = (SimNode *) sim->simnodes.find(id, 0))) Tcl_VarEval(interp, "startrtr ", argv[1], 0); else node->pktdata.queue_xpkt(NULL, SIM_SHUTDOWN, 0, 0); return(TCL_OK);}/* Restart a simulated router. * If it is not running, simply start it. */int RestartRouter(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr id; SimNode *node; id = ntoh32(inet_addr(argv[1])); if (!(node = (SimNode *) sim->simnodes.find(id, 0))) Tcl_VarEval(interp, "startrtr ", argv[1], 0); else { sim->simnodes.remove(node); sim->restart_node(node, node->id(), node->fd, node->home_port); } return(TCL_OK);}/* Perform a hitless restart of a simulated router. * If it is not running, simply start it. */int HitlessRestart(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr id; SimNode *node; HitlessRestartMsg m; m.period = 100; id = ntoh32(inet_addr(argv[1])); if (!(node = (SimNode *) sim->simnodes.find(id, 0))) Tcl_VarEval(interp, "startrtr ", argv[1], 0); else if (node->awaiting_htl_restart) { // Complete hitless restart in_addr addr; node->awaiting_htl_restart = false; node->pktdata.queue_xpkt(&m, SIM_RESTART_HITLESS, 0, sizeof(m)); // Download node's configuration addr.s_addr = hton32(node->id()); if (Tcl_VarEval(sim->interp,"sendcfg ", inet_ntoa(addr),0) != TCL_OK) printf("sendcfg: %s\n", sim->interp->result); } else { // Prepare for hitless restart node->awaiting_htl_restart = true; node->pktdata.queue_xpkt(&m, SIM_RESTART_HITLESS, 0, sizeof(m)); } return(TCL_OK);}/* Start a ping session in the specified router. */int StartPing(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr id; SimNode *node; PingStartMsg m; uns16 s_id; id = ntoh32(inet_addr(argv[1])); if (!(node = (SimNode *) sim->simnodes.find(id, 0))) return(TCL_OK); m.src = ntoh32(inet_addr(argv[2])); m.dest = ntoh32(inet_addr(argv[3])); m.ttl = atoi(argv[4]); s_id = atoi(argv[5]); node->pktdata.queue_xpkt(&m, SIM_START_PING, s_id, sizeof(m)); return(TCL_OK);}/* Stop a ping session in the specified router. */int StopPing(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr id; SimNode *node; uns16 s_id; id = ntoh32(inet_addr(argv[1])); if (!(node = (SimNode *) sim->simnodes.find(id, 0))) return(TCL_OK); s_id = atoi(argv[2]); node->pktdata.queue_xpkt(0, SIM_STOP_PING, s_id, 0); return(TCL_OK);}/* Start a traceroute session in the specified router. */int StartTraceroute(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr id; SimNode *node; PingStartMsg m; uns16 s_id; id = ntoh32(inet_addr(argv[1])); if (!(node = (SimNode *) sim->simnodes.find(id, 0))) return(TCL_OK); m.dest = ntoh32(inet_addr(argv[3])); m.ttl = atoi(argv[4]); s_id = atoi(argv[5]); node->pktdata.queue_xpkt(&m, SIM_START_TR, s_id, sizeof(m)); return(TCL_OK);}/* Start a multicast traceroute session in the specified router. */int StartMtrace(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr id; SimNode *node; MTraceHdr m; uns16 s_id; InAddr net; InMask mask; id = ntoh32(inet_addr(argv[1])); if (!(node = (SimNode *) sim->simnodes.find(id, 0))) return(TCL_OK); m.src = ntoh32(inet_addr(argv[2])); get_prefix(argv[3], net, mask); m.dest = net; m.group = ntoh32(inet_addr(argv[4])); s_id = atoi(argv[5]); m.ttl_qid = atoi(argv[6]); // phyint of destination net node->pktdata.queue_xpkt(&m, SIM_START_MTRACE, s_id, sizeof(m)); return(TCL_OK);}/* Determine whether an address falls under a particular * prefix. */int PrefixMatch(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr net; InAddr mask; InAddr addr; Tcl_SetResult(interp, "1", TCL_STATIC); if (get_prefix(argv[1], net, mask)) { addr = ntoh32(inet_addr(argv[2])); if ((addr & mask) == net) Tcl_SetResult(interp, "0", TCL_STATIC); } return(TCL_OK);}/* Add mapping between IP address and owning router */int AddMapping(ClientData, Tcl_Interp *interp, int, char *argv[]){ InAddr addr; InAddr mask; InAddr rtr; if (get_prefix(argv[1], addr, mask)) { if (mask != 0xffffffff) return(TCL_OK); } else addr = ntoh32(inet_addr(argv[1]));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -