diff --git a/CBSVisualizer/CBSVisualizer.Common/Enums/PreemptionType.cs b/CBSVisualizer/CBSVisualizer.Common/Enums/PreemptionType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8b8d9400313337a4e4db946a58501a3a2358e59c
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Common/Enums/PreemptionType.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CBSVisualizer.Common.Enums
+{
+    /// <summary>
+    /// An enum specifying the available preemption types.
+    /// </summary>
+    public enum PreemptionType
+    {
+        /// <summary>
+        /// Non-preemptive.
+        /// </summary>
+        NonPreemptive,
+
+        /// <summary>
+        /// Preemption no HOLD/RELEASE
+        /// </summary>
+        PreemptionNoHoldRelease,
+
+        /// <summary>
+        /// Preemption with HOLD/RELEASE
+        /// </summary>
+        PreemptionWithHoldRelease
+    }
+}
diff --git a/CBSVisualizer/CBSVisualizer.Common/Interfaces/IPreemptionHandler.cs b/CBSVisualizer/CBSVisualizer.Common/Interfaces/IPreemptionHandler.cs
new file mode 100644
index 0000000000000000000000000000000000000000..899c4f57a4225b0f0f2a5c2d233154dc414b57a0
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Common/Interfaces/IPreemptionHandler.cs
@@ -0,0 +1,34 @@
+using CBSVisualizer.Messaging.Models;
+
+namespace CBSVisualizer.Common.Interfaces
+{
+    public interface IPreemptionHandler
+    {
+        /// <summary>
+        /// Used by the link to determine if the send candidate can actually be sent.
+        /// </summary>
+        /// <param name="candidate">the packet that should be evaluated.</param>
+        /// <param name="byteBudget">the amount of bytes the link could transmit before the gate closes.</param>
+        /// <returns>true if the preemption handler allows the packet to be sent.</returns>
+        bool CanSend(PriorityPacket candidate, long byteBudget);
+
+
+        /// <summary>
+        /// Used by the link to determine if the currently sent packet can be preempted.
+        /// </summary>
+        /// <param name="currentPacket">the packet that is currently sent.</param>
+        /// <param name="leftoverBytes">the bytes that still need to be transmitted.</param>
+        /// <param name="byteBudget">the amount of bytes that the link can transmit before the gate closes.</param>
+        /// <returns>true if the packet can be preempted in favour of a higher priority packet.</returns>
+        bool CanPreempt(PriorityPacket currentPacket, int leftoverBytes, long byteBudget);
+
+
+        /// <summary>
+        /// Constructs the packet with the leftover data that will be sent after the preempting packet.
+        /// </summary>
+        /// <param name="priority">the priority of the original packet -> also the priority of the new packet.</param>
+        /// <param name="leftoverBytes">the leftover bytes of the packet.</param>
+        /// <returns></returns>
+        PriorityPacket ConstructPostPreemptionPacket(int priority, int leftoverBytes);
+    }
+}
diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionFinishedEvent.cs b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionFinishedEvent.cs
index dba806418bd733a1f0e394f3192ec174fb58f90b..6426fe2cc2982bd43ae3d53fc3136c5e85888697 100644
--- a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionFinishedEvent.cs
+++ b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionFinishedEvent.cs
@@ -2,7 +2,7 @@
 
 namespace CBSVisualizer.Messaging.Events.Queue
 {
-    public class TransmissionFinishedEvent : PubSubEvent<int>
+    public class TransmissionFinishedEvent : PubSubEvent<(int Priority, long BytesPerSecond)>
     {
     }
 }
diff --git a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionStartedEvent.cs b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionStartedEvent.cs
index 0537ba3f4843ba56f09a749690b8bec3b5318833..30808a892d29f520eb029800b3823ae3ece398f5 100644
--- a/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionStartedEvent.cs
+++ b/CBSVisualizer/CBSVisualizer.MessagingCore/Events/Queue/TransmissionStartedEvent.cs
@@ -7,7 +7,7 @@ using Prism.Events;
 
 namespace CBSVisualizer.Messaging.Events.Queue
 {
-    public class TransmissionStartedEvent : PubSubEvent<(int Priority, long BytesPerSecond)>
+    public class TransmissionStartedEvent : PubSubEvent<int>
     {
     }
 }
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs
index de8a7e7ad5ba66027b41cf50ba49130a993a1b12..07c49359537db904c6b7c2654a559a2b6bef3670 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Charts/ViewModels/ChartsViewModel.cs
@@ -5,6 +5,7 @@ using System.Collections.ObjectModel;
 using CBSVisualizer.Core.Mvvm;
 using CBSVisualizer.Messaging.Events;
 using CBSVisualizer.Messaging.Events.Charts;
+using CBSVisualizer.Messaging.Events.Simulation;
 using Prism.Events;
 using Prism.Regions;
 using SciChart.Charting.Model.ChartSeries;
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/NoPreemptionHandler.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/NoPreemptionHandler.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d231cabcfe7559b3ddfa0e58c157e03f1720733c
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/NoPreemptionHandler.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CBSVisualizer.Common.Interfaces;
+using CBSVisualizer.Messaging.Models;
+
+namespace CBSVisualizer.Modules.Link.Preemption
+{
+    class NoPreemptionHandler : IPreemptionHandler
+    {
+        public bool CanSend(PriorityPacket candidate, long byteBudget)
+        {
+            return candidate.Size <= byteBudget;
+
+        }
+
+        public bool CanPreempt(PriorityPacket currentPacket, int leftoverBytes, long byteBudget)
+        {
+            return false;
+        }
+
+        public PriorityPacket ConstructPostPreemptionPacket(int priority, int leftoverBytes)
+        {
+            return PriorityPacket.NoPacket;
+        }
+    }
+}
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/PreemptionNoHoldReleaseHandler.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/PreemptionNoHoldReleaseHandler.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a9620bde416194a5eb52983cc7dc6aa68d7b6dab
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/PreemptionNoHoldReleaseHandler.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CBSVisualizer.Common.Interfaces;
+using CBSVisualizer.Messaging.Models;
+
+namespace CBSVisualizer.Modules.Link.Preemption
+{
+    public class PreemptionNoHoldReleaseHandler : IPreemptionHandler
+    {
+        private const int MinPacketSize = 64;
+        private const int TooSmallForPreemption = 123;
+        private const int HeaderSize = 16;
+        private const int TrailerSize = 8;
+
+        public bool CanSend(PriorityPacket candidate, long byteBudget)
+        {
+            // The lower priority packets can always be sent, no guard band.
+            return true;
+        }
+
+        public bool CanPreempt(PriorityPacket currentPacket, int leftoverBytes, long byteBudget)
+        {
+            // Cannot be preempted if either
+            // a) bytes left to transmit < min packet size (64 bytes)
+            // b) frame is too small to be preempted (< 123 bytes)
+            return leftoverBytes >= MinPacketSize && currentPacket.Size >= TooSmallForPreemption;
+        }
+
+        public PriorityPacket ConstructPostPreemptionPacket(int priority, int leftoverBytes)
+        {
+            // If the CBS frame can be preempted, the overhead (header + trailer) per preemption is 24 bytes, assuming 16 bytes header + 8 bytes trailer.
+            return new PriorityPacket(priority, HeaderSize, leftoverBytes, TrailerSize);
+        }
+    }
+}
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/PreemptionWithHoldReleaseHandler.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/PreemptionWithHoldReleaseHandler.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7e77241ba883a281673aca043cf919a803b3a0d8
--- /dev/null
+++ b/CBSVisualizer/CBSVisualizer.Modules.Link/Preemption/PreemptionWithHoldReleaseHandler.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CBSVisualizer.Common.Interfaces;
+using CBSVisualizer.Messaging.Models;
+
+namespace CBSVisualizer.Modules.Link.Preemption
+{
+    public class PreemptionWithHoldReleaseHandler : IPreemptionHandler
+    {
+        private const int ReducedGuardBandSize = 143;
+        private const int HeaderSize = 0;
+        private const int TrailerSize = 8;
+
+        public bool CanSend(PriorityPacket candidate, long byteBudget)
+        {
+            // A reduced Guard Band (143 bytes) is introduced in order to protect the TT window.
+            return byteBudget > ReducedGuardBandSize;
+        }
+
+        public bool CanPreempt(PriorityPacket currentPacket, int leftoverBytes, long byteBudget)
+        {
+            // If the current transmission will be finished outside of the guard band, we cannot preempt it.
+            if (byteBudget - leftoverBytes >= ReducedGuardBandSize)
+            {
+                return false;
+            }
+
+            // If the packet can finish its transmission inside of the guard band, we cannot preempt it.
+            // Otherwise, we can preempt it.
+            return leftoverBytes > ReducedGuardBandSize;
+        }
+
+        public PriorityPacket ConstructPostPreemptionPacket(int priority, int leftoverBytes)
+        {
+            // Overhead is 8 bytes (trailer).
+            return new PriorityPacket(priority, HeaderSize, leftoverBytes, TrailerSize);
+        }
+    }
+}
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs
index 23472656e19a489174f274292185b45830af0091..b6f746e1ae369743d00a7a008cf1aa56348b7e55 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Link/ViewModels/LinkViewModel.cs
@@ -7,10 +7,13 @@ using System.Reflection;
 using System.Threading;
 using System.Threading.Tasks;
 using CBSVisualizer.Common;
+using CBSVisualizer.Common.Enums;
+using CBSVisualizer.Common.Interfaces;
 using CBSVisualizer.Core.Mvvm;
 using CBSVisualizer.Messaging.Events.Queue;
 using CBSVisualizer.Messaging.Events.Simulation;
 using CBSVisualizer.Messaging.Models;
+using CBSVisualizer.Modules.Link.Preemption;
 using CBSVisualizer.Services.SchedulingService.Interface;
 using CBSVisualizer.Services.SettingService.Implementation;
 using log4net;
@@ -21,19 +24,55 @@ namespace CBSVisualizer.Modules.Link.ViewModels
 {
     public class LinkViewModel : RegionViewModelBase, IDisposable
     {
+        /// <summary>
+        /// The key of the "bitrate" setting.
+        /// </summary>
         private const string BitrateSettingKey = "bitrate";
 
+        /// <summary>
+        /// The logger of this ViewModel.
+        /// </summary>
         private static readonly ILog Log =
             LogManager.GetLogger(MethodBase.GetCurrentMethod()?.DeclaringType);
 
+
         private readonly IEventAggregator eventAggregator;
 
+        /// <summary>
+        /// A ConcurrentBag for storing the packets that the opened queues want to send. 
+        /// </summary>
         private readonly ConcurrentBag<PriorityPacket> sendCandidates = new ConcurrentBag<PriorityPacket>();
 
+        /// <summary>
+        /// The Setting Service, for requesting the bitrate and the preemption setting.
+        /// </summary>
         private readonly SettingService settingService;
 
+        /// <summary>
+        /// The PreemptionHandler implementation that is used in the current simulation run.
+        /// </summary>
+        private IPreemptionHandler preemptionHandler;
+
+        /// <summary>
+        /// The thread that does the main work (selecting the currently transmitted packet, notifying the queues etc.).
+        /// </summary>
         private Thread gateThread;
+
+        /// <summary>
+        /// A CancellationTokenSource for the recognition of GateClosedEvents.
+        /// </summary>
         private CancellationTokenSource gateOpenedTokenSrc = new CancellationTokenSource();
+        
+        /// <summary>
+        /// The index of the last preempted queue. -1 if no preemption has taken place.
+        /// </summary>
+        private int preemptedQueue = -1;
+
+        /// <summary>
+        /// These are the bytes that are left to transmit in the "Gate Opened time"  of the high priority queue when a preemption has taken place
+        /// and the link is unable to send the whole packet before the GateClosedEvent of the lower prio gate.
+        /// </summary>
+        private long preemptingPacketLeftoverBytes;
 
         public LinkViewModel(IRegionManager regionManager, IEventAggregator eventAggregator,
             ISchedulingService schedulingService, SettingService settingService)
@@ -80,7 +119,7 @@ namespace CBSVisualizer.Modules.Link.ViewModels
                 gateOpenedTokenSrc = new CancellationTokenSource();
 
                 // Calculate transmittable bytes.
-                var transmittableBytes = settingService.GetSettingValue<int>(BitrateSettingKey) * tuple.OpenedTime / 1000;
+                var transmittableBytes = settingService.GetSettingValue<long>(BitrateSettingKey) * tuple.OpenedTime / 1000;
 
                 eventAggregator.GetEvent<QueueGateOpenedEvent>().Publish(tuple.OpenedGates);
 
@@ -99,6 +138,7 @@ namespace CBSVisualizer.Modules.Link.ViewModels
             gateOpenedTokenSrc.Cancel();
             if (gateThread != null && gateThread.IsAlive)
             {
+                Debug.WriteLine("Joining Gate Thread");
                 gateThread.Join();
             }
         }
@@ -107,10 +147,14 @@ namespace CBSVisualizer.Modules.Link.ViewModels
         {
             eventAggregator.GetEvent<SimulationStartedEvent>().Subscribe(async () =>
             {
+
+                InitializePreemptionHandler();
+
+                Log.Info("Simulation started.");
+
                 // Start scheduling.
                 try
                 {
-                    Log.Info("Simulation started.");
                     await scheduler.StartScheduling().ConfigureAwait(false);
                 }
                 catch (TaskCanceledException)
@@ -136,10 +180,34 @@ namespace CBSVisualizer.Modules.Link.ViewModels
             }, true);
         }
 
-        private void HandleGateOpened(ISet<int> openedGates, int byteBudget)
+        private void InitializePreemptionHandler()
+        {
+            switch (Enum.Parse<PreemptionType>(settingService.GetSettingValue<string>("preemption_mode")))
+            {
+                case PreemptionType.PreemptionNoHoldRelease:
+                    preemptionHandler = new PreemptionNoHoldReleaseHandler();
+                    break;
+                case PreemptionType.PreemptionWithHoldRelease:
+                    preemptionHandler = new PreemptionWithHoldReleaseHandler();
+                    break;
+                case PreemptionType.NonPreemptive:
+                default:
+                    preemptionHandler = new NoPreemptionHandler();
+                    break;
+            }
+        }
+
+        private void HandleGateOpened(ISet<int> openedGates, long byteBudget)
         {
             // Copy transmittable bytes.
-            var totalBudget = byteBudget;
+            var totalBudget = byteBudget - preemptingPacketLeftoverBytes;
+            preemptingPacketLeftoverBytes = 0;
+
+            // If this cycle contains a queue whose packet was preempted, send that packet first.
+            if (preemptedQueue != -1 && openedGates.Contains(preemptedQueue))
+            {
+                totalBudget -= SendPreemptedPacket(totalBudget);
+            }
 
             while (!gateOpenedTokenSrc.IsCancellationRequested)
             {
@@ -147,29 +215,69 @@ namespace CBSVisualizer.Modules.Link.ViewModels
             }
         }
 
-        private int PerformCycle(ISet<int> openedGates, int cycleByteBudget)
+        /// <summary>
+        /// Sends the previously preempted packet (if there was any).
+        /// </summary>
+        /// <param name="totalBudget">the byte budget until the next GateClosedEvent to determine if we can send the packet in time.</param>
+        /// <returns></returns>
+        private long SendPreemptedPacket(long totalBudget)
+        {
+            // Get the preempted packet.
+            sendCandidates.Clear();
+            eventAggregator.GetEvent<PacketSubmitRequestEvent>().Publish(new HashSet<int>{preemptedQueue});
+            AwaitPacketArrival(1);
+
+            // Construct the post-preemption packet.
+            // Important: preemption overhead (header + trailer) does not subtract from the queue's credit. 
+            var postPreemptionPacket = preemptionHandler.ConstructPostPreemptionPacket(preemptedQueue, sendCandidates.First().Size);
+
+            // If we're unable to send the packet before the gate closes again, return 0 to signal that we did not waste any bytes for preempted packets.
+            if (postPreemptionPacket.Size > totalBudget)
+            {
+                Debug.WriteLine($"Unable to send post-preemption packet {postPreemptionPacket} before Gate Closing Event!");
+                return 0;
+            }
+
+            // Signal to the queue that we've accepted the preempted packet and send it atomically.
+            eventAggregator.GetEvent<PacketSubmitResultEvent>().Publish((preemptedQueue, PacketSubmitResult.Accepted));
+
+            Debug.WriteLine($"Sending post-preemption packet {postPreemptionPacket}...");
+            eventAggregator.GetEvent<TransmissionStartedEvent>().Publish(postPreemptionPacket.Priority);
+
+            Thread.Sleep(TimeSpan.FromSeconds(postPreemptionPacket.Size /
+                                              settingService.GetSettingValue<double>(BitrateSettingKey)));
+
+            Debug.WriteLine($"Transmission of post-preemption packet {postPreemptionPacket} finished!");
+            eventAggregator.GetEvent<TransmissionFinishedEvent>().Publish((postPreemptionPacket.Priority,
+                settingService.GetSettingValue<int>(BitrateSettingKey)));
+
+            // Reset the preemptedQueue variable and return the size of the packet that was sent so that the byte budget can be reduced by that number.
+            preemptedQueue = -1;
+            return postPreemptionPacket.Size;
+        }
+
+        private long PerformCycle(ISet<int> openedGates, long cycleByteBudget)
         {
             // Init byte budget.
             var cycleBudget = cycleByteBudget;
 
-            // Cleanup the previous send candidates and request new packets from the queues with opened gates.
+            // Cleanup the previous send candidates and request new packets from the queues with opened gates, except of the one whose packet was previously preempted.
             sendCandidates.Clear();
-            eventAggregator.GetEvent<PacketSubmitRequestEvent>().Publish(openedGates);
+
+            var queriedGates = new HashSet<int>(openedGates.Except(Enumerable.Repeat(preemptedQueue, 1)));
+            eventAggregator.GetEvent<PacketSubmitRequestEvent>().Publish(queriedGates);
 
             // Await all packets to arrive.
-            AwaitPacketArrival(openedGates.Count);
+            AwaitPacketArrival(queriedGates.Count);
 
             // When all packets have arrived, sort them descending and check if we can send them in time.
             var selectedPacket = PriorityPacket.NoPacket;
             foreach (var sendCandidate in sendCandidates.Except(Enumerable.Repeat(PriorityPacket.NoPacket, 1))
                 .OrderByDescending(packet => packet.Priority))
             {
-                if (selectedPacket == PriorityPacket.NoPacket && CanSendInTime(sendCandidate, cycleBudget))
+                if (selectedPacket == PriorityPacket.NoPacket && preemptionHandler.CanSend(sendCandidate, cycleBudget))
                 {
-                    // If we can send it in time and there was nothing selected yet...
-                    // ... reduce transmittable bytes.
-                    cycleBudget -= sendCandidate.Size;
-
+                    // If we can send it and there was nothing selected yet...
                     // ... notify the queue that its packet was selected.
                     eventAggregator.GetEvent<PacketSubmitResultEvent>()
                         .Publish((sendCandidate.Priority, PacketSubmitResult.Accepted));
@@ -177,9 +285,9 @@ namespace CBSVisualizer.Modules.Link.ViewModels
                     //... add it to the sending queue.
                     selectedPacket = sendCandidate;
                 }
-                else if (selectedPacket == PriorityPacket.NoPacket && !CanSendInTime(sendCandidate, cycleBudget))
+                else if (selectedPacket == PriorityPacket.NoPacket && !preemptionHandler.CanSend(sendCandidate, cycleBudget))
                 {
-                    // If nothing was selected and we cannot send in time, the packet was denied due to pre-closing.
+                    // If nothing was selected and we cannot send, the packet was denied due to pre-closing.
                     // Notify the queue.
                     eventAggregator.GetEvent<PacketSubmitResultEvent>()
                         .Publish((sendCandidate.Priority, PacketSubmitResult.DeniedPreClosing));
@@ -196,24 +304,109 @@ namespace CBSVisualizer.Modules.Link.ViewModels
             // Send the packet that we've just selected.
             if (selectedPacket != PriorityPacket.NoPacket)
             {            
-                TransmitPacket(selectedPacket);
+                TransmitPacket(selectedPacket, cycleBudget);
             }
 
+            // Reduce transmittable bytes.
+            cycleBudget -= selectedPacket.Size;
 
             return cycleBudget;
         }
 
-        private void TransmitPacket(PriorityPacket selectedPacket)
+        private void TransmitPacket(PriorityPacket selectedPacket, long byteBudget)
+        {
+            // Highest prio packet cannot be preempted.
+            if (selectedPacket.Priority == 7)
+            {
+                Debug.WriteLine($"Packet {selectedPacket} is being sent non-preemptable.");
+                TransmitNonPreemptable(selectedPacket);
+            }
+            else // All others can.
+            {
+                Debug.WriteLine($"Packet {selectedPacket} is being sent preemptable.");
+                TransmitPreemptable(selectedPacket, byteBudget);
+            }
+        }
+
+        private void TransmitPreemptable(PriorityPacket selectedPacket, long byteBudget)
         {
             Log.Info($"Sending {selectedPacket}...");
-            eventAggregator.GetEvent<TransmissionStartedEvent>().Publish((selectedPacket.Priority,
+            eventAggregator.GetEvent<TransmissionStartedEvent>().Publish(selectedPacket.Priority);
+
+            var bytesLeft = selectedPacket.Size;
+            while (bytesLeft > 0)
+            {
+                // If the GateOpenedEvent for the Higher-Prio gates arrived and the preemption took place, return.
+                if (gateOpenedTokenSrc.IsCancellationRequested && WasPreempted(selectedPacket, byteBudget, bytesLeft))
+                {
+                    return;
+                }
+
+                // Otherwise, just send 32 bytes
+                Thread.Sleep(TimeSpan.FromSeconds(32 /
+                                                  settingService.GetSettingValue<double>(BitrateSettingKey)));
+                bytesLeft -= 32;
+            }
+
+            Log.Info($"Transmission of {selectedPacket} finished!");
+            eventAggregator.GetEvent<TransmissionFinishedEvent>().Publish((selectedPacket.Priority,
                 settingService.GetSettingValue<int>(BitrateSettingKey)));
+        }
+
+        /// <summary>
+        /// Check if preemption can take place and handle it.
+        /// </summary>
+        /// <param name="selectedPacket">the packet that was originally being transmitted</param>
+        /// <param name="byteBudget">the byte budget before the GateCloseEvent</param>
+        /// <param name="bytesLeft">the remaining bytes of the selected packet that need to be transmitted.</param>
+        /// <returns></returns>
+        private bool WasPreempted(PriorityPacket selectedPacket, long byteBudget, int bytesLeft)
+        {
+            // Check if a priority 7 packet is available.
+            var highPriorityPacket = QueryHighPriorityPacket();
+
+            if (highPriorityPacket != PriorityPacket.NoPacket &&
+                preemptionHandler.CanPreempt(selectedPacket, bytesLeft, byteBudget - (selectedPacket.Size - bytesLeft)))
+            {
+                Debug.WriteLine($"Packet {selectedPacket} was preempted by packet {highPriorityPacket}");
+
+                // Signal to the queue that its packet has been preempted.
+                eventAggregator.GetEvent<PacketPreemptedEvent>().Publish((selectedPacket.Priority, bytesLeft));
+
+                // Transmit the high-prio packet.
+                TransmitNonPreemptable(highPriorityPacket);
+
+                // Save the info about how many bytes of the preempting packet we still have to send in the "Gate Opened Time" of the High-Prio gate.
+                preemptingPacketLeftoverBytes = Math.Min(0,
+                    highPriorityPacket.Size - (byteBudget - (selectedPacket.Size - bytesLeft)));
+
+                // Remember that we have to send the leftovers of this packet before the next regular contention cycle of the lower-prio gates.
+                preemptedQueue = selectedPacket.Priority;
+                return true;
+            }
+
+            return false;
+        }
+
+        private PriorityPacket QueryHighPriorityPacket()
+        {
+            sendCandidates.Clear();
+            eventAggregator.GetEvent<PacketSubmitRequestEvent>().Publish(new HashSet<int> {7});
+            AwaitPacketArrival(1);
+            return sendCandidates.First();
+        }
+
+        private void TransmitNonPreemptable(PriorityPacket selectedPacket)
+        {
+            Log.Info($"Sending {selectedPacket}...");
+            eventAggregator.GetEvent<TransmissionStartedEvent>().Publish(selectedPacket.Priority);
 
             Thread.Sleep(TimeSpan.FromSeconds(selectedPacket.Size /
                                               settingService.GetSettingValue<double>(BitrateSettingKey)));
 
             Log.Info($"Transmission of {selectedPacket} finished!");
-            eventAggregator.GetEvent<TransmissionFinishedEvent>().Publish(selectedPacket.Priority);
+            eventAggregator.GetEvent<TransmissionFinishedEvent>().Publish((selectedPacket.Priority,
+                settingService.GetSettingValue<int>(BitrateSettingKey)));
         }
 
         private void AwaitPacketArrival(int openedGatesCount)
@@ -225,11 +418,6 @@ namespace CBSVisualizer.Modules.Link.ViewModels
             }
         }
 
-        private bool CanSendInTime(PriorityPacket packet, int budget)
-        {
-            return packet.Size <= budget;
-        }
-
         /// <summary>
         ///     Sets the status lamps according to the set.
         /// </summary>
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs
index fb81ad22048541a97028b02dcb9bf6d0260f344b..f34fcf8821f9af1b930b4105f8042f8846e2b5d4 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/QueueImplementations/ReturnToZeroQueue.cs
@@ -30,9 +30,10 @@ namespace CBSVisualizer.Modules.Queue.QueueImplementations
 
         public override void OnPacketDeniedPreClosing()
         {
+            var preUpdateCredit = Credit;
             deniedPreClosing = true;
             UpdateUsingInternalSlope();
-            if (Credit > 0)
+            if (preUpdateCredit < 0 && Credit > 0)
             {
                 UpdateCredit(0);
                 Credit = 0;
diff --git a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs
index 9ba6cda7bc09634803b6a084dd23bcb9eedd5fd4..ffff6fe65965459114d58f7db5ee3fcdac59645f 100644
--- a/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs
+++ b/CBSVisualizer/CBSVisualizer.Modules.Queue/ViewModels/QueueViewModel.cs
@@ -161,20 +161,20 @@ namespace CBSVisualizer.Modules.Queue.ViewModels
                 }
             });
 
-            eventAggregator.GetEvent<TransmissionFinishedEvent>().Subscribe(async priority =>
+            eventAggregator.GetEvent<TransmissionFinishedEvent>().Subscribe(async tuple =>
             {
+                var (priority, bitrate) = tuple; 
                 if (priority != Priority)
                 {
                     return;
                 }
 
                 transmissionFinishedPending = false;
-                await Task.Run(() => QueueImplementation.OnTransmissionFinished(Queue.GetRemoveFirstSynchronized(), settings.GetSettingValue<long>("bitrate")));
+                await Task.Run(() => QueueImplementation.OnTransmissionFinished(Queue.GetRemoveFirstSynchronized(), bitrate));
             });
 
-            eventAggregator.GetEvent<TransmissionStartedEvent>().Subscribe(async tuple =>
+            eventAggregator.GetEvent<TransmissionStartedEvent>().Subscribe(async priority =>
             {
-                var (priority, bytesPerSecond) = tuple;
                 if (priority != Priority)
                 {
                     return;
@@ -261,7 +261,7 @@ namespace CBSVisualizer.Modules.Queue.ViewModels
 
             GeneratePacketOnClick = new DelegateCommand(async () =>
             {
-                await Task.Run(() => { Queue.AddSynchronized(packetService.GeneratePacket(Priority)); });
+                await Task.Run(() => Queue.AddSynchronized(packetService.GeneratePacket(Priority)));
             });
         }
     }
diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj b/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj
index eda9d73f06d6235e9421e4ce3541bb4321da4ddf..1a6d97eabd55b33cb39f8d1252cb656d61a81ae9 100644
--- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj
+++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/CBSVisualizer.Services.SettingService.csproj
@@ -12,4 +12,8 @@
     <PackageReference Include="Prism.Core" Version="7.2.0.1422" />
   </ItemGroup>
 
+  <ItemGroup>
+    <ProjectReference Include="..\CBSVisualizer.Common\CBSVisualizer.Common.csproj" />
+  </ItemGroup>
+
 </Project>
diff --git a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs
index d4f53f405dbcdee903b9257292417b69256aa2bc..f2d660fae87e7808c4753af824958853da2ff7e7 100644
--- a/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs
+++ b/CBSVisualizer/CBSVisualizer.Services.SettingsService/Implementation/SettingService.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
+using CBSVisualizer.Common.Enums;
 using CBSVisualizer.Services.SettingService.Types;
 using CBSVisualizer.Services.SettingService.Types.Abstract;
 
@@ -18,6 +19,17 @@ namespace CBSVisualizer.Services.SettingService.Implementation
             InitializeCommonGroup();
             InitializeSchedulersGroup();
             InitializeLoadGenerationGroup();
+            InitializePreemptionGroup();
+        }
+
+        private void InitializePreemptionGroup()
+        {
+            var preemptionGroupMembers = new ObservableCollection<Setting>();
+
+            // Preemption mode.
+            ISet<String> preemptionModes = new HashSet<string>{Enum.GetName(typeof(PreemptionType), PreemptionType.NonPreemptive), Enum.GetName(typeof(PreemptionType), PreemptionType.PreemptionNoHoldRelease), Enum.GetName(typeof(PreemptionType), PreemptionType.PreemptionWithHoldRelease) };
+            preemptionGroupMembers.Add(new SelectionSetting("preemption_mode", "Preemption Mode", preemptionModes.First(), preemptionModes));
+            settingGroups.Add(new SettingGroup("Preemption", preemptionGroupMembers));
         }
 
         private void InitializeLoadGenerationGroup()
@@ -25,7 +37,7 @@ namespace CBSVisualizer.Services.SettingService.Implementation
             var loadGenerationGroupMembers = new ObservableCollection<Setting>();
 
             // Packet interarrival time.
-            loadGenerationGroupMembers.Add(new StringSetting("interarrival_time", "Packet Inter-Arrival Time [ms]", "500"));
+            loadGenerationGroupMembers.Add(new StringSetting("interarrival_time", "Packet Inter-Arrival Time [ms]", "100"));
 
             settingGroups.Add(new SettingGroup("Load Generation", loadGenerationGroupMembers));
         }
@@ -50,7 +62,7 @@ namespace CBSVisualizer.Services.SettingService.Implementation
             var commonGroupMembers = new ObservableCollection<Setting>();
 
             // Link bitrate.
-            commonGroupMembers.Add(new StringSetting("bitrate", "Link Bitrate [byte/s]", "1000"));
+            commonGroupMembers.Add(new StringSetting("bitrate", "Link Bitrate [byte/s]", "10000"));
 
             settingGroups.Add(new SettingGroup("Common", commonGroupMembers));
         }