📄 rsvp_resv.c
字号:
/* * @(#) $Id: rsvp_resv.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//************************ rsvp_resv.c ******************************* * * * Routines to receive, process, and send Resv and ResvTear * * messages. * * * * * *********************************************************************//**************************************************************************** RSVPD -- ReSerVation Protocol Daemon USC Information Sciences Institute Marina del Rey, California Original Version: Shai Herzog, Nov. 1993. Current Version: Steven Berson & Bob Braden, may 1996. Copyright (c) 1998 by the University of Southern California All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation in source and binary forms for any purpose and without fee is hereby granted, provided that both the above copyright notice and this permission notice appear in all copies, and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed in part by the University of Southern California, Information Sciences Institute. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about the suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Other copyrights might apply to parts of this software and are so noted when applicable.********************************************************************/#include "rsvp_daemon.h"/* Define some global objects * */STYLE Style_Obj;CONFIRM Confirm_Obj;/* The following globals are used in merging reservations across * different PSB's for the same PHOP. */static FLOWSPEC *max_specp;static RSB *confRSBp;static Fobject *UnkObjL_perPHOP;/* External declarations */Session *locate_session(SESSION *);Session *locate_session_p(SESSION *);struct packet *new_packet_area(packet_area *);int match_filter(FILTER_SPEC *, FILTER_SPEC *);int Compare_Flowspecs(FLOWSPEC *, FLOWSPEC *);FLOWSPEC *LUB_of_Flowspecs(FLOWSPEC *, FLOWSPEC *);FLOWSPEC *GLB_of_Flowspecs(FLOWSPEC *, FLOWSPEC *);int addTspec2sum(SENDER_TSPEC *, SENDER_TSPEC *);int Compare_Tspecs(SENDER_TSPEC *, SENDER_TSPEC *);u_int32_t Compute_R(TIME_VALUES *), Compute_TTD(TIME_VALUES *);int match_scope(SCOPE *, SCOPE *);int form_scope_union(Session *);void scope_catf(SCOPE **, FILTER_SPEC *);void rsvp_resv_err(int, int, int, FiltSpecStar *, struct packet *);void rsvp_RSB_err(Session *, RSB *, int, int);Object_header *copy_object(Object_header *);void api_RESV_EVENT_upcall(Session *, RSB *);int send_pkt_out_if(int, RSVP_HOP *, struct packet *);void send_confirm(Session *, RSB *);void clear_scope_union(Session *);char *fmt_flowspec(FLOWSPEC *);char *fmt_tspec(SENDER_TSPEC *);char *cnv_flags(char *, u_char);void FQkill(Fobject **);void merge_UnkObjL2(Fobject **, Fobject **, int);int match_policy(POLICY_DATA *, POLICY_DATA *);/* Link-layer Call-back routines. * These core-RSVP routines perform processing that must * follow completion of a corresponding LLDAL call. * This is because LLDAL calls may invoke link-layer control * functions that will not complete immediately, and avoids * internal threading of rsvpd. When an LLDAL call is * asynchronous, it will return an immediate code indicating * that, and then the LLDAL will invoke the call-back routine * with the real return code when the function does complete. */int Complete_NewFlow(Session *, RSB *, int);int Complete_ModFlowspec(Session *, RSB *, int);int Complete_ModFilter(Session *, RSB *, int);int Complete_DelFlow(Session *, RSB *, int);/* Forward declarations */int accept_resv(int, struct packet *);int accept_resv_tear(int, struct packet *);int flow_reservation(Session *, struct packet *, int, FLOWSPEC *, FiltSpecStar *);void resv_tear_PSB(Session *, PSB *, style_t, FILTER_SPEC *, struct packet *);void delete_resv4PSB(Session *, PSB *);static void send_resv_out(PSB *, struct packet *);void common_resv_header(struct packet *, Session *);void common_resv_tear_header(struct packet *, Session *);RSB * make_RSB(Session *, int count);int enlarge_RSB_filtstar(RSB *);RSB * locate_RSB(Session *, RSVP_HOP *, FiltSpecStar *, style_t);RSB * RSB_match_path(Session *, PSB *);int kill_RSB(Session *, RSB *);void kill_newRSB(Session *, RSB *);int kill_RSB1(Session *, RSB *, int);void resv_update_ttd(RSB *, u_int32_t);int resv_refresh(Session *, int);int resv_refresh_TimeOut(Session *);int resv_refresh_PSB(Session *, PSB *, struct packet *, int);void PSB_update_LL(Session *, PSB *);FiltSpecStar * Get_FiltSpecStar(int);int find_fstar(FILTER_SPEC *, FiltSpecStar *);int match_filt2star(FILTER_SPEC *, FiltSpecStar *);int set_need_scope(Session *);int Styles_are_compat(style_t, style_t);int IsRoutePSB2nhop(Session *, PSB *, RSVP_HOP *);int is_scope_needed(Session *, PSB *);void process_dummy_rtear(struct packet *);void coalesce_filtstar(FiltSpecStar *);int sameas_last_spec(FLOWSPEC **, FLOWSPEC *);void process_dummy_rtear(struct packet *pkt);void map2FiltStar(struct packet *, FiltSpecStar *);/* * Common routines used by link-layer adaptation modules */int Is_B_Police(Session *, RSB *);int Compute_Path_Props(Session *, RSB *, FiltSpecStar *, SENDER_TSPEC *, ADSPEC **, int *);#define PSBmaps2RSB(destp, sp, rp) \ (IsRoutePSB2nhop(destp,sp,&rp->rs_rsvp_nhop) \ && (Style_is_Wildcard(rp->rs_style) \ || match_filt2star(sp->ps_templ, rp->rs_filtstar)))/* * accept_resv(): Process incoming Resv message, which is in host * byte order. It may be real packet from remote node or internal * packet from local API. * * pkt struct includes: * pkt_data -> packet buffer * pkt_map -> map of objects in packet * pkt_ttl = TTL with which it arrived (if not UDP) * pkt_flags & PKTFLG_USE_UDP: was it encapsulated? * * This routine does the common checking and then calls * flow_reservation() for each distinct flow descriptor packed * into the message. * */intaccept_resv( int vif, /* Phyint on which Resv msg arrived */ struct packet *pkt) { int out_vif; Session *destp; int i, rc; int need_refresh = 0; style_t style; FiltSpecStar filtss, *filtssp; FLOWSPEC *specp; RSB *rp; assert(pkt->pkt_order == BO_HOST); style = Style(pkt); /* Determine Outgoing Interface OI. * * The logical outgoing interface OI is taken from the LIH in * the NHOP object (non-RSVP cloud may cause packet to appear on * another interface). */ out_vif = IsHopAPI(pkt->rsvp_nhop) ? api_num : hop_lih(pkt->rsvp_nhop); Incr_ifstats(out_vif, rsvpstat_msgs_in[RSVP_RESV]); /* Check that INTEGRITY was included if it is required. */ if ((IF_FLAGS(out_vif)&IF_FLAG_Intgrty) && pkt->pkt_map->rsvp_integrity == NULL) return PKT_ERR_INTEGRITY; /* Look for path state. If it does not exist, send * "No path info" ResvErr msg. If there is confusion about * zero DstPorts, send "Conflicting Dest ports" error. */ destp = locate_session_p(pkt->rsvp_sess); if (!destp) { rsvp_resv_err(RSVP_Err_NO_PATH, 0, 0, (FiltSpecStar *) -1 /*all*/, pkt); return(-1); } else if ((int)destp == -1) { rsvp_resv_err(RSVP_Err_BAD_DSTPORT, 0, 0, (FiltSpecStar *) -1 /*all*/, pkt); return(-1); } /* * Check for incompatible styles, and if found, reject message * with a "Conflicting style" error. * Note: We use the strictest interpretation of conflicting * styles: every RSB in a node must use the same style. * Since the two directions of data flow through a node are * independent and never their reservations are not merged, * this is stronger than necessary. But the less strict test * would require deciding which RSB's cannot be merged together, * which would require nested loops over PSBs and RSBs. * */ for (rp = destp->d_RSB_list; rp != NULL; rp = rp->rs_next) { if (!Styles_are_compat(rp->rs_style, style)) { rsvp_resv_err(RSVP_Err_BAD_STYLE, 0, 0, (FiltSpecStar *) -1 /*all*/, pkt); return(-1); } } /* Process the flow descriptor list to make reservations, * depending upon the style. Filtss is a filter spec list. */ switch (style) { case STYLE_WF: if (!pkt->rsvp_scope) Incr_ifstats(out_vif, rsvpstat_no_inscope); specp = spec_of(FlowDesc_of(pkt, 0)); rc = flow_reservation(destp, pkt, out_vif, specp, NULL); break; case STYLE_FF: /* Style FF: execute independently for each flow * descriptor in the message. */ rc = -1; filtss.fst_count = 1; for (i = 0; i < pkt->rsvp_nflwd; i++) { int trc; filtss.fst_Filtp(0) = filter_of(FlowDesc_of(pkt, i)); filtss.fst_Filt_TTD(0) = 0; specp = spec_of(FlowDesc_of(pkt, i)); trc = flow_reservation(destp, pkt, out_vif, specp, &filtss); rc = MAX(trc, rc); } break; case STYLE_SE: /* Obtain storage and construct FILTER_SPEC*, i.e., * list of FILTER_SPECs, dynamically. */ filtssp = Get_FiltSpecStar(pkt->rsvp_nflwd); if (!filtssp) { Log_Mem_Full("Resv1"); return(-1); } map2FiltStar(pkt, filtssp); specp = spec_of(FlowDesc_of(pkt, 0)); rc = flow_reservation(destp, pkt, out_vif, specp, filtssp); free(filtssp); break; default: rsvp_resv_err(RSVP_Err_UNKNOWN_STYLE, 0, 0, (FiltSpecStar *) -1 /*all*/, pkt); break; } if (rc < 0) return(-1); else if (rc > 0) need_refresh = 1; /* * If any resv succeeded and refresh timer has not * been started, start it now. */ if (destp->d_RSB_list && (Compute_R(&destp->d_timevalr) == 0)) add_to_timer((char *) destp, TIMEV_RESV, destp->d_Rtimor); /* If the refresh_needed flag is now on, execute * resv_refresh to send immediate refresh through every * interface noted in d_r_incifs. */ dump_ds(need_refresh); if (need_refresh) resv_refresh(destp, 0); return(0);}/* * flow_reservation(): Process a given flow descriptor within a Resv * msg, by finding or creating an RSB. But if an error is found, * create no RSB, send ResvErr message, and return. * * Returns: -1 for error * 1 OK, refresh needed * 0 OK, no refresh */intflow_reservation( Session *destp, /* Session */ Resv_pkt *pkt, /* Packet itself */ int out_vif, /* True Outgoing interface */ FLOWSPEC *specp, /* Flowspec */ FiltSpecStar *filtssp) /* FILTER_SPEC* or NULL(WF) */ { RSB *rp; PSB *sp; FILTER_SPEC *filtp; int NeworMod = 0; int new_RSB = 0; int sender_cnt, i, rc, nfilt; u_int32_t time2die; style_t style = Style(pkt); nfilt = (Style_is_Wildcard(style))? 0 : filtssp->fst_count; /* Check the path state, as follows. * * 1. Locate the set of PSBs (senders) that route to OI and * whose SENDER_TEMPLATES match *filtssp. * * Count these PSBs, and add OI to a bit vector of * incoming interfaces for immediate refresh. */ sender_cnt = 0; for (sp = destp->d_PSB_list ; sp != NULL; sp = sp->ps_next) { if (!IsRoutePSB2nhop(destp, sp, pkt->pkt_map->rsvp_hop)) continue; i = find_fstar(sp->ps_templ, filtssp); if (i >= 0) { if (!Style_is_Wildcard(style)) filtssp->fst_Filt_TTD(i) = 1; sender_cnt++; bmp_set(&(destp->d_r_incifs), sp->ps_in_if); } } if (sender_cnt == 0) { /* If this set is empty, build and send an error message * specifying "No Sender Information", and continue with * the next flow descriptor in the Resv message. * * XXX We are using permissive interpretation for SE: OK * if ANY of its FILTER_SPECs matches a sender. */ rsvp_resv_err(RSVP_Err_NO_SENDER, 0, 0, filtssp, pkt); return(-1); } /* Else delete from Filtss any FILTER_SPECs that match no PSB, */ else if (sender_cnt < nfilt) coalesce_filtstar(filtssp); /* * o Find or create a reservation state block (RSB) for * (SESSION, NHOP). If the style is distinct, Filtss is also * used in the selection. Call this the "active RSB". * * o Start or restart the cleanup timer on the active RSB, or, * in the case of SE style, on each FILTER_SPEC of the RSB * that also appears in Filtss. */ time2die = Compute_TTD(pkt->pkt_map->rsvp_timev); rp = locate_RSB(destp, pkt->pkt_map->rsvp_hop, filtssp, style); if (!rp) { rp = make_RSB(destp, nfilt); if (!rp) { Log_Mem_Full("Resv3"); return(-1); } new_RSB = 1; /* Active RSB is new: * 1. Set NHOP, OI, and style from message. * 2. Copy FILTER_SPEC* into the RSB. * 3. Copy the FLOWSPEC and any SCOPE object into RSB. * 4. Set NeworMod flag on. */ rp->rs_nhop = *pkt->rsvp_nhop; rp->rs_OIf = out_vif; rp->rs_style = Style(pkt); for (i = 0; i < nfilt; i++) { filtp = copy_filter(filtssp->fst_Filtp(i)); if (!filtp && (filtssp->fst_Filtp(i))) { kill_newRSB(destp, rp); Log_Mem_Full("Resv5"); return(-1); } rp->rs_Filtp(i) = filtp; rp->rs_Filt_TTD(i) = time2die; rp->rs_fcount++; } rp->rs_spec = copy_spec(specp); if (!rp->rs_spec) { kill_newRSB(destp, rp); Log_Mem_Full("Resv4"); return(-1); } if (pkt->pkt_map->rsvp_scope_list) { rp->rs_scope= copy_scope(pkt->pkt_map->rsvp_scope_list); if (!rp->rs_scope) { kill_newRSB(destp, rp); Log_Mem_Full("Resv6"); return(-1); } } clear_scope_union(destp); /* Set to recompute scope union */ NeworMod = 1; /* Pass new flow to link layer */ rc = LL_NewFlow(rp->rs_OIf, destp, rp); if (rc != LLDAL_RC_LATER) /* synchronous */ Complete_NewFlow(destp, rp, rc); if (rc == LLDAL_RC_ERROR) return(-1); } /* If the active RSB is not new, check whether Filtss from the * message contains FILTER_SPECs that are not in the RSB; if * so, add the new FILTER_SPECs and then invoke LL_ModFilter. * Also update timeout on each filter. * Note that we allow the order to change, requiring an N*N search. */ else { int NewFilter = 0; for (i= 0; i < nfilt; i++) { FILTER_SPEC *nu_filtp = filtssp->fst_Filtp(i); int j; j = find_fstar(nu_filtp, rp->rs_filtstar); if (j < 0) { j = find_fstar(NULL, rp->rs_filtstar); if (j < 0) { if (!enlarge_RSB_filtstar(rp)) { Log_Mem_Full("Resv7"); return(-1); } j = find_fstar(NULL, rp->rs_filtstar); } rp->rs_Filtp(j) = copy_filter(nu_filtp); NewFilter = 1; } rp->rs_Filt_TTD(j) = time2die; } if (NewFilter) { NeworMod = 1; rc = LL_ModFilter(rp->rs_OIf, destp, rp); if (rc != LLDAL_RC_LATER) /* synchronous */ Complete_ModFilter(destp, rp, rc); if (rc == LLDAL_RC_ERROR) return(-1); } } /* Free any old list of unknown objects, and save any new list. */ FQkill(&rp->rs_UnkObjList); rp->rs_UnkObjList = pkt->pkt_map->rsvp_UnkObjList; pkt->pkt_map->rsvp_UnkObjList = NULL; resv_update_ttd(rp, time2die); /* * If the message contained a RESV_CONFIRM object, copy it * into the RSB and turn on the NeworMod flag. */ if (pkt->pkt_map->rsvp_confirm) { rp->rs_confirm = (CONFIRM *) copy_object(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -