From a7f38dc162b2b194cfe84a98d587888ca4033cde Mon Sep 17 00:00:00 2001 From: Loic Guegan Date: Tue, 22 Aug 2023 18:18:32 +0200 Subject: [PATCH] Debug and improve interference detection --- esds/node.py | 8 +-- esds/rcode.py | 4 +- esds/simulator.py | 71 +++++++++---------- .../out | 13 ++++ .../platform.yaml | 17 +++++ .../receiver.py | 9 +++ .../sender.py | 11 +++ tests/api_send_wlan0_2s1r/out | 13 +++- tests/api_send_wlan0_2s1r/receiver.py | 5 +- tests/api_send_wlan0_2s1r/sender.py | 5 +- tests/hidden_node_2s1r/out | 7 +- tests/hidden_node_2s1r/receiver.py | 7 +- tests/hidden_node_2s1r/sender.py | 3 +- 13 files changed, 119 insertions(+), 54 deletions(-) create mode 100644 tests/api_send_interferences_wlan0_ncom_2s1r/out create mode 100644 tests/api_send_interferences_wlan0_ncom_2s1r/platform.yaml create mode 100644 tests/api_send_interferences_wlan0_ncom_2s1r/receiver.py create mode 100644 tests/api_send_interferences_wlan0_ncom_2s1r/sender.py diff --git a/esds/node.py b/esds/node.py index 4bfae71..bca9a5f 100644 --- a/esds/node.py +++ b/esds/node.py @@ -170,9 +170,9 @@ class Node: self.rargs=interface self["state"]="call_blocking" self.wait_ack(["receive"]) - data,start_at,end_at=self["interfaces"][interface].get() + data,start_at,end_at,rcode=self["interfaces"][interface].get() self.plugin_notify("receive_return",(interface,data,start_at,end_at)) - return (RCode.SUCCESS,data) + return (rcode,data) def receivet(self,interface, timeout): if interface not in self["interfaces"]: @@ -196,9 +196,9 @@ class Node: self["request"]="timeout_remove" self["state"]="call_non_blocking" self.wait_ack(["timeout_remove"]) - data,start_at,end_at=self["interfaces"][interface].get() + data,start_at,end_at,rcode=self["interfaces"][interface].get() self.plugin_notify("receivet_return",(interface,data,start_at,end_at)) - result=(RCode.SUCCESS,data) + result=(rcode,data) return result def wait_ack(self, ack_types): diff --git a/esds/rcode.py b/esds/rcode.py index 6600177..1a7ebad 100644 --- a/esds/rcode.py +++ b/esds/rcode.py @@ -5,6 +5,6 @@ class RCode(Enum): FAIL = 1 TIMEOUT_EXPIRE = 2 RECEIVER_TURNED_OFF = 3 - RECEIVER_UNAVAILABLE = 4 - UNKNOWN = 5 + UNKNOWN = 4 + INTERFERENCES = 5 diff --git a/esds/simulator.py b/esds/simulator.py index cdc85d3..fcc759b 100644 --- a/esds/simulator.py +++ b/esds/simulator.py @@ -9,7 +9,7 @@ class Simulator: Flow-Level Discrete Event Simulator for Cyber-Physical Systems The general format for an event is (type,timestamp,event,priority) Event types: - - 0 send (0,timestamp,(src,dst,interface,data,datasize,duration,datasize_remaining,start_timestamp, perform_delivery, receiver_required), 2) + - 0 send (0,timestamp,(src,dst,interface,data,datasize,duration,datasize_remaining,start_timestamp, perform_delivery, receiver_required, RCode), 2) - 1 timeout (1,timestamp,node_id,3) - 2 breakpoint_manual (2,timestamp,0,1) - 3 breakpoint_auto (3,timestamp,0,1) @@ -57,7 +57,7 @@ class Simulator: if int(event[0]) == 0: cur_event=event[2] ts=float(event[1]) - src_id,dst_id,interface, data, datasize,duration, datasize_remaining,start_at,perform_delivery,receiver_required=cur_event + src_id,dst_id,interface, data, datasize,duration, datasize_remaining,start_at,perform_delivery,receiver_required,rcode=cur_event new_bw=netmat[interface]["bandwidth"][int(src_id),int(dst_id)] old_bw=self.netmat[interface]["bandwidth"][int(src_id),int(dst_id)] new_lat=netmat[interface]["latency"][int(src_id),int(dst_id)] @@ -185,7 +185,7 @@ class Simulator: selector=list() for event in self.events: if event[0]==0: - src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required=event[2] + src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required,rcode=event[2] is_wired=self.netmat[interface]["is_wired"] is_wireless=not is_wired if src_id == node_id: @@ -206,7 +206,7 @@ class Simulator: # Update sharing of wired communications and build sender to notify set senders_to_notify=set() for event in self.events[selector]: - src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required=event[2] + src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required,rcode=event[2] if self.netmat[interface]["is_wired"]: # If node is sender if src_id == node_id: @@ -216,7 +216,7 @@ class Simulator: senders_to_notify.add(src_id) # We do not notify sender here since it may change the event list (invalidate selector) # Notify plugins for event in self.events[selector]: - src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required=event[2] + src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required,rcode=event[2] if self.netmat[interface]["is_wired"]: self.notify_node_plugins(self.nodes[src_id], "on_communication_end", event) self.notify_node_plugins(self.nodes[dst_id], "on_communication_end", event) @@ -261,32 +261,21 @@ class Simulator: new events and existing events. """ status=False - selector=list() - notify=set() for event in self.events: event_type=event[0] com=event[2] if event_type==0 and com[2] == interface: com_sender=int(com[0]) com_receiver=int(com[1]) - select=False - if receiver==com_sender: + # All cases where interferences occurs: + receiver_is_sending=(receiver==com_sender) + receiver_is_receiving=(receiver==com_receiver and sender!=com_sender) # We check also if its not our own communication + sender_is_receiving=(sender==com_receiver and com_sender!=com_sender) # We check also if its not our own communication + # Apply rules: + if receiver_is_sending or receiver_is_receiving or sender_is_receiving: status=True - notify.add(receiver) - elif receiver==com_receiver: - status=True - select=True - notify.add(receiver) - if sender==com_receiver and com_sender != com_receiver: - select=True - notify.add(sender) - selector.append(select) - else: - selector.append(False) - if len(selector) != 0: - self.events=self.events[~np.array(selector)] - for node in notify: - self.log("Interferences on "+interface,node=self.nodes[node]) + if com_sender != com_receiver: + event[2][10]=RCode.INTERFERENCES # Tell the sender/receiver interferences occured return status def sync_node_blocking(self, node): @@ -301,9 +290,10 @@ class Simulator: if not (dst >=0 and dst <=len(self.nodes)): self.log("Invalid dst used in send() or sendt(), node "+str(dst)+" not found", node=node) exit(1) - if not self.communicate(interface, node.node_id, dst, data, datasize,receiver_required): + code=self.communicate(interface, node.node_id, dst, data, datasize, receiver_required) + if code!=RCode.SUCCESS: node["state"]="running" - node.rqueue.put(("send",RCode.RECEIVER_UNAVAILABLE)) + node.rqueue.put(("send",code)) # Do not forget to collect the next event (since current event did not happend) # Be careful in node implementation to have no infinite loop when receiver_required=True self.sync_node_non_blocking(node) @@ -336,11 +326,11 @@ class Simulator: exit(1) self.log("Send "+str(datasize)+" bytes to n"+str(dst)+" on "+interface,node=nsrc) if not self.nodes[dst]["turned_on"] and receiver_required: - return(False) + return(RCode.RECEIVER_TURNED_OFF) self.update_sharing(dst,1,interface) # Update sharing first # Note that in the following we send more data than expected to handle bandwidth sharing (datasize*8*sharing): duration=datasize*8/(self.netmat[interface]["bandwidth"][src,dst]/self.sharing[interface][dst])+self.netmat[interface]["latency"][src,dst] - self.add_event(0,duration+self.time,(src,dst,interface,data,datasize,duration,datasize,self.time,self.nodes[dst]["turned_on"],receiver_required)) + self.add_event(0,duration+self.time,(src,dst,interface,data,datasize,duration,datasize,self.time,self.nodes[dst]["turned_on"],receiver_required,RCode.SUCCESS)) else: self.log("Send "+str(datasize)+" bytes on "+interface,node=nsrc) for dst in self.list_receivers(nsrc,interface): @@ -349,12 +339,12 @@ class Simulator: if src == dst: # This event (where src == dst) is used to notify the sender when data is received! # Correspond to the diagonal of the network matrices (bandwidth and latency) - self.add_event(0,duration+self.time,(src,dst,interface,data,datasize,duration,datasize,self.time,True,False)) - elif not self.interferences: - self.add_event(0,duration+self.time,(src,dst,interface,data,datasize,duration,datasize,self.time,True,False)) - elif not self.handle_interferences(src,dst, interface): - self.add_event(0,duration+self.time,(src,dst,interface,data,datasize,duration,datasize,self.time,True,False)) - return(True) + self.add_event(0,duration+self.time,(src,dst,interface,data,datasize,duration,datasize,self.time,True,False,RCode.SUCCESS)) + else: + self.add_event(0,duration+self.time,(src,dst,interface,data,datasize,duration,datasize,self.time,True,False,RCode.SUCCESS)) + if self.interferences: + self.handle_interferences(src,dst, interface) + return(RCode.SUCCESS) def list_receivers(self,node,interface): """ Deduce reachable receivers from the bandwidth matrix (sender is included in the list!) @@ -422,12 +412,12 @@ class Simulator: content=event[2] # Event content self.events=np.delete(self.events,0,0) # Consume events NOW! not at the end of the loop (event list may change in between) if event_type == 0: - src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required=content + src_id,dst_id,interface, data, datasize,duration,datasize_remaining,start_at,perform_delivery,receiver_required,rcode=content src=self.nodes[int(src_id)] dst=self.nodes[int(dst_id)] if self.netmat[interface]["is_wired"]: if perform_delivery: - dst["interfaces"][interface].put((data,start_at,self.time)) + dst["interfaces"][interface].put((data,start_at,self.time,rcode)) dst["interfaces_queue_size"][interface]+=1 self.log("Receive "+str(datasize)+" bytes on "+interface,node=dst) # If node is receiving makes it consume (this way if there is a timeout, it will be removed!) @@ -446,9 +436,12 @@ class Simulator: else: if src.node_id != dst.node_id: if perform_delivery: - dst["interfaces"][interface].put((data,start_at,self.time)) + dst["interfaces"][interface].put((data,start_at,self.time,rcode)) dst["interfaces_queue_size"][interface]+=1 - self.log("Receive "+str(datasize)+" bytes on "+interface,node=dst) + if rcode==RCode.SUCCESS: + self.log("Receive "+str(datasize)+" bytes on "+interface,node=dst) + else: + self.log("Receive "+str(datasize)+" bytes on "+interface+" with errors",node=dst) # If node is receiving makes it consume (this way if there is a timeout, it will be removed!) if dst["state"] == "call_blocking" and dst["request"] == "receive": dst["interfaces_queue_size"][interface]-=1 @@ -458,7 +451,7 @@ class Simulator: self.notify_node_plugins(dst, "on_communication_end", event) else: src["state"]="running" - src.rqueue.put(("send",RCode.SUCCESS)) + src.rqueue.put(("send",rcode)) self.sync_node_non_blocking(src,timeout_remove_only=True) self.notify_node_plugins(src, "on_communication_end", event) elif event_type == 1: # Timeout diff --git a/tests/api_send_interferences_wlan0_ncom_2s1r/out b/tests/api_send_interferences_wlan0_ncom_2s1r/out new file mode 100644 index 0000000..5f5d74b --- /dev/null +++ b/tests/api_send_interferences_wlan0_ncom_2s1r/out @@ -0,0 +1,13 @@ +[t=0.000,src=n1,grp=def] Send 50 bytes on wlan0 +[t=0.000,src=n2,grp=def] Send 50 bytes on wlan0 +[t=133.333,src=n0,grp=def] Receive 50 bytes on wlan0 with errors +[t=133.333,src=n2,grp=def] Receive 50 bytes on wlan0 with errors +[t=133.333,src=n0,grp=def] Receive 50 bytes on wlan0 with errors +[t=133.333,src=n1,grp=def] Receive 50 bytes on wlan0 with errors +[t=133.333,src=n0,grp=def] Receiver receive code 1 is RCode.INTERFERENCES +[t=133.333,src=n1,grp=def] Sender send code is RCode.SUCCESS +[t=133.333,src=n2,grp=def] Sender send code is RCode.SUCCESS +[t=133.333,src=n0,grp=def] Receiver receive code 2 is RCode.INTERFERENCES +[t=133.333,src=n1,grp=def] Sender receive code is RCode.INTERFERENCES +[t=133.333,src=n2,grp=def] Sender receive code is RCode.INTERFERENCES +[t=133.333,src=esds] Simulation ends diff --git a/tests/api_send_interferences_wlan0_ncom_2s1r/platform.yaml b/tests/api_send_interferences_wlan0_ncom_2s1r/platform.yaml new file mode 100644 index 0000000..3480951 --- /dev/null +++ b/tests/api_send_interferences_wlan0_ncom_2s1r/platform.yaml @@ -0,0 +1,17 @@ +general: + interferences: yes + +nodes: + count: 3 + implementations: + - 1-@ sender.py + - 0 receiver.py + +interfaces: + wlan0: + type: "wireless" + nodes: all + links: + - all 3bps 0s all + txperfs: + - all 3bps 0s diff --git a/tests/api_send_interferences_wlan0_ncom_2s1r/receiver.py b/tests/api_send_interferences_wlan0_ncom_2s1r/receiver.py new file mode 100644 index 0000000..a74c0de --- /dev/null +++ b/tests/api_send_interferences_wlan0_ncom_2s1r/receiver.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +def execute(api): + code,data=api.receive("wlan0") + api.log("Receiver receive code 1 is " + str(code)) + code,data=api.receive("wlan0") + api.log("Receiver receive code 2 is " + str(code)) + + diff --git a/tests/api_send_interferences_wlan0_ncom_2s1r/sender.py b/tests/api_send_interferences_wlan0_ncom_2s1r/sender.py new file mode 100644 index 0000000..1c29920 --- /dev/null +++ b/tests/api_send_interferences_wlan0_ncom_2s1r/sender.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +def execute(api): + if api.node_id==0: + code=api.send("wlan0","hello",50,None) + else: + code=api.send("wlan0","hello",50,None) + api.log("Sender send code is "+str(code)) + code,data=api.receive("wlan0") + api.log("Sender receive code is "+str(code)) + \ No newline at end of file diff --git a/tests/api_send_wlan0_2s1r/out b/tests/api_send_wlan0_2s1r/out index f9f2e96..01a1cf1 100644 --- a/tests/api_send_wlan0_2s1r/out +++ b/tests/api_send_wlan0_2s1r/out @@ -1,6 +1,13 @@ [t=0.000,src=n0,grp=def] Send 1 bytes on wlan0 [t=0.000,src=n1,grp=def] Send 1 bytes on wlan0 -[t=0.000,src=n0,grp=def] Interferences on wlan0 -[t=0.000,src=n1,grp=def] Interferences on wlan0 -[t=0.000,src=n2,grp=def] Interferences on wlan0 +[t=1.000,src=n1,grp=def] Receive 1 bytes on wlan0 with errors +[t=1.000,src=n2,grp=def] Receive 1 bytes on wlan0 with errors +[t=1.000,src=n0,grp=def] Receive 1 bytes on wlan0 with errors +[t=1.000,src=n2,grp=def] Receive 1 bytes on wlan0 +[t=1.000,src=n0,grp=def] Sender send code RCode.SUCCESS +[t=1.000,src=n1,grp=def] Sender send code RCode.SUCCESS +[t=1.000,src=n2,grp=def] Receiver code 1 RCode.INTERFERENCES +[t=1.000,src=n0,grp=def] Sender receive code RCode.INTERFERENCES +[t=1.000,src=n1,grp=def] Sender receive code RCode.INTERFERENCES +[t=1.000,src=n2,grp=def] Receiver code 2 RCode.SUCCESS [t=1.000,src=esds] Simulation ends diff --git a/tests/api_send_wlan0_2s1r/receiver.py b/tests/api_send_wlan0_2s1r/receiver.py index 0b48f12..f72d47b 100644 --- a/tests/api_send_wlan0_2s1r/receiver.py +++ b/tests/api_send_wlan0_2s1r/receiver.py @@ -1,5 +1,8 @@ #!/usr/bin/env python def execute(api): - pass + code, data=api.receive("wlan0") + api.log("Receiver code 1 "+str(code)) + code, data=api.receive("wlan0") + api.log("Receiver code 2 "+str(code)) diff --git a/tests/api_send_wlan0_2s1r/sender.py b/tests/api_send_wlan0_2s1r/sender.py index 80f0fc2..bcaaa2a 100644 --- a/tests/api_send_wlan0_2s1r/sender.py +++ b/tests/api_send_wlan0_2s1r/sender.py @@ -1,4 +1,7 @@ #!/usr/bin/env python def execute(api): - api.send("wlan0","Hello World!",1,1) + code=api.send("wlan0","Hello World!",1,1) + api.log("Sender send code "+str(code)) + code, data=api.receive("wlan0") + api.log("Sender receive code "+str(code)) \ No newline at end of file diff --git a/tests/hidden_node_2s1r/out b/tests/hidden_node_2s1r/out index 2b15788..2ce6af9 100644 --- a/tests/hidden_node_2s1r/out +++ b/tests/hidden_node_2s1r/out @@ -1,4 +1,9 @@ [t=0.000,src=n0,grp=def] Send 1 bytes on wlan0 [t=0.000,src=n2,grp=def] Send 1 bytes on wlan0 -[t=0.000,src=n1,grp=def] Interferences on wlan0 +[t=1.000,src=n1,grp=def] Receive 1 bytes on wlan0 with errors +[t=1.000,src=n1,grp=def] Receive 1 bytes on wlan0 with errors +[t=1.000,src=n0,grp=def] Sender RCode.SUCCESS +[t=1.000,src=n1,grp=def] Receiver RCode.INTERFERENCES +[t=1.000,src=n2,grp=def] Sender RCode.SUCCESS +[t=1.000,src=n1,grp=def] Receiver RCode.INTERFERENCES [t=1.000,src=esds] Simulation ends diff --git a/tests/hidden_node_2s1r/receiver.py b/tests/hidden_node_2s1r/receiver.py index 0b48f12..4c66495 100644 --- a/tests/hidden_node_2s1r/receiver.py +++ b/tests/hidden_node_2s1r/receiver.py @@ -1,5 +1,8 @@ #!/usr/bin/env python def execute(api): - pass - + code,data=api.receive("wlan0") + api.log("Receiver "+str(code)) + code,data=api.receive("wlan0") + api.log("Receiver "+str(code)) + diff --git a/tests/hidden_node_2s1r/sender.py b/tests/hidden_node_2s1r/sender.py index 80f0fc2..c07749a 100644 --- a/tests/hidden_node_2s1r/sender.py +++ b/tests/hidden_node_2s1r/sender.py @@ -1,4 +1,5 @@ #!/usr/bin/env python def execute(api): - api.send("wlan0","Hello World!",1,1) + code=api.send("wlan0","Hello World!",1,1) + api.log("Sender "+str(code))