📄 rsvp_resv.c
字号:
if (IsHopAPI(&sp->ps_phop)) { if (rp->rs_confirm) { send_confirm(destp, rp); rp->rs_confirm = NULL; } continue; } /* * 2. (If the B_Merge flag is off then) ignore a blockaded * RSB, as follows. * * Select BSBs that match this RSB. If any of * these BSBs has a Qb that is not strictly larger * than TC_Flowspec, then this RSB is blockaded; * continue processing with the next RSB. */ fwd_specp = (rp->rs_fwd_spec)? rp->rs_fwd_spec: rp->rs_spec; if (BSBp->ps_BSB_Qb && LT(BSBp->ps_BSB_Tb, time_now)) { /* Blockade state has timed out; delete it. */ free(BSBp->ps_BSB_Qb); BSBp->ps_BSB_Qb = NULL; BSBp->ps_BSB_Tb = 0; } if ((BSBp->ps_BSB_Qb) && Compare_Flowspecs(BSBp->ps_BSB_Qb, fwd_specp)!=SPEC1_GTR) { Incr_ifstats(BSBp->ps_in_if, rsvpstat_blockade_ev); continue; } n_match++; /* * 3. Merge the flowspecs from this set of RSBs. * Maintain RSB seen so far that has largest flowspec * in confRSBp, for sending a confirm message. */ cmp = Compare_Flowspecs(fwd_specp, max_specp); assert(cmp != SPECS_INCOMPAT); if (cmp == SPEC1_GTR) { max_specp = fwd_specp; if (confRSBp && !IsHopAPI(&rp->rs_nhop)) send_confirm(destp, confRSBp); confRSBp = NULL; if (rp->rs_confirm) confRSBp = rp; } else { if (cmp == SPECS_USELUB) max_specp = LUB_of_Flowspecs(rp->rs_spec, max_specp); if (rp->rs_confirm) send_confirm(destp, rp); } /* * Also merge the lists of unknown objects, if any. */#define MAKE_COPY 1 merge_UnkObjL2(&rp->rs_UnkObjList, &UnkObjectL, MAKE_COPY); } if (IsHopAPI(&sp->ps_phop)) return(0); /* However, if steps 1 and 2 result in finding that all * RSBs matching this PSB are blockaded, then: * - If this Resv REFRESH sequence was invoked from * accept_resv_err(), then return to the latter. * - Otherwise, turn on the B_Merge flag and restart at * step 1 (actually, second copy of code): */ if (n_match == 0) { if (IsResvErr) return(0); B_Merge = 1; /* (isn't really used) */ max_specp = NULL; for (rp = destp->d_RSB_list; rp != NULL; rp = rp->rs_next) { if (!PSBmaps2RSB(destp, sp, rp)) continue; /* * 3. Merge the flowspecs from this set of * RSBs, as follows. * * Compute the GLB over the Flowspec objects * of this set of RSBs. * While computing the GLB, delete any * RESV_CONFIRM objects. */ n_match++; max_specp = GLB_of_Flowspecs(rp->rs_spec, max_specp); assert(max_specp); /* These flowspecs must be OK */ if (rp->rs_confirm) { free(rp->rs_confirm); rp->rs_confirm = NULL; } confRSBp = NULL; merge_UnkObjL2(&rp->rs_UnkObjList, &UnkObjectL, MAKE_COPY); } } /* * All matching RSB's have been processed. If there * were some, do style-dependent processing: * o Distinct style (FF): Pack flow descriptor into pkt. * o Shared style (SE,WF): continue to merge. */ if (n_match) { flwdp = FlowDesc_of(pkt, pkt->rsvp_nflwd); assert(max_specp); switch (style) { case STYLE_WF: flwdp->rsvp_specp = max_specp; flwdp->rsvp_filtp = NULL; pkt->rsvp_nflwd = 1; /* * If this sender has scope bit on, add this * sender host to the outgoing SCOPE list. */ if (sp->ps_flags & PSBF_InScope) scope_catf(&mapp->rsvp_scope_list, sp->ps_templ); break; case STYLE_FF: if (!confRSBp && sameas_last_spec(&sp->ps_resv_spec, max_specp)) { max_specp = NULL; FQkill(&UnkObjectL); break; } flwdp->rsvp_specp = max_specp; max_specp = NULL; /* To merge filter specs, simply use sender template, */ flwdp->rsvp_filtp = sp->ps_templ; pkt->rsvp_nflwd++; /* Test nflwd for overflow XXX */ break; case STYLE_SE: (FlowDesc_of(pkt, 0))->rsvp_specp = max_specp; flwdp->rsvp_filtp = sp->ps_templ; pkt->rsvp_nflwd++; /* Test nflwd for overflow XXX */ break; } } merge_UnkObjL2(&UnkObjectL, &UnkObjL_perPHOP, !MAKE_COPY); /* * Senders are ordered by phop address. Return if next PSB has * the same PHOP, else finish up message and send it. */ if (sp->ps_next && hop_addr_eq(&sp->ps_next->ps_phop,&sp->ps_phop)) { return(0); } /* If there are no flow descriptors, or if new flowspec is same * as last sent for this PSB, the filter spec list did not change, * and there is no confirmation request, return without sending. */ if (pkt->rsvp_nflwd == 0 || ( Style_is_Shared(style) && !confRSBp && sameas_last_spec(&BSBp->ps_resv_spec, max_specp) )){ FQkill(&UnkObjL_perPHOP); pkt->rsvp_nflwd = 0; return(0); } pkt->pkt_map->rsvp_UnkObjList = UnkObjL_perPHOP; UnkObjL_perPHOP = NULL; /* * If a RESV_CONFIRM object was saved earlier, put a ptr * to it in the new Resv message. */ if (confRSBp) mapp->rsvp_confirm = confRSBp->rs_confirm; /* If the style is wildcard, decide whether a SCOPE object * must be sent. */ if (Style_is_Wildcard(style)) Need_Scope = is_scope_needed(destp, sp); /* * Send Resv message (unless there is an empty scope list) * Must first make copy of filter spec objects and set their * class (because they were SENDER_TEMPLATEs); then free copies. */ if (!Need_Scope || mapp->rsvp_scope_list) { for (i= 0; i < pkt->rsvp_nflwd; i++) { flwdp = FlowDesc_of(pkt, i); if (flwdp->rsvp_filtp) { flwdp->rsvp_filtp= copy_filter(flwdp->rsvp_filtp); Obj_Class(flwdp->rsvp_filtp)= class_FILTER_SPEC; } } send_resv_out(sp, pkt); for (i= 0; i < pkt->rsvp_nflwd; i++) { flwdp = FlowDesc_of(pkt, i); if (flwdp->rsvp_filtp) free(flwdp->rsvp_filtp); } } else /* Was not sent because scope list was empty */ Incr_ifstats(sp->ps_in_if, rsvpstat_no_outscope); /* * Free storage and re-initialize pkt for next PHOP */ for (i= 0; i < pkt->rsvp_nflwd; i++) { flwdp = FlowDesc_of(pkt, i); flwdp->rsvp_specp = NULL; } pkt->rsvp_nflwd = 0; if (mapp->rsvp_scope_list) { free(mapp->rsvp_scope_list); mapp->rsvp_scope_list = NULL; } max_specp = NULL; FQkill(&pkt->pkt_map->rsvp_UnkObjList); return(0);}/* Compare new resv refresh flowspec for particular sender/phop * with the last one sent. If they are equal, return 1, else * save new one and return 0. */intsameas_last_spec(FLOWSPEC **last_specpp, FLOWSPEC *newspecp) { if (*last_specpp && Compare_Flowspecs(*last_specpp, newspecp) == SPECS_EQL) return(1); if (*last_specpp) free(*last_specpp); *last_specpp = copy_spec(newspecp); return(0);}#ifdef ISI_TEST#define MAX_RTEAR_PACK 2 /* XXX (For testing!) ***/#else#define MAX_RTEAR_PACK MAX_FLWDS#endif/* * cleanup_resv_state(): For given session, kill all expired reservations. * For consistency, we kill a reservation by constructing and * processing a dummy RESV_TEAR message. */intcleanup_resv_state(Session *destp) { packet_area data; struct packet *pkt = NULL; RSB *rp, *rpn; FlowDesc *flwdp; int i; rpn = destp->d_RSB_list; /* Next RSB */ while (rpn) { rp = rpn; rpn = rpn->rs_next; if (!LT(rp->rs_ttd, time_now)) continue; Incr_ifstats(rp->rs_OIf, rsvpstat_resv_timeout); /* Found timed-out RSB. Fake teardown message for it. */ if (pkt == NULL) { pkt = new_packet_area(&data); common_resv_tear_header(pkt, destp); } Style_of(pkt)->style_word = rp->rs_style; *pkt->rsvp_nhop = rp->rs_rsvp_nhop; if (Style_is_Wildcard(rp->rs_style)) { flwdp = FlowDesc_of(pkt, 0); flwdp->rsvp_filtp = NULL; flwdp->rsvp_specp = NULL; pkt->rsvp_nflwd = 1; } else { for (i= 0; i < rp->rs_fcount; i++) { if (LT(rp->rs_Filt_TTD(i), time_now)) { /* * Individual filter has timed out. * If packet is full, process dummy pkt and * start again. Add filter to dummy pkt. */ if (pkt->rsvp_nflwd >= MAX_RTEAR_PACK) { process_dummy_rtear(pkt); pkt->rsvp_nflwd = 0; } flwdp = FlowDesc_of(pkt, pkt->rsvp_nflwd); flwdp->rsvp_filtp = copy_filter(rp->rs_Filtp(i)); flwdp->rsvp_specp = NULL; pkt->rsvp_nflwd++; } } } if (Style_is_Shared(rp->rs_style) || rpn == NULL || !hop_addr_eq(&rpn->rs_nhop, &rp->rs_nhop)) { /* A little optimization: if a set of FF-style * reservations time out at the same time, try * (but not hard) to packet teardowns into same * RTear. Works if order of RSB list is right. */ if (pkt->rsvp_nflwd) { process_dummy_rtear(pkt); pkt->rsvp_nflwd = 0; } } } return(0);}voidprocess_dummy_rtear(struct packet *pkt) { int i; if (!pkt) return; accept_resv_tear(-1, pkt); for (i= 0; i < pkt->rsvp_nflwd; i++) { if (spec_of(FlowDesc_of(pkt, i))) free(spec_of(FlowDesc_of(pkt, i))); if (filter_of(FlowDesc_of(pkt, i))) free(filter_of(FlowDesc_of(pkt, i))); }}/* * delete_resv4PSB(): Delete reservations corresponding to given PSB, * which is already deleted from session list. Called from * kill_PSB(). */voiddelete_resv4PSB(Session *destp, PSB *psbp) { RSB *rp, *rpn; int j, rc; /* * Find each RSB that matches this PSB */ for (rp = destp->d_RSB_list; rp != NULL; rp = rpn) { rpn = rp->rs_next; if (!PSBmaps2RSB(destp, psbp, rp)) continue; if (!Style_is_Shared(rp->rs_style)) { kill_RSB(destp, rp); /* Style FF: delete RSB and update link layer. */ } else if (Style_is_Wildcard(rp->rs_style)) { PSB *sp; /* * Wildcard (WF) style => If there is another * matching PSB, update link layer and continue * with next RSB; else, delete RSB & update LL. */ for (sp = destp->d_PSB_list; sp; sp = sp->ps_next) { if (sp != psbp && IsRoutePSB2nhop(destp,sp,&rp->rs_rsvp_nhop)) break; } if (sp) { rc = LL_ModFlowspec(rp->rs_OIf, destp, rp); if (rc != LLDAL_RC_LATER) /* synchronous */ Complete_ModFlowspec(destp, rp, rc); continue; } else kill_RSB(destp, rp); } else { /* Else SE style. Delete matching filter specs. * If filters all gone, delete RSB & update LL. */ for (j= 0; j < rp->rs_fcount; j++) { if (match_filter(psbp->ps_templ, rp->rs_Filtp(j))){ free(rp->rs_Filtp(j)); rp->rs_Filt_TTD(j) = 0; } } coalesce_filtstar(rp->rs_filtstar); if (rp->rs_fcount == 0) kill_RSB(destp, rp); else { rc = LL_ModFilter(rp->rs_OIf, destp, rp); if (rc != LLDAL_RC_LATER) Complete_ModFilter(destp, rp, rc); } } }}/* Update link-layer reservation with respect to given PSB, which * is new or changed. */voidPSB_update_LL(Session *destp, PSB *psbp) { RSB *rp; bitmap out_vifs; int rc; bmp_rst(&out_vifs); /* None seen yet */ for (rp = destp->d_RSB_list; rp != NULL; rp = rp->rs_next) { /* * Search for first RSB for given OI that PSB * routes to and whose Filter_spec_list includes * a FILTER_SPEC matching the SENDER_TEMPLATE. * Using this as the 'active RB', update traffic * control on that OI. Use bit mask out_vifs to * process only one RSB per distinct OI. */ if (!PSBmaps2RSB(destp, psbp, rp)) continue; if (bmp_tst(&out_vifs, rp->rs_OIf)) continue; bmp_set(&out_vifs, rp->rs_OIf); /* ignore later RSBs */ /* * Update traffic control. In unlikely event * that admission Control fails, send ResvErr msg */ rc = LL_ModFlowspec(rp->rs_OIf, destp, rp); if (rc != LLDAL_RC_LATER) /* synchronous */ Complete_ModFlowspec(destp, rp, rc); }}/* * IsRoutePSB2nhop(): Return 1 if sender defined by PSB can * route to specified next hop. */intIsRoutePSB2nhop(Session *destp, PSB *psbp, RSVP_HOP *hopp) { /* * If Resv came from network, it cannot match LocalOnly PSB. */ if (!IsHopAPI(hopp)) { if (psbp->ps_flags & PSBF_LocalOnly) return(0); else if (bmp_tst(&(psbp->ps_outif_list), hop_lih(hopp))) return(1); } else { /* Resv came from API. OK if: * * dest is unicast, or * * incoming interface matches recv interface, or * * PSB not LocalOnly and not from API and routes to OI. */ if (IF_UNICAST(psbp->ps_in_if) == hop_lih(hopp)) return(1); else if (!session_multicast(destp->d_session)) return(1); else if (!(psbp->ps_flags & PSBF_LocalOnly) && !IsHopAPI(&psbp->ps_phop) && bmp_tst(&(psbp->ps_outif_list), hop_lih(hopp))) return(1); } return(0);}/* Search for (any) RSB that matches the given PSB */RSB *RSB_match_path(Session *destp, PSB *psbp) { RSB *rp; for (rp = destp->d_RSB_list; rp; rp = rp->rs_next) { if (PSBmaps2RSB(destp, psbp, rp))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -