|
| 1 | +""" |
| 2 | +Author(s): Kamil Vojanec <[email protected]> |
| 3 | +
|
| 4 | +Copyright: (C) 2024 CESNET, z.s.p.o. |
| 5 | +
|
| 6 | +Common conversion functions. |
| 7 | +""" |
| 8 | + |
| 9 | +import re |
| 10 | +from enum import StrEnum |
| 11 | + |
| 12 | + |
| 13 | +""" |
| 14 | +Extra bytes added to L2 packet size when converting: |
| 15 | +7B preamble + 1B SoF + 4B CRC + 12B minimal IFG. |
| 16 | +""" |
| 17 | +PACKET_EXTRA_BYTES = 24 |
| 18 | + |
| 19 | + |
| 20 | +def mbps_to_mpps(thrpt_mbps: float, pkt_len: int): |
| 21 | + """Convert megabits per second throughput into megapackets per second. |
| 22 | +
|
| 23 | + Parameters |
| 24 | + ---------- |
| 25 | + thrpt_mbps : float |
| 26 | + Throughput value in megabits per second (on L1). |
| 27 | + pkt_len : int |
| 28 | + Individual packet length in bytes (on L2 without FCS). |
| 29 | +
|
| 30 | + Returns |
| 31 | + ------- |
| 32 | + float |
| 33 | + Throughput value in megapackets per second. |
| 34 | + """ |
| 35 | + |
| 36 | + return thrpt_mbps / ((pkt_len + PACKET_EXTRA_BYTES) * 8) |
| 37 | + |
| 38 | + |
| 39 | +def mpps_to_mbps(thrpt_mpps: float, pkt_len: int): |
| 40 | + """Convert megapackets per second throughput into megabits per second. |
| 41 | +
|
| 42 | + Parameters |
| 43 | + ---------- |
| 44 | + thrpt_mpps : float |
| 45 | + Throughput value in megapackets per second. |
| 46 | + pkt_len : int |
| 47 | + Individual packet length in bytes (on L2 without FCS). |
| 48 | +
|
| 49 | + Returns |
| 50 | + ------- |
| 51 | + float |
| 52 | + Throughput value in megabits per second (on L1). |
| 53 | + """ |
| 54 | + |
| 55 | + return thrpt_mpps * ((pkt_len + PACKET_EXTRA_BYTES) * 8) |
| 56 | + |
| 57 | + |
| 58 | +class UnitsPolicy(StrEnum): |
| 59 | + """Units policy to be used in size conversion. |
| 60 | + Used to avoid confusion when comparing decimal and binary |
| 61 | + size values. |
| 62 | + """ |
| 63 | + |
| 64 | + """SI defines base 10 prefixes for conversion. |
| 65 | + See: https://en.wikipedia.org/wiki/Metric_prefix#List_of_SI_prefixes |
| 66 | + """ |
| 67 | + SI = "si" |
| 68 | + |
| 69 | + """IEC Defines binary prefixes for conversion. |
| 70 | + See: https://en.wikipedia.org/wiki/Binary_prefix#Prefixes |
| 71 | + """ |
| 72 | + IEC = "iec" |
| 73 | + |
| 74 | + |
| 75 | +def parse_size( |
| 76 | + size_str: str, |
| 77 | + units: UnitsPolicy = UnitsPolicy.SI, |
| 78 | +) -> int: |
| 79 | + """Parse size - value with k, M, G suffix into |
| 80 | + an integer representing the size in bytes. |
| 81 | +
|
| 82 | + Parameters |
| 83 | + ---------- |
| 84 | + size_str : str |
| 85 | + Size string to be parsed. Contains a value |
| 86 | + with a unit (k, M, G, T). |
| 87 | + units : UnitsPolicy |
| 88 | + Specify the unit used for conversion. |
| 89 | +
|
| 90 | + Returns |
| 91 | + ------- |
| 92 | + int |
| 93 | + Integer size in bytes. |
| 94 | + """ |
| 95 | + |
| 96 | + # First match group matches the value. |
| 97 | + # Second match group matches the unit. |
| 98 | + reg = r"(\d+)\s*([kMGT])" |
| 99 | + match = re.match(reg, size_str).groups() |
| 100 | + |
| 101 | + assert len(match) == 2, "Must match only the value and unit" |
| 102 | + |
| 103 | + mult_table = { |
| 104 | + UnitsPolicy.SI: { |
| 105 | + "k": 1e3, |
| 106 | + "M": 1e6, |
| 107 | + "G": 1e9, |
| 108 | + "T": 1e12, |
| 109 | + }, |
| 110 | + UnitsPolicy.IEC: { |
| 111 | + "k": 2**10, |
| 112 | + "M": 2**20, |
| 113 | + "G": 2**30, |
| 114 | + "T": 2**40, |
| 115 | + }, |
| 116 | + } |
| 117 | + |
| 118 | + val = int(match[0]) |
| 119 | + mult = mult_table[units][match[1]] |
| 120 | + return val * mult |
0 commit comments