introduced xran UE context ID
diff --git a/src/main/java/org.onosproject.xran/controller/XranChannelHandler.java b/src/main/java/org.onosproject.xran/controller/XranChannelHandler.java
index 2a82205..764f55c 100644
--- a/src/main/java/org.onosproject.xran/controller/XranChannelHandler.java
+++ b/src/main/java/org.onosproject.xran/controller/XranChannelHandler.java
@@ -23,23 +23,17 @@
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.channel.sctp.SctpMessage;
 import org.apache.commons.lang.exception.ExceptionUtils;
-import org.onosproject.net.DeviceId;
-import org.onosproject.xran.codecs.pdu.XrancPdu;
 import org.onosproject.xran.codecs.ber.BerByteArrayOutputStream;
+import org.onosproject.xran.codecs.pdu.XrancPdu;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.xml.bind.DatatypeConverter;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
-import java.net.URI;
 import java.net.URISyntaxException;
-import java.nio.charset.Charset;
-
-import static org.onosproject.net.DeviceId.deviceId;
 
 /**
  * Created by dimitris on 7/20/17.
@@ -89,7 +83,7 @@
     }
 
     @Override
-    public void channelRead(ChannelHandlerContext ctx, Object msg) throws IOException {
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws IOException, InterruptedException {
         SctpMessage sctpMessage = (SctpMessage) msg;
         ByteBuf byteBuf = sctpMessage.content();
 
diff --git a/src/main/java/org.onosproject.xran/controller/XranController.java b/src/main/java/org.onosproject.xran/controller/XranController.java
index 02f8378..0ab91ef 100644
--- a/src/main/java/org.onosproject.xran/controller/XranController.java
+++ b/src/main/java/org.onosproject.xran/controller/XranController.java
@@ -28,7 +28,7 @@
  */
 public interface XranController {
 
-    SynchronousQueue<String> sendHORequest(RnibLink newLink, RnibLink oldLink);
+    SynchronousQueue<String> sendHORequest(RnibLink newLink, RnibLink oldLink) throws InterruptedException;
 
     void addListener(XranDeviceListener listener);
 
@@ -43,4 +43,8 @@
     SynchronousQueue<String> sendScellAdd(RnibLink link);
 
     boolean sendScellDelete(RnibLink link);
+
+    int getNorthbound_timeout();
+
+    void setNorthbound_timeout(int northbound_timeout);
 }
diff --git a/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java b/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java
index 9497bf4..99e79a7 100644
--- a/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java
+++ b/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java
@@ -38,7 +38,9 @@
 import org.onosproject.xran.entities.RnibCell;
 import org.onosproject.xran.entities.RnibLink;
 import org.onosproject.xran.entities.RnibUe;
+import org.onosproject.xran.identifiers.EcgiCrntiPair;
 import org.onosproject.xran.identifiers.LinkId;
+import org.onosproject.xran.identifiers.contextUpdateHandler;
 import org.onosproject.xran.impl.XranConfig;
 import org.onosproject.xran.providers.XranDeviceListener;
 import org.onosproject.xran.providers.XranHostListener;
@@ -50,17 +52,14 @@
 
 import java.io.IOException;
 import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.*;
 import java.util.stream.Collectors;
 
 import static org.onosproject.net.DeviceId.deviceId;
 import static org.onosproject.xran.controller.XranChannelHandler.getSctpMessage;
 import static org.onosproject.xran.entities.RnibCell.decodeDeviceId;
 import static org.onosproject.xran.entities.RnibCell.uri;
-import static org.onosproject.xran.entities.RnibUe.hostIdtoMME;
+import static org.onosproject.xran.entities.RnibUe.hostIdtoUEId;
 
 /**
  * Created by dimitris on 7/20/17.
@@ -80,7 +79,7 @@
     private final Controller controller = new Controller();
     private XranConfig xranConfig;
     private ApplicationId appId;
-    public int northbound_timeout;
+    private int northbound_timeout;
     /* Services */
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private DeviceService deviceService;
@@ -108,9 +107,12 @@
     private LinkMap linkMap;
     /* MAPS */
     private ConcurrentMap<String, ECGI> legitCells = new ConcurrentHashMap<>();
-    private ConcurrentMap<ECGI, SynchronousQueue<String>> hoQueue = new ConcurrentHashMap<>();
-    private ConcurrentMap<ECGI, SynchronousQueue<String>> RRMCellQueue = new ConcurrentHashMap<>();
-    private ConcurrentMap<CRNTI, SynchronousQueue<String>> scellAddQueue = new ConcurrentHashMap<>();
+    private ConcurrentMap<ECGI, SynchronousQueue<String>> hoMap = new ConcurrentHashMap<>();
+    private ConcurrentMap<ECGI, SynchronousQueue<String>> RRMCellMap = new ConcurrentHashMap<>();
+    private ConcurrentMap<CRNTI, SynchronousQueue<String>> scellAddMap = new ConcurrentHashMap<>();
+    private ConcurrentMap<EcgiCrntiPair, contextUpdateHandler> contextUpdateMap = new ConcurrentHashMap<>();
+    /* QUEUE */
+    private BlockingQueue<Long> ueIdQueue = new LinkedBlockingQueue<>();
     /* AGENTS */
     private InternalXranDeviceAgent deviceAgent = new InternalXranDeviceAgent();
     private InternalXranHostAgent hostAgent = new InternalXranHostAgent();
@@ -155,24 +157,28 @@
     }
 
     @Override
-    public SynchronousQueue<String> sendHORequest(RnibLink link_t, RnibLink link_s) {
+    public SynchronousQueue<String> sendHORequest(RnibLink link_t, RnibLink link_s) throws InterruptedException {
         ECGI ecgi_t = link_t.getLinkId().getEcgi(),
                 ecgi_s = link_s.getLinkId().getEcgi();
 
-        CRNTI crnti = linkMap.getCrnti(link_t.getLinkId().getMmeues1apid());
+        CRNTI crnti = linkMap.getCrnti(link_t.getLinkId().getUeId());
         ChannelHandlerContext ctx_t = cellMap.getCtx(ecgi_t),
                 ctx_s = cellMap.getCtx(ecgi_s);
 
+
+        SynchronousQueue<String> queue = new SynchronousQueue<>();
         try {
             XrancPdu xrancPdu = HORequest.constructPacket(crnti, ecgi_s, ecgi_t);
+
+            hoMap.put(ecgi_s, queue);
+
             ctx_t.writeAndFlush(getSctpMessage(xrancPdu));
             ctx_s.writeAndFlush(getSctpMessage(xrancPdu));
         } catch (IOException e) {
             e.printStackTrace();
         }
 
-        SynchronousQueue<String> queue = new SynchronousQueue<>();
-        hoQueue.put(ecgi_s, queue);
+        ueIdQueue.put(link_t.getLinkId().getUeId());
 
         return queue;
     }
@@ -198,11 +204,21 @@
     }
 
     @Override
+    public int getNorthbound_timeout() {
+        return northbound_timeout;
+    }
+
+    @Override
+    public void setNorthbound_timeout(int northbound_timeout) {
+        this.northbound_timeout = northbound_timeout;
+    }
+
+    @Override
     public SynchronousQueue<String> sendModifiedRRMConf(RRMConfig rrmConfig, boolean xICIC) {
         ECGI ecgi = rrmConfig.getEcgi();
         ChannelHandlerContext ctx = cellMap.getCtx(ecgi);
         try {
-            XrancPdu pdu = null;
+            XrancPdu pdu;
 
             if (xICIC) {
                 CellConfigReport cellConfigReport = cellMap.get(ecgi).getConf();
@@ -214,7 +230,7 @@
                 pdu = RRMConfig.constructPacket(rrmConfig);
                 ctx.writeAndFlush(getSctpMessage(pdu));
                 SynchronousQueue<String> queue = new SynchronousQueue<>();
-                RRMCellQueue.put(ecgi, queue);
+                RRMCellMap.put(ecgi, queue);
                 return queue;
             }
         } catch (IOException e) {
@@ -231,7 +247,7 @@
         ECGI primaryEcgi = primaryCell.getEcgi();
         ChannelHandlerContext ctx = cellMap.getCtx(primaryEcgi);
 
-        CRNTI crnti = linkMap.getCrnti(link.getLinkId().getMmeues1apid());
+        CRNTI crnti = linkMap.getCrnti(link.getLinkId().getUeId());
 
         CellConfigReport cellReport = secondaryCell.getConf();
 
@@ -247,7 +263,7 @@
             try {
                 ctx.writeAndFlush(getSctpMessage(pdu));
                 SynchronousQueue<String> queue = new SynchronousQueue<>();
-                scellAddQueue.put(crnti, queue);
+                scellAddMap.put(crnti, queue);
 
                 return queue;
             } catch (IOException e) {
@@ -265,7 +281,7 @@
         ECGI primaryEcgi = primaryCell.getEcgi();
         ChannelHandlerContext ctx = cellMap.getCtx(primaryEcgi);
 
-        CRNTI crnti = linkMap.getCrnti(link.getLinkId().getMmeues1apid());
+        CRNTI crnti = linkMap.getCrnti(link.getLinkId().getUeId());
 
         CellConfigReport cellReport = secondaryCell.getConf();
 
@@ -296,7 +312,7 @@
             public void run() {
                 if (ue.getState() == RnibUe.State.IDLE) {
                     hostAgent.removeConnectedHost(ue);
-                    log.info("UE is removed after 10 seconds of IDLE");
+                    log.info("UE is removed after {} ms of IDLE", xranConfig.getIdleUeRemoval());
                 } else {
                     log.info("UE not removed cause its ACTIVE");
                 }
@@ -312,7 +328,7 @@
             public void run() {
                 LinkId linkId = link.getLinkId();
                 xranStore.removeLink(linkId);
-                log.info("Link is removed after not receiving Meas Reports for 10 seconds");
+                log.info("Link is removed after not receiving Meas Reports for {} ms", xranConfig.getNoMeasLinkRemoval());
             }
         }, xranConfig.getNoMeasLinkRemoval());
 
@@ -363,7 +379,7 @@
                                                         });
                                                         XrancPdu xrancPdu = RXSigMeasConfig.constructPacket(
                                                                 primary_ecgi,
-                                                                ue.getRanId(),
+                                                                ue.getCrnti(),
                                                                 measCells,
                                                                 xranConfig.getRxSignalInterval()
                                                         );
@@ -415,7 +431,7 @@
             switch (event.type()) {
                 case HOST_ADDED:
                 case HOST_MOVED: {
-                    RnibUe ue = ueMap.get(hostIdtoMME(event.subject().id()));
+                    RnibUe ue = ueMap.get(hostIdtoUEId(event.subject().id()));
                     if (ue != null) {
                         ECGI ecgi_primary = linkMap.getPrimaryCell(ue).getEcgi();
                         RnibCell primary = cellMap.get(ecgi_primary);
@@ -431,7 +447,7 @@
                                                     ChannelHandlerContext ctx = cellMap.getCtx(primary.getEcgi());
                                                     XrancPdu xrancPdu = UECapabilityEnquiry.constructPacket(
                                                             primary.getEcgi(),
-                                                            ue.getRanId());
+                                                            ue.getCrnti());
                                                     ctx.writeAndFlush(getSctpMessage(xrancPdu));
                                                 } catch (IOException e) {
                                                     log.warn(ExceptionUtils.getFullStackTrace(e));
@@ -461,7 +477,7 @@
                                     });
                                     XrancPdu xrancPdu = RXSigMeasConfig.constructPacket(
                                             primary.getEcgi(),
-                                            ue.getRanId(),
+                                            ue.getCrnti(),
                                             measCells,
                                             xranConfig.getRxSignalInterval()
                                     );
@@ -535,13 +551,15 @@
         @Override
         public boolean addConnectedHost(RnibUe ue, RnibCell cell, ChannelHandlerContext ctx) {
 
-            if (ueMap.get(ue.getMmeS1apId()) != null) {
+            if (ue.getId() != null && ueMap.get(ue.getId()) != null) {
                 linkMap.putPrimaryLink(cell, ue);
 
-                Set<ECGI> ecgiSet = xranStore.getLinksByUeId(ue.getMmeS1apId().longValue())
+                Set<ECGI> ecgiSet = Sets.newConcurrentHashSet();
+
+                ecgiSet.add(xranStore.getLinksByUeId(ue.getId())
                         .stream()
-                        .map(l -> l.getLinkId().getEcgi())
-                        .collect(Collectors.toSet());
+                        .filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY))
+                        .findFirst().get().getLinkId().getEcgi());
 
                 for (XranHostListener l : xranHostListeners) {
                     l.hostAdded(ue, ecgiSet);
@@ -563,9 +581,9 @@
 
         @Override
         public boolean removeConnectedHost(RnibUe ue) {
-            List<RnibLink> links = xranStore.getLinksByUeId(ue.getMmeS1apId().longValue());
+            List<RnibLink> links = xranStore.getLinksByUeId(ue.getId());
             links.forEach(rnibLink -> xranStore.removeLink(rnibLink.getLinkId()));
-            if (ueMap.remove(ue.getMmeS1apId())) {
+            if (ueMap.remove(ue.getId())) {
                 for (XranHostListener l : xranHostListeners) {
                     l.hostRemoved(ue.getHostId());
                 }
@@ -577,7 +595,7 @@
 
     public class InternalXranPacketAgent implements XranPacketProcessor {
         @Override
-        public void handlePacket(XrancPdu recv_pdu, ChannelHandlerContext ctx) throws IOException {
+        public void handlePacket(XrancPdu recv_pdu, ChannelHandlerContext ctx) throws IOException, InterruptedException {
             XrancPdu send_pdu;
 
             int apiID = recv_pdu.getHdr().getApiId().intValue();
@@ -621,23 +639,46 @@
                             ue.setState(RnibUe.State.IDLE);
                         }
                     }
+
+                    if (ueAdmissionStatus.getAdmEstStatus().value.intValue() == 0) {
+                        EcgiCrntiPair ecgiCrntiPair = EcgiCrntiPair.valueOf(ueAdmissionStatus.getEcgi(), ueAdmissionStatus.getCrnti());
+                        contextUpdateMap.compute(ecgiCrntiPair, (k, v) -> {
+                            if (v == null) {
+                                v = new contextUpdateHandler();
+                            }
+                            if (v.setAdmissionStatus(ueAdmissionStatus)) {
+                                handleContextUpdate(v.getContextUpdate(), ctx, false);
+                            }
+                            return v;
+                        });
+                    }
                     break;
                 }
                 case 5: {
-                    // Decode UE Admission Context Update.
+                    // Decode UE Context Update.
                     UEContextUpdate ueContextUpdate = recv_pdu.getBody().getUEContextUpdate();
+                    EcgiCrntiPair ecgiCrntiPair = EcgiCrntiPair.valueOf(ueContextUpdate.getEcgi(), ueContextUpdate.getCrnti());
 
-                    RnibUe ue = ueMap.get(ueContextUpdate.getMMEUES1APID());
-                    RnibCell cell = xranStore.getCell(ueContextUpdate.getEcgi());
-                    if (ue == null) {
-                        ue = new RnibUe();
-                    }
-
-                    ue.setMmeS1apId(ueContextUpdate.getMMEUES1APID());
-                    ue.setEnbS1apId(ueContextUpdate.getENBUES1APID());
-                    ue.setRanId(ueContextUpdate.getCrnti());
-
-                    hostAgent.addConnectedHost(ue, cell, ctx);
+                    contextUpdateMap.compute(ecgiCrntiPair, (k, v) -> {
+                        if (v == null) {
+                            v = new contextUpdateHandler();
+                        }
+                        if (v.setContextUpdate(ueContextUpdate)) {
+                            HOComplete hoComplete = v.getHoComplete();
+                            handleContextUpdate(ueContextUpdate, ctx, hoComplete != null);
+                            if (hoComplete != null) {
+                                try {
+                                    hoMap.get(hoComplete.getEcgiS()).put("Hand Over Completed");
+                                } catch (InterruptedException e) {
+                                    log.error(ExceptionUtils.getFullStackTrace(e));
+                                    e.printStackTrace();
+                                } finally {
+                                    hoMap.remove(hoComplete.getEcgiS());
+                                }
+                            }
+                        }
+                        return v;
+                    });
 
                     break;
                 }
@@ -647,7 +688,7 @@
                     RnibUe ue = ueMap.get(ueReconfigInd.getEcgi(), ueReconfigInd.getCrntiOld());
 
                     if (ue != null) {
-                        ue.setRanId(ueReconfigInd.getCrntiNew());
+                        ue.setCrnti(ueReconfigInd.getCrntiNew());
                     } else {
                         log.warn("Could not find UE with this CRNTI: {}", ueReconfigInd.getCrntiOld());
                     }
@@ -718,13 +759,14 @@
                     HOFailure hoFailure = recv_pdu.getBody().getHOFailure();
 
                     try {
-                        hoQueue.get(hoFailure.getEcgi())
+                        hoMap.get(hoFailure.getEcgi())
                                 .put("Hand Over Failed with cause: " + hoFailure.getCause());
                     } catch (InterruptedException e) {
                         log.error(ExceptionUtils.getFullStackTrace(e));
                         e.printStackTrace();
                     } finally {
-                        hoQueue.remove(hoFailure.getEcgi());
+                        hoMap.remove(hoFailure.getEcgi());
+                        ueIdQueue.take();
                     }
                     break;
 
@@ -732,15 +774,26 @@
                 case 14: {
                     HOComplete hoComplete = recv_pdu.getBody().getHOComplete();
 
-                    try {
-                        hoQueue.get(hoComplete.getEcgiS())
-                                .put("Hand Over Completed");
-                    } catch (InterruptedException e) {
-                        log.error(ExceptionUtils.getFullStackTrace(e));
-                        e.printStackTrace();
-                    } finally {
-                        hoQueue.remove(hoComplete.getEcgiS());
-                    }
+                    EcgiCrntiPair ecgiCrntiPair = EcgiCrntiPair.valueOf(hoComplete.getEcgiT(), hoComplete.getCrntiNew());
+                    contextUpdateMap.compute(ecgiCrntiPair, (k, v) -> {
+                        if (v == null) {
+                            v = new contextUpdateHandler();
+                        }
+                        if (v.setHoComplete(hoComplete)) {
+                            handleContextUpdate(v.getContextUpdate(), ctx, true);
+
+                            try {
+                                hoMap.get(hoComplete.getEcgiS()).put("Hand Over Completed");
+                            } catch (InterruptedException e) {
+                                log.error(ExceptionUtils.getFullStackTrace(e));
+                                e.printStackTrace();
+                            } finally {
+                                hoMap.remove(hoComplete.getEcgiS());
+                            }
+                        }
+                        return v;
+                    });
+
                     break;
                 }
 
@@ -749,73 +802,83 @@
                     RXSigMeasReport rxSigMeasReport = recv_pdu.getBody().getRXSigMeasReport();
                     List<RXSigReport> rxSigReportList = rxSigMeasReport.getCellMeasReports().getRXSigReport();
 
-                    if (!rxSigReportList.isEmpty()) {
-                        rxSigReportList.forEach(rxSigReport -> {
-                            RnibCell cell = cellMap.get(rxSigReport.getPciArfcn());
-                            if (cell != null) {
-                                ECGI ecgi = cell.getEcgi();
-                                RnibLink link = linkMap.get(ecgi, rxSigMeasReport.getCrnti());
-                                if (link == null) {
-                                    log.warn("Could not find link between: {}-{} | Creating non-serving link..", ecgi, rxSigMeasReport.getCrnti());
-                                    link = linkMap.putNonServingLink(cell, rxSigMeasReport.getCrnti());
-                                }
+                    RnibUe ue = ueMap.get(rxSigMeasReport.getEcgi(), rxSigMeasReport.getCrnti());
+                    if (ue != null) {
+                        Long ueId = ue.getId();
 
-                                if (link != null) {
-                                    if (link.getType().equals(RnibLink.Type.NON_SERVING)) {
-                                        restartTimer(link);
+                        if (!rxSigReportList.isEmpty()) {
+                            rxSigReportList.forEach(rxSigReport -> {
+                                RnibCell cell = cellMap.get(rxSigReport.getPciArfcn());
+                                if (cell != null) {
+                                    ECGI ecgi = cell.getEcgi();
+
+                                    RnibLink link = linkMap.get(ecgi, ueId);
+                                    if (link == null) {
+                                        log.warn("Could not find link between: {}-{} | Creating non-serving link..", ecgi, ueId);
+                                        link = linkMap.putNonServingLink(cell, ueId);
                                     }
 
-                                    RSRQRange rsrq = rxSigReport.getRsrq();
-                                    RSRPRange rsrp = rxSigReport.getRsrp();
+                                    if (link != null) {
+                                        if (link.getType().equals(RnibLink.Type.NON_SERVING)) {
+                                            restartTimer(link);
+                                        }
 
-                                    RnibLink.LinkQuality quality = link.getQuality();
-                                    quality.setRX(new RnibLink.LinkQuality.RX(
-                                            rsrp.value.intValue() - 140,
-                                            (rsrq.value.intValue() * 0.5) - 19.5
-                                    ));
+                                        RSRQRange rsrq = rxSigReport.getRsrq();
+                                        RSRPRange rsrp = rxSigReport.getRsrp();
+
+                                        RnibLink.LinkQuality quality = link.getQuality();
+                                        quality.setRX(new RnibLink.LinkQuality.RX(
+                                                rsrp.value.intValue() - 140,
+                                                (rsrq.value.intValue() * 0.5) - 19.5
+                                        ));
+                                    }
+                                } else {
+                                    log.warn("case 16: Could not find cell with PCI-ARFCN: {}", rxSigReport.getPciArfcn());
                                 }
-                            } else {
-                                log.warn("case 16: Could not find cell with PCI-ARFCN: {}", rxSigReport.getPciArfcn());
-                            }
-                        });
+                            });
+                        }
                     }
                     break;
                 }
                 case 18: {
                     RadioMeasReportPerUE radioMeasReportPerUE = recv_pdu.getBody().getRadioMeasReportPerUE();
 
-                    List<RadioRepPerServCell> servCells = radioMeasReportPerUE.getRadioReportServCells().getRadioRepPerServCell();
+                    RnibUe ue = ueMap.get(radioMeasReportPerUE.getEcgi(), radioMeasReportPerUE.getCrnti());
+                    if (ue != null) {
+                        Long ueId = ue.getId();
+                        List<RadioRepPerServCell> servCells = radioMeasReportPerUE.getRadioReportServCells().getRadioRepPerServCell();
 
-                    servCells.forEach(servCell -> {
-                        RnibCell cell = cellMap.get(servCell.getPciArfcn());
-                        if (cell != null) {
-                            RnibLink link = linkMap.get(cell.getEcgi(), radioMeasReportPerUE.getCrnti());
-                            if (link != null) {
-                                RadioRepPerServCell.CqiHist cqiHist = servCell.getCqiHist();
-                                RnibLink.LinkQuality quality = link.getQuality();
+                        servCells.forEach(servCell -> {
+                            RnibCell cell = cellMap.get(servCell.getPciArfcn());
+                            if (cell != null) {
+                                RnibLink link = linkMap.get(cell.getEcgi(), ueId);
+                                if (link != null) {
+                                    RadioRepPerServCell.CqiHist cqiHist = servCell.getCqiHist();
+                                    RnibLink.LinkQuality quality = link.getQuality();
 
-                                final double[] values = {0, 0, 0};
-                                final int[] i = {1};
-                                cqiHist.getBerInteger().forEach(value -> {
-                                    values[0] = Math.max(values[0], value.intValue());
-                                    values[1] += i[0] * value.intValue();
-                                    values[2] += value.intValue();
-                                    i[0]++;
-                                });
+                                    final double[] values = {0, 0, 0};
+                                    final int[] i = {1};
+                                    cqiHist.getBerInteger().forEach(value -> {
+                                        values[0] = Math.max(values[0], value.intValue());
+                                        values[1] += i[0] * value.intValue();
+                                        values[2] += value.intValue();
+                                        i[0]++;
+                                    });
 
-                                quality.setCQI(new RnibLink.LinkQuality.CQI(
-                                        cqiHist,
-                                        values[0],
-                                        values[1] / values[0]
-                                ));
+                                    quality.setCQI(new RnibLink.LinkQuality.CQI(
+                                            cqiHist,
+                                            values[0],
+                                            values[1] / values[0]
+                                    ));
 
+                                } else {
+                                    log.warn("Could not find link between: {}-{}", cell.getEcgi(), ueId);
+                                }
                             } else {
-                                log.warn("Could not find link between: {}-{}", cell.getEcgi(), radioMeasReportPerUE.getCrnti());
+                                log.warn("case 18: Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
                             }
-                        } else {
-                            log.warn("case 18: Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
-                        }
-                    });
+                        });
+                    }
                     break;
                 }
                 case 19: {
@@ -824,31 +887,36 @@
                 }
                 case 20: {
                     SchedMeasReportPerUE schedMeasReportPerUE = recv_pdu.getBody().getSchedMeasReportPerUE();
-                    List<SchedMeasRepPerServCell> servCells = schedMeasReportPerUE.getSchedReportServCells()
-                            .getSchedMeasRepPerServCell();
 
-                    servCells.forEach(servCell -> {
-                        RnibCell cell = cellMap.get(servCell.getPciArfcn());
-                        if (cell != null) {
-                            RnibLink link = linkMap.get(cell.getEcgi(), schedMeasReportPerUE.getCrnti());
-                            if (link != null) {
-                                link.getQuality().setMCS(new RnibLink.LinkQuality.MCS(
-                                        servCell.getMcsDl(),
-                                        servCell.getMcsUl()
-                                ));
+                    RnibUe ue = ueMap.get(schedMeasReportPerUE.getEcgi(), schedMeasReportPerUE.getCrnti());
+                    if (ue != null) {
+                        Long ueId = ue.getId();
 
-                                link.setResourceUsage(new RnibLink.ResourceUsage(
-                                        servCell.getPrbUsage().getPrbUsageDl(),
-                                        servCell.getPrbUsage().getPrbUsageUl()
-                                ));
+                        List<SchedMeasRepPerServCell> servCells = schedMeasReportPerUE.getSchedReportServCells()
+                                .getSchedMeasRepPerServCell();
+
+                        servCells.forEach(servCell -> {
+                            RnibCell cell = cellMap.get(servCell.getPciArfcn());
+                            if (cell != null) {
+                                RnibLink link = linkMap.get(cell.getEcgi(), ueId);
+                                if (link != null) {
+                                    link.getQuality().setMCS(new RnibLink.LinkQuality.MCS(
+                                            servCell.getMcsDl(),
+                                            servCell.getMcsUl()
+                                    ));
+
+                                    link.setResourceUsage(new RnibLink.ResourceUsage(
+                                            servCell.getPrbUsage().getPrbUsageDl(),
+                                            servCell.getPrbUsage().getPrbUsageUl()
+                                    ));
+                                } else {
+                                    log.warn("Could not find link between: {}-{}", cell.getEcgi(), ueId);
+                                }
                             } else {
-                                log.warn("Could not find link between: {}-{}", cell.getEcgi(),
-                                        schedMeasReportPerUE.getCrnti());
+                                log.warn("case 20: Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
                             }
-                        } else {
-                            log.warn("case 20: Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
-                        }
-                    });
+                        });
+                    }
                     break;
                 }
                 case 21: {
@@ -869,20 +937,23 @@
                 case 22: {
                     PDCPMeasReportPerUe pdcpMeasReportPerUe = recv_pdu.getBody().getPDCPMeasReportPerUe();
 
-                    RnibLink link = linkMap.get(pdcpMeasReportPerUe.getEcgi(), pdcpMeasReportPerUe.getCrnti());
-                    if (link != null) {
-                        link.setPdcpThroughput(new RnibLink.PDCPThroughput(
-                                pdcpMeasReportPerUe.getThroughputDl(),
-                                pdcpMeasReportPerUe.getThroughputUl()
-                        ));
+                    RnibUe ue = ueMap.get(pdcpMeasReportPerUe.getEcgi(), pdcpMeasReportPerUe.getCrnti());
+                    if (ue != null) {
+                        Long ueId = ue.getId();
+                        RnibLink link = linkMap.get(pdcpMeasReportPerUe.getEcgi(), ueId);
+                        if (link != null) {
+                            link.setPdcpThroughput(new RnibLink.PDCPThroughput(
+                                    pdcpMeasReportPerUe.getThroughputDl(),
+                                    pdcpMeasReportPerUe.getThroughputUl()
+                            ));
 
-                        link.setPdcpPackDelay(new RnibLink.PDCPPacketDelay(
-                                pdcpMeasReportPerUe.getPktDelayDl(),
-                                pdcpMeasReportPerUe.getPktDelayUl()
-                        ));
-                    } else {
-                        log.warn("Could not find link between: {}-{}", pdcpMeasReportPerUe.getEcgi(),
-                                pdcpMeasReportPerUe.getCrnti());
+                            link.setPdcpPackDelay(new RnibLink.PDCPPacketDelay(
+                                    pdcpMeasReportPerUe.getPktDelayDl(),
+                                    pdcpMeasReportPerUe.getPktDelayUl()
+                            ));
+                        } else {
+                            log.warn("Could not find link between: {}-{}", pdcpMeasReportPerUe.getEcgi(), ueId);
+                        }
                     }
                     break;
                 }
@@ -909,41 +980,44 @@
                 case 27: {
                     //Decode ScellAddStatus
                     ScellAddStatus scellAddStatus = recv_pdu.getBody().getScellAddStatus();
-                    try {
-                        scellAddQueue.get(scellAddStatus.getCrnti()).put("Scell's status: " + scellAddStatus.getStatus());
-                        if (scellAddStatus.getStatus().getBerEnum().get(0).value.intValue() == 0) {
+                    RnibUe ue = ueMap.get(scellAddStatus.getEcgi(), scellAddStatus.getCrnti());
+                    if (ue != null) {
+                        Long ueId = ue.getId();
+                        try {
+                            scellAddMap.get(scellAddStatus.getCrnti()).put("Scell's status: " + scellAddStatus.getStatus());
+                            if (scellAddStatus.getStatus().getBerEnum().get(0).value.intValue() == 0) {
 
-                            scellAddStatus.getScellsInd().getPCIARFCN().forEach(
-                                    pciarfcn -> {
-                                        RnibCell cell = cellMap.get(pciarfcn);
-                                        RnibLink link = linkMap.get(cell.getEcgi(), scellAddStatus.getCrnti());
-                                        link.setType(RnibLink.Type.SERVING_SECONDARY_CA);
-                                    }
-                            );
-                        } else {
-                            log.error("Scell addition failed.");
+                                scellAddStatus.getScellsInd().getPCIARFCN().forEach(
+                                        pciarfcn -> {
+                                            RnibCell cell = cellMap.get(pciarfcn);
+                                            RnibLink link = linkMap.get(cell.getEcgi(), ueId);
+                                            link.setType(RnibLink.Type.SERVING_SECONDARY_CA);
+                                        }
+                                );
+                            } else {
+                                log.error("Scell addition failed.");
+                            }
+                        } catch (InterruptedException e) {
+                            log.error(ExceptionUtils.getFullStackTrace(e));
+                            e.printStackTrace();
+                        } finally {
+                            scellAddMap.remove(scellAddStatus.getCrnti());
                         }
-                    } catch (InterruptedException e) {
-                        log.error(ExceptionUtils.getFullStackTrace(e));
-                        e.printStackTrace();
-                    } finally {
-                        scellAddQueue.remove(scellAddStatus.getCrnti());
                     }
                     break;
                 }
                 // TODO: 28: ScellDelete
-
                 case 30: {
                     // Decode RRMConfig Status
                     RRMConfigStatus rrmConfigStatus = recv_pdu.getBody().getRRMConfigStatus();
                     try {
-                        RRMCellQueue.get(rrmConfigStatus.getEcgi())
+                        RRMCellMap.get(rrmConfigStatus.getEcgi())
                                 .put("RRM Config's status: " + rrmConfigStatus.getStatus());
                     } catch (InterruptedException e) {
                         log.error(ExceptionUtils.getFullStackTrace(e));
                         e.printStackTrace();
                     } finally {
-                        RRMCellQueue.remove(rrmConfigStatus.getEcgi());
+                        RRMCellMap.remove(rrmConfigStatus.getEcgi());
                     }
                     break;
                 }
@@ -951,21 +1025,25 @@
                 case 34: {
                     TrafficSplitConfig trafficSplitConfig = recv_pdu.getBody().getTrafficSplitConfig();
 
-                    List<TrafficSplitPercentage> splitPercentages = trafficSplitConfig.getTrafficSplitPercent().getTrafficSplitPercentage();
+                    RnibUe ue = ueMap.get(trafficSplitConfig.getEcgi(), trafficSplitConfig.getCrnti());
+                    if (ue != null) {
+                        Long ueId = ue.getId();
+                        List<TrafficSplitPercentage> splitPercentages = trafficSplitConfig.getTrafficSplitPercent().getTrafficSplitPercentage();
 
-                    splitPercentages.forEach(trafficSplitPercentage -> {
-                        RnibCell cell = cellMap.get(trafficSplitPercentage.getEcgi());
-                        if (cell != null) {
-                            RnibLink link = linkMap.get(cell.getEcgi(), trafficSplitConfig.getCrnti());
-                            if (link != null) {
-                                link.setTrafficPercent(trafficSplitPercentage);
+                        splitPercentages.forEach(trafficSplitPercentage -> {
+                            RnibCell cell = cellMap.get(trafficSplitPercentage.getEcgi());
+                            if (cell != null) {
+                                RnibLink link = linkMap.get(cell.getEcgi(), ueId);
+                                if (link != null) {
+                                    link.setTrafficPercent(trafficSplitPercentage);
+                                } else {
+                                    log.warn("Could not find link between: {}-{}", cell.getEcgi(), ueId);
+                                }
                             } else {
-                                log.warn("Could not find link between: {}-{}", cell.getEcgi(), trafficSplitConfig.getCrnti());
+                                log.warn("Could not find cell with ECGI: {}", trafficSplitConfig.getEcgi());
                             }
-                        } else {
-                            log.warn("Could not find cell with ECGI: {}", trafficSplitConfig.getEcgi());
-                        }
-                    });
+                        });
+                    }
                     break;
                 }
                 default: {
@@ -975,6 +1053,29 @@
             }
 
         }
+
+        private void handleContextUpdate(UEContextUpdate contextUpdate, ChannelHandlerContext ctx, boolean handoff) {
+            RnibUe ue;
+            RnibCell cell = xranStore.getCell(contextUpdate.getEcgi());
+
+            if (handoff) {
+                try {
+                    ue = ueMap.get(ueIdQueue.take());
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                    log.error(ExceptionUtils.getFullStackTrace(e));
+                    ue = new RnibUe();
+                }
+            } else {
+                ue = new RnibUe();
+            }
+
+            ue.setMmeS1apId(contextUpdate.getMMEUES1APID());
+            ue.setEnbS1apId(contextUpdate.getENBUES1APID());
+            ue.setCrnti(contextUpdate.getCrnti());
+
+            hostAgent.addConnectedHost(ue, cell, ctx);
+        }
     }
 
     class InternalNetworkConfigListener implements NetworkConfigListener {
diff --git a/src/main/java/org.onosproject.xran/controller/XranPacketProcessor.java b/src/main/java/org.onosproject.xran/controller/XranPacketProcessor.java
index c2e1bbc..73cb587 100644
--- a/src/main/java/org.onosproject.xran/controller/XranPacketProcessor.java
+++ b/src/main/java/org.onosproject.xran/controller/XranPacketProcessor.java
@@ -23,5 +23,5 @@
 import java.io.IOException;
 
 public interface XranPacketProcessor {
-    void handlePacket(XrancPdu pdu, ChannelHandlerContext ctx) throws IOException;
+    void handlePacket(XrancPdu pdu, ChannelHandlerContext ctx) throws IOException, InterruptedException;
 }