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

📄 ospfd_sim.c

📁 BCAST Implementation for NS2
💻 C
📖 第 1 页 / 共 2 页
字号:
	ospf->cfgOspf((CfgGen *) msg);	break;      case CfgType_Area:	ospf->cfgArea((CfgArea *)msg, status);	break;      case CfgType_Range:	ospf->cfgRnge((CfgRnge *)msg, status);	break;      case CfgType_Host:	ospf->cfgHost((CfgHost *)msg, status);	break;      case CfgType_Ifc:	ifcmsg = (CfgIfc *)msg;	if (!(phyp = (PhyintMap *)port_map.find(ifcmsg->phyint, 0))) {	    phyp = new PhyintMap(ifcmsg->phyint);	    port_map.add(phyp);	}	phyp->addr = ifcmsg->address;	phyp->mask = ifcmsg->mask;	if (!my_addr)	    my_addr = ifcmsg->address;	ospf->cfgIfc(ifcmsg, status);	break;      case CfgType_VL:	ospf->cfgVL((CfgVL *)msg, status);	break;      case CfgType_Nbr:	ospf->cfgNbr((CfgNbr *)msg, status);	break;      case CfgType_Route:	ospf->cfgExRt((CfgExRt *)msg, status);	break;      case CfgType_Key:	ospf->cfgAuKey((CfgAuKey *)msg, status);	break;      default:	break;    }}/* Constructor for the physical interface. */PhyintMap::PhyintMap(int phyint) : AVLitem(phyint,0){    working = true;    promiscuous = false;    sprintf(name, "N%d", phyint);}/* Send a tick response, listing the current state * of the link-state database. */void SimSys::send_tick_response(){    DBStats *statp;    SpfArea *ap;    SpfArea *low;    int mlen;    low = 0;    statp = new DBStats;    mlen = sizeof(DBStats);    if (ospf) {	AreaIterator iter(ospf);    statp->n_exlsas = ospf->n_extLSAs();    statp->ex_dbxsum = ospf->xsum_extLSAs();    while ((ap = iter.get_next())) {      if (ap->n_active_if == 0)	  continue;      if (!low || low->id() > ap->id())	  low = ap;    }    }    else {	statp->n_exlsas = 0;	statp->ex_dbxsum = 0;    }    if (low) {	statp->area_id = low->id();	statp->n_lsas = low->n_LSAs();	statp->dbxsum = low->database_xsum();    }    else {	statp->area_id = 0;	statp->n_lsas = 0;	statp->dbxsum = 0;    }    ctl_pkt.queue_xpkt(statp, SIM_TICK_RESPONSE, 0, mlen);    delete statp;}/* Queue a received packet, until it is time to process * it. */void SimSys::queue_rcv(struct SimPktHdr *pkt, int plen){    SimPktQ *qptr;    qptr = new SimPktQ;    qptr->next = 0;    qptr->ip_data = (SimPktHdr *) new byte[plen];    memcpy(qptr->ip_data, pkt, plen);    if (rcv_head == 0)        rcv_head = rcv_tail = qptr;    else {        rcv_tail->next = qptr;	rcv_tail = qptr;    }}/* After receiving a tick, process the queue of packets * that were delayed until this time interval. */void SimSys::process_rcvqueue(){    SimPktQ *qptr;    SimPktQ *next;    SimPktQ *prev;    SPFtime limit;    prev = 0;    time_add(sys_etime, 1000/TICKS_PER_SECOND, &limit);    for (qptr = rcv_head; qptr; qptr = next) {	SimPktHdr *pkthdr;        next = qptr->next;	pkthdr = qptr->ip_data;	// Time to process?	if (time_less(pkthdr->ts, limit)) {	    // Remove from receive queue	    if (rcv_head == qptr)	        rcv_head = next;	    else	        prev->next = next;	    if (rcv_tail == qptr)	        rcv_tail = prev;	    delete qptr;	    rxpkt(pkthdr);	    delete [] ((byte *) pkthdr);	}	else	    prev = qptr;    }}/* Forward a multicast datagram. * Have MOSPF calculate the forwarding cache entry. * If the incoming interface is not -1, and not in the * cache entry, just discard. Otherwise, forward out all * of the specified output interfaces. */void SimSys::mc_fwd(int in_phyint, InPkt *pkt){    size_t len;    SimPktHdr *data;    MCache *ce;    if (!ospf)        return;    len = ntoh16(pkt->i_len);    data = (SimPktHdr *) new byte[len+sizeof(SimPktHdr)];    data->ts = xmt_stamp;    memcpy(data+1, pkt, len);    // Calculate cache entry    if ((ce = ospf->mclookup(ntoh32(pkt->i_src), ntoh32(pkt->i_dest)))) {	// Verify incoming interface        if (ce->valid_incoming(in_phyint)) {	    int i;	    /* If locally originated, send out upstream interface.	     * will then be forwarded correctly when received	     * by us and *other* routers.	     */	    if (in_phyint == -1 &&		ce->n_upstream != 0 && ce->up_phys[0] != -1) {	        data->phyint = hton32(ce->up_phys[0]);		send_multicast(data, len, true);	    }	    else {	        // Send to all outgoing interfaces, and neighbors	        for (i = 0; i < ce->n_downstream; i++) {		    if (pkt->i_ttl <= ce->down_str[i].ttl)		        continue;		    if (ce->down_str[i].nbr_addr == 0) {		        data->phyint = hton32(ce->down_str[i].phyint);			send_multicast(data, len, true);		    }		    else 		        sendpkt(pkt, ce->down_str[i].phyint, 				ce->down_str[i].nbr_addr);		}	    }	}    }    delete [] ((byte *)data);}/* Send a multicast packet. Find all the routers attached * to the segment and broadcast to them individually. * Router does not send the multicast to itself. This routine * is also used to deliver packets over unnumbered point-to-point * links. */void SimSys::send_multicast(SimPktHdr *data, size_t len, bool loopback){    int phyint;    AddressMap *mapp;    AVLsearch iter(&address_map);    InPkt *pkt;    InAddr dest;    pkt = (InPkt *) (data+1);    dest = ntoh32(pkt->i_dest);    phyint = ntoh32(data->phyint);    iter.seek(phyint, 0);    while ((mapp = (AddressMap *) iter.next())) {	sockaddr_in to;        if (mapp->index1() != (uns32) phyint)	    break;	// Loopback ping packets        if (mapp->home == my_id) {	    if (loopback)	       rxpkt(data); 	    continue;	}	to.sin_family = AF_INET;	to.sin_addr.s_addr = inet_addr(LOOPADDR);	to.sin_port = hton16(mapp->port);	if (sendto(uni_fd, data, len+sizeof(SimPktHdr), 0,		   (sockaddr *) &to, sizeof(to)) == -1)	  perror("sendto");	//sys_spflog(ERR_SYS, "sendto failed");    }}/* Return the port that is listening for unicast * packets to te simulated router. */uns16 SimSys::get_port_addr(InAddr addr, InAddr &owner){    AddressMap *mapp;    AVLsearch iter(&address_map);    iter.seek(addr, 0);    if (!(mapp = (AddressMap *) iter.next()) ||	(mapp->index1() != addr))        return(0);    owner = mapp->home;    return (mapp->port);}/* Contructor for an entry in the address map, that maps * unicast addresses to group addresses to simulate * data-link address translation. */AddressMap::AddressMap(InAddr addr, InAddr home) : AVLitem(addr, home){}/* Construct a ping session. */PingSession::PingSession(uns16 id, InAddr s, InAddr d, byte t) : AVLitem(id, 0){    src = s;    dest = d;    ttl = t;    seqno = 0;}/* When the ping session timer fires, we send another ICMP * echo. */void PingSession::action(){    simsys->sendicmp(ICMP_TYPE_ECHO, 0, src, dest, 0, index1(), seqno++, ttl);}/* Construct a traceroute session. */TRSession::TRSession(uns16 id, InAddr d, byte t) : AVLitem(id, 0){    dest = d;    maxttl = t;    seqno = 0;    ttl = 0;    iteration = MAXITER;    terminating = false;}/* Probe has timed out. Send a timeout message to the controller, * and then just act as if a response was received. */void TRSession::action(){    simsys->ctl_pkt.queue_xpkt(0, SIM_TRACEROUTE_TMO, index1(), 0);    response_received(255);}/* Traceroute response received. If it is any form of destination * unreachable, we are going to end the probes after the * current iteration. Otherwise, send a new ping and start * the timer again. * "type" is the ICMP packet type of any ICMP error received. * type == 255 indicates a timeout. */void TRSession::response_received(byte type){    TrTtlMsg ttlm;    stop();    if (type == ICMP_TYPE_UNREACH || type == ICMP_TYPE_ECHOREPLY) {        if (iteration == 0)          terminating = true;    } else        terminating = false;    // Start of new probe sequence?    if (iteration++ == MAXITER) {        if (terminating || ++ttl > maxttl) {	    simsys->traceroutes.remove(this);	    delete this;	    return;	}	iteration = 0;	ttlm.ttl = ttl;	simsys->ctl_pkt.queue_xpkt(&ttlm, SIM_TRACEROUTE_TTL,				   index1(), sizeof(ttlm));    }    // Send next probe packet    simsys->sendicmp(ICMP_TYPE_ECHO, 0, 0, dest, 0, index1(), seqno++, ttl);    start(2*maxttl*10, false);}/* When the ping session timer fires, we send another ICMP * echo. */void SimSys::sendicmp(byte type, byte code, InAddr src, InAddr dest,		      InPkt *rcvd, uns16 id, uns16 seqno, byte ttl){    InPkt *iphdr;    IcmpPkt *icmphdr;    int len;    IcmpPkt *r_icmp = 0;    int iphlen = 0;    if (rcvd) {        dest = ntoh32(rcvd->i_src);        iphlen = (rcvd->i_vhlen & 0xf) << 2;	r_icmp = (IcmpPkt *) (((byte *) rcvd) + iphlen);    }    switch (type) {      case ICMP_TYPE_ECHO:	len = sizeof(InPkt) + sizeof(IcmpPkt) + sizeof(SPFtime);	break;      case ICMP_TYPE_ECHOREPLY:	len = ntoh16(rcvd->i_len) - iphlen;	len += sizeof(InPkt);	break;      default:	// Don't respond to errors with errors	if (rcvd->i_prot == PROT_ICMP &&	    r_icmp->ic_type != ICMP_TYPE_ECHO &&	    r_icmp->ic_type != ICMP_TYPE_ECHOREPLY)	    return;	len = MIN(ntoh16(rcvd->i_len), ICMP_ERR_RETURN_BYTES);	len += sizeof(InPkt) + sizeof(IcmpPkt);	break;    }    iphdr = (InPkt *) new byte[len];    iphdr->i_vhlen = IHLVER;    iphdr->i_tos = 0;    iphdr->i_ffo = 0;    iphdr->i_prot = PROT_ICMP;    iphdr->i_len = hton16(len);    iphdr->i_id = 0;    iphdr->i_ttl = ((ttl != 0) ? ttl : DEFAULT_TTL);    iphdr->i_src = src ? hton32(src) : hton32(ip_source(dest));    iphdr->i_dest = hton32(dest);    iphdr->i_chksum = 0;	// Don't bother    icmphdr = (IcmpPkt *) (iphdr + 1);    icmphdr->ic_type = type;    icmphdr->ic_code = code;    icmphdr->ic_chksum = 0;	// Don't bother    // Fill in body    switch (type) {	int rlen;      case ICMP_TYPE_ECHO:	SPFtime *timep;	icmphdr->ic_id = hton16(id);	icmphdr->ic_seqno = hton16(seqno);	timep = (SPFtime *) (icmphdr+1);	*timep = sys_etime;	break;      case ICMP_TYPE_ECHOREPLY:	icmphdr->ic_id = r_icmp->ic_id;	icmphdr->ic_seqno = r_icmp->ic_seqno;	rlen = ntoh16(rcvd->i_len) - iphlen - sizeof(IcmpPkt);	if (rlen > 0)	    memcpy(icmphdr+1, r_icmp+1, rlen);	break;      default:	rlen = MIN(ntoh16(rcvd->i_len), ICMP_ERR_RETURN_BYTES);	memcpy(icmphdr+1, rcvd, rlen);	break;    }    if (iphdr->i_ttl-- == 1)        sendicmp(ICMP_TYPE_TTL_EXCEED, 0, 0, 0, iphdr, 0, 0, 0);    else        simsys->sendpkt(iphdr);    delete [] ((byte *) iphdr);}/* The follow two routines taken from ospfd's INtbl * and INrte classes. * Should make these utility routines. *//* Add an entry to an IP routing table entry. Install the * prefix pointers so that the best match operations will * work correctly. */SimRte *SimRttbl::add(uns32 net, uns32 mask){    SimRte *rte;    SimRte *parent;    SimRte *child;    AVLsearch iter(&routes);    if ((rte = (SimRte *) routes.find(net, mask)))	return(rte);    // Add to routing table entry    rte = new SimRte(net, mask);    routes.add(rte);    // Set prefix pointer    parent = (SimRte *) routes.previous(net, mask);    for (; parent; parent = parent->prefix) {	if (rte->is_child(parent)) {	    rte->prefix = parent;	    break;	}    }    // Set children's parent pointers    iter.seek(rte);    while ((child = (SimRte *)iter.next()) && child->is_child(rte)) {	if (child->prefix && child->prefix->is_child(rte))	    continue;	child->prefix = rte;    }    return(rte);}/* Find the best matching routing table entry for a given * IP destination. */SimRte *SimRttbl::best_match(uns32 addr){    SimRte *rte;    SimRte *prev;    rte = (SimRte *) routes.root();    prev = 0;    while (rte) {	if (addr < rte->net())	    rte = (SimRte *) rte->go_left();	else if (addr > rte->net() ||		 0xffffffff > rte->mask()) {	    prev = rte;	    rte = (SimRte *) rte->go_right();	}	else	    // Matching host route	    break;    }    // If no exact match, take previous entry    if (!rte)	rte = prev;    // Go up prefix chain, looking for valid routes    for (; rte; rte = rte->prefix) {	if ((addr & rte->mask()) != rte->net())	    continue;	if (rte->reachable)	    break;    }    return((!rte || rte->reject) ? 0 : rte);}/* Find the source address that would be used to send * packets to the given destination. */InAddr SimSys::ip_source(InAddr dest){    SimRte *rte;    if ((rte = rttbl.best_match(dest))) {        if (rte->if_addr != 0)	    return(rte->if_addr);    }    return(my_addr);}

⌨️ 快捷键说明

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