Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

221 lines
8.2KB

  1. #!/usr/bin/env python3
  2. import math
  3. import multiprocessing
  4. import os
  5. from argparse import ArgumentParser
  6. import matplotlib
  7. import numpy as np
  8. import pandas as pd
  9. import matplotlib.pyplot as plt
  10. # Using seaborn's style
  11. #plt.style.use('seaborn')
  12. tex_fonts = {
  13. "pgf.texsystem": "lualatex",
  14. # "legend.fontsize": "x-large",
  15. # "figure.figsize": (15, 5),
  16. "axes.labelsize": 15, # "small",
  17. # "axes.titlesize": "x-large",
  18. "xtick.labelsize": 15, # "small",
  19. "ytick.labelsize": 15, # "small",
  20. "legend.fontsize": 15,
  21. "axes.formatter.use_mathtext": True,
  22. "mathtext.fontset": "dejavusans",
  23. }
  24. #plt.rcParams.update(tex_fonts)
  25. def convert_cellid(value):
  26. if isinstance(value, str):
  27. try:
  28. r = int(value.split(" ")[-1].replace("(", "").replace(")", ""))
  29. return r
  30. except Exception as e:
  31. return -1
  32. else:
  33. return int(-1)
  34. if __name__ == "__main__":
  35. parser = ArgumentParser()
  36. parser.add_argument("-s", "--serial_file", required=True, help="Serial csv file.")
  37. parser.add_argument("-p", "--pcap_csv_folder", required=True, help="PCAP csv folder.")
  38. parser.add_argument("--save", required=True, help="Location to save pdf file.")
  39. parser.add_argument(
  40. "-i",
  41. "--interval",
  42. default=10,
  43. type=int,
  44. help="Time interval for rolling window.",
  45. )
  46. args = parser.parse_args()
  47. pcap_csv_list = list()
  48. for filename in os.listdir(args.pcap_csv_folder):
  49. if filename.endswith(".csv") and "tcp" in filename:
  50. pcap_csv_list.append(filename)
  51. counter = 1
  52. if len(pcap_csv_list) == 0:
  53. print("No CSV files found.")
  54. pcap_csv_list.sort(key=lambda x: int(x.split("_")[-1].replace(".csv", "")))
  55. for csv in pcap_csv_list:
  56. print("\rProcessing {} out of {} CSVs.\t({}%)\t".format(counter, len(pcap_csv_list), math.floor(counter/len(pcap_csv_list))))
  57. #try:
  58. transmission_df = pd.read_csv(
  59. "{}{}".format(args.pcap_csv_folder, csv),
  60. dtype=dict(is_retranmission=bool, is_dup_ack=bool),
  61. )
  62. transmission_df["datetime"] = pd.to_datetime(transmission_df["datetime"]) - pd.Timedelta(hours=1)
  63. transmission_df = transmission_df.set_index("datetime")
  64. transmission_df.index = pd.to_datetime(transmission_df.index)
  65. transmission_df = transmission_df.sort_index()
  66. # srtt to [s]
  67. transmission_df["srtt"] = transmission_df["srtt"].apply(lambda x: x / 10**6)
  68. # key for columns and level for index
  69. transmission_df["goodput"] = transmission_df["payload_size"].groupby(pd.Grouper(level="datetime", freq="{}s".format(args.interval))).transform("sum")
  70. transmission_df["goodput"] = transmission_df["goodput"].apply(
  71. lambda x: ((x * 8) / args.interval) / 10**6
  72. )
  73. transmission_df["goodput_rolling"] = transmission_df["payload_size"].rolling("{}s".format(args.interval)).sum()
  74. transmission_df["goodput_rolling"] = transmission_df["goodput_rolling"].apply(
  75. lambda x: ((x * 8) / args.interval) / 10 ** 6
  76. )
  77. # set meta values and remove all not needed columns
  78. cc_algo = transmission_df["congestion_control"].iloc[0]
  79. cc_algo = cc_algo.upper()
  80. transmission_direction = transmission_df["direction"].iloc[0]
  81. #transmission_df = transmission_df.filter(["goodput", "datetime", "ack_rtt", "goodput_rolling", "snd_cwnd"])
  82. # read serial csv
  83. serial_df = pd.read_csv(args.serial_file, converters={"Cell_ID": convert_cellid})
  84. serial_df["datetime"] = pd.to_datetime(serial_df["datetime"]) - pd.Timedelta(hours=1)
  85. serial_df = serial_df.set_index("datetime")
  86. serial_df.index = pd.to_datetime(serial_df.index)
  87. serial_df.sort_index()
  88. #print(serial_df["Cell_ID"])
  89. #serial_df["Cell_ID"] = serial_df["Cell_ID"].apply(
  90. # lambda x: int(x.split(" ")[-1].replace("(", "").replace(")", "")))
  91. transmission_df = pd.merge_asof(
  92. transmission_df,
  93. serial_df,
  94. tolerance=pd.Timedelta("1s"),
  95. right_index=True,
  96. left_index=True,
  97. )
  98. transmission_df.index = transmission_df["arrival_time"]
  99. # replace 0 in RSRQ with Nan
  100. transmission_df["NR5G_RSRQ_(dB)"] = transmission_df["NR5G_RSRQ_(dB)"].replace(0, np.NaN)
  101. transmission_df["RSRQ_(dB)"] = transmission_df["RSRQ_(dB)"].replace(0, np.NaN)
  102. # stacked plot for bandwidth
  103. transmission_df["lte_bw_sum"] = transmission_df["bw_sum"] - transmission_df["NR5G_dl_bw"]
  104. transmission_df["nr_bw_sum"] = transmission_df["NR5G_dl_bw"]
  105. # transmission timeline
  106. scaley = 1.5
  107. scalex = 1.0
  108. plt.title("{} with {}".format(transmission_direction, cc_algo))
  109. fig, ax = plt.subplots(2, 1, figsize=[6.4 * scaley, 4.8 * scalex])
  110. fig.subplots_adjust(right=0.75)
  111. fig.suptitle("{} with {}".format(transmission_direction, cc_algo))
  112. ax0 = ax[0]
  113. ax1 = ax0.twinx()
  114. ax2 = ax0.twinx()
  115. #ax2.spines.right.set_position(("axes", 1.22))
  116. ax00 = ax[1]
  117. ax01 = ax00.twinx()
  118. ax02 = ax00.twinx()
  119. # Plot vertical lines
  120. first = True
  121. lte_handovers = transmission_df["Cell_ID"].dropna().diff()
  122. for index, value in lte_handovers.items():
  123. if value > 0:
  124. if first:
  125. ax00.axvline(index, ymin=0, ymax=1, color="skyblue", label="4G Handover")
  126. first = False
  127. else:
  128. ax00.axvline(index, ymin=0, ymax=1, color="skyblue")
  129. first = True
  130. nr_handovers = transmission_df["NR5G_Cell_ID"].replace(0, np.NaN).dropna().diff()
  131. for index, value in nr_handovers.items():
  132. if value > 0:
  133. if first:
  134. ax00.axvline(index, ymin=0, ymax=1, color="greenyellow", label="5G Handover")
  135. first = False
  136. else:
  137. ax00.axvline(index, ymin=0, ymax=1, color="greenyellow")
  138. ax0.plot(transmission_df["snd_cwnd"].dropna(), color="lime", linestyle="dashed", label="cwnd")
  139. ax1.plot(transmission_df["srtt"].dropna(), color="red", linestyle="dashdot", label="sRTT")
  140. ax2.plot(transmission_df["goodput_rolling"], color="blue", linestyle="solid", label="goodput")
  141. #ax2.plot(transmission_df["goodput"], color="blue", linestyle="solid", label="goodput")
  142. ax01.plot(transmission_df["bw_sum"].dropna(), color="peru", linestyle="solid", label="bandwidth")
  143. ax01.plot(transmission_df["lte_bw_sum"].dropna(), color="lightsteelblue", linestyle="solid", label="4G bandwidth", alpha=.5)
  144. ax01.plot(transmission_df["nr_bw_sum"].dropna(), color="cornflowerblue", linestyle="solid",label="5G bandwidth", alpha=.5)
  145. #ax01.stackplot(transmission_df["arrival_time"].to_list(),
  146. # [transmission_df["lte_bw_sum"].to_list(), transmission_df["nr_bw_sum"].to_list()],
  147. # colors=["lightsteelblue", "cornflowerblue"],
  148. # labels=["4G bandwidth", "5G bandwidth"]
  149. # )
  150. ax02.plot(transmission_df["RSRQ_(dB)"].dropna(), color="purple", linestyle="dotted", label="LTE RSRQ")
  151. ax00.plot(transmission_df["NR5G_RSRQ_(dB)"].dropna(), color="magenta", linestyle="dotted", label="NR RSRQ")
  152. ax2.spines.right.set_position(("axes", 1.1))
  153. ax02.spines.right.set_position(("axes", 1.1))
  154. ax0.set_ylim(0, 5000)
  155. ax1.set_ylim(0, 0.3)
  156. ax2.set_ylim(0, 500)
  157. ax00.set_ylim(-25, 0)
  158. ax01.set_ylim(0, 250)
  159. # second dB axis
  160. ax02.set_ylim(-25, 0)
  161. ax02.set_axis_off()
  162. ax00.set_xlabel("arrival time [s]")
  163. ax2.set_ylabel("Goodput [mbps]")
  164. ax00.set_ylabel("LTE/NR RSRQ [dB]")
  165. #ax02.set_ylabel("LTE RSRQ [dB]")
  166. ax1.set_ylabel("sRTT [s]")
  167. ax0.set_ylabel("cwnd")
  168. ax01.set_ylabel("Bandwidth [MHz]")
  169. fig.legend(loc="lower right")
  170. plt.savefig("{}{}_plot.pdf".format(args.save, csv.replace(".csv", "")))
  171. #except Exception as e:
  172. # print("Error processing file: {}".format(csv))
  173. # print(str(e))
  174. counter += 1
  175. plt.close(fig)
  176. plt.clf()