00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef lint
00035 static const char rcsid[] =
00036 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/emulate/tap.cc,v 1.14 2001/05/15 21:19:27 alefiyah Exp $ (UCB)";
00037 #endif
00038
00039 #include "tap.h"
00040
00041 static class TapAgentClass : public TclClass {
00042 public:
00043 TapAgentClass() : TclClass("Agent/Tap") {}
00044 TclObject* create(int, const char*const*) {
00045 return (new TapAgent());
00046 }
00047 } class_tap_agent;
00048
00049 TapAgent::TapAgent() : Agent(PT_LIVE), net_(NULL)
00050 {
00051 bind("maxpkt_", &maxpkt_);
00052 }
00053
00054
00055
00056
00057 int
00058 TapAgent::linknet()
00059 {
00060 int mode = net_->mode();
00061 int rchan = net_->rchannel();
00062 int wchan = net_->schannel();
00063
00064 unlink();
00065 if (mode == O_RDONLY || mode == O_RDWR) {
00066
00067 if (rchan < 0) {
00068 fprintf(stderr,
00069 "TapAgent(%s): network %s not open for reading (mode:%d)\n",
00070 name(), net_->name(), mode);
00071 return (TCL_ERROR);
00072 }
00073 link(rchan, TCL_READABLE);
00074 TDEBUG3("TapAgent(%s): linked sock %d as READABLE\n",
00075 name(), rchan);
00076 } else if (mode != O_WRONLY) {
00077 if (mode == -1) {
00078 fprintf(stderr,
00079 "TapAgent(%s): Network(%s) not opened properly.\n",
00080 name(), net_->name());
00081 fprintf(stderr,
00082 "(choose: readonly, readwrite, or writeonly)\n");
00083 } else {
00084 fprintf(stderr,
00085 "TapAgent(%s): unknown mode %d in Network(%s)\n",
00086 name(), mode, net_->name());
00087 }
00088 return (TCL_ERROR);
00089 }
00090
00091 if (mode == O_WRONLY || mode == O_RDWR) {
00092
00093 if (wchan < 0) {
00094 fprintf(stderr,
00095 "TapAgent(%s): network %s not open for writing\n",
00096 name(), net_->name());
00097 return (TCL_ERROR);
00098 }
00099 }
00100 return (TCL_OK);
00101 }
00102
00103 int
00104 TapAgent::command(int argc, const char*const* argv)
00105 {
00106 Tcl& tcl = Tcl::instance();
00107
00108 if (argc == 2) {
00109 if (strcmp(argv[1], "network") == 0) {
00110 tcl.result(name());
00111 return(TCL_OK);
00112 }
00113 }
00114 if (argc == 3) {
00115 if (strcmp(argv[1], "network") == 0) {
00116 net_ = (Network *)TclObject::lookup(argv[2]);
00117 if (net_ != 0) {
00118 return(linknet());
00119 } else {
00120 fprintf(stderr,
00121 "TapAgent(%s): unknown network %s\n",
00122 name(), argv[2]);
00123 return (TCL_ERROR);
00124 }
00125 return(TCL_OK);
00126 }
00127 }
00128 return (Agent::command(argc, argv));
00129 }
00130
00131
00132
00133
00134 void
00135 TapAgent::recvpkt()
00136 {
00137
00138 if (net_->mode() != O_RDWR && net_->mode() != O_RDONLY) {
00139 fprintf(stderr,
00140 "TapAgent(%s): recvpkt called while in write-only mode!\n",
00141 name());
00142 return;
00143 }
00144
00145 if (maxpkt_ <= 0) {
00146 fprintf(stderr,
00147 "TapAgent(%s): recvpkt: maxpkt_ value too low (%d)\n",
00148 name(), maxpkt_);
00149 return;
00150 }
00151
00152
00153 Packet* p = allocpkt(maxpkt_);
00154
00155
00156 sockaddr addr;
00157 double tstamp;
00158 int cc = net_->recv(p->accessdata(), maxpkt_, addr, tstamp);
00159 if (cc <= 0) {
00160 if (cc < 0) {
00161 perror("recv");
00162 }
00163 Packet::free(p);
00164 return;
00165 }
00166
00167 TDEBUG4("%f: Tap(%s): recvpkt, cc:%d\n", now(), name(), cc);
00168
00169
00170 hdr_cmn* ch = HDR_CMN(p);
00171 ch->size() = cc;
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 double when = tstamp - now();
00184
00185 if (when > 0.0) {
00186 TDEBUG5("%f: Tap(%s): DEFERRED PACKET %f secs, uid: %d\n",
00187 now(), name(), when, p->uid_);
00188 ch->timestamp() = when;
00189 Scheduler::instance().schedule(target_, p, when);
00190 } else {
00191 TDEBUG4("%f: Tap(%s): recvpkt, writing to target: %s\n",
00192 now(), name(), target_->name());
00193 ch->timestamp() = now();
00194 target_->recv(p);
00195 }
00196 return;
00197 }
00198
00199 void
00200 TapAgent::dispatch(int)
00201 {
00202
00203
00204
00205
00206
00207
00208 #ifdef notdef
00209 Scheduler::instance().sync();
00210 #endif
00211 recvpkt();
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void
00223 TapAgent::recv(Packet* p, Handler*)
00224 {
00225 (void) sendpkt(p);
00226 Packet::free(p);
00227 return;
00228 }
00229
00230 int
00231 TapAgent::sendpkt(Packet* p)
00232 {
00233 if (net_->mode() != O_RDWR && net_->mode() != O_WRONLY) {
00234 fprintf(stderr,
00235 "TapAgent(%s): sendpkt called while in read-only mode!\n",
00236 name());
00237 return (-1);
00238 }
00239
00240
00241 hdr_cmn* hc = HDR_CMN(p);
00242 if (net_ == NULL) {
00243 fprintf(stderr,
00244 "TapAgent(%s): sendpkt attempted with NULL net\n",
00245 name());
00246 drop(p);
00247 return (-1);
00248 }
00249 if (net_->send(p->accessdata(), hc->size()) < 0) {
00250 fprintf(stderr,
00251 "TapAgent(%s): sendpkt (%p, %d): %s\n",
00252 name(), p->accessdata(), hc->size(), strerror(errno));
00253 return (-1);
00254
00255 }
00256 TDEBUG3("TapAgent(%s): sent packet (sz: %d)\n",
00257 name(), hc->size());
00258 return 0;
00259 }