📄 rsvp.cc
字号:
delete temp; num_rsb_--; } else { r = r->next; } } } if (s->rsb_list == NULL) { s->resv_ref = -1; }}/* Find a PSB for a session whose SENDER_TEMPLATE matches 'sender'. Return NULL if no such PSB is found. */psb *RSVPAgent::find_psb(session *s, nsaddr_t sender) { psb *search = s->psb_list; while ((search != NULL) && (search->sender->get_addr() != sender)) { search = search->next; } return search;}/* Find an RSB for a session whose FILTERSPEC matches 'sender' and whose NHOP matches 'nhop'. Return NULL if no such PSB is found. */rsb *RSVPAgent::find_rsb(session *s, nsaddr_t sender, nsaddr_t nhop) { rsb *search = s->rsb_list; while ((search != NULL) && ((search->sender->get_addr() != sender) || (search->nhop->get_hop() != nhop))) { search = search->next; } return search;}/* Return 1 if there is an RSB with the corresponding PSB 'p', otherwise return 0. */int RSVPAgent::find_rsb_for_psb(session *s, psb *p) { rsb *r = s->rsb_list; while ((r != NULL) && (r->p != p)) { r = r->next; } return (r != NULL);}/* Return a pointer to the session with the destination address 'dst' and the flow id 'fid' or return NULL if none is found. */session *RSVPAgent::find_session_dst(nsaddr_t dst, int fid) { session *s = s_list_; while ((s != NULL) && ((s->s->get_dest() != dst) || (s->s->get_fid() != fid))) { s = s->next; } if (s == NULL) { return NULL; } else { return s; }}/* Return a pointer to the session with the id 'sid' or return NULL if not found. */session *RSVPAgent::find_session_sid(long sid) { session *s = s_list_; while ((s != NULL) && (s->sid > sid)) { s = s->next; } if ((s == NULL) || (s->sid != sid)) { return NULL; } else { return s; }}void RSVPAgent::give(Packet *p, RSVPChecker *ret) { //hdr_rsvp* rsvp_hdr = (hdr_rsvp*)p->access(off_rsvp_); hdr_rsvp* rsvp_hdr = hdr_rsvp::access(p); //hdr_cmn* cmn_hdr = (hdr_cmn*)p->access(off_cmn_); hdr_cmn *cmn_hdr = hdr_cmn::access(p); RSVPmessage *msg = new RSVPmessage(p->accessdata()); switch (msg->get_type()) { case PATH: process_path_message(msg, cmn_hdr->iface_, ret); break; case PATHTEAR: process_path_tear_message(msg, cmn_hdr->iface_, ret); break; case RESV: process_resv_message(msg, rsvp_hdr->fromhop); break; case RESVTEAR: process_resv_tear_message(msg); break; case RESVERR: process_resv_err_message(msg); break; case RESVCONF: process_resv_conf_message(msg); break; } delete msg; Packet::free(p);}/* This function is needed to correct the problem that there seem to be some accuracy problems in C++ so that two doubles are not necessarily equal even if they 'look' equal. The range of 0.00001 seconds should not affect the simulations at all (where the refresh time is chosen randomly from a certain range anyway). */char RSVPAgent::in_range(double x, double y) { return (x - 0.00001) <= y;}/* Checks for a packet if the current node is a leaf node in a multicast tree. */char RSVPAgent::is_leaf(nsaddr_t src, nsaddr_t dst) { Tcl& tcl = Tcl::instance(); tcl.evalf("%s is-leaf %d %d", name(), src, dst); return (atoi(tcl.result()));}void RSVPAgent::list_sessions(char *buf, int size) { session *s = s_list_; char *ptr; ptr = buf; buf[0] = '\0'; while ((s != NULL) && (ptr < buf + size - 10)) { sprintf(ptr, "%ld ", s->sid); s = s->next; ptr = ptr + strlen(ptr); }}/* Returns the path_ref or resv_ref of a session, whichever is lesser */double RSVPAgent::minref(session *s) { if (s->path_ref == -1) { return s->resv_ref; } if (s->resv_ref == -1) { return s->path_ref; } if (s->path_ref < s->resv_ref) { return s->path_ref; } else { return s->resv_ref; }}/* Create a new PSB for a given session, add it to the session's PSB list, reschedule the session for refreshing. */void RSVPAgent::new_psb(session *s, double rate, long bucket, char ttl, nsaddr_t sender, nsaddr_t phop, double refresh, int iface, RSVPChecker *check) { psb *p = new psb(); p->sender = new SENDER_TEMPLATE(sender, ip6_); p->s_tspec = new SENDER_TSPEC(rate, bucket); p->phop = new RSVP_HOP(phop, ip6_); p->ttl = ttl; p->iif = iface; p->check = check; if (phop > -1) { // Call came from API p->timeout = (lifetime_factor_ + 0.5) * 1.5 * refresh + Scheduler::instance().clock(); } if ((s->psb_list == NULL) || (s->psb_list->sender->get_addr() > sender)) { p->next = s->psb_list; s->psb_list = p; } else { psb *search = s->psb_list; while ((search->next != NULL) && (search->next->sender->get_addr() < sender)) { search = search->next; } p->next = search->next; search->next = p; } send_path_message(s, p); /* Reschedule the session if this is the first PSB. Send a path message for this PSB. */ if (s->path_ref == -1) { s->path_ref = Scheduler::instance().clock() + s->path_tv->get_r(); reschedule_session(s); } /* Make an upcall to the API if necessary */ if ((noisy_ & UPC_PATH) && (phop > -1)) { Tcl& tcl = Tcl::instance(); tcl.evalf("%s upcall-path %d %f %d %d", name(), s->sid, rate, bucket, sender); }}/* Create a new RSB for a given session and add it to the session's RSB list. */rsb *RSVPAgent::new_rsb(session *s, psb *p, nsaddr_t sender, FLOWSPEC *fl, const char *style, nsaddr_t nhop, double refresh, nsaddr_t fromhop) { rsb *r = new rsb(); r->nhop = new RSVP_HOP(nhop, ip6_); r->sender = new FILTER_SPEC(sender, ip6_); r->fspec = new FLOWSPEC(fl->get_contents()); r->p = p; r->oifhop = fromhop; r->modified = 1; r->is_new = 1; /* Only valid values for 'style' should arrive here */ if (strcasecmp(style, "FF") == 0) { r->st = new STYLE(STYLE_FF); } if (nhop > -1) { // Call came from API r->timeout = (lifetime_factor_ + 0.5) * 1.5 * refresh + Scheduler::instance().clock(); } if ((s->rsb_list == NULL) || (s->rsb_list->sender->get_addr() > sender)) { s->rsb_list = r; } else { rsb *search = s->rsb_list; while ((search->next != NULL) && (search->next->sender->get_addr() < sender)) { search = search->next; } r->next = search->next; search->next = r; } return r;}/* Create a new session and add it to the session list, then return a pointer to the session. */session *RSVPAgent::new_session_p(nsaddr_t dst, int fid, char local) { RNG* defaultRNG = RNG::defaultrng() ; session *n, *s; n = new session(); n->s = new SESSION(dst, 0, fid, ip6_); // Set the refresh timer as described in section 3.7 of RFC 2205: n->path_tv = new TIME_VALUES((defaultRNG->uniform_double() + 0.5) * refresh_ ); n->resv_tv = new TIME_VALUES((defaultRNG->uniform_double() + 0.5) * refresh_ ); n->sid = next_sid_; n->local = local; next_sid_++; if (next_sid_ > MAXSID) { next_sid_ = 0; } // The session list is sorted in descending order of the sid's if ((s_list_ == NULL) || (s_list_->sid < n->sid)) { n->next = s_list_; s_list_ = n; } else { s = s_list_; while ((s->next != NULL) && (s->next->sid > n->sid)) { s = s->next; } n->next = s->next; s->next = n; } return n;}/* Create a new session and add it to the session list, then return the sid. */int RSVPAgent::new_session_sid(nsaddr_t dst, int fid, char local) { RNG* defaultRNG = RNG::defaultrng() ; session *n, *s; n = new session(); n->s = new SESSION(dst, 0, fid, ip6_); // Set the refresh timer as described in section 3.7 of RFC 2205: n->path_tv = new TIME_VALUES((defaultRNG->uniform_double() + 0.5) * refresh_ ); n->resv_tv = new TIME_VALUES((defaultRNG->uniform_double() + 0.5) * refresh_ ); n->sid = next_sid_; n->local = local; next_sid_++; if (next_sid_ > MAXSID) { next_sid_ = 0; } // The session list is sorted in descending order of the sid's if ((s_list_ == NULL) || (s_list_->sid < n->sid)) { n->next = s_list_; s_list_ = n; } else { s = s_list_; while ((s->next != NULL) && (s->next->sid > n->sid)) { s = s->next; } n->next = s->next; s->next = n; } return n->sid;}void RSVPAgent::process_ff_request(session *s, int argc, const char*const* argv) { Tcl &tcl = Tcl::instance(); int i = 4; rsb *r; psb *p; nsaddr_t sender; char modified = 0; FLOWSPEC *fl; /* The following code parses a flow descriptor list which matches the following Backus-Naur form: <flow descriptor list> ::= <FLOWSPEC> <FILTER_SPEC> | <flow descriptor list><FF flow descriptor> <FF flow descriptor> ::= [ <FLOWSPEC> ] <FILTER_SPEC> This conforms with the description in RFC 2205 and means that there can be any number of FILTER_SPEC objects for a FLOWSPEC object. */ while (i < argc) { if (i + 1 >= argc) { tcl.evalf("%s RSVP: FLOWSPEC incomplete", name()); } fl = new FLOWSPEC(atoi(argv[i]), atoi(argv[i+1])); i += 2; if ((i >= argc) || (argv[i][0] == '+')) { tcl.evalf("%s RSVP: FILTER_SPEC missing", name()); } while ((i < argc) && (argv[i][0] != '+')) { if (argv[i][0] == '_') { tcl.evalf("%s id", argv[i]); sender = atoi(tcl.result()); } else { sender = atoi(argv[i]); } if (((p = find_psb(s, sender)) == NULL) && (noisy_ & UPC_RESVERR)) { tcl.evalf("%s upcall-resv-error %s 4 0 %d %d", name(), argv[2], // addr_ >> Address::instance().NodeShift_[1], sender); here_.addr_ , sender); } if ((r = find_rsb(s, sender, -1)) == NULL) { new_rsb(s, p, sender, fl, "FF", -1, refresh_, -1); num_rsb_++; } else { update_rsb(s, r, p, sender, fl, "FF", -1, refresh_, -1); } i++; } delete fl; } rsb *rsearch = s->rsb_list; while (rsearch != NULL) { if (rsearch->modified || rsearch->is_new) { modified = 1; rsearch->modified = 0; rsearch->is_new = 0; } rsearch = rsearch->next; } refresh_resv(s, 0);}void RSVPAgent::process_path_message(RSVPmessage *msg, int iface, RSVPChecker *check) { SESSION *se = (SESSION *)msg->get_first(1); session *s; if ((s = find_session_dst(se->get_dest(), se->get_fid())) == NULL) { s = new_session_p(se->get_dest(), se->get_fid(), 0); }; psb *p; SENDER_TEMPLATE *sender = (SENDER_TEMPLATE *)msg->get_first(11); TIME_VALUES *tv = (TIME_VALUES *)msg->get_first(5); SENDER_TSPEC *s_tspec = (SENDER_TSPEC *)msg->get_first(12); RSVP_HOP *hop = (RSVP_HOP *)msg->get_first(3); if ((p = find_psb(s, sender->get_addr())) == NULL) { new_psb(s, s_tspec->get_rate(), s_tspec->get_size(), msg->get_ttl(), sender->get_addr(), hop->get_hop(), tv->get_r(), iface, check); num_psb_++; } else { update_psb(s, p, s_tspec->get_rate(), s_tspec->get_size(), msg->get_ttl(), sender->get_addr(), hop->get_hop(), tv->get_r(), iface, check); }}void RSVPAgent::process_path_tear_message(RSVPmessage *msg, int iface, RSVPChecker *check) { SESSION *se = (SESSION *)msg->get_first(1); session *s; if ((s = find_session_dst(se->get_dest(), se->get_fid())) != NULL) { psb *p; SENDER_TEMPLATE *sender = (SENDER_TEMPLATE *)msg->get_first(11); RSVP_HOP *hop = (RSVP_HOP *)msg->get_first(3); /* Note: Even if there was a SENDER_TSPEC object in this message, it is supposed to be ignored according to RFC 2205. */ if ((p = find_psb(s, sender->get_addr())) != NULL) { /* According to RFC 2205, the RSVP_HOP and the PHOP have to be identical. RFC 2209 does not mention that. */ if (p->phop->get_hop() == hop->get_hop()) { if (noisy_ & UPC_PATHTEAR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -