📄 rsvp_llkern.c
字号:
/* * @(#) $Id: rsvp_LLkern.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//************************ rsvp_LLkern.c ***************************** * * * Link-layer-dependent adaptation layer (LLDAL) routines * * for interfacing to a "kernel" traffic control mechanism. * * This supports QoS over passive media such as leased lines or * * (today's) shared LAN media. * * * * * *********************************************************************//**************************************************************************** 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) 1996 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"#include "rsvp_TCif.h"/* * External declarations */int Compute_Path_Props(Session *, RSB *, FiltSpecStar *, SENDER_TSPEC *, ADSPEC **, int *);int Is_B_Police(Session *, RSB *);Object_header * copy_object(Object_header *);int match_filter(FILTER_SPEC *, FILTER_SPEC *);int Compare_Flowspecs(FLOWSPEC *, FLOWSPEC *);FLOWSPEC * LUB_of_Flowspecs(FLOWSPEC *, FLOWSPEC *);int Compare_Tspecs(SENDER_TSPEC *, SENDER_TSPEC *);void send_confirm(Session *, RSB *);int find_fstar(FILTER_SPEC *, FiltSpecStar *);FiltSpecStar * Get_FiltSpecStar(int);char * fmt_flowspec(FLOWSPEC *);char * fmt_tspec(SENDER_TSPEC *);char * cnv_flags(char *, u_char);/* * Forward declarations */TCSB * locate_TCSB(Session *, int, FiltSpecStar *, style_t);/* * RSBs4_sameLL(rp1, rp2): Predicate true if two RSBs map into * the same link layer reservation block. */#define RSBs4_sameLL(rp1, rp2) ((rp1->rs_OIf == rp2->rs_OIf) && \ ( Style_is_Shared(rp1->rs_style) || \ match_filter(rp1->rs_filter0, rp2->rs_filter0)))/* Call-back routines. * * External references to the core-RSVP routines that do 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. */extern int Complete_NewFlow(Session *, RSB *, int);extern int Complete_ModFlowspec(Session *, RSB *, int);extern int Complete_ModFilter(Session *, RSB *, int);extern int Complete_DelFlow(Session *, RSB *, int);/** extern int Complete_Advertise(Session *, PSB *, int); **//** extern int Complete_BugDump(Session *, int); **//* * Forward declarations: LLDAL Interface Routines */void KernTC_if_init(int OIf);int KernTC_NewFlow(Session *, RSB *);int KernTC_ModFlowspec(Session *, RSB *);int KernTC_ModFilter(Session *, RSB *);int KernTC_DelFlow(Session *, RSB *);int KernTC_Advertise(int, Session *, PSB *);int KernTC_GetInfo(Session *, RSB *);int KernTC_BugDump(int OIf, Session *);/* * Forward declarations: Internal Routines */int Kernel_SetFilters(Session *, TCSB *, FiltSpecStar *);int Kernel_Merge(Session *, RSB *, FLOWSPEC **, FiltSpecStar **);int Kernel_Return_Spec(Session *, RSB *, FLOWSPEC *);int union_filtstar(FiltSpecStar *, FiltSpecStar **);TCSB * make_TCSB(Session *, int, int);TCSB * trade_TCSB(Session *, TCSB *, int);void kill_TCSB(Session *, TCSB *);void log_K(int, Session *, TCSB *);/* * Initialize transfer vector for a given interface */voidKernTC_if_init(int OIf) { if_vec[OIf].if_LLifv.LL_NewFlow_p = &KernTC_NewFlow; if_vec[OIf].if_LLifv.LL_ModFlowspec_p = &KernTC_ModFlowspec; if_vec[OIf].if_LLifv.LL_ModFilter_p = &KernTC_ModFilter; if_vec[OIf].if_LLifv.LL_DelFlow_p = &KernTC_DelFlow; if_vec[OIf].if_LLifv.LL_Advertise_p = &KernTC_Advertise; if_vec[OIf].if_LLifv.LL_GetInfo_p = &KernTC_GetInfo; if_vec[OIf].if_LLifv.LL_BugDump_p = &KernTC_BugDump;#ifdef SCHEDULE TC_init(OIf);#endif /* SCHEDULE */}/* * KernTC_NewFlow(Session, active RSB [=> Interface, NextHop, * FiltSpecList, Flowspec, Style) * * Add a new flow reservation request. RSB is used as a parameter * list to pass (interface, NHOP, style, flowspec, filter_spec_list). */intKernTC_NewFlow(Session *destp, RSB *rp) { TCSB *kp = NULL; FLOWSPEC *Fwd_specp = NULL; SENDER_TSPEC Path_Te; ADSPEC *adspecp = NULL; int TC_kflags = 0, s_count; u_long handle; /* Assume memory error */ rsvp_errno = Set_Errno( RSVP_Err_RSVP_SYS_ERROR, RSVP_Erv_MEMORY); /* Compute Branch_Merge flag from RSBs [This might be better * be done in core RSVP]. */ TC_kflags |= Is_B_Police(destp, rp); /* Find out if there is already a matching reservation in * place for different NHOPs: search for a TCSB matching * (OI, session, [filter_spec_list (distinct style)]). */ kp = locate_TCSB(destp, rp->rs_OIf, rp->rs_filtstar, rp->rs_style); if (!kp) { /* This is first reservation. Build TCSB, send flowspec, * filter_spec_list, etc. to traffic control, and if there * is no error, fill in TCSB. */ kp = make_TCSB(destp, rp->rs_OIf, rp->rs_fcount); if (!kp) goto TC_add_error; /* Compute path properties -- * Path_Te = sum of sender Tspecs, * [composed] Adspecs (for Guaranteed Service Slack Calc) * Entry_Police and Merge_Police flags -- * from PSBs that match this request. * * Note: this calculation will generally be independent of * the particular next hop, so it could be done in core RSVP. * However, there is at least a theoretical possibility of * further routing in the link layer driver, in which case * the selection of matching PSBs can only be done in the * LLDAL. Therefore, we execute it in the LLDAL (although * code currently defined in rsvp_resv.c). */ s_count = Compute_Path_Props(destp, rp, rp->rs_filtstar, &Path_Te, &adspecp, &TC_kflags); assert(s_count > 0); /* Caller checked: there are matching senders*/#ifdef SCHEDULE handle = TC_AddFlowspec(kp->tcs_OIf, rp->rs_spec, &Path_Te, adspecp, TC_kflags, &Fwd_specp); kp->tcs_rhandle = handle;#endif if (IsDebug(DEBUG_ALL)) { char out[80]; log_K(LOGEV_TC_addflow, destp, kp); if (IsDebug(DEBUG_EVENTS)) { strncpy(out, fmt_tspec(&Path_Te), 80); log(LOG_DEBUG, 0, " flowspec= %s Tspec=%s\n", fmt_flowspec(rp->rs_spec), out); } } if (handle == TC_ERROR) /* Failed. rsvp_errno is set. */ goto TC_add_error; if (Fwd_specp) { /* An updated flowspec was returned. Pass * it back to the core. */ if (Kernel_Return_Spec(destp, rp, Fwd_specp) == LLDAL_RC_ERROR) goto TC_add_error; } /* Copy filter spec list into TCSB and install filters * in traffic control. */ if (Kernel_SetFilters(destp, kp, rp->rs_filtstar) == LLDAL_RC_ERROR) goto TC_add_error; /* Error; rsvp_errno set */ /* Flowspec and filter spec(s) installed OK. Set * TCSB and return. */ kp->tcs_spec = copy_spec(rp->rs_spec); kp->tcs_tspec = copy_tspec(&Path_Te); kp->tcs_kflags = TC_kflags; if (!kp->tcs_spec || !kp->tcs_tspec) goto TC_add_error; /* out of memory */ return(LLDAL_RC_OK); } /* A reservation is already in place. Change it if necessary. * For simplicity (and at the cost of some efficiency) just use * LL_ModFlowspec. */ if (adspecp) free(adspecp); /* (KernTC_ModFlowspec will recompute */ /* * Note: we could avoid calling KernTC_ModFlowspec if new * flowspec LEQ against tcs_spec, and we could avoid calling * KernTC_ModFilter if new filter spec list is identical to * that in the TCSB. Leave those optimizations for later. */ return(KernTC_ModFlowspec(destp, rp));TC_add_error: /* * Error cases: release resources and free TCSB as necessary. */ if (kp && kp->tcs_rhandle && kp->tcs_rhandle != TC_ERROR) {#ifdef SCHEDULE TC_DelFlowspec(kp->tcs_OIf, kp->tcs_rhandle);#endif if (IsDebug(DEBUG_ALL)) { log_K(LOGEV_TC_delflow, destp, kp); if (IsDebug(DEBUG_EVENTS)) log(LOG_DEBUG, 0, " flowspec= %s\n", fmt_flowspec(rp->rs_spec)); } } if (kp) kill_TCSB(destp, kp); if (adspecp) free(adspecp); return(LLDAL_RC_ERROR); }/* * KernTC_ModFlowspec(Session, active RSB) * * Modify an existing reservation because a component flowspec, * sender Tspec, or Adspec has changed. RSB *rp specifies NHOP, OIf, * OIf, and (for Distinct) the filter spec. */intKernTC_ModFlowspec(Session *destp, RSB *rp) { TCSB *kp; FLOWSPEC *TC_specp, *Fwd_specp; FiltSpecStar *TC_FiltSp; SENDER_TSPEC Path_Te; ADSPEC *adspecp; int TC_kflags = 0; u_long rc; /* Scan RSBs and merge: * flowspecs -> TC_specp * filter specs -> TC_FiltSp. */ rc = Kernel_Merge(destp, rp, &TC_specp, &TC_FiltSp); if (rc != LLDAL_RC_OK) return(rc); assert(TC_specp && TC_FiltSp); /* Compute path properties -- Path_Te = sum of sender Tspecs, * [composed] Adspecs, Entry_Police and Merge_Police flags -- * from PSBs that match this request. */ if (Compute_Path_Props(destp, rp, TC_FiltSp, &Path_Te, &adspecp, &TC_kflags) == 0) return(LLDAL_RC_OK); /* ??? Can this ever happen? */ /* Compute Branch_Merge flag from RSBs [This might better * be done in core RSVP? Or in Kernel_Merge?] */ TC_kflags |= Is_B_Police(destp, rp); /* Find matching TCSB for reservation in place; match * (OI, session, [filter_spec_list (distinct style)]). * * XXX we could be cleverer, save A(TCSB) in RSB (except * this makes problems if we have to trade TCSBs!) */ kp = locate_TCSB(destp, rp->rs_OIf, rp->rs_filtstar, rp->rs_style); assert(kp); /* Record merged flag in TCSB */ kp->tcs_flags &= ~TCF_MERGED; if (rp->rs_flags & RSB_FLAG_MERGED) kp->tcs_flags |= TCF_MERGED; /* * If TC_Flowspec, Path_Te, or police flags have changed, * modify reservation. */ if (Compare_Flowspecs(TC_specp, kp->tcs_spec) != SPECS_EQL || Compare_Tspecs(&Path_Te, kp->tcs_tspec) != SPECS_EQL || TC_kflags != kp->tcs_kflags) {#ifdef SCHEDULE rc = TC_ModFlowspec(kp->tcs_OIf, kp->tcs_rhandle, TC_specp, &Path_Te, adspecp, TC_kflags, &Fwd_specp);#endif if (IsDebug(DEBUG_ALL)) { log_K(LOGEV_TC_modflow, destp, kp); if (IsDebug(DEBUG_EVENTS)) { char out[80]; strncpy(out, fmt_tspec(kp->tcs_tspec), 80); log(LOG_DEBUG, 0, " Old: flowspec=%s Tspec=%s\n", fmt_flowspec(kp->tcs_spec), out); strncpy(out, fmt_tspec(&Path_Te), 80); log(LOG_DEBUG, 0, " New: flowspec=%s Tspec=%s\n", fmt_flowspec(TC_specp), out); } } if (rc == TC_ERROR) /* Failed. rsvp_errno is set. */ return(LLDAL_RC_ERROR); } /* Set filters if necessary, too. */ rc = Kernel_SetFilters(destp, kp, TC_FiltSp); if (rc == LLDAL_RC_ERROR) goto TC_mod_error; /* * Since TC calls succeeded, update TCSB now. */ free(kp->tcs_spec); kp->tcs_spec = copy_spec(TC_specp); if (kp->tcs_tspec) free(kp->tcs_tspec); kp->tcs_tspec = copy_tspec(&Path_Te); kp->tcs_kflags = TC_kflags; if (!kp->tcs_spec || !kp->tcs_tspec) { rsvp_errno = Set_Errno( RSVP_Err_RSVP_SYS_ERROR, RSVP_Erv_MEMORY); rc = LLDAL_RC_ERROR; }TC_mod_error: free(TC_FiltSp); free(TC_specp); if (adspecp) free(adspecp); return(rc);}/* * KernTC_ModFilter(Session *, active RSB *) * * Modify the filter spec list for an existing reservation */intKernTC_ModFilter(Session *destp, RSB *rp) { FiltSpecStar *TC_FiltSp; FLOWSPEC *TC_specp; TCSB *kp; int rc; kp = locate_TCSB(destp, rp->rs_OIf, rp->rs_filtstar, rp->rs_style); if (!kp) return(LLDAL_RC_OK); rc = Kernel_Merge(destp, rp, &TC_specp, &TC_FiltSp); if (rc != LLDAL_RC_OK) return(rc); return(Kernel_SetFilters(destp, kp, TC_FiltSp));}/* * KernTC_DelFlow(Session, active RSB) * * Active RSB has been deleted; update Kernel TC state to correspond. * * FF (distinct style) case is a little tricky: the RSB parameter must * specify the filter spec to define the flow to be deleted; yet this * RSB must not itself appear in the list of current RSBs. */intKernTC_DelFlow(Session *destp, RSB *rp) { TCSB *kp; FLOWSPEC *TC_specp; FiltSpecStar *TC_FiltSp; u_long rc = TC_OK; /* Find matching TCSB for reservation in place; match * (OI, session, [filter_spec_list (distinct style)]). */ kp = locate_TCSB(destp, rp->rs_OIf, rp->rs_filtstar, rp->rs_style); if (!kp) return(LLDAL_RC_OK); rc = Kernel_Merge(destp, rp, &TC_specp, &TC_FiltSp); assert(rc == LLDAL_RC_OK); /* Record merged flag in TCSB */ kp->tcs_flags &= ~TCF_MERGED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -