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
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include "flags.h"
00064 #include "delay.h"
00065 #include "gk.h"
00066 #include "math.h"
00067
00068 static class GKClass : public TclClass {
00069 public:
00070 GKClass() : TclClass("Queue/GK") {}
00071 TclObject* create(int argc, const char*const* argv) {
00072 if (argc==5)
00073 return (new GK(argv[4]));
00074 else
00075 return (new GK("Drop"));
00076 }
00077 } class_gk;
00078
00079 GK::GK(const char * trace):link_(NULL), EDTrace(NULL), tchan_(0)
00080 {
00081 q_ = new PacketQueue;
00082 pq_ = q_;
00083 bind_bool("drop_front_", &drop_front_);
00084 bind("ecnlim_", &ecnlim_);
00085 bind("mean_pktsize_", &mean_pktsize_);
00086 bind("curq_", &curq_);
00087 vq_len = 0.0;
00088 prev_time = 0.0;
00089 mark_flag = 0;
00090 }
00091
00092 int GK::command(int argc, const char*const* argv) {
00093 Tcl& tcl = Tcl::instance();
00094 if (argc == 3) {
00095 if (strcmp(argv[1], "link") == 0) {
00096 LinkDelay* del = (LinkDelay*)TclObject::lookup(argv[2]);
00097 if (del == 0) {
00098 return(TCL_ERROR);
00099 }
00100
00101 link_ = del;
00102 c_ = del->bandwidth();
00103 c_ = c_ / (8.0 * mean_pktsize_);
00104 return (TCL_OK);
00105 }
00106 if (!strcmp(argv[1], "packetqueue-attach")) {
00107 delete q_;
00108 if (!(q_ = (PacketQueue*) TclObject::lookup(argv[2])))
00109 return (TCL_ERROR);
00110 else {
00111 pq_ = q_;
00112 return (TCL_OK);
00113 }
00114 }
00115
00116 if (strcmp(argv[1], "attach") == 0) {
00117 int mode;
00118 const char* id = argv[2];
00119 tchan_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);
00120 if (tchan_ == 0) {
00121 tcl.resultf("Vq: trace: can't attach %s for writing", id);
00122 return (TCL_ERROR);
00123 }
00124 return (TCL_OK);
00125 }
00126 }
00127 return Queue::command(argc, argv);
00128 }
00129
00130 void GK::enque(Packet* p)
00131 {
00132 q_->enque(p);
00133
00134 curr_time = Scheduler::instance().clock();
00135
00136
00137
00138 if(curr_time > prev_time){
00139 deque_vq();
00140 }
00141
00142 vq_len = vq_len + 1.0;
00143
00144
00145
00146 if(vq_len > (ecnlim_ * qlim_)){
00147 mark_flag = 1;
00148 vq_len = vq_len - 1.0;
00149 }
00150
00151 if (q_->length() >= qlim_) {
00152 if (drop_front_) {
00153 Packet *pp = q_->deque();
00154 drop(pp);
00155 } else {
00156 q_->remove(p);
00157 drop(p);
00158 }
00159 }
00160 curq_ = q_->length();
00161 }
00162
00163 Packet* GK::deque()
00164 {
00165
00166
00167 curr_time = Scheduler::instance().clock();
00168 deque_vq();
00169
00170
00171
00172 if((q_->length() > 0) && (mark_flag == 1)){
00173 Packet *pp = q_->deque();
00174 hdr_flags* hf = hdr_flags::access(pp);
00175 if(hf->ect() == 1)
00176 hf->ce() = 1;
00177 return pp;
00178 }
00179 else return q_->deque();
00180 }
00181
00182
00183 void GK::deque_vq(){
00184 if(vq_len > 0.0){
00185 vq_len = vq_len - (ecnlim_ * c_ * (curr_time - prev_time));
00186 prev_time = curr_time;
00187
00188
00189 if(vq_len <= 0.0){
00190 vq_len = 0.0;
00191 mark_flag = 0;
00192 }
00193 }
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203 void GK::trace(TracedVar* v)
00204 {
00205 char wrk[500], *p;
00206
00207 if ((p = strstr(v->name(), "curq")) == NULL) {
00208 fprintf(stderr, "Vq:unknown trace var %s\n", v->name());
00209 return;
00210 }
00211
00212 if (tchan_) {
00213 int n;
00214 double t = Scheduler::instance().clock();
00215
00216 if (*p == 'c') {
00217 sprintf(wrk, "Q %g %d", t, int(*((TracedInt*) v)));
00218 } else {
00219 sprintf(wrk, "%c %g %g", *p, t, double(*((TracedDouble*) v)));
00220 }
00221 n = strlen(wrk);
00222 wrk[n] = '\n';
00223 wrk[n+1] = 0;
00224 (void)Tcl_Write(tchan_, wrk, n+1);
00225 }
00226 return;
00227 }