📄 tc_linux.c
字号:
a.g_sum += fa->rate; a.cl_rate = a.bw_max - a.g_sum; goto finish; } return -1;finish: *ai = a; fa->commited = 1; return 0;}int tc_admit(rsvp_qdisc_t *qi, struct admission_info *ai, flow_acinfo_t *a){ switch (a->admtype) { case ADM_CL_STAT: return is_cl_stat_admit(qi, ai, a); case ADM_CL_DET: case ADM_G_DET: return is_g_det_admit(qi, ai, a); default: return -1; }}void tc_unadmit(rsvp_qdisc_t *qi, struct admission_info *ai, flow_acinfo_t *a){ switch (a->admtype) { case ADM_CL_STAT: is_cl_stat_unadmit(qi, ai, a); break; case ADM_CL_DET: case ADM_G_DET: is_g_det_unadmit(qi, ai, a); break; }}/* * TC_AddFlowspec(): Call the kernel to make reservation for a flow. * It checks admission control, and returns a handle for the * reservation, or -1 if an error. It may also set *fwd_specpp * to point to a modified flowspec to be forwarded. */unsigned longTC_AddFlowspec(int OIf, FLOWSPEC *spec, SENDER_TSPEC *stspec, ADSPEC *adspp, int flags, FLOWSPEC **fwd_specpp){ rsvp_qdisc_t *qi; rsvp_flow_t *f = NULL; struct admission_info ai; rsvp_errno = 0; *fwd_specpp = NULL; if (OIf == if_num) return 0; if (!if_vec[OIf].if_up || (qi = ifl_vec[OIf].ifl_qdisc) == NULL) { log(LOG_ERR, 0, "TC_AddFlowspec: err1 %d\n", OIf); goto some_error; } f = malloc(sizeof(*f)); if (f == NULL) goto some_error; memset(f, 0, sizeof(*f)); f->qi = qi; switch (Obj_CType(spec)) { case ctype_FLOWSPEC_Intserv0: is_admission_strategy(f, spec, stspec, adspp, flags); break; default: log(LOG_ERR, 0, "TC_AddFlowspec: nosvc1\n"); goto nosvc_error; } if (f->ai.admtype == 0) { log(LOG_ERR, 0, "TC_AddFlowspec: nosvc2\n"); goto nosvc_error; } ai = qi->ai; if (tc_admit(qi, &qi->ai, &f->ai)) { log(LOG_ERR, 0, "TC_AddFlowspec: nobw1\n"); goto nobw_error; } if (qi->qops->new_flow(f) == 0) { f->next = qi->flow_list; qi->flow_list = f; f->magic = RSVP_FLOW_MAG; return (unsigned long)f; } log(LOG_ERR, 0, "TC_AddFlowspec: new_flow\n"); qi->ai = ai;some_error: rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, 0);err_out: if (f) free(f); return TC_ERROR;nosvc_error: rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, RSVP_Erv_No_Serv); goto err_out;nobw_error: rsvp_errno = Set_Errno(RSVP_Err_ADMISSION, RSVP_Erv_Bandwidth); goto err_out;}/* * TC_ModFlowspec(): Modifies a flowspec of a given flow. * * It may also set *fwd_specpp to point to a modified flowspec to * be forwarded. */intTC_ModFlowspec(int OIf, u_long rhandle, FLOWSPEC *specp, SENDER_TSPEC *stspecp, ADSPEC *adspecp, int flags, FLOWSPEC **fwd_specpp){ rsvp_flow_t *f = (rsvp_flow_t*)rhandle; rsvp_qdisc_t *qi; rsvp_flow_t **fp; rsvp_flow_t new_f; rsvp_filter_t *fh; struct admission_info ai; if (OIf == if_num) return 0; if (!if_vec[OIf].if_up || (qi = ifl_vec[OIf].ifl_qdisc) == NULL) goto some_error; if (f == NULL || f->magic != RSVP_FLOW_MAG) { log(LOG_ERR, 0, "bad flow %p/%d\n", f, f ? f->magic : 345); goto some_error; } qi = f->qi; for (fp = &qi->flow_list; *fp; fp = &(*fp)->next) { if (*fp == f) break; } if (*fp == NULL) { log(LOG_ERR, 0, "TC_ModFlowspec: flow is lost!\n"); goto some_error; } *fwd_specpp = NULL; memset(&new_f, 0, sizeof(new_f)); new_f.qi = qi; switch (Obj_CType(specp)) { case ctype_FLOWSPEC_Intserv0: is_admission_strategy(&new_f, specp, stspecp, adspecp, flags); break; default: goto nosvc_error; } if (new_f.ai.admtype == 0) goto nosvc_error; ai = qi->ai; tc_unadmit(qi, &qi->ai, &f->ai); if (tc_admit(qi, &qi->ai, &new_f.ai)) { qi->ai = ai; goto nobw_error; } if (qi->qops->mod_flow(f, &new_f)) { qi->ai = ai; goto some_error; } f->ai = new_f.ai; f->class = new_f.class; f->classid = new_f.classid; f->policer = new_f.policer; for (fh = f->filters; fh; fh = fh->next) tc_mod_filter(fh); return TC_OK;some_error: rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, 0);err_out: return TC_ERROR;nosvc_error: rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, RSVP_Erv_No_Serv); goto err_out;nobw_error: rsvp_errno = Set_Errno(RSVP_Err_ADMISSION, RSVP_Erv_Bandwidth); goto err_out;}/* * TC_DelFlowspec(): This routine deletes flow for specified handle */intTC_DelFlowspec(int OIf, unsigned long rhandle){ rsvp_flow_t *f = (rsvp_flow_t*)rhandle; rsvp_qdisc_t *qi; rsvp_flow_t **fp; rsvp_filter_t *fh; if (f == NULL || f->magic != RSVP_FLOW_MAG) { log(LOG_ERR, 0, "bad flow %p/%d\n", f, f ? f->magic : 345); return 0; } qi = f->qi; /* Kill filters owned by this flow */ while ((fh = f->filters) != NULL) { f->filters = fh->next; tc_del_filter(fh); fh->magic = -fh->magic; free(fh); } for (fp = &qi->flow_list; *fp; fp = &(*fp)->next) { if (*fp == f) { *fp = f->next; tc_unadmit(qi, &qi->ai, &f->ai); qi->qops->del_flow(f); f->magic = -f->magic; free(f); return 0; } } log(LOG_ERR, 0, "TC_DelFlowspec: flow is lost!\n"); f->magic = -f->magic; return 0;}/* * TC_AddFilter(): Adds a filter for an existing flow. * * Returns fhandle or TC_ERROR. */unsigned longTC_AddFilter(int OIf, unsigned long rhandle, Session *dest, FILTER_SPEC *filtp){ rsvp_filter_t *fh; rsvp_flow_t *f = (rsvp_flow_t*)rhandle; if (f == NULL || OIf == if_num || !if_vec[OIf].if_up) return TC_OK; assert(f->qi->link == &ifl_vec[OIf]); rsvp_errno = 0; fh = malloc(sizeof(*fh)); if (fh) { memset(fh, 0, sizeof(*fh)); fh->flow = f; if (tc_add_filter(fh, filtp, dest) == 0) { fh->next = f->filters; f->filters = fh; fh->magic = RSVP_FILTER_MAG; return (unsigned long)fh; } free(fh); } if (!rsvp_errno) rsvp_errno = RSVP_Err_TC_ERROR; return TC_ERROR;}/* * TC_DelFilter(): Deletes existing filter. */intTC_DelFilter(int OIf, unsigned long fhandle){ rsvp_filter_t **fhp; rsvp_filter_t *fh = (rsvp_filter_t*)fhandle; rsvp_flow_t *f; rsvp_errno = 0; if (fh == NULL || fh->magic != RSVP_FILTER_MAG) { log(LOG_ERR, 0, "bad filter %p/%d\n", fh, fh ? fh->magic : 345); rsvp_errno = RSVP_Err_TC_ERROR; return TC_ERROR; } f = fh->flow; for (fhp = &f->filters; *fhp; fhp = &(*fhp)->next) { if (fh == *fhp) { *fhp = fh->next; if (f->policer.action == TC_POLICE_RECLASSIFY && f->filters == NULL) f->policer.index = 0; tc_del_filter(fh); fh->magic = -fh->magic; free(fh); return TC_OK; } } fh->magic = -fh->magic; log(LOG_ERR, 0, "TC_DelFilter: filter is lost!\n"); if (!rsvp_errno) rsvp_errno = RSVP_Err_TC_ERROR; return TC_ERROR;}#define CLAMPED_ADD(a, b) \({ __u32 _a = (a); __u32 _b = (b); \ if (_b == 0xFFFFFFFFU || _b >= 0xFFFFFFFFU - _a) \ (a) = 0xFFFFFFFFU; \ else \ (a) = _a + _b; \})static int adspec_adv_gen_parms(int OIf, IS_serv_hdr_t *shp){ IS_parm_hdr_t *php; IS_parm_hdr_t *lastphp; rsvp_qdisc_t *qi = ifl_vec[OIf].ifl_qdisc; float32_t hop_bw; u_int32_t hop_latency, hop_mtu; if (qi) hop_bw = qi->ai.bw_max - qi->ai.g_sum; else hop_bw = qi->link->ifl_path_bw ? : TC_DFLT_PATH_BW; hop_latency = qi->link->ifl_min_latency ? : TC_DFLT_MIN_LATENCY; hop_mtu = qi->link->ifl_path_mtu ? : TC_DFLT_MTU; php = (IS_parm_hdr_t *)(shp+1); lastphp = (IS_parm_hdr_t *)Next_Serv_Hdr(shp); while (php < lastphp) { switch (php->isph_parm_num) { case IS_WKP_HOP_CNT: (*(u_int32_t *)(php+1))++; break; case IS_WKP_MIN_LATENCY: CLAMPED_ADD(*(u_int32_t *)(php+1), hop_latency); break; case IS_WKP_COMPOSED_MTU: (*(u_int32_t *)(php+1)) = MIN(hop_mtu, (*(u_int32_t *)(php+1))); break; case IS_WKP_PATH_BW: (*(float32_t *)(php+1)) = MIN(hop_bw, (*(float32_t *)(php+1))); break; default: break; } php = Next_Parm_Hdr(php); } return 0;}static int adspec_adv_gs_parms(int OIf, IS_serv_hdr_t *shp){ IS_parm_hdr_t *php; IS_parm_hdr_t *lastphp; rsvp_qdisc_t *qi = ifl_vec[OIf].ifl_qdisc; php = (IS_parm_hdr_t *)(shp+1); lastphp = (IS_parm_hdr_t *)Next_Serv_Hdr(shp); while (php < lastphp) { switch (php->isph_parm_num) { case GUAR_ADSPARM_Csum: /* Hey, guys! How can I know here, that I am reshaper and, hence, should reset Csum/Dsum ? I need at least path information to make it. Is it bug in functional spec?? */ if (0) (*(u_int32_t *)(php+1)) = 0; case GUAR_ADSPARM_Ctot: CLAMPED_ADD(*(u_int32_t *)(php+1), qi->C); break; case GUAR_ADSPARM_Dsum: if (0) (*(u_int32_t *)(php+1)) = 0; case GUAR_ADSPARM_Dtot: CLAMPED_ADD(*(u_int32_t *)(php+1), qi->D*1000000); break; default: break; } php = Next_Parm_Hdr(php); } return 0;}static int adspec_new_gs_parms(int OIf, IS_serv_hdr_t *shp){ Gads_parms_t *g = (Gads_parms_t*)shp; memset(shp+1, 0, sizeof(Gads_parms_t)-sizeof(*shp)); Issh_len32b(shp) = wordsof(sizeof(Gads_parms_t))-1; g->Gads_Ctot_hdr.isph_parm_num = GUAR_ADSPARM_Ctot; g->Gads_Ctot_hdr.isph_len32b = 1; g->Gads_Dtot_hdr.isph_parm_num = GUAR_ADSPARM_Dtot; g->Gads_Dtot_hdr.isph_len32b = 1; g->Gads_Csum_hdr.isph_parm_num = GUAR_ADSPARM_Csum; g->Gads_Csum_hdr.isph_len32b = 1; g->Gads_Dsum_hdr.isph_parm_num = GUAR_ADSPARM_Dsum; g->Gads_Dsum_hdr.isph_len32b = 1; return 0;}/* * TC_Advertise(): Given existing OPWA ADSPEC, return a new updated object. */ADSPEC *TC_Advertise(int OIf, ADSPEC * old_asp, int flags){ /* Room for expanded Guaranteed svc header is reserved */ ADSPEC *new_asp = (void*)malloc(Object_Size(old_asp) + sizeof(Gads_parms_t)); const IS_main_hdr_t *old_mhp = (IS_main_hdr_t *) Obj_data(old_asp); IS_serv_hdr_t *shp, *lastshp; IS_main_hdr_t *mhp; rsvp_qdisc_t *qi = ifl_vec[OIf].ifl_qdisc; Obj_Class(new_asp) = Obj_Class(old_asp); Obj_CType(new_asp) = Obj_CType(old_asp); Obj_Length(new_asp) = sizeof(Object_header); /* Copy main header */ mhp = (IS_main_hdr_t *) Obj_data(new_asp); Obj_Length(new_asp) += sizeof(*old_mhp); *mhp = *old_mhp; mhp->ismh_len32b = 0; /* Scan service headers and copy them */ shp = (IS_serv_hdr_t *)(old_mhp+1); lastshp = (IS_serv_hdr_t *) Next_Main_Hdr(old_mhp); while (shp < lastshp) { IS_serv_hdr_t *nshp = (void*)Next_Main_Hdr(mhp); /* Copy all the service header */ memcpy(nshp, shp, Issh_len32b(shp)*4 + sizeof(*shp)); if (!if_vec[OIf].if_up || qi == NULL) { /* No RSVP support here */ if (shp->issh_service != GENERAL_INFO) Set_Break_Bit(nshp); } else { switch (shp->issh_service) { default: Set_Break_Bit(nshp); /* Update gen parms in any case... */ case GENERAL_INFO: case CONTROLLED_LOAD_SERV: adspec_adv_gen_parms(OIf, nshp); break; case GUARANTEED_SERV: if (Issh_len32b(nshp) == 0) { adspec_new_gs_parms(OIf, nshp); } else if (Issh_len32b(nshp) < wordsof(sizeof(Gads_parms_t))-1) { log(LOG_ERR, 0, "illegal Gads parms\n"); Set_Break_Bit(nshp); break; } adspec_adv_gs_parms(OIf, nshp); adspec_adv_gen_parms(OIf, nshp); break; } /* ADVERTF_NonRSVP flag means, that PREVIOUS hop is non-RSVP. However, we update adspec, it could be still useful. */ if (flags & ADVERTF_NonRSVP) Set_Break_Bit(nshp); } mhp->ismh_len32b += Issh_len32b(nshp) + 1; Obj_Length(new_asp) += (Issh_len32b(nshp) + 1) * 4; shp = Next_Serv_Hdr(shp); } return new_asp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -