📄 rsvp_path.c
字号:
Session *destp; PSB *psbp; packet_area data; /* Packet area */ struct packet *new_pkt; SenderDesc *sdp = SenderDesc_of(pkt); /* Added by Mohit * Check that INTEGRITY was included if it is required. */ if (in_vif >= 0 && (IF_FLAGS(IF_UNICAST(in_vif))&IF_FLAG_Intgrty) && pkt->pkt_map->rsvp_integrity == NULL) return PKT_ERR_INTEGRITY; destp = locate_session(pkt->rsvp_sess); if (destp == NULL) { log_event(LOGEV_ignore, "PATH-TEAR", pkt->pkt_map->rsvp_session, "// No dest\n"); return(0); } /* Locate PSB for same: * [Multicast dest:] (session, sender, PHOP, in_if) * [Unicast dest:] (session, sender, PHOP) */ psbp = session_multicast(destp->d_session)? locate_PSB(destp, sdp->rsvp_stempl, in_vif,pkt->pkt_map->rsvp_hop): locate_PSB(destp, sdp->rsvp_stempl, -1, pkt->pkt_map->rsvp_hop); if (!psbp) return(0); if (pkt->pkt_ttl == 0) { Incr_ifstats(psbp->ps_in_if, rsvpstat_path_ttl0_in); return(0); } Incr_ifstats(psbp->ps_in_if, rsvpstat_msgs_in[RSVP_PATH_TEAR]); /* * If the PSB to be killed has the route change notification flag * set, and it's a multicast session, send a route query with * notification flag cleared to remove this route from notification * list in the multicast routing daemon. */ if (session_multicast(destp->d_session) && BIT_TST(psbp->ps_rsrr_flags, PSBF_RSRR_NOTIFY)) unnotify_rsrr(psbp, destp); new_pkt = new_packet_area(&data); tear_PSB(destp, psbp, new_pkt, pkt->pkt_map->rsvp_UnkObjList); return 0;}/* * path_refresh(): This routine is called upon refresh timeout, to * send Path refresh for all PSBs. */intpath_refresh(Session *destp){ packet_area data; /* Packet area */ struct packet *pkt; PSB *psbp; /* Time out expired path state. If it's all gone, return -1. */ if (cleanup_path_state(destp) < 0) return(-1); /* Build packet struct, map vector, and packet buffer, and * set up common part of Path msg in map. */ pkt = new_packet_area(&data); pkt->pkt_map->rsvp_msgtype = RSVP_PATH; common_path_header(destp, pkt); /* * For PSB, send refresh. */ for (psbp= destp->d_PSB_list; psbp; psbp = psbp->ps_next) { path_refresh_common(destp, psbp, pkt); } dump_ds(0); /* record state but not too often... */ return (0);}/* * path_refresh_PSB: This routine is called when path state is created * or modified, to do an immediate refresh for specified PSB. */intpath_refresh_PSB(Session *destp, PSB *psbp){ packet_area data; /* Packet area */ struct packet *pkt; /* Build packet struct, map vector, and packet buffer, and * set up common part of Path msg in map. */ pkt = new_packet_area(&data); pkt->pkt_map->rsvp_msgtype = RSVP_PATH; common_path_header(destp, pkt); path_refresh_common(destp, psbp, pkt); dump_ds(0); /* record state but not too often... */ return (0);}/* * This routine sends a path refresh for a particular sender, * i.e., a PSB. This routine may be entered by either the * expiration of the path refresh timer or directly as the result * of the (Path_)Refresh_Needed flag being turned on during the * processing of a received Path message. */intpath_refresh_common(Session *destp, PSB *psbp, struct packet *pkt){ SenderDesc *sdscp = SenderDesc_of(pkt); int vif; /* Compute the IP TTL for the Path message as one less than * the TTL value from the sender. However, if the result is * zero, return without sending the Path message. */ if ((pkt->pkt_ttl = psbp->ps_ip_ttl - 1) <= 0) { Incr_ifstats(psbp->ps_in_if, rsvpstat_path_ttl0_out); return(0); } /* Create a sender descriptor containing the SENDER_TEMPLATE, * SENDER_TSPEC, and POLICY_DATA objects, if present in the * PSB, and pack it into the Path message being built. */ sdscp->rsvp_stempl = psbp->ps_templ; sdscp->rsvp_stspec = psbp->ps_tspec; /* * Copy into Path msg map a pointer to list of unknown objects * to be forwarded. */ pkt->pkt_map->rsvp_UnkObjList = psbp->ps_UnkObjList; /* Send a copy of the Path message to each interface OI in * OutInterface_list. Before sending each copy: * 1. Pass any ADSPEC and SENDER_TSPEC objects present in the PSB * to the traffic control call TC_Advertise. Insert the * modified ADSPEC object that is returned into the Path * message. * 2. If the PSB has the E_Police flag on but interface OI is * incapable of policing, turn on the E_Police flag in the * message. * 3. Insert into the PHOP object the interface address and * the LIH for the interface. */ sdscp->rsvp_adspec = NULL; for (vif= 0; vif < if_num; vif++) { if (IsNumAPI(vif)) continue; if (IF_DOWN(vif)) continue; if (!bmp_tst(&(psbp->ps_outif_list), vif)) continue;#ifdef SCHEDULE if (psbp->ps_adspec) sdscp->rsvp_adspec = TC_Advertise(vif, psbp->ps_adspec, (int) psbp->ps_flags&PSBF_NonRSVP);#endif /* SCHEDULE */ if ((psbp->ps_flags&PSBF_E_Police)&& if_vec[vif].if_up==0) session_set_flags(pkt->rsvp_sess, session_get_flags(pkt->rsvp_sess) | SESSFLG_E_Police); send_path_out_vif(vif, destp, STempl_of(sdscp), pkt); if (sdscp->rsvp_adspec) { free(sdscp->rsvp_adspec); sdscp->rsvp_adspec = NULL; } } return(0);}/* * locate_PSB() returns the PSB matching a (SESSION, SENDER_TEMPLATE) and * possibly in_vif and/or PHOP address. In_vif < 0 and NULL * PHOP address are wildcards. * */PSB *locate_PSB(Session *destp, SENDER_TEMPLATE *filtp, int in_vif, RSVP_HOP *phop){ PSB *sp; for (sp = destp->d_PSB_list; sp != NULL; sp = sp->ps_next) { if (match_filter(filtp, sp->ps_templ)) { if ( (in_vif < 0 || in_vif == sp->ps_in_if) && (phop == NULL || hop_addr_eq(phop,&sp->ps_phop))) return sp; } } return (NULL);}/* * make_PSB(): Add a PSB data structure to a session */PSB *make_PSB(Session *dst, RSVP_HOP *phop, SENDER_TEMPLATE *stemp){ PSB *psbp, **spp, *tsp; psbp = (PSB *) calloc(1, sizeof(PSB)); if (!psbp) { Log_Mem_Full("New sender"); return(NULL); } psbp->ps_ttd = time_now; psbp->ps_next = NULL; bmp_rst(&(psbp->ps_outif_list)); psbp->ps_rsrr_flags = 0; /* * Insert PSB in list in ascending order by sender IP address * within phop. */ for (spp = &dst->d_PSB_list; ; spp = &((*spp)->ps_next)){ if (!(*spp) || hop_addr_lt(phop,&(*spp)->ps_phop)) { /* First sender for this PHOP: insert it here and * set 1stphop field to point to itself. */ psbp->ps_next = *spp; *spp = psbp; psbp->ps_1stphop = psbp; return(psbp); } if (hop_addr_eq(phop,&(*spp)->ps_phop)) break; } /* * PHOP address already in list. */ if (filterspec_lt(stemp,(*spp)->ps_templ)){ /* * Special case: new sender is first (smallest) address */ psbp->ps_1stphop = psbp; /* pt to itself */ for (tsp = *spp; tsp ; tsp = tsp->ps_next) { if (!hop_addr_eq(phop,&tsp->ps_phop)) break; tsp->ps_1stphop = psbp; } } else { psbp->ps_1stphop = *spp; assert((*spp)->ps_1stphop == *spp); for (spp = &((*spp)->ps_next); *spp ; spp = &((*spp)->ps_next)){ if (hop_addr_lt(phop,&(*spp)->ps_phop) || filterspec_lt(stemp,(*spp)->ps_templ)) break; } } psbp->ps_next = *spp; *spp = psbp; return (psbp);}/* * kill_PSB(): This routine frees a PSB data structure. * Called from cleanup_path_state (when sender times out) or * from accept_path_tear. * It deletes any dependent reservation state, and if all path and * reservation state is gone, it deletes the session and returns -1. */intkill_PSB(Session *destp, PSB *psbp) { PSB **spp, *sp, *fsp; int from_net; assert(destp); if (!psbp) return(0); /* * remove PSB from linked list */ for (spp = &destp->d_PSB_list; (*spp) != NULL; spp = &((*spp)->ps_next)) { if ((*spp)->ps_1stphop == (*spp)) fsp = *spp; if ((*spp) == psbp) break; } if (*spp != NULL) *spp = psbp->ps_next; /* If this was first PSB per phop, recompute 1stphop pointers. */ if (fsp == psbp) { for (sp = psbp->ps_next; sp; sp = sp->ps_next) { if (sp->ps_1stphop != psbp) break; sp->ps_1stphop = psbp->ps_next; } } delete_resv4PSB(destp, psbp); /* Delete any dangling reservations */ clear_scope_union(destp); /* Set to recompute scope union */ from_net = !IsHopAPI(&psbp->ps_phop); free((char *) psbp->ps_templ); if (psbp->ps_tspec) free((char *) psbp->ps_tspec); if (psbp->ps_adspec) free((char *) psbp->ps_adspec); if (psbp->ps_BSB_Qb) free((char *) psbp->ps_BSB_Qb); if (psbp->ps_resv_spec) free(psbp->ps_resv_spec); FQkill(&psbp->ps_UnkObjList); free((char *) psbp); /* delete the PSB block itself */ /* Send Path Event upcall to all matching apps, except local state*/ if (from_net) api_PATH_EVENT_upcall(destp); if (!destp->d_PSB_list && !destp->d_RSB_list) { kill_session(destp); return(-1); } return (0);}/* Locate "forwarding" PSB for specified session, sender. Forwarding * PSB is the PSB that is *not* marked LocalyOnly. Return addr of PSB * or NULL if there is none. */PSB *Find_fPSB(Session *destp, SENDER_TEMPLATE *filtp){ PSB *sp; for (sp = destp->d_PSB_list; sp != NULL; sp = sp->ps_next){ if (match_filter(filtp, sp->ps_templ)) { if (!(sp->ps_flags&PSBF_LocalOnly)) return(sp); } } return(NULL);}/* * cleanup_path_state(): For given session, kill all expired path state. * Return 1 if something was killed, -1 if entire session * was killed, else 0. */intcleanup_path_state(Session *destp){ PSB *psbp, *psbpx; packet_area data; /* Packet area */ struct packet *pkt = NULL; int rc, killed = 0; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -