📄 scrapi.c
字号:
} s->status &= ~S_RECV_REQUESTS; s->status |= status; s->spec.specbody_qosx.spec_type = service;}/****************************************************************************** * * Machinery to make reservations. * *****************************************************************************/staticvoidsend_reservations_shared(rapi_sid_t sid,int n,rapi_flowspec_t *spec){ int i; session *sp; sender *s; rapi_filter_t *filter; sp = &sessions[sid]; filter = (rapi_filter_t *) malloc(n * sizeof(rapi_filter_t)); i = 0; for (s = sp->flows;s != NULL;s = s->next) { if (!(s->status & S_PATH)) continue; if (!(s->status & S_RESV_REQUEST)) continue; filter[i] = s->src; spec[i++] = s->spec; } sp->errno = map_errno[rapi_reserve(sid,RAPI_REQ_CONFIRM,NULL, RAPI_RSTYLE_SE,NULL,NULL,n,filter,1,spec)]; free(filter);}staticvoidsend_reservations_distinct(rapi_sid_t sid,int n){ int i; session *sp; sender *s; rapi_filter_t *filter; rapi_flowspec_t *spec; sp = &sessions[sid]; filter = (rapi_filter_t *) malloc(n * sizeof(rapi_filter_t)); spec = (rapi_flowspec_t *) malloc(n * sizeof(rapi_flowspec_t)); i = 0; for (s = sp->flows;s != NULL;s = s->next) { if (!(s->status & S_PATH)) continue; if (!(s->status & S_RESV_REQUEST)) continue; filter[i] = s->src; spec[i++] = s->spec; } sp->errno = map_errno[rapi_reserve(sid,RAPI_REQ_CONFIRM,NULL, RAPI_RSTYLE_FIXED,NULL,NULL,n,filter,n,spec)]; free(filter); free(spec);}staticvoidsend_reservations(rapi_sid_t sid){ int nflows,nreqs; session *sp; sender *s; rapi_flowspec_t spec; qos_flowspecx_t *q = &spec.specbody_qosx; sp = &sessions[sid]; Object_Type(&spec) = RAPI_FLOWSTYPE_Simplified; Object_Length(&spec) = sizeof(rapi_flowspec_t); q->spec_type = sp->service; q->xspec_r = 0; q->xspec_R = 0; q->xspec_S = ULONG_MAX; q->xspec_b = 0; q->xspec_p = 0; q->xspec_m = ULONG_MAX; q->xspec_M = 0; nflows = 0; nreqs = 0; for (s = sp->flows;s != NULL;s = s->next) { if (!(s->status & S_PATH)) continue; nflows++; if (!(s->status & S_RESV_REQUEST)) continue; q->xspec_r = C_MAX(q->xspec_r,s->spec.specbody_qosx.xspec_r); q->xspec_R = C_MAX(q->xspec_R,s->spec.specbody_qosx.xspec_r); q->xspec_S = C_MIN(q->xspec_S,s->spec.specbody_qosx.xspec_S); q->xspec_b = C_MAX(q->xspec_b,s->spec.specbody_qosx.xspec_b); q->xspec_p = C_MAX(q->xspec_p,s->spec.specbody_qosx.xspec_p); q->xspec_m = C_MIN(q->xspec_m,s->spec.specbody_qosx.xspec_m); q->xspec_M = C_MAX(q->xspec_M,s->spec.specbody_qosx.xspec_M); nreqs++; } if (nreqs == 0) { sp->errno = map_errno[rapi_reserve(sid,0,NULL, RAPI_RSTYLE_SE,NULL,NULL,0,NULL,0,NULL)]; return; } switch (sp->style) { case scrapi_style_distinct: send_reservations_distinct(sid,nreqs); break; case scrapi_style_shared: if (nflows == nreqs) sp->errno = map_errno[rapi_reserve(sid, RAPI_REQ_CONFIRM,NULL, RAPI_RSTYLE_WILDCARD,NULL,NULL, 0,NULL,1,&spec)]; else send_reservations_shared(sid,nreqs,&spec); break; default: }}staticintcallback(rapi_sid_t sid,rapi_eventinfo_t event,int style, int errcode,int errval,struct sockaddr *errnode,u_char errflag, int nfilts,rapi_filter_t *filt,int nspecs,rapi_flowspec_t *spec, int nadspecs,rapi_adspec_t *adspec,void *data){ int i; session *sp; sender *s; static void print_callback(rapi_sid_t,rapi_eventinfo_t,int,int,int, struct sockaddr *,u_char,int, rapi_filter_t *,int, rapi_flowspec_t *,int,rapi_adspec_t *,void *); if (dout) { print_callback(sid,event,style,errcode,errval,errnode,errflag, nfilts,filt,nspecs,spec,nadspecs,adspec,data); } sp = &sessions[sid]; switch (event) { case RAPI_PATH_EVENT: break; case RAPI_RESV_EVENT: if (nspecs == 0) sp->status &= ~S_RESV; else { sp->status |= S_RESV; sp->status &= ~S_PATH_ERROR; } return(0); case RAPI_RESV_CONFIRM: sp->status |= S_CONFIRM; sp->status &= ~S_RESV_ERROR; if (filt != NULL) { s = get_sender(sid,filt); s->status |= S_CONFIRM; s->status &= ~S_RESV_ERROR; } return(0); case RAPI_PATH_ERROR: sp->status |= S_PATH_ERROR; return(0); case RAPI_RESV_ERROR: sp->status |= S_RESV_ERROR; sp->status &= ~S_CONFIRM; if (filt != NULL) { s = get_sender(sid,filt); s->status |= S_RESV_ERROR; s->status &= ~S_CONFIRM; } return(0); default: return(0); } for (s = sp->flows;s != NULL;s = s->next) s->status &= ~S_PATH; nspecs = C_MIN(nspecs,nfilts); for (i = 0;i < nspecs; i++) { if (Object_Type(spec) != RAPI_TSPECTYPE_Simplified) continue; set_sender(sid,filt,spec); spec = Object_Next(rapi_flowspec_t,spec); filt = Object_Next(rapi_filter_t,filt); } for (s = sp->flows;s != NULL;s = s->next) if (!(s->status & S_PATH)) s->status &= ~S_RECV_NOT_REQUESTS; if (nspecs == 0) sp->status &= ~S_RECV_NOT_REQUESTS; send_reservations(sid); return(0);}/****************************************************************************** * * Utility functions for session information. * *****************************************************************************/staticrapi_sid_tfind_session(const struct sockaddr *dst,int proto,const struct sockaddr *src){ int i; session *sp; for (i = 0;i < MAXSESSIONS; i++) { sp = &sessions[i]; if (!(sp->status & S_OPEN)) continue; if (!sockaddr_equal(dst,SAP(&sp->dst))) continue; if (proto != sp->proto) continue; if (sockaddr_equal(src,SAP(&sp->src))) return(i); } return(NULL_SID);}staticrapi_sid_tget_session(const struct sockaddr *dst,int proto,const struct sockaddr *src){ int error; rapi_sid_t sid; session *sp; sid = find_session(dst,proto,src); if (sid != NULL_SID) return(sid); sid = rapi_session(SAP(dst),proto,0,&callback,NULL,&error); if (sid >= MAXSESSIONS) return(NULL_SID); /* FIX: map sids to index values in sessions[] */ sp = &sessions[sid]; sockaddr_assign(SAP(&sp->dst),dst); sp->proto = proto; sockaddr_assign(SAP(&sp->src),src); sp->flows = NULL; sp->errno = map_errno[error]; if (sid != NULL_SID) { sp->status = S_OPEN; nsessions++; } return(sid);}staticintclose_session(rapi_sid_t sid){ session *sp; sender *s,*next; sp = &sessions[sid]; for (s = sp->flows;s != NULL;s = next) { next = s->next; free(s); } sp->status = S_NONE; nsessions--; return(rapi_release(sid) == RAPI_ERR_OK);}staticintclose_inactive_session(rapi_sid_t sid){ session *sp; sender *s; sp = &sessions[sid]; if (sp->status & S_REQUESTS) return(TRUE); for (s = sp->flows;s != NULL;s = s->next) if (s->status & S_REQUESTS) return(TRUE); return(close_session(sid));}/****************************************************************************** * * Miscellaneous utility functions. * *****************************************************************************/staticintdispatch(rapi_sid_t sid){ int error; error = rapi_dispatch(); if (error == RAPI_ERR_OK) return(TRUE); sessions[sid].errno = map_errno[error]; close_inactive_session(sid); return(FALSE);}staticintbad_parameter(rapi_sid_t sid){ sessions[sid].errno = SCRAPI_ERRNO_PARAM; close_inactive_session(sid); return(FALSE);}staticinttimed_wait(rapi_sid_t sid,unsigned long flags,unsigned long msecs){ int n; session *sp; struct timeval tv,tv1,tv2; fd_set rfds; if (msecs == 0) return(TRUE); tv.tv_sec = msecs / 1000; tv.tv_usec = 1000 * (msecs - 1000 * (msecs / 1000)); FD_ZERO(&rfds); FD_SET(rapi_getfd(sid),&rfds); sp = &sessions[sid]; do { if (!dispatch(sid)) return(FALSE); if (sp->status & flags) return(TRUE); if (sp->status & S_ERRORS) { sp->errno = SCRAPI_ERRNO_NONE; return(FALSE); } tv2 = tv; gettimeofday(&tv1,NULL); n = select(FD_SETSIZE,&rfds,(fd_set *) NULL, (fd_set *) NULL,&tv2); gettimeofday(&tv2,NULL); tv.tv_sec -= tv2.tv_sec - tv1.tv_sec; tv.tv_usec -= tv2.tv_usec - tv1.tv_usec; } while (n == 1); sp->errno = SCRAPI_ERRNO_TIMEOUT; return(FALSE);}/* * This is unfortunately very system dependent! */staticunsigned intmax_packet_size(){ int fd,mtu = MAX_PACKET_SIZE; struct ifconf ifc; struct ifreq ifr,*p,*last; static char buffer[MAX_INTERFACES * sizeof(struct ifreq) + sizeof(struct ifconf)]; fd = socket(AF_INET,SOCK_DGRAM,PF_UNSPEC); if (FAILED(fd)) return(mtu); ifc.ifc_buf = buffer; ifc.ifc_len = sizeof(buffer); if (FAILED(ioctl(fd,SIOCGIFCONF,(caddr_t) &ifc))) { close(fd); return(mtu); } last = ((struct ifreq *) ifc.ifc_req) + ifc.ifc_len; for (p = (struct ifreq *) ifc.ifc_req;p < last;#ifdef __FreeBSD__ p = (struct ifreq *) (((char *) &p->ifr_addr) + p->ifr_addr.sa_len)) {#else /* __FreeBSD__ */ p++) {#endif /* __FreeBSD__ */ if (strncmp(p->ifr_name,"",IFNAMSIZ) == 0) break; if (strncmp(p->ifr_name,"lo0",IFNAMSIZ) == 0) continue; switch (p->ifr_addr.sa_family) { case AF_INET:#ifdef USE_IPV6 case AF_INET6:#endif /* USE_IPV6 */ break; default: continue; } strncpy(ifr.ifr_name,p->ifr_name,IFNAMSIZ); if (FAILED(ioctl(fd,SIOCGIFMTU,(caddr_t) &ifr))) continue; mtu = C_MAX(mtu,ifr.ifr_metric); } close(fd); return(mtu);}/****************************************************************************** * * Simplified RAPI inteface. * *****************************************************************************/intscrapi_sender(const struct sockaddr *dst,int proto, const struct sockaddr *src,double bw,int ttl,unsigned long msecs){ rapi_sid_t sid; session *sp; rapi_tspec_t tspec; qos_tspecx_t *q = &tspec.tspecbody_qosx; struct SOCKADDR any; if (!scrapi_sockaddr_any(SAP(&any),dst->sa_family)) return(FALSE); if ((src == NULL) || sockaddr_equal(src,SAP(&any))) { sid = get_session(dst,proto,SAP(&any)); if (sid == NULL_SID) return(FALSE); return(bad_parameter(sid)); } sid = get_session(dst,proto,src); if (sid == NULL_SID) return(FALSE); if (!dispatch(sid)) return(FALSE); if (bw == 0) return(close_session(sid)); sp = &sessions[sid]; sp->status &= ~S_SEND_REQUESTS; sp->status |= S_PATH_REQUEST; q->spec_type = QOS_TSPEC; q->xtspec_r = bw; q->xtspec_b = 2 * bw; q->xtspec_p = 2 * bw; q->xtspec_m = MIN_PACKET_SIZE; q->xtspec_M = max_packet_size(); tspec.form = RAPI_TSPECTYPE_Simplified; tspec.len = sizeof(rapi_hdr_t) + sizeof(qos_tspecx_t); sp->errno = map_errno[rapi_sender(sid,0,SAP(src), filter_from_sockaddr(src),&tspec,NULL,NULL,ttl)]; if (sp->errno != SCRAPI_ERRNO_NONE) { close_session(sid); return(FALSE); } return(timed_wait(sid,S_RESV,msecs));}intscrapi_receiver(const struct sockaddr *dst,int proto, const struct sockaddr *src,int on,scrapi_service service, scrapi_style style,unsigned long msecs){ rapi_sid_t sid; session *sp; sender *s; rapi_filter_t *f; enum qos_service_type serv; struct SOCKADDR any; unsigned long status; if (!scrapi_sockaddr_any(SAP(&any),dst->sa_family)) return(FALSE); if (src == NULL) src = SAP(&any); sid = get_session(dst,proto,src); if (sid == NULL_SID) return(FALSE); if (!dispatch(sid)) return(FALSE); if (scrapi_sockaddr_get_port(src) != htons(0)) if (sockaddr_equal_wild(src,SAP(&any))) return(bad_parameter(sid)); switch (service) { case scrapi_service_cl: serv = QOS_CNTR_LOAD; break; case scrapi_service_gs: serv = QOS_GUARANTEED; break; default: return(bad_parameter(sid)); } if (!sockaddr_equal(src,SAP(&any))) { close_inactive_session(sid); sid = get_session(dst,proto,SAP(&any)); if (sid == NULL_SID) return(FALSE); } sp = &sessions[sid]; sp->service = serv; sp->style = style; status = on ? S_RESV_REQUEST : S_NONE; f = filter_from_sockaddr(src); mod_sender(get_sender(sid,f),sp->service,status); if (sockaddr_equal(src,SAP(&any))) { /* * Apply the wild src to all sources. */ for (s = sp->flows;s != NULL;s = s->next) mod_sender(s,sp->service,status); } else { /* * Apply the wild src port to all sources with the * same address. */ if (scrapi_sockaddr_get_port(src) == htons(0)) for (s = sp->flows;s != NULL;s = s->next) { if (!filter_equal_wild(f,&s->src)) continue; mod_sender(s,sp->service,status); } } send_reservations(sid); if (on) return(timed_wait(sid,S_CONFIRM,msecs)); return(close_inactive_session(sid));}intscrapi_close(const struct sockaddr *dst,int proto, const struct sockaddr *src){ int i,ret = TRUE; rapi_sid_t sid; session *sp; struct SOCKADDR any; if (dst != NULL) { if (!scrapi_sockaddr_any(SAP(&any),dst->sa_family)) return(FALSE); } if ((dst == NULL) || sockaddr_equal(dst,SAP(&any))) { for (i = 0;i < MAXSESSIONS; i++) if (sessions[i].status & S_OPEN) ret |= close_session(i); return(ret); } sid = find_session(dst,proto,SAP(&any)); if (sid != NULL_SID) { sp = &sessions[sid]; /* FIX: doesn't take wild address */ scrapi_receiver(dst,proto,src,FALSE,sp->service,sp->style,0); } if ((src == NULL) || sockaddr_equal(src,SAP(&any))) { if (!dispatch(sid)) return(FALSE); for (i = 0;i < MAXSESSIONS; i++) { if (i == sid) continue; sp = &sessions[i]; if (!(sp->status & S_OPEN)) continue; if (!sockaddr_equal(dst,SAP(&sp->dst))) continue; if (proto != sp->proto) continue; ret |= close_session(i); } return(ret); } /* FIX: doesn't take wild port */ sid = find_session(dst,proto,src); if (sid != NULL_SID) { if (!dispatch(sid)) return(FALSE); return(close_session(sid)); } return(ret);}intscrapi_dispatch(){ int error; rapi_sid_t sid; struct SOCKADDR host; if (nsessions == 0) { if (!scrapi_sockaddr_parse(SAP(&host),"10.0.0.1",htons(1))) return(FALSE); sid = rapi_session(SAP(&host),IPPROTO_UDP,0,&callback, NULL,&error); if (sid == NULL_SID) return(FALSE); rapi_release(sid); return(TRUE); } return(rapi_dispatch() != RAPI_ERR_NORSVP);}voidscrapi_poll_list(fd_set *set){ int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -