📄 rsvp_api.c
字号:
filtp = (API_FilterSpec *) resp->resp_flows; for (sp = destp->d_PSB_list; sp != NULL; sp = sp->ps_next) { if (mode != UPCALL_MODE_STAT && IsHopAPI(&sp->ps_phop)) continue; tspecp = (API_TSpec *) Move_filter_d2api(sp->ps_templ, filtp); /* Move TSpec or empty object */ filtp = (API_FilterSpec *) Move_tspec_d2api(sp->ps_tspec, tspecp); resp->resp_nflwd++; } /* * Third pass over PSBs to insert adspec list */ adsp = (API_Adspec *) filtp; for (sp = destp->d_PSB_list; sp != NULL; sp = sp->ps_next) { if (mode != UPCALL_MODE_STAT && IsHopAPI(&sp->ps_phop)) continue; adsp = (API_Adspec *) Move_adspec_d2api(sp->ps_adspec, adsp); } upcall_to_appl(resp, (char *) adsp - resp_buf, NULL, sid); /* * If notifying of PATH state and there was a * pending Resv from API, retry Resv immediately. */ if (mode == UPCALL_MODE_PATH) { for(sid = 0; sid < API_TABLE_SIZE; sid++) { api_rec *recp = &api_table[sid]; if (resp->resp_nflwd && recp->api_r_packet.pkt_data) rsvp_pkt_process(&recp->api_r_packet, NULL, api_num); } } free(resp_buf);}/* * api_PATH_ERR_upcall: Pass Path Error message across API to all * application(s) that match it. */voidapi_PATH_ERR_upcall(struct packet *pkt) { char resp_buf[MAX_PKT]; rsvp_resp *resp = (rsvp_resp *) resp_buf; API_FilterSpec *api_filtp = (API_FilterSpec *) &resp->resp_flows; API_TSpec *api_tspecp; SenderDesc *sdscp = SenderDesc_of(pkt); FORCE_HOST_ORDER(pkt); memset(resp, 0, MAX_PKT); /* Excessive... */ resp->resp_type = RAPI_PATH_ERROR; api_ERR_upcall_common(resp, pkt); assert(pkt->rsvp_nflwd <= 1); if (pkt->rsvp_nflwd < 1) return; resp->resp_nflwd = 1; api_tspecp = (API_TSpec *) Move_filter_d2api(sdscp->rsvp_stempl, api_filtp); api_filtp = (API_FilterSpec *) Move_tspec_d2api(sdscp->rsvp_stspec, api_tspecp); upcall_to_appl(resp, (char *)api_filtp - resp_buf, sdscp->rsvp_stempl, ALL_SID);}voidapi_RESV_EVENT_upcall(Session *destp, RSB *rp) { api_RESV_EVENT_upcall1(destp, rp, 0);}voidapi_RESV_EVENT_upcall_stat(Session *destp, RSB *rp) { api_RESV_EVENT_upcall1(destp, rp, 1);}/* * api_RESV_EVENT_upcall1() [Inner routine] * * Make RESV_EVENT upcall to application for specific RSB. * If is_stat is non-zero, use STATUS type in response msg. */voidapi_RESV_EVENT_upcall1(Session *destp, RSB *rp, int is_stat) { char resp_buf[MAX_PKT]; rsvp_resp *resp = (rsvp_resp *) resp_buf; API_Flowspec *api_specp; API_FilterSpec *api_filtp; int i; memset(resp, 0, MAX_PKT); resp->resp_type = (is_stat)? RAPI_RESV_STATUS: RAPI_RESV_EVENT; resp_session_assign(resp,destp->d_session); /* Map style into external style id */ switch (rp->rs_style) { case STYLE_WF: resp->resp_style = RAPI_RSTYLE_WILDCARD; break; case STYLE_FF: resp->resp_style = RAPI_RSTYLE_FIXED; break; case STYLE_SE: resp->resp_style = RAPI_RSTYLE_SE; break; default: assert(0); } api_filtp = (API_FilterSpec *) resp->resp_flows; if (rp->rs_spec == NULL) { resp->resp_nflwd = 0; upcall_to_appl(resp, (char *)api_filtp-resp_buf,NULL,ALL_SID); return; } /* After rq_policy in API response comes pair: * Style=WF: <NUL,Q> * Style=FF: <F,Q> * Style=SE: <F,Q> * Note that only one flowspec is passed per upcall; one FF * style Resv may produce multiple upcalls. Furthermore, only * the matching filter spec is passed for SE. But if state * has been torn down, make empty upcall. */ resp->resp_nflwd = 1; if (resp->resp_style == RAPI_RSTYLE_WILDCARD) { api_specp = (API_Flowspec *) Move_filter_d2api(NULL, api_filtp); api_filtp = (API_FilterSpec *) Move_spec_d2api(rp->rs_spec, api_specp); upcall_to_appl(resp, (char *) api_filtp-resp_buf,NULL,ALL_SID); return; } for (i = 0; i < rp->rs_fcount; i++) { api_specp = (API_Flowspec *) Move_filter_d2api(rp->rs_Filtp(i), api_filtp); api_filtp = (API_FilterSpec *) Move_spec_d2api(rp->rs_spec, api_specp); upcall_to_appl(resp, (char *) api_filtp - resp_buf, rp->rs_Filtp(i), ALL_SID); }}/* api_RESV_ERR_upcall: Send reservation error or confirmation to * all applications matching session. */voidapi_RESV_ERR_upcall(struct packet *pkt) { char resp_buf[MAX_PKT]; rsvp_resp *resp = (rsvp_resp *) resp_buf; int i; API_FilterSpec *api_filtp = (API_FilterSpec *) &resp->resp_flows; API_Flowspec *api_specp; FORCE_HOST_ORDER(pkt); memset(resp, 0, MAX_PKT); /* Excessive... */ resp->resp_type = (errorspec_get_errcode(pkt->rsvp_errs) == RSVP_Err_NONE)? RAPI_RESV_CONFIRM: RAPI_RESV_ERROR; api_ERR_upcall_common(resp, pkt); /* Map style into external style id */ switch (Style(pkt)) { case STYLE_WF: resp->resp_style = RAPI_RSTYLE_WILDCARD; break; case STYLE_FF: resp->resp_style = RAPI_RSTYLE_FIXED; break; case STYLE_SE: resp->resp_style = RAPI_RSTYLE_SE; break; default: assert(0); } resp->resp_nflwd = pkt->rsvp_nflwd; for (i = 0; i < pkt->rsvp_nflwd; i++) { FlowDesc *flwdp = FlowDesc_of(pkt, i); api_specp = (API_Flowspec *) Move_filter_d2api(flwdp->rsvp_filtp, api_filtp); api_filtp = (API_FilterSpec *) Move_spec_d2api(flwdp->rsvp_specp, api_specp); } upcall_to_appl(resp, (char *) api_filtp - resp_buf, NULL, ALL_SID);}voidapi_ERR_upcall_common(rsvp_resp *resp, struct packet *pkt) { SESSION *session = pkt->rsvp_sess; ERROR_SPEC *errorspec = pkt->rsvp_errs; if (Obj_Class(session) != class_SESSION) return; if (Obj_Class(errorspec) != class_ERROR_SPEC) return; resp_session_assign(resp, session); switch(Obj_CType(session)) { case ctype_SESSION_ipv4: case ctype_SESSION_ipv4GPI: if (Obj_CType(errorspec) != ctype_ERROR_SPEC_ipv4) return; resp->resp_errcode = errorspec->errspec4_code; resp->resp_errval = errorspec->errspec4_value; resp->resp_errflags = errorspec->errspec4_flags; NET_SOCKADDR_IPv4( (struct sockaddr_in *) &resp->resp_errnode, errorspec->errspec4_enode); return;#ifdef USE_IPV6 case ctype_SESSION_ipv6: case ctype_SESSION_ipv6GPI: if (Obj_CType(errorspec) != ctype_ERROR_SPEC_ipv6) return; resp->resp_errcode = errorspec->errspec6_code; resp->resp_errval = errorspec->errspec6_value; resp->resp_errflags = errorspec->errspec6_flags; NET_SOCKADDR_IPv6( (struct sockaddr_in6 *) &resp->resp_errnode, errorspec->errspec6_enode); return;#endif /* USE_IPV6 */ default: return; }}staticintresp_session_assign(rsvp_resp *resp,SESSION *session) { if (Obj_Class(session) != class_SESSION) return(FALSE); resp->resp_flags = 0; switch(Obj_CType(session)) { case ctype_SESSION_ipv4GPI: resp->resp_flags |= RAPI_GPI_SESSION; case ctype_SESSION_ipv4: resp->resp_dest.type = htons(API_ADDR_TYPE_IPv4); resp->resp_dest.port = session->sess4_port; memcpy(&resp->resp_dest.u.addr_ipv4, &session->sess4_addr, sizeof(resp->resp_dest.u.addr_ipv4)); resp->resp_protid = session->sess4_prot; return(TRUE);#ifdef USE_IPV6 case ctype_SESSION_ipv6GPI: resp->resp_flags |= RAPI_GPI_SESSION; case ctype_SESSION_ipv6: resp->resp_dest.type = htons(API_ADDR_TYPE_IPv6); resp->resp_dest.port = session->sess6_port; memcpy(&resp->resp_dest.u.addr_ipv6, &session->sess6_addr, sizeof(resp->resp_dest.u.addr_ipv6)); resp->resp_protid = session->sess6_prot; return(TRUE);#endif /* USE_IPV6 */ default: return(FALSE); }}/* Vector of direction flags for each event type. */static int DIR_per_EVENT[] = {0, 0, /* 1- Path event: OK even if dir not set */ API_DIR_SEND, /* 2- Resv event */ API_DIR_SEND, /* 3- Path error event */ API_DIR_RECV, /* 4- Resv error event */ API_DIR_RECV, /* 5- Confirmation event */ 0, 0, 0, 0, /* 9- Path status */ API_DIR_SEND /* 10- Resv status */ };/* Given response message, pass it to specified API session. If * sid = -1 (ALL_SID), pass it to all API sessions with matching * session and direction, and for FILTER_SPEC *filtp matching sender * if filtp is not NULL. Otherwise, pass to specific sid. * */static voidupcall_to_appl(rsvp_resp *resp, int len, FILTER_SPEC *filtp, int sid) { api_rec *recp; net_addr dest; resp->resp_version = VERSION_API; if (sid >= 0) { upcall_to_sid(resp, len, sid); return; } net_addr_assign_api_addr(&dest,&resp->resp_dest,1); for(sid = 0; sid < API_TABLE_SIZE; sid++) { recp = &api_table[sid]; if (recp->api_fd == 0) continue; if (DIR_per_EVENT[resp->resp_type] && (recp->api_flags & DIR_per_EVENT[resp->resp_type]) == 0) continue; if (filtp) { if (!recp->api_p_packet.pkt_data) continue; else if (!match_filter(filtp, (SenderDesc_of(&recp->api_p_packet))->rsvp_stempl)) continue; } if (net_addr_equal(&dest, &recp->api_dest) && (resp->resp_protid == recp->api_protid)) upcall_to_sid(resp, len, sid); }}/* Given response message and length, send as upcall to specified * API session (inner routine of upcall_to_appl()) */void upcall_to_sid(rsvp_resp *resp, int len, int sid) { api_rec *recp = &api_table[sid]; resp->resp_a_sid = recp->api_a_sid; /* Client's SID */ if (IsDebug(DEBUG_ALL)) { static char *Event_Names[] = { "", "Path Evt", "Resv Evt", "Perr Evt", "Rerr Evt", "RConfirm", "??6 Ev", "??7 Ev", "??8 Ev", "Pstat Ev", "Rstat Ev"}; net_addr dest; net_addr_assign_api_addr(&dest,&resp->resp_dest,1); log_api_event(LOGEV_API_upcall, Event_Names[resp->resp_type], &dest, resp->resp_protid, "> API pid=%d Asid=%d\n", recp->api_pid, recp->api_a_sid); } if (NetByteOrderResp(sid)) { char *newbuf = malloc(len); if (!newbuf) return; memcpy(newbuf, (char *)resp, len); hton_api_resp((rsvp_resp *)newbuf, len); send_to_api(sid, (rsvp_resp *)newbuf, len); free(newbuf); } else send_to_api(sid, resp, len);}/* * Write message 'resp' of length 'len' bytes across API to application * with local session id 'sid'. * */voidsend_to_api(int sid, rsvp_resp *resp, int len) { struct iovec iov[2]; int nlen = len; if (l_debug >= LOG_HEXD && len > 0) { hexf(stderr, (char *) resp, len); } if (NetByteOrderResp(sid)) HTON32(nlen); iov[0].iov_base = (char *) (&nlen); iov[0].iov_len = sizeof(int); iov[1].iov_base = (char *) resp; iov[1].iov_len = len; if (writev(api_table[sid].api_fd, iov, 2) == -1) { log(LOG_ERR, errno, "NBIO write error\n"); }}intapi_refresh_delay(int sid) { api_rec *recp = &api_table[sid]; if (recp->api_p_packet.pkt_data) return ((&recp->api_p_packet)->rsvp_R); else if (recp->api_r_packet.pkt_data) return ((&recp->api_r_packet)->rsvp_R); else return (0);}Session *locate_api_session(rsvp_req *req, int gpi) { SESSION Session_obj; net_addr dest; net_addr_assign_api_addr(&dest,&req->rq_dest,1); session_create(&Session_obj,&dest, (req->rq_protid)?req->rq_protid:RSVP_DFLT_PROTID,0,gpi); return(locate_session(&Session_obj));}voidlog_api_event(int evtype, char *type, net_addr *adrp, int protid, const char *format, int pid, int asid) { SESSION Session_obj; session_create(&Session_obj,adrp,protid,0,FALSE); log_event(evtype, type, &Session_obj, format, pid, asid);}static voidprint_api_request(rsvp_req *req, int len, int sid) { api_rec *recp = &api_table[sid];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -