📄 rsvp_api.c
字号:
} /* Rebuild old packet map to include only those filter * specs that don't match new packet map. If any filter * specs remain, send old packet as ResvTear. */ oj = 0; for (oi = 0; oi < o_pkt->rsvp_nflwd; oi++) { FILTER_SPEC *o_filtp = filter_of(FlowDesc_of(o_pkt, oi)); for (nk = 0; nk < n_pkt->rsvp_nflwd; nk++) { if (match_filter(o_filtp, filter_of(FlowDesc_of(n_pkt, nk)))) break; } if (nk == n_pkt->rsvp_nflwd) { /* No match, filter should be torn down. */ if (!Style_is_Shared(style)) spec_of(FlowDesc_of(o_pkt, oj)) = spec_of(FlowDesc_of(o_pkt, oi)); filter_of(FlowDesc_of(o_pkt, oj++)) = filter_of(FlowDesc_of(o_pkt, oi)); } } if (oj) { o_pkt->rsvp_nflwd = oj; rsvp_pkt_process(o_pkt, NULL, api_num); } api_free_packet(o_pkt); return(0);}/* * api_prepare_resv(): Accepts an API request for a resv. and turns it * into a standard RSVP Resv packet... as if it arrived * from another router (except in host byte order). * Returns -1 if error, else 0. */intapi_prepare_resv(rsvp_req *req, api_rec *recp, struct packet *pkt) { Object_header *objp; packet_map *mapp = pkt->pkt_map; int styleID,LIH; net_addr host; memset((char *)pkt->pkt_data, 0, sizeof(common_header)); mapp->rsvp_msgtype = pkt->pkt_data->rsvp_type = RSVP_RESV; objp = (Object_header *)(pkt->pkt_data + 1); mapp->rsvp_session = (SESSION *) objp; session_create(mapp->rsvp_session, &recp->api_dest, recp->api_protid, 0, (recp->api_flags&RAPI_GPI_SESSION) ); objp = Next_Object(objp); /* XXX Should check dstport != 0 if protid = 6 or 17. */ /* Reservation local address: apply default and then * map into interface number, which is passed in LIH. */ net_addr_assign_api_addr(&host,&req->rq_host,0); if (IsAddrAPI(&host)) host = Get_local_addr; /* This assumes if's are subset of vif's XXX */ LIH = map_if_addr(&host); /* (signals: from API) */ mapp->rsvp_hop = (RSVP_HOP *) objp; hop_if_create(pkt->rsvp_nhop,&GET_IF(api_num),LIH); objp = Next_Object(objp); New_Object(mapp->rsvp_timev, TIME_VALUES, TIME_VALUES_CTYPE); pkt->rsvp_R = api_refresh_t; /* If requested by application, send CONFIRM object. */ if (req->rq_flags & RAPI_REQ_CONFIRM) { mapp->rsvp_confirm = (CONFIRM *) objp; confirm_if_create(mapp->rsvp_confirm,&Get_local_interface); objp = Next_Object(objp); } /* Style: Map RAPI style into option vector */ styleID = req->rq_style; New_Object(mapp->rsvp_style, STYLE, STYLE_CTYPE); if (styleID > RAPI_RSTYLE_MAX) { log(LOG_ERR, 0, "API: bad styleid\n"); return(-1); } mapp->rsvp_style->style_word = Styleid_to_Optvec[styleID]; pkt->rsvp_nflwd = req->rq_nflwd; api_get_flows(objp, req, pkt); /* XXX test for error */ /* Finish up common header. * Note: no checksum for API packet (per byte-order field) */ pkt->pkt_data->rsvp_cksum = 0; pkt->pkt_data->rsvp_verflags = RSVP_MAKE_VERFLAGS(RSVP_VERSION, 0); pkt->pkt_data->rsvp_length = pkt->pkt_len = (char *)objp - (char *) pkt->pkt_data; /* * If client sent bad local addr, send error upcall and return 0. */ if (LIH < 0) { rsvp_resv_err(RSVP_Err_API_ERROR, RAPI_ERR_BADRECV, 0, (FiltSpecStar *) -1, pkt); return(0); } /* * If client sent DstPort in the SESSION object of zero * but SrcPort in a FILTER_SPEC is non-zero, send * "Conflicting Src Port" error upcall and return 0. */ if (session_get_port(pkt->rsvp_sess) == 0 && filter_of(FlowDesc_of(pkt,0))) { int i; for (i =0; i < pkt->rsvp_nflwd ; i++) if (filterspec_port(filter_of(FlowDesc_of(pkt,i))) != 0) { rsvp_resv_err(RSVP_Err_API_ERROR, RAPI_ERR_BADSPORT, 0, (FiltSpecStar *) -1, pkt); return(0); } } return(1); /* OK */}/* Parse flow descriptor list of reservation request from API, and * build map entries. */intapi_get_flows(Object_header *objp, rsvp_req *req, struct packet *pkt) { int i; API_Flowspec *api_specp; API_FilterSpec *api_filtp; FlowDesc *flwdp; api_filtp = (API_FilterSpec *) After_APIObj(req->rq_policy); for (i = 0; i < pkt->rsvp_nflwd; i++) { flwdp = FlowDesc_of(pkt, i); api_specp = (API_Flowspec *) After_APIObj(api_filtp); switch (api_specp->form) { case RAPI_FLOWSTYPE_Intserv: /* Check Intserv version */ if ((api_specp->specbody_IS.spec_mh.ismh_version& INTSERV_VERS_MASK) != INTSERV_VERSION0) return -1; /* XXX */ New_VObject(flwdp->rsvp_specp, FLOWSPEC, FLOWSPEC_Intserv0, size_api2d(api_specp->len)); Move_spec_api2d(api_specp, flwdp->rsvp_specp); break; case RAPI_EMPTY_OTYPE: flwdp->rsvp_specp = NULL; break; default: return -1; /* XXX Reason code */ } if (api_filtp->form != RAPI_EMPTY_OTYPE) { flwdp->rsvp_filtp = (FILTER_SPEC *) objp; Move_filter_api2d(api_filtp, flwdp->rsvp_filtp, TRUE); objp = Next_Object(objp); } else flwdp->rsvp_filtp = NULL; api_filtp = (API_FilterSpec *) After_APIObj(api_specp); } return(0);}/* * api_prepare_path(): Accepts an API request for a path and turns * it into a standard RSVP Path packet... as if it arrived * from another router (except in host byte order). */intapi_prepare_path( rsvp_req *req, int len, api_rec *recp, struct packet *pkt) { SenderDesc *sdscp; Object_header *objp; packet_map *mapp = pkt->pkt_map; API_FilterSpec *api_filtp; API_TSpec *api_tspecp; API_Adspec *api_adspecp; int LIH; memset((char *)pkt->pkt_data, 0, sizeof(common_header)); mapp->rsvp_msgtype = pkt->pkt_data->rsvp_type = RSVP_PATH; objp = (Object_header *)(pkt->pkt_data + 1); mapp->rsvp_session = (SESSION *) objp; session_create(mapp->rsvp_session, &recp->api_dest, recp->api_protid, SESSFLG_E_Police, recp->api_flags & RAPI_GPI_SESSION); objp = Next_Object(objp); /* * Push flags from map into packet itself, and set version */ pkt->pkt_data->rsvp_verflags = RSVP_MAKE_VERFLAGS(RSVP_VERSION, mapp->rsvp_flags); /* * Only one flowspec (Tspec) per request. * (Should be enforced by the client library routine). */ if (req->rq_nflwd != 1) { log(LOG_ERR, 0, "API: sender nflwd > 1\n"); return(-1); } pkt->rsvp_nflwd = 1; sdscp = SenderDesc_of(pkt); api_filtp = (API_FilterSpec *) After_APIObj(req->rq_policy); api_tspecp = (API_TSpec *) After_APIObj(api_filtp); api_adspecp = (API_Adspec *) After_APIObj(api_tspecp); if ((char *)api_adspecp == (char *)req + len) { /* No Adspec included in request */ api_adspecp = NULL; } else if (After_APIObj(api_adspecp) != (char *)req + len) { log(LOG_ERR, 0, "API: Req len err\n"); return(-1); } /* If local address is INADDR_ANY, set default interface. * Map sender local address into interface number and pass * it in LIH. But if *not* our interface, set LIH = -1 */ LIH = path_set_laddr(api_filtp); /* (signals: from API) */ mapp->rsvp_hop = (RSVP_HOP *) objp; hop_if_create(pkt->rsvp_phop,&GET_IF(api_num),LIH); objp = Next_Object(objp); New_Object(mapp->rsvp_timev, TIME_VALUES, TIME_VALUES_CTYPE); pkt->rsvp_R = api_refresh_t; sdscp->rsvp_stempl = (SENDER_TEMPLATE *) objp; Move_filter_api2d(api_filtp, sdscp->rsvp_stempl, FALSE); objp = Next_Object(objp); New_VObject(sdscp->rsvp_stspec, SENDER_TSPEC, SENDER_TSPEC_CTYPE, size_api2d(api_tspecp->len)); Move_tspec_api2d(api_tspecp, sdscp->rsvp_stspec); /* If sender gave us initial adspec, put it into Path message. * Otherwise, call Traffic Control interface to create minimal * adspec, and put that into message. */ if (api_adspecp) { New_VObject(sdscp->rsvp_adspec, ADSPEC, ADSPEC_INTSERV, size_api2d(api_adspecp->len)); Move_adspec_api2d(api_adspecp, sdscp->rsvp_adspec); } else { New_VObject(sdscp->rsvp_adspec, ADSPEC, ADSPEC_INTSERV, (DFLT_ADSPEC_LEN)); New_Adspec(sdscp->rsvp_adspec); } /* Finish up common header. * Note: no checksum for API packet (per byte order field) */ pkt->pkt_data->rsvp_cksum = 0; pkt->pkt_data->rsvp_length = pkt->pkt_len = (char *)objp - (char *) pkt->pkt_data; pkt->pkt_data->rsvp_snd_TTL = (req->rq_ttl)? req->rq_ttl+1: RSVP_TTL_MAX; /* If local sender address was bad, generate an error upcall * and return 0 => free the packet buffer */ if (LIH < 0) { rsvp_path_err(-1, RSVP_Err_API_ERROR, RAPI_ERR_BADSEND, pkt); return(0); } /* * If the DstPort in the SESSION object was zero * but SrcPort in SENDER_TEMPLATE was non-zero, * upcall with "Conflicting Src Port" error and free packet. */ if (session_get_port(pkt->rsvp_sess) == 0 && filterspec_port(STempl_of(SenderDesc_of(pkt))) != 0) { rsvp_path_err(-1, RSVP_Err_API_ERROR, RAPI_ERR_BADSPORT, pkt); return(0); } return(1);}/* Process rapi_status request. */intapi_status(rsvp_req *req) { Session *destp; api_rec *apip; int i; net_addr dest; net_addr_assign_api_addr(&dest,&req->rq_dest,1); if (!IsAddrAPI(&dest)) { /* Specific destination -- * Find the dest (session) record */ destp = locate_api_session(req,0); if (!destp) { destp = locate_api_session(req,1); if (!destp) return(-1); } api_dest_status(destp, req); return(0); } /* Else status of all destinations for this user process */ for (i=0, apip= api_table; i < API_TABLE_SIZE; i++, apip++) { if (apip->api_fd == 0) break; if (apip->api_pid != req->rq_pid) break; destp = locate_api_session(req, (apip->api_flags&RAPI_GPI_SESSION)); if (destp) api_dest_status(destp, req); } return(0);}intapi_dest_status(Session *dest, rsvp_req *req) {#ifdef ISI_TEST if (req->rq_flags & RAPI_STAT_PATH) { api_PATH_EVENT_upcall1(dest, UPCALL_MODE_STAT, ALL_SID); /* ?? XXX */ } if (req->rq_flags & RAPI_STAT_RESV) { /*** Need to call api_RESV_EVENT_upcall for all RSBs api_RESV_EVENT_upcall_stat(dest, rp); ***/ }#endif /* ISI_TEST */ return(0);}/* * api_PATH_EVENT_upcall(): Notify local API clients of (remote) * Path state. Also, if there is an active reservation request * from API, refresh it immediately. */voidapi_PATH_EVENT_upcall(Session *destp) { api_PATH_EVENT_upcall1(destp, UPCALL_MODE_PATH, ALL_SID);}/* * Special case of PATH EVENT upcall: new API session has just * registered; deliver any pending path state to it immediately. * */voidapi_PATH_EVENT_init(Session *destp, int sid) { api_PATH_EVENT_upcall1(destp, UPCALL_MODE_IFANY, sid);} voidapi_PATH_EVENT_upcall1(Session *destp, int mode, int sid) { char *resp_buf; rsvp_resp *resp; API_TSpec *tspecp; API_FilterSpec *filtp; API_Adspec *adsp; PSB *sp; int resp_len; /* Make first pass over PSBs to compute length of required * response message, and then malloc a buffer of that length. */ resp_len = sizeof(rsvp_resp); for (sp = destp->d_PSB_list; sp != NULL; sp = sp->ps_next) { if (mode != UPCALL_MODE_STAT && IsHopAPI(&sp->ps_phop)) continue; resp_len += sizeof(rapi_filter_t) + size_d2api(Object_Size(sp->ps_tspec)); if (sp->ps_adspec) resp_len += size_d2api(Object_Size(sp->ps_adspec)); } /* If there were no matches and if mode calls for suppression * of null responses, return now. */ if (resp_len == sizeof(rsvp_resp) && mode != UPCALL_MODE_PATH) return; if (!(resp_buf = malloc(resp_len))) { Log_Mem_Full("API Resp"); return; } memset(resp = (rsvp_resp *)resp_buf, 0, resp_len); resp->resp_type = (mode == UPCALL_MODE_STAT)? RAPI_PATH_STATUS: RAPI_PATH_EVENT; resp_session_assign(resp,destp->d_session); /* * Second pass over PSBs to insert sender tspecs and templates */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -