daemon: added link option to configure buffer, added support in pygui to allow configuring buffer
This commit is contained in:
parent
d95c2ec05f
commit
a35e91aeba
8 changed files with 68 additions and 5 deletions
|
@ -128,6 +128,7 @@ def add_link_data(
|
|||
options.mer = options_proto.mer
|
||||
options.burst = options_proto.burst
|
||||
options.mburst = options_proto.mburst
|
||||
options.buffer = options_proto.buffer
|
||||
options.unidirectional = options_proto.unidirectional
|
||||
options.key = options_proto.key
|
||||
return iface1_data, iface2_data, options, link_type
|
||||
|
@ -329,6 +330,7 @@ def convert_link_options(options_data: LinkOptions) -> core_pb2.LinkOptions:
|
|||
burst=options_data.burst,
|
||||
delay=options_data.delay,
|
||||
dup=options_data.dup,
|
||||
buffer=options_data.buffer,
|
||||
unidirectional=options_data.unidirectional,
|
||||
)
|
||||
|
||||
|
|
|
@ -972,6 +972,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
mburst=options_proto.mburst,
|
||||
unidirectional=options_proto.unidirectional,
|
||||
key=options_proto.key,
|
||||
buffer=options_proto.buffer,
|
||||
)
|
||||
session.update_link(node1_id, node2_id, iface1_id, iface2_id, options)
|
||||
iface1 = InterfaceData(id=iface1_id)
|
||||
|
|
|
@ -457,6 +457,7 @@ class LinkOptions:
|
|||
delay: int = 0
|
||||
dup: int = 0
|
||||
unidirectional: bool = False
|
||||
buffer: int = 0
|
||||
|
||||
@classmethod
|
||||
def from_proto(cls, proto: core_pb2.LinkOptions) -> "LinkOptions":
|
||||
|
@ -471,6 +472,7 @@ class LinkOptions:
|
|||
delay=proto.delay,
|
||||
dup=proto.dup,
|
||||
unidirectional=proto.unidirectional,
|
||||
buffer=proto.buffer,
|
||||
)
|
||||
|
||||
def to_proto(self) -> core_pb2.LinkOptions:
|
||||
|
@ -485,6 +487,7 @@ class LinkOptions:
|
|||
delay=self.delay,
|
||||
dup=self.dup,
|
||||
unidirectional=self.unidirectional,
|
||||
buffer=self.buffer,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -172,6 +172,7 @@ class LinkOptions:
|
|||
mburst: int = None
|
||||
unidirectional: int = None
|
||||
key: int = None
|
||||
buffer: int = None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
@ -49,12 +49,14 @@ class LinkConfigurationDialog(Dialog):
|
|||
self.jitter: tk.StringVar = tk.StringVar()
|
||||
self.loss: tk.StringVar = tk.StringVar()
|
||||
self.duplicate: tk.StringVar = tk.StringVar()
|
||||
self.buffer: tk.StringVar = tk.StringVar()
|
||||
|
||||
self.down_bandwidth: tk.StringVar = tk.StringVar()
|
||||
self.down_delay: tk.StringVar = tk.StringVar()
|
||||
self.down_jitter: tk.StringVar = tk.StringVar()
|
||||
self.down_loss: tk.StringVar = tk.StringVar()
|
||||
self.down_duplicate: tk.StringVar = tk.StringVar()
|
||||
self.down_buffer: tk.StringVar = tk.StringVar()
|
||||
|
||||
self.color: tk.StringVar = tk.StringVar(value=self.edge.color)
|
||||
self.color_button: Optional[tk.Button] = None
|
||||
|
@ -187,6 +189,19 @@ class LinkConfigurationDialog(Dialog):
|
|||
entry.grid(row=row, column=2, sticky=tk.EW, pady=PADY)
|
||||
row = row + 1
|
||||
|
||||
label = ttk.Label(frame, text="Buffer (Packets)")
|
||||
label.grid(row=row, column=0, sticky=tk.EW)
|
||||
entry = validation.PositiveIntEntry(
|
||||
frame, empty_enabled=False, textvariable=self.buffer
|
||||
)
|
||||
entry.grid(row=row, column=1, sticky=tk.EW, pady=PADY)
|
||||
if not self.is_symmetric:
|
||||
entry = validation.PositiveIntEntry(
|
||||
frame, empty_enabled=False, textvariable=self.down_buffer
|
||||
)
|
||||
entry.grid(row=row, column=2, sticky=tk.EW, pady=PADY)
|
||||
row = row + 1
|
||||
|
||||
label = ttk.Label(frame, text="Color")
|
||||
label.grid(row=row, column=0, sticky=tk.EW)
|
||||
self.color_button = tk.Button(
|
||||
|
@ -224,9 +239,15 @@ class LinkConfigurationDialog(Dialog):
|
|||
jitter = get_int(self.jitter)
|
||||
delay = get_int(self.delay)
|
||||
duplicate = get_int(self.duplicate)
|
||||
buffer = get_int(self.buffer)
|
||||
loss = get_float(self.loss)
|
||||
options = LinkOptions(
|
||||
bandwidth=bandwidth, jitter=jitter, delay=delay, dup=duplicate, loss=loss
|
||||
bandwidth=bandwidth,
|
||||
jitter=jitter,
|
||||
delay=delay,
|
||||
dup=duplicate,
|
||||
loss=loss,
|
||||
buffer=buffer,
|
||||
)
|
||||
link.options = options
|
||||
iface1_id = link.iface1.id if link.iface1 else None
|
||||
|
@ -243,6 +264,7 @@ class LinkConfigurationDialog(Dialog):
|
|||
down_jitter = get_int(self.down_jitter)
|
||||
down_delay = get_int(self.down_delay)
|
||||
down_duplicate = get_int(self.down_duplicate)
|
||||
down_buffer = get_int(self.down_buffer)
|
||||
down_loss = get_float(self.down_loss)
|
||||
options = LinkOptions(
|
||||
bandwidth=down_bandwidth,
|
||||
|
@ -250,6 +272,7 @@ class LinkConfigurationDialog(Dialog):
|
|||
delay=down_delay,
|
||||
dup=down_duplicate,
|
||||
loss=down_loss,
|
||||
buffer=down_buffer,
|
||||
unidirectional=True,
|
||||
)
|
||||
self.edge.asymmetric_link = Link(
|
||||
|
@ -304,6 +327,7 @@ class LinkConfigurationDialog(Dialog):
|
|||
self.duplicate.set(str(link.options.dup))
|
||||
self.loss.set(str(link.options.loss))
|
||||
self.delay.set(str(link.options.delay))
|
||||
self.buffer.set(str(link.options.buffer))
|
||||
if not self.is_symmetric:
|
||||
asym_link = self.edge.asymmetric_link
|
||||
self.down_bandwidth.set(str(asym_link.options.bandwidth))
|
||||
|
@ -311,3 +335,4 @@ class LinkConfigurationDialog(Dialog):
|
|||
self.down_duplicate.set(str(asym_link.options.dup))
|
||||
self.down_loss.set(str(asym_link.options.loss))
|
||||
self.down_delay.set(str(asym_link.options.delay))
|
||||
self.down_buffer.set(str(asym_link.options.buffer))
|
||||
|
|
|
@ -456,6 +456,7 @@ class CoreNetwork(CoreNetworkBase):
|
|||
iface.setparam("loss", options.loss),
|
||||
iface.setparam("duplicate", options.dup),
|
||||
iface.setparam("jitter", options.jitter),
|
||||
iface.setparam("buffer", options.buffer),
|
||||
]
|
||||
)
|
||||
if not changed:
|
||||
|
@ -470,6 +471,7 @@ class CoreNetwork(CoreNetworkBase):
|
|||
options.loss is None or options.loss <= 0,
|
||||
options.dup is None or options.dup <= 0,
|
||||
options.bandwidth is None or options.bandwidth <= 0,
|
||||
options.buffer is None or options.buffer <= 0,
|
||||
]
|
||||
):
|
||||
if not iface.getparam("has_netem"):
|
||||
|
@ -483,7 +485,9 @@ class CoreNetwork(CoreNetworkBase):
|
|||
if options.bandwidth is not None:
|
||||
limit = 1000
|
||||
bw = options.bandwidth / 1000
|
||||
if options.delay and options.bandwidth:
|
||||
if options.buffer is not None and options.buffer > 0:
|
||||
limit = options.buffer
|
||||
elif options.delay and options.bandwidth:
|
||||
delay = options.delay / 1000
|
||||
limit = max(2, math.ceil((2 * bw * delay) / (8 * iface.mtu)))
|
||||
netem += f" rate {bw}kbit"
|
||||
|
|
|
@ -777,6 +777,7 @@ message LinkOptions {
|
|||
int64 delay = 8;
|
||||
int32 dup = 9;
|
||||
bool unidirectional = 10;
|
||||
int32 buffer = 11;
|
||||
}
|
||||
|
||||
message Interface {
|
||||
|
|
|
@ -83,6 +83,7 @@ class TestLinks:
|
|||
loss = 25
|
||||
dup = 25
|
||||
jitter = 10
|
||||
buffer = 100
|
||||
node1 = session.add_node(CoreNode)
|
||||
node2 = session.add_node(SwitchNode)
|
||||
iface1_data = ip_prefixes.create_iface(node1)
|
||||
|
@ -93,10 +94,16 @@ class TestLinks:
|
|||
assert iface1.getparam("loss") != loss
|
||||
assert iface1.getparam("duplicate") != dup
|
||||
assert iface1.getparam("jitter") != jitter
|
||||
assert iface1.getparam("buffer") != buffer
|
||||
|
||||
# when
|
||||
options = LinkOptions(
|
||||
delay=delay, bandwidth=bandwidth, loss=loss, dup=dup, jitter=jitter
|
||||
delay=delay,
|
||||
bandwidth=bandwidth,
|
||||
loss=loss,
|
||||
dup=dup,
|
||||
jitter=jitter,
|
||||
buffer=buffer,
|
||||
)
|
||||
session.update_link(
|
||||
node1.id, node2.id, iface1_id=iface1_data.id, options=options
|
||||
|
@ -108,6 +115,7 @@ class TestLinks:
|
|||
assert iface1.getparam("loss") == loss
|
||||
assert iface1.getparam("duplicate") == dup
|
||||
assert iface1.getparam("jitter") == jitter
|
||||
assert iface1.getparam("buffer") == buffer
|
||||
|
||||
def test_update_net_to_node(self, session: Session, ip_prefixes: IpPrefixes):
|
||||
# given
|
||||
|
@ -116,6 +124,7 @@ class TestLinks:
|
|||
loss = 25
|
||||
dup = 25
|
||||
jitter = 10
|
||||
buffer = 100
|
||||
node1 = session.add_node(SwitchNode)
|
||||
node2 = session.add_node(CoreNode)
|
||||
iface2_data = ip_prefixes.create_iface(node2)
|
||||
|
@ -126,10 +135,16 @@ class TestLinks:
|
|||
assert iface2.getparam("loss") != loss
|
||||
assert iface2.getparam("duplicate") != dup
|
||||
assert iface2.getparam("jitter") != jitter
|
||||
assert iface2.getparam("buffer") != buffer
|
||||
|
||||
# when
|
||||
options = LinkOptions(
|
||||
delay=delay, bandwidth=bandwidth, loss=loss, dup=dup, jitter=jitter
|
||||
delay=delay,
|
||||
bandwidth=bandwidth,
|
||||
loss=loss,
|
||||
dup=dup,
|
||||
jitter=jitter,
|
||||
buffer=buffer,
|
||||
)
|
||||
session.update_link(
|
||||
node1.id, node2.id, iface2_id=iface2_data.id, options=options
|
||||
|
@ -141,6 +156,7 @@ class TestLinks:
|
|||
assert iface2.getparam("loss") == loss
|
||||
assert iface2.getparam("duplicate") == dup
|
||||
assert iface2.getparam("jitter") == jitter
|
||||
assert iface2.getparam("buffer") == buffer
|
||||
|
||||
def test_update_ptp(self, session: Session, ip_prefixes: IpPrefixes):
|
||||
# given
|
||||
|
@ -149,6 +165,7 @@ class TestLinks:
|
|||
loss = 25
|
||||
dup = 25
|
||||
jitter = 10
|
||||
buffer = 100
|
||||
node1 = session.add_node(CoreNode)
|
||||
node2 = session.add_node(CoreNode)
|
||||
iface1_data = ip_prefixes.create_iface(node1)
|
||||
|
@ -161,15 +178,22 @@ class TestLinks:
|
|||
assert iface1.getparam("loss") != loss
|
||||
assert iface1.getparam("duplicate") != dup
|
||||
assert iface1.getparam("jitter") != jitter
|
||||
assert iface1.getparam("buffer") != buffer
|
||||
assert iface2.getparam("delay") != delay
|
||||
assert iface2.getparam("bw") != bandwidth
|
||||
assert iface2.getparam("loss") != loss
|
||||
assert iface2.getparam("duplicate") != dup
|
||||
assert iface2.getparam("jitter") != jitter
|
||||
assert iface2.getparam("buffer") != buffer
|
||||
|
||||
# when
|
||||
options = LinkOptions(
|
||||
delay=delay, bandwidth=bandwidth, loss=loss, dup=dup, jitter=jitter
|
||||
delay=delay,
|
||||
bandwidth=bandwidth,
|
||||
loss=loss,
|
||||
dup=dup,
|
||||
jitter=jitter,
|
||||
buffer=buffer,
|
||||
)
|
||||
session.update_link(node1.id, node2.id, iface1_data.id, iface2_data.id, options)
|
||||
|
||||
|
@ -179,11 +203,13 @@ class TestLinks:
|
|||
assert iface1.getparam("loss") == loss
|
||||
assert iface1.getparam("duplicate") == dup
|
||||
assert iface1.getparam("jitter") == jitter
|
||||
assert iface1.getparam("buffer") == buffer
|
||||
assert iface2.getparam("delay") == delay
|
||||
assert iface2.getparam("bw") == bandwidth
|
||||
assert iface2.getparam("loss") == loss
|
||||
assert iface2.getparam("duplicate") == dup
|
||||
assert iface2.getparam("jitter") == jitter
|
||||
assert iface2.getparam("buffer") == buffer
|
||||
|
||||
def test_delete_ptp(self, session: Session, ip_prefixes: IpPrefixes):
|
||||
# given
|
||||
|
|
Loading…
Reference in a new issue