📄 rsvp.cc
字号:
Tcl& tcl = Tcl::instance(); tcl.evalf("%s upcall-path-tear %d %d", name(), s->sid, sender->get_addr()); } /* The necessary actions for deleting the path state would be fairly complicated. The PSB and all corresponding RSBs have to be deleted and the session has to be removed if this PSB was the last state block. To make this short, a 'trick' will be used. The timeout for this PSB will be set to -1, and then a check_path will be performed, which will definitely remove this PSB (and perhaps even clean up some other PSBs which are due for removal in the process). */ p->timeout = -1; if (!check_path(s)) { reschedule_session(s); } } } }}void RSVPAgent::process_resv_conf_message(RSVPmessage *msg) { RESV_CONFIRM *confirm = (RESV_CONFIRM *)msg->get_first(15); // if (confirm->get_addr() == addr_ >> Address::instance().NodeShift_[1]) { if (confirm->get_addr() == here_.addr_ ) { SESSION *se = (SESSION *)msg->get_first(1); session *s; if ((s = find_session_dst(se->get_dest(), se->get_fid())) != NULL) { FILTER_SPEC *sender = (FILTER_SPEC *)msg->get_first(10); ERROR_SPEC *err = (ERROR_SPEC *)msg->get_first(6); if (noisy_ & UPC_RESVCONF) { Tcl& tcl = Tcl::instance(); tcl.evalf("%s upcall-resv-confirm %d %d %d", name(), s->s->get_fid(), sender->get_addr(), err->get_errnode()); } } } else { if (ip6_) { size_ = msg->get_length() + 40; // Size for standard IPv6 header } else { size_ = msg->get_length() + 24; } Tcl& tcl = Tcl::instance(); tcl.evalf("[Simulator instance] connect-rsvp-agents %d %d", // addr_ >> Address::instance().NodeShift_[1], here_.addr_ , confirm->get_addr()); Packet *pkt = allocpkt(); pkt->allocdata(msg->get_conlength()); memcpy(pkt->accessdata(), msg->get_contents(), msg->get_conlength()); send(pkt, 0); }}void RSVPAgent::process_resv_err_message(RSVPmessage *msg) { SESSION *se = (SESSION *)msg->get_first(1); session *s; rsb *r; Tcl& tcl = Tcl::instance(); if ((s = find_session_dst(se->get_dest(), se->get_fid())) == NULL) { } else { RSVP_HOP *nhop = (RSVP_HOP *)msg->get_first(3); FILTER_SPEC *sender = (FILTER_SPEC *)msg->get_first(10); ERROR_SPEC *err = (ERROR_SPEC *)msg->get_first(6); /* First mark all RSBs which route to the outgoing interface where the ResvErr message came from. */ while (sender != NULL) { r = s->rsb_list; while (r != NULL) { if ((r->p->phop->get_hop() == nhop->get_hop()) && (r->sender->get_addr() == sender->get_addr())) { r->processed = 1; } r = r->next; } msg->delete_first(10); sender = (FILTER_SPEC *)msg->get_first(10); } /* Now send ResvErr messages to each nhop that appears in the marked RSBs. */ r = s->rsb_list; while (r != NULL) { if (r->processed) { send_resv_err_message(s, msg, r); } r->processed = 0; r = r->next; } if (noisy_ & UPC_RESVERR) { tcl.evalf("%s upcall-resv-error %d %d %d %d", name(), s->sid, err->get_errcode(), err->get_errvalue(), err->get_errnode()); } }}void RSVPAgent::process_resv_message(RSVPmessage *msg, nsaddr_t fromhop) { SESSION *se = (SESSION *)msg->get_first(1); session *s; char modified = 0; if ((s = find_session_dst(se->get_dest(), se->get_fid())) == NULL) { send_resv_err_message(msg, 3); } else { RSVP_HOP *nhop = (RSVP_HOP *)msg->get_first(3); TIME_VALUES *tv = (TIME_VALUES *)msg->get_first(5); rsb *r; psb *p; FLOWSPEC *fl; FILTER_SPEC *sender; long senderaddr ; // SM fl = (FLOWSPEC *)msg->get_first(9); while (fl != NULL) { sender = (FILTER_SPEC *)msg->get_first(10); // There was a problem here - the sender is deleted below with // the delete_first method, but is still assumed to contain valid // data in the while loop below. To overcome this, I create a // new variable - senderaddr - this is used below - SM senderaddr = sender->get_addr() ; if ((p = find_psb(s, sender->get_addr())) == NULL) { send_resv_err_message(msg, 4); } if ((r = find_rsb(s, sender->get_addr(), nhop->get_hop())) == NULL) { r = new_rsb(s, p, sender->get_addr(), fl, "FF", nhop->get_hop(), tv->get_r(), fromhop); num_rsb_++; } else { update_rsb(s, r, p, sender->get_addr(), fl, "FF", nhop->get_hop(), tv->get_r(), fromhop); } RESV_CONFIRM *confirm = (RESV_CONFIRM *)msg->get_first(15); if (confirm != NULL) { r->confirm = new RESV_CONFIRM(confirm->get_contents()); } modified += update_traffic_control(s, r); msg->delete_first(9); msg->delete_first(10); fl = (FLOWSPEC *)msg->get_first(9); } rsb *rsearch = s->rsb_list; while (rsearch != NULL) { if (rsearch->modified || rsearch->is_new) { rsearch->modified = 0; rsearch->is_new = 0; /* Make an upcall to the API if necessary. One upcall is made for each new RSB, and resv upcalls are not only made on leaf nodes. */ if (noisy_ & UPC_RESV) { Tcl& tcl = Tcl::instance(); tcl.evalf("%s upcall-resv %d %f %d %d", name(), s->sid, r->fspec->get_rate(), r->fspec->get_size(), //sender->get_addr()); senderaddr) ; // SM } } rsearch = rsearch->next; } refresh_resv(s, 0); }}void RSVPAgent::process_resv_tear_message(RSVPmessage *msg) { SESSION *se = (SESSION *)msg->get_first(1); session *s; // Tcl& tcl = Tcl::instance(); - unused rsb *r, *r_list, *temp; /* Check if a session exists for this ResvTear message, otherwise drop the message silently. */ if ((s = find_session_dst(se->get_dest(), se->get_fid())) != NULL) { FILTER_SPEC *sender; RSVP_HOP *nhop = (RSVP_HOP *)msg->get_first(3); r_list = 0; sender = (FILTER_SPEC *)msg->get_first(10); /* Read each FILTER_SPEC from the message and delete the corresponding RSBs from the rsb_list, putting them in a different list for further processing. */ while (sender != NULL) { while ((s->rsb_list != NULL) && (s->rsb_list->sender->get_addr() == sender->get_addr()) && (s->rsb_list->nhop->get_hop() == nhop->get_hop())) { temp = s->rsb_list; s->rsb_list = temp->next; temp->next = r_list; r_list = temp; update_traffic_control(s, temp); if ((noisy_ & UPC_RESVTEAR) && (temp->timeout != -1)) { Tcl& tcl = Tcl::instance(); tcl.evalf("%s upcall-resv-tear %d %d", name(), s->sid, temp->sender->get_addr()); } } if (s->rsb_list != NULL) { r = s->rsb_list; while (r != NULL) { if ((r->next != NULL) && (r->next->sender->get_addr() == sender->get_addr()) && (r->next->nhop->get_hop() == nhop->get_hop())) { temp = r->next; r->next = temp->next; temp->next = r_list; r_list = temp; num_rsb_--; update_traffic_control(s, temp); if ((noisy_ & UPC_RESVTEAR) && (temp->timeout != -1)) { Tcl& tcl = Tcl::instance(); tcl.evalf("%s upcall-resv-tear %d %d", name(), s->sid, temp->sender->get_addr()); } } r = r->next; } } msg->delete_first(10); sender = (FILTER_SPEC *)msg->get_first(10); } } if (r_list != NULL) { refresh_resv(s, 0); while ((r_list != NULL) && (find_rsb_for_psb(s, r_list->p))) { temp = r_list; r_list = r_list->next; clear_rsb(temp); delete temp; } if (r_list != NULL) { r = r_list; while (r->next != NULL) { if (find_rsb_for_psb(s, r->p)) { temp = r->next; r->next = temp->next; clear_rsb(temp); delete temp; } } } if (r_list != NULL) { send_resv_tear_messages(s, r_list); } while (r_list != NULL) { temp = r_list; r_list = r_list->next; clear_rsb(temp); delete temp; } }}void RSVPAgent::recv(Packet* p, Handler* h) { /* All packets are already being processed by the 'give' function, so get rid of this packet. */ Packet::free(p);}/* Refresh the path/reservation state for all sessions that need to be refreshed (usually that should only be the first session in the timer list). */void RSVPAgent::refresh() { double now = Scheduler::instance().clock(); /* PSB and RSB timeouts are checked with every refresh for this session and not when the actual timeout occurs. That means that path and reservation state might time out a bit slower in the simulation than in a real system (though no refresh messages from these states will be sent after the timeout), but this behaviour is not incorrect, since RFC 2205 states that L (a state's lifetime) should be equal *or greater* than (K + 0.5) * 1.5 * R. */ if ((t_list_ != NULL) && in_range(minref(t_list_), now)) { check_path(t_list_); if (t_list_ != NULL) { check_resv(t_list_); } if (t_list_ != NULL) { if (in_range(minref(t_list_), now)) { if (minref(t_list_) == t_list_->path_ref) { refresh_path(t_list_); } else { /* Force a reservation refresh */ refresh_resv(t_list_, 1); } } else { reschedule_session(t_list_); } } }}/* Create and send path messages for this session, then reschedule the session. */void RSVPAgent::refresh_path(session *s) { psb *p = s->psb_list; while (p != NULL) { if (!is_mcast(s->s->get_dest()) || !is_leaf(p->sender->get_addr(), s->s->get_dest())) { send_path_message(s, p); } p = p->next; } s->path_ref = Scheduler::instance().clock() + s->path_tv->get_r(); reschedule_session(s);}/* Create and send resv messages for this session, then reschedule the session. If the 'forced' flag is off, this function merely checks if a refresh is necessary (for example after a new RSB was added). If it finds a reservation state that has to be updated, it performs a normal refresh. */void RSVPAgent::refresh_resv(session *s, char forced) { rsb *rsearch = s->rsb_list; rsb *rsearch2; while (rsearch != NULL) { if (!rsearch->processed) { /* Send a reservation message for all RSBs with the same PHOP in their corresponding PSBs as rsearch. */ if (send_resv_message(s, rsearch, forced) && !forced) { /* A reservation has changed and had to be forwarded. Force a refresh for the whole reservation state. */ forced = 1; rsearch2 = s->rsb_list; while (rsearch2 != NULL) { rsearch2->processed = 0; rsearch2 = rsearch2->next; } rsearch2 = s->rsb_list; while (rsearch2 != rsearch) { if (rsearch->processed) { send_resv_message(s, rsearch2, forced); } rsearch2 = rsearch2->next; } } } rsearch = rsearch->next; } rsearch = s->rsb_list; while (rsearch != NULL) { rsearch->processed = 0; rsearch = rsearch->next; } if (forced) { /* Only set a new refresh timeout if any messages were actually sent. */ s->resv_ref = Scheduler::instance().clock() + s->resv_tv->get_r(); reschedule_session(s); }}/* Release a session. Remove it from the timer list and from the session list, and send appropriate teardown messages for all path and reservation states. */void RSVPAgent::release_session(session *s) { session *search, *temp; // Tcl& tcl = Tcl::instance(); - unused /* First remove the session from the timer list */ if (t_list_ != NULL) { if (t_list_ == s) { t_list_ = t_list_->t_next; } else { search = t_list_; while ((search->t_next != s) && (search->t_next != NULL)) { search = search->t_next; } if (search->t_next != NULL) { search->t_next = search->t_next->t_next; } } } /* Now remove the session from the session list and send teardown messages for all existing path and reservation states. */ if (s_list_ == s) { s_list_ = s_list_->next; temp = s; } else { search = s_list_; while ((search->next != s) && (search->next != NULL)) { search = search->next; } temp = search->next; search->next = search->next->next; } psb *p; rsb *r; /* Tear down all reservation states */ send_resv_tear_messages(s, s->rsb_list); while ((r = temp->rsb_list) != NULL) { temp->rsb_list = temp->rsb_list->next; update_traffic_control(temp, r); clear_rsb(r); delete r; num_rsb_--; } /* Tear down all path states */ while ((p = temp->psb_list) != NULL) { send_path_tear_message(s, p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -