Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On error functional, with 2 exceptions: All-1 lost and final Ack lost #24

Merged
merged 1 commit into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions fragmentation_layer/code/schc_base/bitmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def has_missing(self):
break
return 0 < sum(self.__bitmap__[i+1:])

def get_missing(self, fcn=False):
def get_missing(self, fcn=False, after=None):
"""
Gets first index of reported missing tile. If fcn is True, passes
as fcn
Expand All @@ -127,13 +127,22 @@ def get_missing(self, fcn=False):
----------
fcn : bool, optional
If fcn is True, missing as fcn
after : int, optional
Check after a particular fcn
Returns
-------
int
First index with missing tile
"""
i = self.__bitmap__.index(False)
if after is None:
i = self.__bitmap__.index(False)
else:
if fcn:
i = self.__bitmap__[self.protocol.WINDOW_SIZE - after:].index(False)
return after - 1 - i
else:
i = self.__bitmap__[after + 1:].index(False) + after + 1
if fcn:
return self.protocol.WINDOW_SIZE - 1 - i
else:
Expand Down
199 changes: 154 additions & 45 deletions fragmentation_layer/code/schc_machines/lorawan/ack_on_error_receiver.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
""" ack_on_error_receiver: AckOnError receiver state machine """

from machine import Timer
from schc_base import Bitmap
from schc_base import Bitmap, Tile
from schc_machines import SCHCReceiver
from schc_messages import RegularSCHCFragment, SCHCAck, All1SCHCFragment, SCHCAckReq, SCHCReceiverAbort

Expand Down Expand Up @@ -84,6 +84,7 @@ def on_expiration_time(self, alarm) -> None:

def receive_regular_schc_fragment(self, schc_message):
"""
Behaviour when receiving a Regular SCHC Fragment
Parameters
----------
Expand All @@ -103,7 +104,9 @@ def receive_regular_schc_fragment(self, schc_message):
self._logger_.debug("Window received: {}\tTiles from: {} to {}".format(
schc_message.header.w.w, fcn, fcn - tiles_received + 1))
for tile in range(tiles_received):
self.sm.payload.add_content(tiles[0:self.sm.protocol.TILE_SIZE // 8])
self.sm.add_tile(Tile(
tiles[0:self.sm.protocol.TILE_SIZE // 8]
), w=self.sm.__cw__, fcn=self.sm.__fcn__)
tiles = tiles[self.sm.protocol.TILE_SIZE // 8:]
self.sm.bitmaps[
self.sm.__cw__
Expand Down Expand Up @@ -149,12 +152,13 @@ def receive_all1_schc_fragment(self, schc_message):
if self.sm.__cw__ == schc_message.header.w:
self.sm.__last_window__ = True
last_payload = schc_message.payload.as_bytes()
self.sm.payload.add_content(last_payload)
self.sm.add_tile(Tile(last_payload), w=self.sm.__cw__, fcn=self.sm.__fcn__)
bitmap = self.sm.bitmaps[schc_message.header.w.w]
if bitmap.has_missing():
integrity = False
compressed_bitmap = bitmap.generate_compress()
else:
self.sm.reassemble()
rcs = self.sm.protocol.calculate_rcs(
self.sm.payload.as_bits()
)
Expand All @@ -164,12 +168,21 @@ def receive_all1_schc_fragment(self, schc_message):
compressed_bitmap = None
self.__success__ = True
else:
self._logger_.error("Integrity check failed:\tSender: {}\tReceiver:{}".format(
self._logger_.error("Integrity check failed:\tSender: {}\tReceiver: {}".format(
schc_message.header.rcs.rcs,
rcs
))
compressed_bitmap = bitmap.generate_compress()
return integrity, compressed_bitmap
abort = SCHCReceiverAbort(
rule_id=self.sm.__rule_id__,
protocol=self.sm.protocol.id,
dtag=self.sm.__dtag__,
w=self.sm.__cw__
)
abort.add_padding()
self.sm.message_to_send.append(abort)
self.sm.state = self.sm.states["error"]
self.sm.state.enter_state()
return
ack = SCHCAck(self.sm.__rule_id__,
self.sm.protocol.id,
c=integrity,
Expand All @@ -180,7 +193,7 @@ def receive_all1_schc_fragment(self, schc_message):
self.sm.message_to_send.append(ack)
return
else:
self._logger_.degug("(All-1) Different window received")
self._logger_.debug("(All-1) Different window received")
return

def receive_schc_ack_req(self, schc_message):
Expand Down Expand Up @@ -213,6 +226,9 @@ def receive_schc_ack_req(self, schc_message):
return
if bitmap.is_missing():
self._logger_.debug("Window {} has missing tiles".format(w))
self.sm.state = self.sm.states["waiting_phase"]
self.sm.state.enter_state()
self.sm.inactivity_timer.reset()
self.sm.message_to_send.append(
SCHCAck(self.sm.__rule_id__, self.sm.protocol.id,
False, w=w, compressed_bitmap=bitmap.generate_compress())
Expand Down Expand Up @@ -263,29 +279,10 @@ def receive_regular_schc_fragment(self, schc_message):
self.sm.state.receive_regular_schc_fragment(schc_message)
else:
self._logger_.debug("Receiving failed ones")
fcn = schc_message.header.fcn.fcn
tiles_received = schc_message.payload.size // self.sm.protocol.TILE_SIZE
tiles = schc_message.payload.as_bytes()
for tile in range(tiles_received):
self._logger_.debug("Window received: {}\tTile {}".format(
schc_message.header.w.w, fcn))
self.sm.payload.add_content(tiles[0:self.sm.protocol.TILE_SIZE // 8])
tiles = tiles[self.sm.protocol.TILE_SIZE // 8:]
self.sm.bitmaps[self.sm.__cw__].tile_received(fcn)
if self.sm.bitmaps[self.sm.__cw__].is_missing():
fcn = self.sm.bitmaps[self.sm.__cw__].get_missing(fcn=True)
else:
ack = SCHCAck(
rule_id=self.sm.__rule_id__,
protocol=self.sm.protocol.id,
c=False,
dtag=self.sm.__dtag__,
w=self.sm.__cw__,
compressed_bitmap=self.sm.bitmaps[self.sm.__cw__].generate_compress()
)
ack.add_padding()
self.sm.message_to_send.append(ack)
return
self.sm.__cw__ = schc_message.header.w.w
self.sm.state = self.sm.states["receiving_missing_phase"]
self.enter_state()
self.sm.state.receive_regular_schc_fragment(schc_message)
return

def receive_all1_schc_fragment(self, schc_message):
Expand Down Expand Up @@ -322,14 +319,16 @@ def receive_schc_ack_req(self, schc_message):
w = schc_message.header.w.w
if w not in self.sm.bitmaps.keys():
return
if not self.sm.__last_window__:
self.sm.message_to_send.append(
SCHCAck(self.sm.__rule_id__, self.sm.protocol.id,
c=False, w=w, compressed_bitmap=self.sm.bitmaps[w].generate_compress())
)
self.sm.attempts.increment()
else:
pass
ack = SCHCAck(
rule_id=self.sm.__rule_id__,
protocol=self.sm.protocol.id,
c=False,
w=w,
compressed_bitmap=self.sm.bitmaps[w].generate_compress()
)
ack.add_padding()
self.sm.message_to_send.append(ack)
self.sm.attempts.increment()
return

def on_expiration_time(self, alarm) -> None:
Expand All @@ -348,10 +347,120 @@ def on_expiration_time(self, alarm) -> None:
std_on_expiration_time(self, alarm)
return

class ReceivingMissingPhase(SCHCReceiver.ReceiverState):
"""
Receiving Missing Phase, machine receive missing fragments
"""
__name__ = "Receiving Missing Phase"

def receive_regular_schc_fragment(self, schc_message):
"""
Behaviour when receiving a Regular SCHC Fragment
Parameters
----------
schc_message : RegularSCHCFragment
A regular Fragment received
Returns
-------
None, alter state
"""
self.sm.inactivity_timer.stop()
if self.sm.__cw__ == schc_message.header.w:
fcn = schc_message.header.fcn.fcn
tiles_received = schc_message.payload.size // self.sm.protocol.TILE_SIZE
tiles = schc_message.payload.as_bytes()
for tile in range(tiles_received):
self._logger_.debug("Window received: {}\tTile {}".format(
schc_message.header.w.w, fcn))
self.sm.add_tile(Tile(
tiles[0:self.sm.protocol.TILE_SIZE // 8]
), w=self.sm.__cw__, fcn=fcn)
tiles = tiles[self.sm.protocol.TILE_SIZE // 8:]
self.sm.bitmaps[self.sm.__cw__].tile_received(fcn)
try:
fcn = self.sm.bitmaps[self.sm.__cw__].get_missing(fcn=True, after=fcn)
except ValueError:
try:
fcn = self.sm.bitmaps[self.sm.__cw__].get_missing(fcn=True)
except ValueError:
ack = SCHCAck(
rule_id=self.sm.__rule_id__,
protocol=self.sm.protocol.id,
c=False,
dtag=self.sm.__dtag__,
w=self.sm.__cw__,
compressed_bitmap=self.sm.bitmaps[self.sm.__cw__].generate_compress()
)
ack.add_padding()
self.sm.message_to_send.append(ack)
self.sm.state = self.sm.states["waiting_phase"]
self.sm.state.enter_state()
self.sm.inactivity_timer.reset()
return
self._logger_.debug("Current bitmap: {}. Waiting for w={} fcn={} tile".format(
self.sm.bitmaps[
self.sm.__cw__
], self.sm.__cw__, fcn)
)
else:
self._logger_.debug("Different window received")
return

def receive_all1_schc_fragment(self, schc_message):
"""
Behaviour when receiving All-1 SCHC Fragment
Parameters
----------
schc_message : All1SCHCFragment
Last fragment to be received
Returns
-------
None, alter state
"""
self.sm.state = self.sm.states["receiving_phase"]
self.sm.state.enter_state()
self.sm.state.receive_all1_schc_fragment(schc_message)
return

def receive_schc_ack_req(self, schc_message):
"""
Behaviour when SCHC Ack Request
Parameters
----------
schc_message : SCHCAckReq
SCHC message received
Returns
-------
None, alter state
"""
w = schc_message.header.w.w
if w not in self.sm.bitmaps.keys():
return
if not self.sm.__last_window__:
ack = SCHCAck(
rule_id=self.sm.__rule_id__,
protocol=self.sm.protocol.id,
c=False,
w=w,
compressed_bitmap=self.sm.bitmaps[w].generate_compress()
)
ack.add_padding()
self.sm.message_to_send.append(ack)
else:
pass
return

def __init__(self, protocol, dtag=None, on_success=None):
super().__init__(protocol, dtag=dtag)
self.states["receiving_phase"] = AckOnErrorReceiver.ReceivingPhase(self)
self.states["waiting_phase"] = AckOnErrorReceiver.WaitingPhase(self)
self.states["receiving_missing_phase"] = AckOnErrorReceiver.ReceivingMissingPhase(self)
self.state = self.states["receiving_phase"]
self.inactivity_timer.reset()
self.state.enter_state()
Expand All @@ -376,12 +485,12 @@ def std_on_expiration_time(state, alarm):
"""
state.sm.state = state.sm.states["error"]
state.sm.state.enter_state()
state.sm.message_to_send.append(
SCHCReceiverAbort(
rule_id=state.sm.__rule_id__,
protocol=state.sm.protocol.id,
dtag=state.sm.__dtag__,
w=state.sm.__cw__
)
abort = SCHCReceiverAbort(
rule_id=state.sm.__rule_id__,
protocol=state.sm.protocol.id,
dtag=state.sm.__dtag__,
w=state.sm.__cw__
)
abort.add_padding()
state.sm.message_to_send.append(abort)
return
Loading