pcie-model / model /eth.py
Rolf Neugebauer
eth: Tweak Ethernet calculation
7554275
Raw
History Blame Contribute Delete
5.46 kB
## Copyright (C) 2015-2018 Rolf Neugebauer. All rights reserved.
## Copyright (C) 2015 Netronome Systems, Inc. All rights reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
"""Some general function and data to calculate rates for Ethernet"""
# pylint: disable=bad-whitespace
# pylint: disable=invalid-name
# pylint: disable=too-many-instance-attributes
import sys
# Configuration options
Variants = ['400GigE', '200GigE', '100GigE', '50GigE', '40GigE', '25GigE', '10GigE', 'GigE']
# Various fields on the wire, all in Bytes
Pre = 7 # Preamble
SOF = 1 # Start of Frame indicator
Hdr = 14 # Header
Hdr_VLAN = 18 # Header including 802.18 Tag
MinPayLoad = 46 # Minimum Payload size
MinPayLoad_VLAN = 42 # Minimum Payload size
CRC = 4 # Checksum
IFG = 12 # Interframe Gap
IFG_GigE = 8 # Optionally reduce IFG for 1GigE
IFG_10GigE = 5 # Optionally reduce IFG for 10GigE
IFG_25GigE = 5 # Optionally reduce IFG for 10GigE
IFG_40plusGigE = 1 # Optionally reduce IFG for 40GigE
class Cfg():
"""A class representing an Ethernet link. Allows to get
various metrics based on a specific configuration"""
def __init__(self, variant='40GigE', vlan=True, ifg_min=False):
"""Instantiate a Ethernet config.
- variant: One of the Variants
- vlan: Should the frames contain a VLAN tag
- ifg_min: minimum allowed interframe gap or standard
"""
if variant not in Variants:
raise Exception("Unsupported ethernet variant: %s" % variant)
self.variant = variant
self.vlan = vlan
self.ifg_min = ifg_min
if variant == '400GigE':
self.rate = 400 * 1000 * 1000 * 1000
elif variant == '200GigE':
self.rate = 200 * 1000 * 1000 * 1000
elif variant == '100GigE':
self.rate = 100 * 1000 * 1000 * 1000
elif variant == '50GigE':
self.rate = 50 * 1000 * 1000 * 1000
elif variant == '40GigE':
self.rate = 40 * 1000 * 1000 * 1000
elif variant == '25GigE':
self.rate = 25 * 1000 * 1000 * 1000
elif variant == '10GigE':
self.rate = 10 * 1000 * 1000 * 1000
elif variant == 'GigE':
self.rate = 1000 * 1000 * 1000
self.pre_sz = Pre + SOF
if vlan:
self.hdr_sz = Hdr_VLAN
self.min_pay = MinPayLoad_VLAN
else:
self.hdr_sz = Hdr
self.min_pay = MinPayLoad
if ifg_min:
if variant == 'GigE':
self.trail_sz = IFG_GigE
elif variant == '10GigE':
self.trail_sz = IFG_10GigE
elif variant == '25GigE':
self.trail_sz = IFG_25GigE
else:
self.trail_sz = IFG_40plusGigE
else:
self.trail_sz = IFG
self.crc_sz = CRC
def pps(self, payload):
"""Return the rate of packets for a given payload"""
if payload < self.min_pay:
p_sz = self.min_pay
else:
p_sz = payload
s = self.pre_sz + self.hdr_sz + p_sz + self.crc_sz + self.trail_sz
return self.rate / float(s * 8)
def bps(self, payload):
"Bits per second of payload bits"
p = self.pps(payload)
return p * payload * 8
def pps_ex(self, frame_sz):
"""Return the rate of packets for a given payload. Assume
@frame_sz includes ethernet header and CRC"""
s = frame_sz - self.hdr_sz - self.crc_sz
return self.pps(s)
def bps_ex(self, frame_sz):
"""Bits per second of payload bits for a given payload. Assume
@frame_sz includes ethernet header and CRC"""
p = self.pps_ex(frame_sz)
return p * frame_sz * 8
def us_ex(self, frame_sz):
"""Calculate how long (in us) it takes to transmit a frame
of a given size. Assume @frame_sz includes ethernet header and CRC."""
s = (frame_sz + self.pre_sz + self.trail_sz)
return (float(s * 8)/self.rate) * 1000 * 1000
if __name__ == '__main__':
variant = '100GigE'
if len(sys.argv) == 2:
variant = sys.argv[1]
# not much of a test
e = Cfg(variant)
print("%4s %9s %11s %s" % ("sz", "pps", "bps", "ns"))
for sz in [64, 128, 256, 512, 1024, 1518, 4096, 9000]:
print("%4d %9d %11d %.2f" % (sz, e.pps_ex(sz), e.bps_ex(sz), 1000.0 * e.us_ex(sz)))
dat = open("eth.dat", "w")
dat.write("\"Frame Size(Bytes)\" "
"\"Packets/s\" "
"\"Bits/s\" "
"\"Gb/s\" "
"\"Time (us)\" "
"\n")
for sz in range(64, 1519):
_pps = e.pps_ex(sz)
bw = e.bps_ex(sz)
gbs = float(bw) / (1000 * 1000 * 1000)
us = e.us_ex(sz)
dat.write("%d %f %f %f %f\n" % (sz, _pps, bw, gbs, us))