⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ospfd_sim.c

📁 BCAST Implementation for NS2
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   OSPFD routing daemon *   Copyright (C) 1998 by John T. Moy *    *   This program is free software; you can redistribute it and/or *   modify it under the terms of the GNU General Public License *   as published by the Free Software Foundation; either version 2 *   of the License, or (at your option) any later version. *    *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. *    *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/time.h>#include <sys/resource.h>#include <unistd.h>#include <tcl.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <net/if.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include "../src/ospfinc.h"#include "../src/monitor.h"#include "../src/system.h"#include "tcppkt.h"#include "machtype.h"#include "sim.h"#include "mtrace.h"#include "ospfd_sim.h"#include <time.h>#include "icmp.h"rtid_t my_id;SimSys *simsys;char buffer[MAX_IP_PKTSIZE];char *LOOPADDR = "127.0.0.1";char *BROADADDR = "127.255.255.255";// External declarations/* The main simulated OSPF loop. Loops getting messages (packets, timer * ticks, configuration messages, etc.) and never returns * until the simulated OSPF process is told to exit. * Syntax: *	ospfd_sim "router_id" "controller_port" */int main(int argc, char *argv[]){    int n_fd;    fd_set fdset;    fd_set wrset;    uns16 controller_port;    char temp[30];    int stat;    int ctl_fd;    // Get command line arguments    if (argc != 3) {        printf("syntax: ospfd_mon $router_id $controller_port\n");	exit(1);    }    my_id = ntoh32(inet_addr(argv[1]));    controller_port = atoi(argv[2]);    // Start random number generator    srand(getpid());    // Connect to simulation controller    // Keep on trying if we're getting timeouts    do {        sockaddr_in ctl_addr;	if (!(ctl_fd = socket(AF_INET, SOCK_STREAM, 0))) {	    perror("create control socket");	    exit(1);	}	memset((char *) &ctl_addr, 0, sizeof(ctl_addr));	ctl_addr.sin_family = AF_INET;	ctl_addr.sin_addr.s_addr = inet_addr(LOOPADDR);	ctl_addr.sin_port = hton16(controller_port);	stat = connect(ctl_fd, (struct sockaddr *) &ctl_addr,sizeof(ctl_addr));	if (stat < 0) {	    close(ctl_fd);	    usleep ((int) ((1000000.0*rand())/(RAND_MAX+1.0)));	}    } while (stat < 0);    // Create simulation environment    sys = simsys = new SimSys(ctl_fd);    // Log command arguments    sprintf(temp, "invoked: ospfd_sim %s %s", argv[1], argv[2]);    simsys->sys_spflog(ERR_SYS, temp);    // Main loop, never exits    while (1) {        bool ifc_data=false;	FD_ZERO(&fdset);	FD_ZERO(&wrset);	// Flush any logging messages	if (ospf)	    ospf->logflush();	// If hitless restart preparation done, start ospfd again	if (simsys->hitless_preparation_complete) {	    simsys->hitless_preparation_complete = false;	    delete ospf;	    ospf = 0;	}	// Add connection to controller	n_fd = simsys->ctl_fd;	FD_SET(simsys->ctl_fd, &fdset);	if (simsys->ctl_pkt.xmt_pending())	    FD_SET(simsys->ctl_fd, &wrset);	// Add our private port	n_fd = MAX(n_fd, simsys->uni_fd);	FD_SET(simsys->uni_fd, &fdset);	// Add monitoring connection	simsys->mon_fd_set(n_fd, &fdset, &wrset);	// Wait for I/O	if (select(n_fd+1, &fdset, &wrset, 0, 0) < 0)	    simsys->halt(1, "select failed");	// Process received data	if (FD_ISSET(simsys->ctl_fd, &wrset))	    simsys->ctl_pkt.sendpkt();	// Received OSPF packets?	if (FD_ISSET(simsys->uni_fd, &fdset)) {	    ifc_data = true;	    simsys->process_uni_fd();	}	// Instructions from controller?	if (!ifc_data && FD_ISSET(simsys->ctl_fd, &fdset))	    simsys->recv_ctl_command();	// Process monitor queries and responses	simsys->process_mon_io(&fdset, &wrset);    }    exit(0);}/* Process packets received on our private socket. * These are packets that have been sent directly * to us. If the destination address belongs to us, * forward it to the demux. Otherwise, do a routing lookup * on the packet and forward it further. */void SimSys::process_uni_fd(){    int plen;    sockaddr_in addr;    socklen fromlen=sizeof(addr);    SimPktHdr *pkthdr;    InPkt *pkt;    SPFtime rcvd;    SPFtime limit;    plen = recvfrom(uni_fd, buffer, sizeof(buffer),		    0, (sockaddr *)&addr, &fromlen);    pkthdr = (SimPktHdr *) buffer;    pkt = (InPkt *) (pkthdr+1);    if (plen < (int) sizeof(SimPktHdr) ||	plen < (int) (sizeof(SimPktHdr) + ntoh16(pkt->i_len))) {        perror("recvfrom");	return;    }    rcvd = pkthdr->ts;    time_add(rcvd, LINK_DELAY, &pkthdr->ts);    time_add(sys_etime, 1000/TICKS_PER_SECOND, &limit);    if (time_less(pkthdr->ts, limit))        rxpkt(pkthdr);    else        queue_rcv(pkthdr, plen);}/* Process a received packet. Determine whether it is for us. * if not, try to forward, otherwise perform the local demux * functions. */void SimSys::rxpkt(SimPktHdr *pkthdr){    InPkt *pkt;    InAddr daddr;    SimRte *rte;    pkt = (InPkt *) (pkthdr+1);    daddr = ntoh32(pkt->i_dest);    xmt_stamp = pkthdr->ts;    if (!IN_CLASSD(daddr)) {	InAddr home;        if ((!get_port_addr(daddr, home)) || (home != my_id)) {	    if (!(rte = rttbl.best_match(daddr))) {	        sendicmp(ICMP_TYPE_UNREACH, ICMP_CODE_UNREACH_HOST,			 0, 0, pkt, 0, 0, 0);	    }	    // Decrement TTL. We don't use checksums in the	    // IP header of simulated packets	    else if (pkt->i_ttl == 0 || pkt->i_ttl-- == 1) {	        sendicmp(ICMP_TYPE_TTL_EXCEED, 0, 0, 0, pkt, 0, 0, 0);	    }	    else {	        InAddr gw;		gw = rte->gw;		if (gw != 0 && rte->if_addr == 0)		    gw = (InAddr) -1;	        sendpkt(pkt, rte->phyint, gw);	    }	}	else	    local_demux(pkthdr);    }    else {        mc_fwd(ntoh32(pkthdr->phyint), pkt);	local_demux(pkthdr);    }}/* Have received an IP packet that is addressed to * us (may be a multicast). * Fir determine if we are a member of the multicast group, * and then dispatch on protocol number. */void SimSys::local_demux(SimPktHdr *pkthdr){    InAddr dest;    PhyintMap *phyp;    InPkt *pkt;    int phyint;    pkt = (InPkt *) (pkthdr+1);    phyint = ntoh32(pkthdr->phyint);    if (!(phyp = (PhyintMap *)port_map.find(phyint,0)))        return;    if (phyp->promiscuous && pkt->i_prot == PROT_IGMP) {        igmp_demux(phyint, pkt);	return;    }    dest = ntoh32(pkt->i_dest);    if (IN_CLASSD(dest)) {        if (!membership.find(dest, phyint))	    return;    }    switch(pkt->i_prot) {      case PROT_OSPF:	// Discard packet if OSPF not ready	if (ospf)	ospf->rxpkt(phyint, pkt, ntoh16(pkt->i_len));	break;      case PROT_ICMP:	IcmpPkt *icmphdr;	SPFtime *timep;	IcmpErrMsg emsg;	uns16 s_id;	TRSession *tr;	icmphdr = (IcmpPkt *) (pkt + 1);	switch (icmphdr->ic_type) {	  case ICMP_TYPE_ECHO:	    sendicmp(ICMP_TYPE_ECHOREPLY, 0, 0, 0, pkt, 0, 0, 0);	    break;	  case ICMP_TYPE_ECHOREPLY:	    s_id = ntoh16(icmphdr->ic_id);	    timep = (SPFtime *) (icmphdr+1);	    if ((tr = (TRSession *)traceroutes.find(s_id,0))) {		emsg.src = ntoh32(pkt->i_src);		emsg.type = icmphdr->ic_type;		emsg.code = icmphdr->ic_code;		emsg.msd = time_diff(pkthdr->ts, *timep);		emsg.icmp_seq = ntoh16(icmphdr->ic_seqno);		ctl_pkt.queue_xpkt(&emsg, SIM_ICMP_ERROR, s_id, sizeof(emsg));	        tr->response_received(ICMP_TYPE_ECHOREPLY);	    }	    else {	        EchoReplyMsg msg;	        msg.src = ntoh32(pkt->i_src);		msg.msd = time_diff(pkthdr->ts, *timep);		msg.icmp_seq = ntoh16(icmphdr->ic_seqno);		msg.ttl = pkt->i_ttl;		ctl_pkt.queue_xpkt(&msg, SIM_ECHO_REPLY, s_id, sizeof(msg));	    }	    break;	    // ICMP error messages come here!	  default:	    InPkt *encap_hdr;	    s_id = 0;	    emsg.src = ntoh32(pkt->i_src);	    emsg.type = icmphdr->ic_type;	    emsg.code = icmphdr->ic_code;	    encap_hdr = (InPkt *) (icmphdr +1);	    if (encap_hdr->i_prot == PROT_ICMP) {	        IcmpPkt *encap_icmp;		encap_icmp = (IcmpPkt *) (encap_hdr + 1);		s_id = ntoh16(encap_icmp->ic_id);		timep = (SPFtime *) (encap_icmp+1);		emsg.msd = time_diff(pkthdr->ts, *timep);		emsg.icmp_seq = ntoh16(encap_icmp->ic_seqno);	    }	    ctl_pkt.queue_xpkt(&emsg, SIM_ICMP_ERROR, s_id, sizeof(emsg));	    if ((tr = (TRSession *)traceroutes.find(s_id,0)))	        tr->response_received(emsg.type);	    break;	}	break;      case PROT_IGMP:	igmp_demux(phyint, pkt);	break;      default:	break;    }}/* Initialize the Simulation environment. * Connect to the controller * Start the random number generator. */SimSys::SimSys(int fd) : OSInstance(0), ctl_pkt(fd){//  rlimit rlim;    sockaddr_in addr;    socklen size;    SimHello hello;    grace_period = sys_etime;    hitless_preparation = false;    hitless_preparation_complete = false;    ctl_fd = fd;    my_addr = 0;    // Initialize time    ticks = 0;    // Allow core files//  rlim.rlim_max = RLIM_INFINITY;//  (void) setrlimit(RLIMIT_CORE, &rlim);    // Open our unicast socket, where people send packets    // addressed to us (unicasts and multicasts)    uni_fd = socket(AF_INET, SOCK_DGRAM, 0);    memset(&addr, 0, sizeof(addr));    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = htonl(INADDR_ANY);    if (bind(uni_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)	perror("bind fails");    size = sizeof(addr);    if (getsockname(uni_fd, (struct sockaddr *) &addr, &size) < 0) {	perror("getsockname");	exit (1);    }    uni_port = ntohs(addr.sin_port);    // Identify ourselves to the server    hello.rtrid = my_id;    hello.myport = hton16(uni_port);    ctl_pkt.queue_xpkt(&hello, SIM_HELLO, 0, sizeof(hello));    // Open monitoring listen socket    monitor_listen();    // Set transmission timestamp    xmt_stamp = sys_etime;    // Initialize mtrace query IDs    mtrace_qid = 0;}/* Destructor not expected to be called during the life * of the program. */SimSys::~SimSys(){}/* Process command received over the controller * connection. */void SimSys::recv_ctl_command(){    uns16 type;    uns16 subtype;    int nbytes;    char *msg;    char *end;    nbytes = ctl_pkt.receive((void **)&msg, type, subtype);    if (nbytes < 0)	simsys->halt(1, "Lost controller connection");    else if (type != 0) {        AddrMap *addrmap;	PingSession *ping;	TRSession *tr;	PingStartMsg *pm;	MTraceHdr *mtrm;	MTraceSession *mtrace;	HitlessRestartMsg *htlm;	int phyint;        end = msg + nbytes;	xmt_stamp = sys_etime;        switch (type) {	    TickBody *tm;	    GroupMsg *grpm;	  case SIM_FIRST_TICK:	    // Init time before any configuration is downloaded	    tm = (TickBody *) msg;	    ticks = tm->tick;	    sys_etime.sec = ticks/TICKS_PER_SECOND;	    sys_etime.msec = (ticks%TICKS_PER_SECOND) * 1000/TICKS_PER_SECOND;	    xmt_stamp = sys_etime;	    // Start OSPF, delayed so that time is initialized	    // correctly	    ospf = new OSPF(my_id, sys_etime);	    break;	  case SIM_TICK:	    // Advance time	    tm = (TickBody *) msg;	    ticks = tm->tick;	    sys_etime.sec = ticks/TICKS_PER_SECOND;	    sys_etime.msec = (ticks%TICKS_PER_SECOND) * 1000/TICKS_PER_SECOND;	    xmt_stamp = sys_etime;	    // Process any pending timers	    if (ospf)	    ospf->tick();	    // Process any queued receives	    process_rcvqueue();	    // Send tick reponse	    send_tick_response();	    break;          case SIM_CONFIG:          case SIM_CONFIG_DEL:	    config(type, subtype, msg);	    break; 	  case SIM_SHUTDOWN:	    if (ospf)	    ospf->shutdown(10);	    break;	  case SIM_ADDRMAP:	    addrmap = (AddrMap *) msg;	    for (; (char *)(addrmap + 1) <= end; addrmap++) {	        AddressMap *entry;		InAddr addr;		InAddr home;		addr = addrmap->addr;		home = addrmap->home;	        if (!(entry = (AddressMap *) address_map.find(addr, home))) {		    entry = new AddressMap(addr, home);		    address_map.add(entry);		}		if (addrmap->port == 0) {		    address_map.remove(entry);		    delete entry;		}		else {		    entry->port = (uns16) addrmap->port;		    entry->home = addrmap->home;		}	    }	    break;	  case SIM_START_PING:	    pm = (PingStartMsg *) msg;	    ping = new PingSession(subtype, pm->src, pm->dest, pm->ttl);	    pings.add(ping);	    ping->start(Timer::SECOND, false);	    break;	  case SIM_STOP_PING:	    if ((ping = (PingSession *)pings.find(subtype, 0))) {	        ping->stop();		pings.remove(ping);		delete ping;	    }	    break;	  case SIM_START_TR:	    pm = (PingStartMsg *) msg;	    tr = new TRSession(subtype, pm->dest, pm->ttl);	    traceroutes.add(tr);	    tr->response_received(255);	    break;	  case SIM_ADD_MEMBER:	    grpm = (GroupMsg *) msg;	    if (ospf)	    ospf->join_indication(grpm->group, grpm->phyint);	    join(grpm->group, grpm->phyint);	    break;	  case SIM_DEL_MEMBER:	    grpm = (GroupMsg *) msg;	    if (ospf)	    ospf->leave_indication(grpm->group, grpm->phyint);	    leave(grpm->group, grpm->phyint);	    break;	  case SIM_START_MTRACE:	    mtrm = (MTraceHdr *) msg;	    phyint = (int) mtrm->ttl_qid;	    mtrm->ttl_qid = 0;	    mtrace = new MTraceSession(subtype, phyint, mtrm);	    mtraces.add(mtrace);	    mtrace->send_query();	    break; 	  case SIM_RESTART:	    close_monitor_connections();	    delete ospf;	    ospf = 0;	    // Will then get First tick, and config	    break; 	  case SIM_RESTART_HITLESS:	    htlm = (HitlessRestartMsg *) msg;	    if (ospf)	        ospf->hitless_restart(htlm->period, 1);	    else	        ospf = new OSPF(my_id, grace_period);	    break;	  default:	    break;      }    }}/* Configuration request. Dispatch to the correct routine * to do specific processing. */void SimSys::config(int type, int subtype, void *msg){    int status;        status = (type == SIM_CONFIG) ? ADD_ITEM : DELETE_ITEM;    if (!ospf)        return;    switch(subtype) {        PhyintMap *phyp;	CfgIfc *ifcmsg;      case CfgType_Gen:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -