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

📄 agent.cc.svn-base

📁 diff serve for ns-2, work for version 2.29
💻 SVN-BASE
字号:
/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1990-1997 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the Computer Systems *	Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used *    to endorse or promote products derived from this software without *    specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic const char rcsid[] =    "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/agent.cc,v 1.78 2005/07/13 03:51:23 tomh Exp $ (LBL)";#endif#include <assert.h>#include <stdlib.h>#include "config.h"#include "agent.h"#include "ip.h"#include "flags.h"#include "address.h"#include "app.h"#ifdef HAVE_STL#include "nix/hdr_nv.h"#include "nix/nixnode.h"#endif //HAVE_STL#ifndef min#define min(a, b) (((a) < (b)) ? (a) : (b))#endifstatic class AgentClass : public TclClass {public:	AgentClass() : TclClass("Agent") {} 	TclObject* create(int, const char*const*) {		return (new Agent(PT_NTYPE));	}} class_agent;int Agent::uidcnt_;		/* running unique id */Agent::Agent(packet_t pkttype) : 	size_(0), type_(pkttype), app_type_(PT_NTYPE), 	channel_(0), traceName_(NULL),	oldValueList_(NULL), app_(0), et_(0){}Agent::Agent(packet_t pkttype, packet_t app_type) :       size_(0), type_(pkttype), app_type_(app_type),       channel_(0), traceName_(NULL),       oldValueList_(NULL), app_(0){}voidAgent::delay_bind_init_all(){	delay_bind_init_one("agent_addr_");	delay_bind_init_one("agent_port_");	delay_bind_init_one("dst_addr_");	delay_bind_init_one("dst_port_");	delay_bind_init_one("fid_");	delay_bind_init_one("prio_");	delay_bind_init_one("flags_");	delay_bind_init_one("ttl_");	delay_bind_init_one("class_");	Connector::delay_bind_init_all();}intAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer){	if (delay_bind(varName, localName, "agent_addr_", (int*)&(here_.addr_), tracer)) return TCL_OK;	if (delay_bind(varName, localName, "agent_port_", (int*)&(here_.port_), tracer)) return TCL_OK;	if (delay_bind(varName, localName, "dst_addr_", (int*)&(dst_.addr_), tracer)) return TCL_OK;	if (delay_bind(varName, localName, "dst_port_", (int*)&(dst_.port_), tracer)) return TCL_OK;	if (delay_bind(varName, localName, "fid_", (int*)&fid_, tracer)) return TCL_OK;	if (delay_bind(varName, localName, "prio_", (int*)&prio_, tracer)) return TCL_OK;	if (delay_bind(varName, localName, "flags_", (int*)&flags_, tracer)) return TCL_OK;	if (delay_bind(varName, localName, "ttl_", &defttl_, tracer)) return TCL_OK;	if (delay_bind(varName, localName, "class_", (int*)&fid_, tracer)) return TCL_OK;	return Connector::delay_bind_dispatch(varName, localName, tracer);}Agent::~Agent(){	if (oldValueList_ != NULL) {		OldValue *p = oldValueList_;		while (oldValueList_ != NULL) {			oldValueList_ = oldValueList_->next_;			delete p;			p = oldValueList_; 		}	}}int Agent::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "delete-agent-trace") == 0) {			if ((traceName_ == 0) || (channel_ == 0))				return (TCL_OK);			deleteAgentTrace();			return (TCL_OK);		} else if (strcmp(argv[1], "show-monitor") == 0) {			if ((traceName_ == 0) || (channel_ == 0))				return (TCL_OK);			monitorAgentTrace();			return (TCL_OK);		} else if (strcmp(argv[1], "close") == 0) {			close();			return (TCL_OK);		} else if (strcmp(argv[1], "listen") == 0) {                        listen();                        return (TCL_OK);                } else if (strcmp(argv[1], "dump-namtracedvars") == 0) {			enum_tracedVars();			return (TCL_OK);		}			}	else if (argc == 3) {		if (strcmp(argv[1], "attach") == 0) {			int mode;			const char* id = argv[2];			channel_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);			if (channel_ == 0) {				tcl.resultf("trace: can't attach %s for writing", id);				return (TCL_ERROR);			}			return (TCL_OK);		} else if (strcmp(argv[1], "add-agent-trace") == 0) {			// we need to write nam traces and set agent trace name			if (channel_ == 0) {				tcl.resultf("agent %s: no trace file attached", name_);				return (TCL_OK);			}			addAgentTrace(argv[2]);			return (TCL_OK);		} else if (strcmp(argv[1], "connect") == 0) {			connect((nsaddr_t)atoi(argv[2]));			return (TCL_OK);		} else if (strcmp(argv[1], "send") == 0) {			sendmsg(atoi(argv[2]));			return (TCL_OK);		} else if (strcmp(argv[1], "set_pkttype") == 0) {			set_pkttype(packet_t(atoi(argv[2])));			return (TCL_OK);               } else if (strcmp(argv[1], "set_apptype") == 0) {                       set_apptype(packet_t(atoi(argv[2])));                       return (TCL_OK);        	}	}	else if (argc == 4) {			if (strcmp(argv[1], "sendmsg") == 0) {			sendmsg(atoi(argv[2]), argv[3]);			return (TCL_OK);		}	}	else if (argc == 5) {		if (strcmp(argv[1], "sendto") == 0) {			sendto(atoi(argv[2]), argv[3], (nsaddr_t)atoi(argv[4]));			return (TCL_OK);		}	}	if (strcmp(argv[1], "tracevar") == 0) {		// wrapper of TclObject's trace command, because some tcl		// agents (e.g. srm) uses it.		const char* args[4];		char tmp[6];		strcpy(tmp, "trace");		args[0] = argv[0];		args[1] = tmp;		args[2] = argv[2];		if (argc > 3)			args[3] = argv[3];		return (Connector::command(argc, args));	}	return (Connector::command(argc, argv));}void Agent::flushAVar(TracedVar *v){	char wrk[256], value[128];	int n;	// XXX we need to keep track of old values. What's the best way?	v->value(value, 128);	if (strcmp(value, "") == 0) 		// no value, because no writes has occurred to this var		return;	sprintf(wrk, "f -t "TIME_FORMAT" -s %d -d %d -n %s -a %s -o %s -T v -x",		Scheduler::instance().clock(), addr(), dst_.addr_,		v->name(), traceName_, value); 	n = strlen(wrk);	wrk[n] = '\n';	wrk[n+1] = 0;	(void)Tcl_Write(channel_, wrk, n+1);}void Agent::deleteAgentTrace(){	char wrk[256];	// XXX we don't know InstVar outside of Tcl! Is there any	// tracedvars hidden in InstVar? If so, shall we have a tclclInt.h?	TracedVar* var = tracedvar_;	for ( ;  var != 0;  var = var->next_) 		flushAVar(var);	// we need to flush all var values to trace file, 	// so nam can do backtracing	sprintf(wrk, "a -t "TIME_FORMAT" -s %d -d %d -n %s -x",		Scheduler::instance().clock(), here_.addr_,		dst_.addr_, traceName_); 	if (traceName_ != NULL)		delete[] traceName_;	traceName_ = NULL;}OldValue* Agent::lookupOldValue(TracedVar *v){	OldValue *p = oldValueList_;	while ((p != NULL) && (p->var_ != v))		p = p->next_;	return p;}void Agent::insertOldValue(TracedVar *v, const char *value){	OldValue *p = new OldValue;	assert(p != NULL);	strncpy(p->val_, value, min(strlen(value)+1, TRACEVAR_MAXVALUELENGTH));	p->var_ = v;	p->next_ = NULL;	if (oldValueList_ == NULL) 		oldValueList_ = p;	else {		p->next_ = oldValueList_;		oldValueList_ = p;	}}// callback from traced variable updatesvoid Agent::trace(TracedVar* v) {	if (channel_ == 0)		return;	char wrk[256], value[128];	int n;	// XXX we need to keep track of old values. What's the best way?	v->value(value, 128);	// XXX hack: how do I know ns has not started yet?	// if there's nothing in value, return	static int started = 0;	if (!started) {		Tcl::instance().evalc("[Simulator instance] is-started");		if (Tcl::instance().result()[0] == '0')			// Simulator not started, do nothing			return;		// remember for next time (so we don't always have to call to tcl)		started = 1;	};	OldValue *ov = lookupOldValue(v);	if (ov != NULL) {		sprintf(wrk, 			"f -t "TIME_FORMAT" -s %d -d %d -n %s -a %s -v %s -o %s -T v",			Scheduler::instance().clock(), here_.addr_,			dst_.addr_, v->name(), traceName_, value, ov->val_);		strncpy(ov->val_, 			value,			min(strlen(value)+1, TRACEVAR_MAXVALUELENGTH));	} else {		// if there is value, insert it into old value list		sprintf(wrk, "f -t "TIME_FORMAT" -s %d -d %d -n %s -a %s -v %s -T v",			Scheduler::instance().clock(), here_.addr_,			dst_.addr_, v->name(), traceName_, value);		insertOldValue(v, value);	}	n = strlen(wrk);	wrk[n] = '\n';	wrk[n+1] = 0;	(void)Tcl_Write(channel_, wrk, n+1);}void Agent::monitorAgentTrace(){	char wrk[256];	int n;	double curTime = (&Scheduler::instance() == NULL ? 0 : 			  Scheduler::instance().clock());		sprintf(wrk, "v -t "TIME_FORMAT" -e monitor_agent %d %s",		curTime, here_.addr_, traceName_);	n = strlen(wrk);	wrk[n] = '\n';	wrk[n+1] = 0;	if (channel_)		(void)Tcl_Write(channel_, wrk, n+1);}void Agent::addAgentTrace(const char *name){	char wrk[256];	int n;	double curTime = (&Scheduler::instance() == NULL ? 0 : 			  Scheduler::instance().clock());		sprintf(wrk, "a -t "TIME_FORMAT" -s %d -d %d -n %s",		curTime, here_.addr_, dst_.addr_, name);	n = strlen(wrk);	wrk[n] = '\n';	wrk[n+1] = 0;	if (channel_)		(void)Tcl_Write(channel_, wrk, n+1);	// keep agent trace name	if (traceName_ != NULL)		delete[] traceName_;	traceName_ = new char[strlen(name)+1];	strcpy(traceName_, name);}void Agent::timeout(int){}/*  * Callback to application to notify the reception of a number of bytes   */void Agent::recvBytes(int nbytes){	if (app_)		app_->recv(nbytes);	}/*  * Callback to application to notify the termination of a connection   */void Agent::idle(){	if (app_)		app_->resume();}/*  * Assign application pointer for callback purposes     */void Agent::attachApp(Application *app){	app_ = app;}void Agent::close(){}void Agent::listen(){}/*  * This function is a placeholder in case applications want to dynamically * connect to agents (presently, must be done at configuration time). */void Agent::connect(nsaddr_t /*dst*/){/*	dst_ = dst;*/}/* * Place holders for sending application data */ void Agent::sendmsg(int /*sz*/, AppData* /*data*/, const char* /*flags*/){	fprintf(stderr, 	"Agent::sendmsg(int, AppData*, const char*) not implemented\n");	abort();}void Agent::sendmsg(int /*nbytes*/, const char* /*flags*/){}void Agent::sendto(int /*sz*/, AppData* /*data*/, const char* /*flags*/,		   nsaddr_t /*dst*/){	fprintf(stderr, 	"Agent::sendmsg(int, AppData*, const char*) not implemented\n");	abort();}// to support application using message passingvoid Agent::sendto(int /*sz*/, AppData* /*data*/, const char* /*flags*/,		   ns_addr_t /*dst*/){}/*  * This function is a placeholder in case applications want to dynamically * connect to agents (presently, must be done at configuration time). */void Agent::sendto(int /*nbytes*/, const char /*flags*/[], nsaddr_t /*dst*/){/*	dst_ = dst;	sendmsg(nbytes, flags);*/}// to support application using message passingvoid Agent::sendto(int /*nbytes*/, const char /*flags*/[], ns_addr_t /*dst*/){}void Agent::recv(Packet* p, Handler*){	if (app_)		app_->recv(hdr_cmn::access(p)->size());	/*	 * didn't expect packet (or we're a null agent?)	 */	Packet::free(p);}/* * initpkt: fill in all the generic fields of a pkt */voidAgent::initpkt(Packet* p) const{	hdr_cmn* ch = hdr_cmn::access(p);	ch->uid() = uidcnt_++;	ch->ptype() = type_;        ch->app_type() = app_type_;	ch->size() = size_;	ch->timestamp() = Scheduler::instance().clock();	ch->iface() = UNKN_IFACE.value(); // from packet.h (agent is local)	ch->direction() = hdr_cmn::NONE;	ch->error() = 0;	/* pkt not corrupt to start with */	hdr_ip* iph = hdr_ip::access(p);	iph->saddr() = here_.addr_;	iph->sport() = here_.port_;	iph->daddr() = dst_.addr_;	iph->dport() = dst_.port_;		//DEBUG	//if (dst_ != -1)	//  printf("pl break\n");		iph->flowid() = fid_;	iph->prio() = prio_;	iph->ttl() = defttl_;	hdr_flags* hf = hdr_flags::access(p);	hf->ecn_capable_ = 0;	hf->ecn_ = 0;	hf->eln_ = 0;	hf->ecn_to_echo_ = 0;	hf->fs_ = 0;	hf->no_ts_ = 0;	hf->pri_ = 0;	hf->cong_action_ = 0;	hf->qs_ = 0;#ifdef HAVE_STL 	hdr_nv* nv = hdr_nv::access(p); 	if (0)		printf("Off hdr_nv %d, ip_hdr %d myaddr %d\n",		       hdr_nv::offset(), hdr_ip::offset(), here_.addr_); 	NixNode* pNixNode = NixNode::GetNodeObject(here_.addr_); 	if (0)		printf("Node Object %p\n", pNixNode); 	if (pNixNode) {  		// If we get non-null, indicates nixvector routing in use 		// Delete any left over nv in the packet 		// Get a nixvector to the target (may create new) 		NixVec* pNv = pNixNode->GetNixVector(dst_.addr_); 		pNv->Reset(); 		nv->nv() = pNv; // And set the nixvec in the packet 		nv->h_used = 0; // And reset used portion to 0 	}#endif //HAVE_STL}/* * allocate a packet and fill in all the generic fields */Packet*Agent::allocpkt() const{	Packet* p = Packet::alloc();	initpkt(p);	return (p);}/* allocate a packet and fill in all the generic fields and allocate * a buffer of n bytes for data */Packet*Agent::allocpkt(int n) const{        Packet* p = allocpkt();	if (n > 0)	        p->allocdata(n);	return(p);}

⌨️ 快捷键说明

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