def find_retx_within_a_range(QCATEntries, startIndex, endIndex, direction): tot_rlc_count = rw.initFullRRCMap(0.0) retx_rlc_count = rw.initFullRRCMap(0.0) # method 2 exist_sn_set = set([]) for index in range(startIndex, endIndex + 1): cur_entry = QCATEntries[index] if cur_entry.logID == const.UL_PDU_ID or \ cur_entry.logID == const.DL_PDU_ID: cur_rrcID = cur_entry.rrcID cur_rlc_pdus = cur_entry.ul_pdu[0] if direction.lower() == "down": cur_rlc_pdus = cur_entry.dl_pdu[0] if cur_rrcID: # check current sequence number for sn in cur_rlc_pdus["sn"]: if sn in exist_sn_set: retx_rlc_count[cur_rrcID] += 1 else: exist_sn_set.add(sn) tot_rlc_count[cur_rrcID] += 1 ratio = 0.0 total_sum = float(sum(tot_rlc_count.values())) retx_sum = float(sum(retx_rlc_count.values())) if total_sum > 0.0: ratio = retx_sum / total_sum # ratio = retx_sum return tot_rlc_count, retx_rlc_count, ratio, total_sum
def UDP_loss_stats(QCATEntries, udp_clt_lookup_table, udp_srv_lookup_table, hash_target, srv_ip): # Statistic result udp_loss_per_rrc_map = rw.initFullRRCMap(0.0) udp_total_per_rrc_map = rw.initFullRRCMap(0.0) udp_srv_fail_recv_list = [] # list of UDP dropped over the internet udp_clt_fail_log_list = [] # parse each UDP entry to check whether if appears on the server side table # use server ip to script the direction for hash_key, indexList in udp_clt_lookup_table.items(): for entryIndex in indexList: cur_entry = QCATEntries[entryIndex] # count the src UDP packet udp_total_per_rrc_map[cur_entry.rrcID] += 1 if not udp_srv_lookup_table.has_key(hash_key): udp_loss_per_rrc_map[cur_entry.rrcID] += 1 udp_srv_fail_recv_list.append(entryIndex) # reverse map server side to the client side to check whether mis-log for hash_key in udp_srv_lookup_table.keys(): if not udp_clt_lookup_table.has_key(hash_key): udp_clt_fail_log_list.append(hash_key) return udp_loss_per_rrc_map, udp_total_per_rrc_map, udp_srv_fail_recv_list, udp_clt_fail_log_list
def find_retx_within_a_range(QCATEntries, startIndex, endIndex, direction): tot_rlc_count = rw.initFullRRCMap(0.0) retx_rlc_count = rw.initFullRRCMap(0.0) # method 2 exist_sn_set = set([]) for index in range(startIndex, endIndex+1): cur_entry = QCATEntries[index] if cur_entry.logID == const.UL_PDU_ID or \ cur_entry.logID == const.DL_PDU_ID: cur_rrcID = cur_entry.rrcID cur_rlc_pdus = cur_entry.ul_pdu[0] if direction.lower() == "down": cur_rlc_pdus = cur_entry.dl_pdu[0] if cur_rrcID: # check current sequence number for sn in cur_rlc_pdus["sn"]: if sn in exist_sn_set: retx_rlc_count[cur_rrcID] += 1 else: exist_sn_set.add(sn) tot_rlc_count[cur_rrcID] += 1 ratio = 0.0 total_sum = float(sum(tot_rlc_count.values())) retx_sum = float(sum(retx_rlc_count.values())) if total_sum > 0.0: ratio = retx_sum / total_sum # ratio = retx_sum return tot_rlc_count, retx_rlc_count, ratio, total_sum
def UDP_loss_stats (QCATEntries, udp_clt_lookup_table, udp_srv_lookup_table, hash_target, srv_ip): # Statistic result udp_loss_per_rrc_map = rw.initFullRRCMap(0.0) udp_total_per_rrc_map = rw.initFullRRCMap(0.0) udp_srv_fail_recv_list = [] # list of UDP dropped over the internet udp_clt_fail_log_list = [] # parse each UDP entry to check whether if appears on the server side table # use server ip to script the direction for hash_key, indexList in udp_clt_lookup_table.items(): for entryIndex in indexList: cur_entry = QCATEntries[entryIndex] # count the src UDP packet udp_total_per_rrc_map[cur_entry.rrcID] += 1 if not udp_srv_lookup_table.has_key(hash_key): udp_loss_per_rrc_map[cur_entry.rrcID] += 1 udp_srv_fail_recv_list.append(entryIndex) # reverse map server side to the client side to check whether mis-log for hash_key in udp_srv_lookup_table.keys(): if not udp_clt_lookup_table.has_key(hash_key): udp_clt_fail_log_list.append(hash_key) return udp_loss_per_rrc_map, udp_total_per_rrc_map, udp_srv_fail_recv_list, udp_clt_fail_log_list
def cal_UDP_RTT_per_state (QCATEntries, direction, clt_up_table, clt_down_table): udp_rtt_per_state = rw.initFullRRCMap(0.0) for k in udp_rtt_per_state: udp_rtt_per_state[k] = [] lookup_table = clt_up_table if direction.lower() != "up": lookup_table = clt_down_table for index_list in lookup_table.values(): for index in index_list: cur_entry = QCATEntries[index] if cur_entry.rrcID and cur_entry.rtt["udp"] and cur_entry.rtt["udp"] > 0: udp_rtt_per_state[cur_entry.rrcID].append(cur_entry.rtt["udp"]) return udp_rtt_per_state
def cal_UDP_RTT_per_state(QCATEntries, direction, clt_up_table, clt_down_table): udp_rtt_per_state = rw.initFullRRCMap(0.0) for k in udp_rtt_per_state: udp_rtt_per_state[k] = [] lookup_table = clt_up_table if direction.lower() != "up": lookup_table = clt_down_table for index_list in lookup_table.values(): for index in index_list: cur_entry = QCATEntries[index] if cur_entry.rrcID and cur_entry.rtt[ "udp"] and cur_entry.rtt["udp"] > 0: udp_rtt_per_state[cur_entry.rrcID].append(cur_entry.rtt["udp"]) return udp_rtt_per_state
def get_gap_to_rtt_map(QCATEntries): gap_rtt_per_rrc_map = {} gap_rtt_list_map = {} index = 0 entry_length = len(QCATEntries) while index < entry_length: cur_entry = QCATEntries[index] cur_gap = cur_entry.udp["gap"] if cur_entry.ip["tlp_id"] == const.UDP_ID and cur_gap >= 0: # find the last gap_period message last_map_index = find_last_same_gap_entry_index( QCATEntries, index, cur_gap) # update the RTT map table for temp_index in range(index, last_map_index + 1): temp_entry = QCATEntries[temp_index] cur_rtt = temp_entry.rtt["udp"] cur_rrc = temp_entry.rrcID # append to RTT list if cur_rtt: if gap_rtt_list_map.has_key(cur_gap): gap_rtt_list_map[cur_gap].append(cur_rtt) else: gap_rtt_list_map[cur_gap] = [cur_rtt] # update RRC map if cur_rrc: if not gap_rtt_per_rrc_map.has_key(cur_gap): gap_rtt_per_rrc_map[cur_gap] = rw.initFullRRCMap([]) gap_rtt_per_rrc_map[cur_gap][cur_rrc].append(cur_rtt) # leap the index index = last_map_index # update the index index += 1 # display all the RTT timer if True: for k in sorted(gap_rtt_list_map.keys()): mean, stdev = util.meanStdevPair(gap_rtt_list_map[k]) print "%f\t%f\t%f" % (k, mean, stdev) return gap_rtt_list_map, gap_rtt_per_rrc_map
def get_gap_to_rtt_map(QCATEntries): gap_rtt_per_rrc_map = {} gap_rtt_list_map = {} index = 0 entry_length = len(QCATEntries) while index < entry_length: cur_entry = QCATEntries[index] cur_gap = cur_entry.udp["gap"] if cur_entry.ip["tlp_id"] == const.UDP_ID and cur_gap >= 0: # find the last gap_period message last_map_index = find_last_same_gap_entry_index(QCATEntries, index, cur_gap) # update the RTT map table for temp_index in range(index, last_map_index+1): temp_entry = QCATEntries[temp_index] cur_rtt = temp_entry.rtt["udp"] cur_rrc = temp_entry.rrcID # append to RTT list if cur_rtt: if gap_rtt_list_map.has_key(cur_gap): gap_rtt_list_map[cur_gap].append(cur_rtt) else: gap_rtt_list_map[cur_gap] = [cur_rtt] # update RRC map if cur_rrc: if not gap_rtt_per_rrc_map.has_key(cur_gap): gap_rtt_per_rrc_map[cur_gap] = rw.initFullRRCMap([]) gap_rtt_per_rrc_map[cur_gap][cur_rrc].append(cur_rtt) # leap the index index = last_map_index # update the index index += 1 # display all the RTT timer if True: for k in sorted(gap_rtt_list_map.keys()): mean, stdev = util.meanStdevPair(gap_rtt_list_map[k]) print "%f\t%f\t%f" % (k, mean, stdev) return gap_rtt_list_map, gap_rtt_per_rrc_map
def UDP_loss_cross_analysis(QCATEntries, loss_index_list, logID): # Loss over cellular network if # 1. exceeding max Retx count # 2. there is a reset PDU in between the mapped RLC list and the next control message udp_loss_in_cellular = { "reset": rw.initFullRRCMap(0.0), "max_retx": rw.initFullRRCMap(0.0) } udp_loss_in_internet = rw.initFullRRCMap(0.0) entry_len = len(QCATEntries) max_retx_count_overall = 0.0 for loss_index in loss_index_list: cur_entry = QCATEntries[loss_index] mapped_rlc_tuple_list, mapped_sn_list = clw.cross_layer_mapping_WCDMA_uplink( QCATEntries, loss_index, logID) if mapped_rlc_tuple_list and cur_entry.rrcID: first_mapped_rlc_index = mapped_rlc_tuple_list[0][1] last_mapped_rlc_index = mapped_rlc_tuple_list[-1][1] first_mapped_rlc_sn = min( QCATEntries[first_mapped_rlc_index].ul_pdu[0]["sn"]) last_mapped_rlc_sn = min( QCATEntries[last_mapped_rlc_index].ul_pdu[0]["sn"]) max_tx_config = cur_entry.ul_config["max_tx"] next_ack_index = clw.findNextCtrlMsg(QCATEntries, loss_index, ctrl_type="ack", cur_seq=last_mapped_rlc_sn) next_list_index = clw.findNextCtrlMsg(QCATEntries, loss_index, ctrl_type="list", cur_seq=last_mapped_rlc_sn) ctrl_index = entry_len if next_ack_index: ctrl_index = min(next_ack_index, ctrl_index) if next_list_index: ctrl_index = min(next_list_index, ctrl_index) # check reset reset_index = clw.find_reset_ack(QCATEntries, last_mapped_rlc_index + 1, ctrl_index) # check for exceeding retx count rlc_tx_map = clw.find_SN_within_interval( QCATEntries, first_mapped_rlc_index + 1, ctrl_index) max_tx_count_num = 0 if rlc_tx_map: max_tx_count_num = max([len(i) for i in rlc_tx_map.values()]) if max_tx_count_num > max_retx_count_overall: max_retx_count_overall = max_tx_count_num if reset_index: udp_loss_in_cellular["reset"][cur_entry.rrcID] += 1 if DEBUG: print "-------------- Detect Reset --------------" elif max_tx_config and max_tx_count_num >= max_tx_config: udp_loss_in_cellular["max_retx"][cur_entry.rrcID] += 1 if DEBUG: print "%%%%%%%%%%%% Max retx configued: ", max_tx_config print "%%%%%%%%%%%% Cur retx configued: ", max_tx_count_num else: udp_loss_in_internet[cur_entry.rrcID] += 1 """ # print out retransmission over PCH promotion # investigate high PCH loss rate #if cur_entry.rrcID and cur_entry.rrcID == const.PCH_TO_FACH_ID: print "%"* 100 print "%"* 40 + "Curious Case:" + "%"* 40 pw.printUDPEntry(cur_entry) print "%"* 100 print "%"* 100 # find the lower bound of the range max_index = clw.find_nearest_status(QCATEntries, loss_index, max(mapped_sn_list)) print "is max index correct %s" % (max_index > loss_index) target_sn_set = set(mapped_sn_list) dup_sn_map, rlc_tx_index_list = clw.loss_analysis_with_rlc_retx(QCATEntries, loss_index, max_index, target_sn_set) print "max # of retx is %d" % max([len(i) for i in dup_sn_map.values()]) pw.print_loss_case(QCATEntries, loss_index, rlc_tx_index_list) """ if CUR_DEBUG: print "Max RLC retx is ", max_retx_count_overall return udp_loss_in_cellular, udp_loss_in_internet
def UDP_loss_cross_analysis(QCATEntries, loss_index_list, logID): # Loss over cellular network if # 1. exceeding max Retx count # 2. there is a reset PDU in between the mapped RLC list and the next control message udp_loss_in_cellular = {"reset": rw.initFullRRCMap(0.0), "max_retx": rw.initFullRRCMap(0.0)} udp_loss_in_internet = rw.initFullRRCMap(0.0) entry_len = len(QCATEntries) max_retx_count_overall = 0.0 for loss_index in loss_index_list: cur_entry = QCATEntries[loss_index] mapped_rlc_tuple_list, mapped_sn_list = clw.cross_layer_mapping_WCDMA_uplink(QCATEntries, loss_index, logID) if mapped_rlc_tuple_list and cur_entry.rrcID: first_mapped_rlc_index = mapped_rlc_tuple_list[0][1] last_mapped_rlc_index = mapped_rlc_tuple_list[-1][1] first_mapped_rlc_sn = min(QCATEntries[first_mapped_rlc_index].ul_pdu[0]["sn"]) last_mapped_rlc_sn = min(QCATEntries[last_mapped_rlc_index].ul_pdu[0]["sn"]) max_tx_config = cur_entry.ul_config["max_tx"] next_ack_index = clw.findNextCtrlMsg(QCATEntries, loss_index, ctrl_type = "ack", cur_seq = last_mapped_rlc_sn) next_list_index = clw.findNextCtrlMsg(QCATEntries, loss_index, ctrl_type = "list", cur_seq = last_mapped_rlc_sn) ctrl_index = entry_len if next_ack_index: ctrl_index = min(next_ack_index, ctrl_index) if next_list_index: ctrl_index = min(next_list_index, ctrl_index) # check reset reset_index = clw.find_reset_ack(QCATEntries, last_mapped_rlc_index + 1, ctrl_index) # check for exceeding retx count rlc_tx_map = clw.find_SN_within_interval(QCATEntries, first_mapped_rlc_index + 1, ctrl_index) max_tx_count_num = 0 if rlc_tx_map: max_tx_count_num = max([len(i) for i in rlc_tx_map.values()]) if max_tx_count_num > max_retx_count_overall: max_retx_count_overall = max_tx_count_num if reset_index: udp_loss_in_cellular["reset"][cur_entry.rrcID] += 1 if DEBUG: print "-------------- Detect Reset --------------" elif max_tx_config and max_tx_count_num >= max_tx_config: udp_loss_in_cellular["max_retx"][cur_entry.rrcID] += 1 if DEBUG: print "%%%%%%%%%%%% Max retx configued: " , max_tx_config print "%%%%%%%%%%%% Cur retx configued: " , max_tx_count_num else: udp_loss_in_internet[cur_entry.rrcID] += 1 """ # print out retransmission over PCH promotion # investigate high PCH loss rate #if cur_entry.rrcID and cur_entry.rrcID == const.PCH_TO_FACH_ID: print "%"* 100 print "%"* 40 + "Curious Case:" + "%"* 40 pw.printUDPEntry(cur_entry) print "%"* 100 print "%"* 100 # find the lower bound of the range max_index = clw.find_nearest_status(QCATEntries, loss_index, max(mapped_sn_list)) print "is max index correct %s" % (max_index > loss_index) target_sn_set = set(mapped_sn_list) dup_sn_map, rlc_tx_index_list = clw.loss_analysis_with_rlc_retx(QCATEntries, loss_index, max_index, target_sn_set) print "max # of retx is %d" % max([len(i) for i in dup_sn_map.values()]) pw.print_loss_case(QCATEntries, loss_index, rlc_tx_index_list) """ if CUR_DEBUG: print "Max RLC retx is ", max_retx_count_overall return udp_loss_in_cellular, udp_loss_in_internet
def get_RRC_timer_map(QCATEntries, demote_accurate=False): # use two RRC log ID difference to measure the difference rrc_to_rrc_timer_map = rw.initFullRRCMap({}, const.RRC_ORIG_MAP) # use the RRC log ID to nearest IP packets as metric rrc_to_nearest_ip_timer_map = rw.initFullRRCMap({}, const.RRC_ORIG_MAP) # store the percentage of RRC_to_IP / RRC_to_RRC percentage_map = rw.initFullRRCMap({}, const.RRC_ORIG_MAP) for k in rrc_to_rrc_timer_map: rrc_to_rrc_timer_map[k] = rw.initFullRRCMap([], const.RRC_ORIG_MAP) rrc_to_nearest_ip_timer_map[k] = rw.initFullRRCMap([], const.RRC_ORIG_MAP) percentage_map[k] = rw.initFullRRCMap([], const.RRC_ORIG_MAP) rrcID_domain = set(const.RRC_ORIG_MAP) # check for the previous index priv_rrc_entry_index = None for index in range(len(QCATEntries)): cur_entry = QCATEntries[index] if cur_entry.logID == const.RRC_ID and cur_entry.rrcID in rrcID_domain: if priv_rrc_entry_index: priv_entry = QCATEntries[priv_rrc_entry_index] time_diff = cur_entry.timestamp - priv_entry.timestamp rrc_to_rrc_timer_map[priv_entry.rrcID][cur_entry.rrcID].append( time_diff) # Find the nearest IP log ip_log_index = find_nearest_ip_index(QCATEntries, index - 1, priv_rrc_entry_index + 1) # Assign RRC to IP timer map new_time_diff = time_diff if ip_log_index: ip_log = QCATEntries[ip_log_index] new_time_diff = cur_entry.timestamp - ip_log.timestamp rrc_to_nearest_ip_timer_map[priv_entry.rrcID][ cur_entry.rrcID].append(new_time_diff) if time_diff: percentage_map[priv_entry.rrcID][cur_entry.rrcID].append( new_time_diff / time_diff) priv_rrc_entry_index = index if DEBUG: print "FACH promote Timer:", len( rrc_to_rrc_timer_map[const.FACH_ID][const.DCH_ID]) print util.listToStr( util.quartileResult( rrc_to_rrc_timer_map[const.FACH_ID][const.DCH_ID])) print "PCH promote Timer:", len( rrc_to_rrc_timer_map[const.PCH_ID][const.FACH_ID]) print util.listToStr( util.quartileResult( rrc_to_rrc_timer_map[const.PCH_ID][const.FACH_ID])) print "DCH demotion Timer:", len( rrc_to_rrc_timer_map[const.DCH_ID][const.FACH_ID]) print util.listToStr( util.quartileResult( rrc_to_rrc_timer_map[const.DCH_ID][const.FACH_ID])) print "FACH demotion Timer:", len( rrc_to_rrc_timer_map[const.FACH_ID][const.PCH_ID]) print util.listToStr( util.quartileResult( rrc_to_rrc_timer_map[const.FACH_ID][const.PCH_ID])) print ">" * 50 print "IP FACH promote Timer:", len( rrc_to_nearest_ip_timer_map[const.FACH_ID][const.DCH_ID]) print util.listToStr( util.quartileResult( rrc_to_nearest_ip_timer_map[const.FACH_ID][const.DCH_ID])) print "IP PCH promote Timer:", len( rrc_to_nearest_ip_timer_map[const.PCH_ID][const.FACH_ID]) print util.listToStr( util.quartileResult( rrc_to_nearest_ip_timer_map[const.PCH_ID][const.FACH_ID])) print "IP DCH demotion Timer:", len( rrc_to_nearest_ip_timer_map[const.DCH_ID][const.FACH_ID]) print util.listToStr( util.quartileResult( rrc_to_nearest_ip_timer_map[const.DCH_ID][const.FACH_ID])) print "IP FACH demotion Timer:", len( rrc_to_nearest_ip_timer_map[const.FACH_ID][const.PCH_ID]) print util.listToStr( util.quartileResult( rrc_to_nearest_ip_timer_map[const.FACH_ID][const.PCH_ID])) print ">" * 50 print "Percentage FACH promote Timer:", len( percentage_map[const.FACH_ID][const.DCH_ID]) print util.listToStr( util.quartileResult(percentage_map[const.FACH_ID][const.DCH_ID])) print "Percentage PCH promote Timer:", len( percentage_map[const.PCH_ID][const.FACH_ID]) print util.listToStr( util.quartileResult(percentage_map[const.PCH_ID][const.FACH_ID])) print "Percentage DCH demotion Timer:", len( percentage_map[const.DCH_ID][const.FACH_ID]) print util.listToStr( util.quartileResult(percentage_map[const.DCH_ID][const.FACH_ID])) print "Percentage FACH demotion Timer:", len( percentage_map[const.FACH_ID][const.PCH_ID]) print util.listToStr( util.quartileResult(percentage_map[const.FACH_ID][const.PCH_ID])) return (rrc_to_rrc_timer_map, rrc_to_nearest_ip_timer_map)
def get_RRC_timer_map(QCATEntries, demote_accurate = False): # use two RRC log ID difference to measure the difference rrc_to_rrc_timer_map = rw.initFullRRCMap({}, const.RRC_ORIG_MAP) # use the RRC log ID to nearest IP packets as metric rrc_to_nearest_ip_timer_map = rw.initFullRRCMap({}, const.RRC_ORIG_MAP) # store the percentage of RRC_to_IP / RRC_to_RRC percentage_map = rw.initFullRRCMap({}, const.RRC_ORIG_MAP) for k in rrc_to_rrc_timer_map: rrc_to_rrc_timer_map[k] = rw.initFullRRCMap([], const.RRC_ORIG_MAP) rrc_to_nearest_ip_timer_map[k] = rw.initFullRRCMap([], const.RRC_ORIG_MAP) percentage_map[k] = rw.initFullRRCMap([], const.RRC_ORIG_MAP) rrcID_domain = set(const.RRC_ORIG_MAP) # check for the previous index priv_rrc_entry_index = None for index in range(len(QCATEntries)): cur_entry = QCATEntries[index] if cur_entry.logID == const.RRC_ID and cur_entry.rrcID in rrcID_domain: if priv_rrc_entry_index: priv_entry = QCATEntries[priv_rrc_entry_index] time_diff = cur_entry.timestamp - priv_entry.timestamp rrc_to_rrc_timer_map[priv_entry.rrcID][cur_entry.rrcID].append(time_diff) # Find the nearest IP log ip_log_index = find_nearest_ip_index(QCATEntries, index - 1, priv_rrc_entry_index + 1) # Assign RRC to IP timer map new_time_diff = time_diff if ip_log_index: ip_log = QCATEntries[ip_log_index] new_time_diff = cur_entry.timestamp - ip_log.timestamp rrc_to_nearest_ip_timer_map[priv_entry.rrcID][cur_entry.rrcID].append(new_time_diff) if time_diff: percentage_map[priv_entry.rrcID][cur_entry.rrcID].append(new_time_diff/time_diff) priv_rrc_entry_index = index if DEBUG: print "FACH promote Timer:", len(rrc_to_rrc_timer_map[const.FACH_ID][const.DCH_ID]) print util.listToStr(util.quartileResult(rrc_to_rrc_timer_map[const.FACH_ID][const.DCH_ID])) print "PCH promote Timer:", len(rrc_to_rrc_timer_map[const.PCH_ID][const.FACH_ID]) print util.listToStr(util.quartileResult(rrc_to_rrc_timer_map[const.PCH_ID][const.FACH_ID])) print "DCH demotion Timer:", len(rrc_to_rrc_timer_map[const.DCH_ID][const.FACH_ID]) print util.listToStr(util.quartileResult(rrc_to_rrc_timer_map[const.DCH_ID][const.FACH_ID])) print "FACH demotion Timer:", len(rrc_to_rrc_timer_map[const.FACH_ID][const.PCH_ID]) print util.listToStr(util.quartileResult(rrc_to_rrc_timer_map[const.FACH_ID][const.PCH_ID])) print ">"*50 print "IP FACH promote Timer:", len(rrc_to_nearest_ip_timer_map[const.FACH_ID][const.DCH_ID]) print util.listToStr(util.quartileResult(rrc_to_nearest_ip_timer_map[const.FACH_ID][const.DCH_ID])) print "IP PCH promote Timer:", len(rrc_to_nearest_ip_timer_map[const.PCH_ID][const.FACH_ID]) print util.listToStr(util.quartileResult(rrc_to_nearest_ip_timer_map[const.PCH_ID][const.FACH_ID])) print "IP DCH demotion Timer:", len(rrc_to_nearest_ip_timer_map[const.DCH_ID][const.FACH_ID]) print util.listToStr(util.quartileResult(rrc_to_nearest_ip_timer_map[const.DCH_ID][const.FACH_ID])) print "IP FACH demotion Timer:", len(rrc_to_nearest_ip_timer_map[const.FACH_ID][const.PCH_ID]) print util.listToStr(util.quartileResult(rrc_to_nearest_ip_timer_map[const.FACH_ID][const.PCH_ID])) print ">"*50 print "Percentage FACH promote Timer:", len(percentage_map[const.FACH_ID][const.DCH_ID]) print util.listToStr(util.quartileResult(percentage_map[const.FACH_ID][const.DCH_ID])) print "Percentage PCH promote Timer:", len(percentage_map[const.PCH_ID][const.FACH_ID]) print util.listToStr(util.quartileResult(percentage_map[const.PCH_ID][const.FACH_ID])) print "Percentage DCH demotion Timer:", len(percentage_map[const.DCH_ID][const.FACH_ID]) print util.listToStr(util.quartileResult(percentage_map[const.DCH_ID][const.FACH_ID])) print "Percentage FACH demotion Timer:", len(percentage_map[const.FACH_ID][const.PCH_ID]) print util.listToStr(util.quartileResult(percentage_map[const.FACH_ID][const.PCH_ID])) return (rrc_to_rrc_timer_map, rrc_to_nearest_ip_timer_map)