Transmission

class dsns.transmission.MessageLocationTracker
__init__()
remove_message_from_location(message: DirectMessage, link: Link)
add_message_to_location(message: DirectMessage, link: Link)
get_messages_in_location(link: Link)
is_message_at_location(message: DirectMessage, link: Link)
class dsns.transmission.MessageScheduledSendCompletedEvent(time: float, send_start_time: float, source: int, destination: int, message: BaseMessage)

Event for when a message was scheduled to have been fully transmitted onto the link.

__init__(time: float, send_start_time: float, source: int, destination: int, message: BaseMessage)
message: BaseMessage
class dsns.transmission.BandwidthUpdateEvent(time: float, source: int, destination: int, bandwidth: float)

Event to update the bandwidth of a link.

__init__(time: float, source: int, destination: int, bandwidth: float)
class dsns.transmission.TransmissionInterval(start_time: float, end_time: float)
start_time: float
end_time: float
__init__(start_time: float, end_time: float) None
class dsns.transmission.LinkTransmissionActor(default_bandwidth: float, per_link_bandwidth: dict | None = None, buffer_if_link_busy: bool = False, reroute_on_link_down: bool = True, message_location_tracker: ~dsns.transmission.MessageLocationTracker = <dsns.transmission.MessageLocationTracker object>)

Models bandwidth to schedule when messages are sent This actor schedules one message at a time

__init__(default_bandwidth: float, per_link_bandwidth: dict | None = None, buffer_if_link_busy: bool = False, reroute_on_link_down: bool = True, message_location_tracker: ~dsns.transmission.MessageLocationTracker = <dsns.transmission.MessageLocationTracker object>)
initialize() list[Event]

Initialize the actor.

Returns:

List of events to add to the event queue.

handle_message_queued_event(mobility: MultiConstellation, event: MessageQueuedEvent, message: BaseMessage) list[Event]
handle_message_scheduled_send_completed_event(mobility: MultiConstellation, event: MessageScheduledSendCompletedEvent, message: BaseMessage) list[Event]

Check if this scheduled send completion is stale. If not raise the corresponding MessageSentEvent to signal that the entire message was successfully transmitted onto the link.

Assume for now that if buffering is enabled a message is buffered (not sent) until it can and is successfully sent TODO: expand this later for specific behavior depending on what goes down

handle_message_sent_event(mobility: MultiConstellation, event: MessageSentEvent, message: BaseMessage) list[Event]

MessageSentEvent signifies the entire message was transmitted onto the link successfully. If there is a next message waiting to be sent on that link, schedule it.

Recomputes scheduled send completion events for buffered messages Note these must be scheduled before any new store and forward messages are queued and scheduled for

handle_bandwidth_update_event(mobility: MultiConstellation, event: BandwidthUpdateEvent)
handle_event(mobility: MultiConstellation, event) list[Event]

Handle an event.

Parameters:
  • mobility – The mobility model to handle the event with.

  • event – The event to handle.

Returns:

List of events to add to the event queue.

class dsns.transmission.MessageTransmissionTimeoutEvent(time: float, message: BaseMessage, source: int, destination: int)
__init__(time: float, message: BaseMessage, source: int, destination: int)
message: int
source: int
destination: int
class dsns.transmission.LTPSegmentDroppedEvent(time: float, source: int, message: LTPSegment, reason: DropReason = DropReason.UNKNOWN)

Event for when an LTP Segment is dropped. Source refers to the satellite that dropped the message.

__init__(time: float, source: int, message: LTPSegment, reason: DropReason = DropReason.UNKNOWN)
message: LTPSegment
class dsns.transmission.AbortReason(*values)
LTP_SESSION_CANCELATION = 'LTP_SESSION_CANCELATION'
UNKNOWN = 'UNKNWON'
class dsns.transmission.MessageReceptionCanceledEvent(time: float, source: int, message: BaseMessage, destination: int, reason: AbortReason = AbortReason.UNKNOWN)

Event for when a receiver aborts receiving a message from a sender. Note sender can drop the message, but receiver cannot drop something they don’t have yet. They can only abort its reception.

__init__(time: float, source: int, message: BaseMessage, destination: int, reason: AbortReason = AbortReason.UNKNOWN)
message: BaseMessage
class dsns.transmission.RetransmissionConfig(timeout: ~typing.Callable[[float], float] = <function RetransmissionConfig.<lambda>>, max_retries: int = 10)

Configuration for retransmission timeouts.

“Then, to account for the additional delay imposed by interrupted

connectivity, we dynamically suspend timers during periods when the relevant remote LTP engines are known to be unable to transmit responses.” - Not a concern as we start timers when message fully transmitted.

LTP RFC 5325 - Read Section ‘3.1.3. Timers’ for Justification “So the initial expected arrival time for each acknowledging segment is typically computed as simply the current time at the moment that radiation of the original segment begins, plus twice the one-way light time, plus 2*N seconds of margin to account for processing and queuing delays and for radiation time at both ends. N is a parameter set by network management for which 2 seconds seem to be a reasonable default value.”

We simplify this by starting timers when the message is fully transmitted into the link (but since message size <<< bandwidth this is negligible).

Then compute timeout by default as recommende in the RFC as RTT + 2*N, where N=2 as recommended

timeout()

No real optimal value. Based on RFC this is a limit dependent on the network config. Given the loose retransmission timeout (extra 4 seconds on RTT), 10 retries should be sufficient.

https://support.microsoft.com/en-gb/topic/how-to-modify-the-tcp-ip-maximum-retransmission-time-out-7ae0982a-4963-fa7e-ee79-ff6d0da73db8 TCP default value for TcpMaxDataRetransmissions is 5. Standard value I would argue. So this is more than enough.

max_retries: int = 10
__init__(timeout: ~typing.Callable[[float], float] = <function RetransmissionConfig.<lambda>>, max_retries: int = 10) None
class dsns.transmission.LTPSessionID(source: int, destination: int, underlying_message_uid: int, session: int)
source: int
destination: int
underlying_message_uid: int
session: int
__init__(source: int, destination: int, underlying_message_uid: int, session: int) None
class dsns.transmission.LTPMessageRetransmissionActor(config: ~dsns.transmission.RetransmissionConfig, report_segment_base_size: int = 9, report_ack_size: int = 5, model_bandwidth=False, message_location_tracker: ~dsns.transmission.MessageLocationTracker = <dsns.transmission.MessageLocationTracker object>)

https://www.rfc-editor.org/rfc/pdfrfc/rfc5326.txt.pdf RFC 5326 Implements LTP based retransmission for satelite communication. Each original direct message is now encapsulated as a series of LTP segments in an LTPBlock. The remaining LTPMessage’s are control messages for sending a checkpoint, report segment and report ack.

Each LTPBlock has a red part for reliable transfer and green part for unreliable transfer. Each LTPBlock must be followed by a checkpoint segment at the end. Checkpoints require sender to reply with a report segment of missing data When a sender gets a report segment they acknowledge it and retransmit missing data.

Checkpoints and report segments have timeouts.

Retransmission timers for timeouts are started when the message is sent and not when it’s queued. This is so that we don’t retransmit messages that are waiting for transmission because of bandwidth availability.

__init__(config: ~dsns.transmission.RetransmissionConfig, report_segment_base_size: int = 9, report_ack_size: int = 5, model_bandwidth=False, message_location_tracker: ~dsns.transmission.MessageLocationTracker = <dsns.transmission.MessageLocationTracker object>)
initialize() list[Event]

Initialize the actor.

Returns:

List of events to add to the event queue.

handle_message_sent_event(mobility: MultiConstellation, event: MessageSentEvent, message: LTPSegment) list[Event]
handle_data_segment_received_event(mobility: MultiConstellation, event: LTPSegmentReceivedEvent, message: LTPDataSegment) list[Event]
handle_report_segment_received_event(mobility: MultiConstellation, event: LTPSegmentReceivedEvent, message: LTPReportSegment) list[Event]

If its a duplicate report segment We only ack it but don’t retransmit missing data again As per 6.13 in https://www.rfc-editor.org/rfc/pdfrfc/rfc5326.txt.pdf

As per 6.13 if the session is canceled (underlying message or corresponding checkpoint is dropped) we only ack.

handle_report_ack_received_event(mobility: MultiConstellation, event: LTPSegmentReceivedEvent, message: LTPReportAcknowledgementSegment) list[Event]
handle_message_dropped_event(mobility: MultiConstellation, event: LTPSegmentDroppedEvent, message: LTPSegment) list[Event]
handle_message_transmission_timeout_event(mobility: MultiConstellation, event: MessageTransmissionTimeoutEvent, message: LTPSegment) list[Event]
handle_ltp_segment_created_event(mobility: MultiConstellation, event: LTPSegmentCreatedEvent, message: LTPSegment)
handle_message_reroute_event(mobility: MultiConstellation, event: MessageRerouteEvent)
handle_event(mobility: MultiConstellation, event: Event) list[Event]

Handle an event.

Parameters:
  • mobility – The mobility model to handle the event with.

  • event – The event to handle.

Returns:

List of events to add to the event queue.