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…
	
	Add table
		Add a link
		
	
		Reference in a new issue