Skip to content

Commit

Permalink
Merge pull request #24 from niclabs/feat-lost-fragments
Browse files Browse the repository at this point in the history
On error functional, with 2 exceptions: All-1 lost and final Ack lost
  • Loading branch information
felipe-canales committed Jun 17, 2021
2 parents 59bc46f + 954d3a7 commit d2a082e
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 111 deletions.
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

0 comments on commit d2a082e

Please sign in to comment.