introduced xran UE context ID
diff --git a/src/main/java/org.onosproject.xran/XranStore.java b/src/main/java/org.onosproject.xran/XranStore.java
index 257e908..00984b9 100644
--- a/src/main/java/org.onosproject.xran/XranStore.java
+++ b/src/main/java/org.onosproject.xran/XranStore.java
@@ -43,11 +43,11 @@
 
     List<RnibLink> getLinksByCellId(String eciHex);
 
-    List<RnibLink> getLinksByUeId(long euId);
+    List<RnibLink> getLinksByUeId(long ueId);
 
-    RnibLink getLinkBetweenCellIdUeId(String cellId, long euId);
+    RnibLink getLinkBetweenCellIdUeId(String cellId, long ueId);
 
-    RnibLink getLink(ECGI ecgi, MMEUES1APID mme);
+    RnibLink getLink(ECGI ecgi, Long ueId);
 
     void modifyLinkRrmConf(RnibLink link, JsonNode rrmConf);
 
@@ -95,9 +95,7 @@
 
     RnibUe getUe(long euId);
 
-    RnibUe getUe(MMEUES1APID mme);
-
     void storeUe(RnibUe ue);
 
-    boolean removeUe(MMEUES1APID mme);
+    boolean removeUe(long ueId);
 }
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;
 }
diff --git a/src/main/java/org.onosproject.xran/entities/RnibCell.java b/src/main/java/org.onosproject.xran/entities/RnibCell.java
index 3179357..ac29eba 100644
--- a/src/main/java/org.onosproject.xran/entities/RnibCell.java
+++ b/src/main/java/org.onosproject.xran/entities/RnibCell.java
@@ -18,9 +18,7 @@
 
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.JsonNode;
-import com.google.common.collect.Lists;
 import org.onosproject.net.DeviceId;
-import org.onosproject.store.Timestamp;
 import org.onosproject.store.service.WallClockTimestamp;
 import org.onosproject.xran.codecs.api.ECGI;
 import org.onosproject.xran.codecs.api.PRBUsage;
@@ -159,7 +157,7 @@
 
     public void modifyRrmConfig(JsonNode rrmConfigNode, List<RnibUe> ueList) throws Exception {
         RRMConfig.Crnti crnti = new RRMConfig.Crnti();
-        ueList.forEach(ue -> crnti.addCRNTI(ue.getRanId()));
+        ueList.forEach(ue -> crnti.addCRNTI(ue.getCrnti()));
 
         {
             JsonNode p_a = rrmConfigNode.path("p_a");
diff --git a/src/main/java/org.onosproject.xran/entities/RnibLink.java b/src/main/java/org.onosproject.xran/entities/RnibLink.java
index 7d2b374..13a0d93 100644
--- a/src/main/java/org.onosproject.xran/entities/RnibLink.java
+++ b/src/main/java/org.onosproject.xran/entities/RnibLink.java
@@ -92,7 +92,7 @@
 
         rrmParameters = new RRMConfig();
         RRMConfig.Crnti crnti = new RRMConfig.Crnti();
-        crnti.addCRNTI(linkId.getUe().getRanId());
+        crnti.addCRNTI(linkId.getUe().getCrnti());
         rrmParameters.setCrnti(crnti);
         rrmParameters.setEcgi(linkId.getEcgi());
     }
diff --git a/src/main/java/org.onosproject.xran/entities/RnibUe.java b/src/main/java/org.onosproject.xran/entities/RnibUe.java
index fb5bb71..3afcb04 100644
--- a/src/main/java/org.onosproject.xran/entities/RnibUe.java
+++ b/src/main/java/org.onosproject.xran/entities/RnibUe.java
@@ -30,8 +30,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.util.Objects;
 import java.util.Timer;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -42,6 +41,7 @@
  * Created by dimitris on 7/22/17.
  */
 @JsonPropertyOrder({
+        "ID",
         "IMSI",
         "ENBUES1APID",
         "MMEUES1APID",
@@ -58,6 +58,8 @@
     private static final Logger log =
             LoggerFactory.getLogger(RnibUe.class);
 
+    @JsonProperty("ID")
+    private Long id;
     @JsonProperty("IMSI")
     private String imsi;
     @JsonProperty("ENBUES1APID")
@@ -65,7 +67,7 @@
     @JsonProperty("MMEUES1APID")
     private MMEUES1APID mmeS1apId;
     @JsonProperty("CRNTI")
-    private CRNTI ranId;
+    private CRNTI crnti;
     @JsonProperty("State")
     private State state;
     @JsonProperty("Capability")
@@ -80,23 +82,11 @@
         timer = new Timer();
     }
 
-    public static URI uri(RnibUe ue) {
-        MMEUES1APID mmeS1apId = ue.getMmeS1apId();
-        if (mmeS1apId != null) {
-            try {
-                return new URI(SCHEME, mmeS1apId.toString(), null);
-            } catch (URISyntaxException e) {
-                return null;
-            }
-        }
-        return null;
-    }
-
-    public static MMEUES1APID hostIdtoMME(HostId hostId) {
+    public static Long hostIdtoUEId(HostId hostId) {
         String mac = hostId.mac().toString();
         mac = mac.replace(":", "");
         long l = Long.parseLong(mac, 16);
-        return new MMEUES1APID(l);
+        return l;
     }
 
     @JsonIgnore
@@ -132,13 +122,13 @@
     }
 
     @JsonProperty("CRNTI")
-    public CRNTI getRanId() {
-        return ranId;
+    public CRNTI getCrnti() {
+        return crnti;
     }
 
     @JsonProperty("CRNTI")
-    public void setRanId(CRNTI ranId) {
-        this.ranId = ranId;
+    public void setCrnti(CRNTI crnti) {
+        this.crnti = crnti;
     }
 
     @JsonProperty("IMSI")
@@ -154,7 +144,7 @@
     @JsonIgnore
     public HostId getHostId() {
         try {
-            String text = this.mmeS1apId.value.toString(16),
+            String text = Long.toHexString(this.id),
                     res = "";
             int charsLeft = 12 - text.length();
             if (charsLeft > 0) {
@@ -220,17 +210,25 @@
         this.state = state;
     }
 
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
     @Override
     public String toString() {
         return "RnibUe{" +
-                "imsi='" + imsi + '\'' +
+                "id=" + id +
+                ", imsi='" + imsi + '\'' +
                 ", enbS1apId=" + enbS1apId +
                 ", mmeS1apId=" + mmeS1apId +
-                ", ranId=" + ranId +
+                ", crnti=" + crnti +
                 ", state=" + state +
                 ", capability=" + capability +
                 ", measConfig=" + measConfig +
-                ", timer=" + timer +
                 '}';
     }
 
@@ -238,17 +236,13 @@
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-
         RnibUe rnibUe = (RnibUe) o;
-
-        return mmeS1apId.equals(rnibUe.mmeS1apId) && ranId.equals(rnibUe.ranId);
+        return Objects.equals(id, rnibUe.id);
     }
 
     @Override
     public int hashCode() {
-        int result = mmeS1apId.hashCode();
-        result = 31 * result + ranId.hashCode();
-        return result;
+        return Objects.hash(id);
     }
 
     public enum State {
diff --git a/src/main/java/org.onosproject.xran/identifiers/EcgiCrntiPair.java b/src/main/java/org.onosproject.xran/identifiers/EcgiCrntiPair.java
new file mode 100644
index 0000000..6347788
--- /dev/null
+++ b/src/main/java/org.onosproject.xran/identifiers/EcgiCrntiPair.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.xran.identifiers;
+
+import com.google.common.base.Objects;
+import javafx.util.Pair;
+import org.onosproject.xran.codecs.api.CRNTI;
+import org.onosproject.xran.codecs.api.ECGI;
+
+public class EcgiCrntiPair extends Pair<ECGI, CRNTI> {
+
+    /**
+     * Creates a new pair
+     *
+     * @param key   The key for this pair
+     * @param value The value to use for this pair
+     */
+    public EcgiCrntiPair(ECGI key, CRNTI value) {
+        super(key, value);
+    }
+
+    public static EcgiCrntiPair valueOf(ECGI key, CRNTI value) {
+        return new EcgiCrntiPair(key, value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(getKey(), getValue());
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof EcgiCrntiPair) {
+            return ((EcgiCrntiPair) o).getKey().equals(getKey()) &&
+                    ((EcgiCrntiPair) o).getValue().equals(getValue());
+        }
+        return super.equals(o);
+    }
+}
diff --git a/src/main/java/org.onosproject.xran/identifiers/LinkId.java b/src/main/java/org.onosproject.xran/identifiers/LinkId.java
index 8b7dabb..e2b489a 100644
--- a/src/main/java/org.onosproject.xran/identifiers/LinkId.java
+++ b/src/main/java/org.onosproject.xran/identifiers/LinkId.java
@@ -21,13 +21,12 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import org.onosproject.xran.codecs.api.ECGI;
-import org.onosproject.xran.codecs.api.MMEUES1APID;
 import org.onosproject.xran.entities.RnibCell;
 import org.onosproject.xran.entities.RnibUe;
 
 @JsonPropertyOrder({
         "ECGI",
-        "MMEUES1APID"
+        "UEID"
 })
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class LinkId {
@@ -45,12 +44,12 @@
         return new LinkId(cell, ue);
     }
 
-    public static LinkId valueOf(ECGI ecgi, MMEUES1APID mmeues1APID) {
+    public static LinkId valueOf(ECGI ecgi, Long UeId) {
         RnibCell cell = new RnibCell();
         RnibUe ue = new RnibUe();
 
         cell.setEcgi(ecgi);
-        ue.setMmeS1apId(mmeues1APID);
+        ue.setId(UeId);
         return new LinkId(cell, ue);
     }
 
@@ -64,14 +63,14 @@
         cell.setEcgi(sourceId);
     }
 
-    @JsonProperty("MMEUES1APID")
-    public MMEUES1APID getMmeues1apid() {
-        return ue.getMmeS1apId();
+    @JsonProperty("UEID")
+    public Long getUeId() {
+        return ue.getId();
     }
 
-    @JsonProperty("MMEUES1APID")
-    public void setMmeues1apid(MMEUES1APID destinationId) {
-        ue.setMmeS1apId(destinationId);
+    @JsonProperty("UEID")
+    public void setUeId(Long destinationId) {
+        ue.setId(destinationId);
     }
 
     @JsonIgnore
@@ -100,14 +99,14 @@
                 o != null &&
                         o instanceof LinkId &&
                         cell.getEcgi().equals(((LinkId) o).cell.getEcgi()) &&
-                        ue.getMmeS1apId().equals(((LinkId) o).ue.getMmeS1apId());
+                        ue.getId().equals(((LinkId) o).ue.getId());
 
     }
 
     @Override
     public int hashCode() {
         int result = cell.getEcgi().hashCode();
-        result = 31 * result + ue.getMmeS1apId().hashCode();
+        result = 31 * result + ue.getId().hashCode();
         return result;
     }
 
diff --git a/src/main/java/org.onosproject.xran/identifiers/contextUpdateHandler.java b/src/main/java/org.onosproject.xran/identifiers/contextUpdateHandler.java
new file mode 100644
index 0000000..82fdaed
--- /dev/null
+++ b/src/main/java/org.onosproject.xran/identifiers/contextUpdateHandler.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.xran.identifiers;
+
+import org.onosproject.xran.codecs.pdu.HOComplete;
+import org.onosproject.xran.codecs.pdu.UEAdmissionStatus;
+import org.onosproject.xran.codecs.pdu.UEContextUpdate;
+
+public class contextUpdateHandler {
+    private UEContextUpdate contextUpdate;
+    private UEAdmissionStatus admissionStatus;
+    private HOComplete hoComplete;
+
+    public UEContextUpdate getContextUpdate() {
+        return contextUpdate;
+    }
+
+    public boolean setContextUpdate(UEContextUpdate contextUpdate) {
+        this.contextUpdate = contextUpdate;
+
+        return admissionStatus != null || hoComplete != null;
+
+    }
+
+    public UEAdmissionStatus getAdmissionStatus() {
+        return admissionStatus;
+    }
+
+    public boolean setAdmissionStatus(UEAdmissionStatus admissionStatus) {
+        this.admissionStatus = admissionStatus;
+
+        return contextUpdate != null;
+    }
+
+    public HOComplete getHoComplete() {
+        return hoComplete;
+    }
+
+    public boolean setHoComplete(HOComplete hoComplete) {
+        this.hoComplete = hoComplete;
+
+        return contextUpdate != null;
+    }
+
+    @Override
+    public String toString() {
+        return "contextUpdateHandler{" +
+                "contextUpdate=" + (contextUpdate != null) +
+                ", admissionStatus=" + (admissionStatus != null) +
+                ", hoComplete=" + (hoComplete != null) +
+                '}';
+    }
+}
diff --git a/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java b/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java
index 9dab964..19e50ab 100644
--- a/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java
+++ b/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java
@@ -22,11 +22,11 @@
 import org.apache.felix.scr.annotations.*;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.core.IdGenerator;
 import org.onosproject.store.AbstractStore;
 import org.onosproject.xran.XranStore;
 import org.onosproject.xran.codecs.api.ECGI;
 import org.onosproject.xran.codecs.api.EUTRANCellIdentifier;
-import org.onosproject.xran.codecs.api.MMEUES1APID;
 import org.onosproject.xran.controller.XranController;
 import org.onosproject.xran.entities.RnibCell;
 import org.onosproject.xran.entities.RnibLink;
@@ -57,18 +57,23 @@
     protected CoreService coreService;
     private ConcurrentMap<LinkId, RnibLink> linkMap = new ConcurrentHashMap<>();
     private ConcurrentMap<ECGI, RnibCell> cellMap = new ConcurrentHashMap<>();
-    private ConcurrentMap<MMEUES1APID, RnibUe> ueMap = new ConcurrentHashMap<>();
+    private ConcurrentMap<Long, RnibUe> ueMap = new ConcurrentHashMap<>();
     private ConcurrentMap<Object, RnibSlice> sliceMap = new ConcurrentHashMap<>();
     private XranController controller;
 
+    private IdGenerator ueIdGenerator;
+
     @Activate
     public void activate() {
         ApplicationId appId = coreService.getAppId(XRAN_APP_ID);
+
+        ueIdGenerator = coreService.getIdGenerator("xran-ue-id");
+
         log.info("XRAN Default Store Started");
     }
 
     @Deactivate
-    public void deactive() {
+    public void deactivate() {
         log.info("XRAN Default Store Stopped");
     }
 
@@ -110,12 +115,11 @@
     @Override
     public List<RnibLink> getLinksByUeId(long euId) {
         List<RnibLink> list = Lists.newArrayList();
-        MMEUES1APID mme = new MMEUES1APID(euId);
 
         list.addAll(
                 linkMap.keySet()
                         .stream()
-                        .filter(k -> k.getMmeues1apid().equals(mme))
+                        .filter(k -> k.getUeId().equals(euId))
                         .map(v -> linkMap.get(v))
                         .collect(Collectors.toList()));
 
@@ -126,12 +130,11 @@
     @Override
     public RnibLink getLinkBetweenCellIdUeId(String eciHex, long euId) {
         EUTRANCellIdentifier eci = hexToECI(eciHex);
-        MMEUES1APID mme = new MMEUES1APID(euId);
 
         Optional<LinkId> first = linkMap.keySet()
                 .stream()
                 .filter(linkId -> linkId.getEcgi().getEUTRANcellIdentifier().equals(eci))
-                .filter(linkId -> linkId.getMmeues1apid().equals(mme))
+                .filter(linkId -> linkId.getUeId().equals(euId))
                 .findFirst();
 
         return first.map(linkId -> linkMap.get(linkId)).orElse(null);
@@ -144,7 +147,7 @@
                 // if we add a primary link then change the primary to non serving
                 if (link.getType().equals(RnibLink.Type.SERVING_PRIMARY)) {
                     RnibUe ue = link.getLinkId().getUe();
-                    getLinksByUeId(ue.getMmeS1apId().longValue())
+                    getLinksByUeId(ue.getId())
                             .forEach(l -> {
                                 if (l.getType().equals(RnibLink.Type.SERVING_PRIMARY)) {
                                     l.setType(RnibLink.Type.NON_SERVING);
@@ -162,9 +165,9 @@
     }
 
     @Override
-    public RnibLink getLink(ECGI ecgi, MMEUES1APID mme) {
+    public RnibLink getLink(ECGI ecgi, Long ueId) {
 
-        LinkId linkId = LinkId.valueOf(ecgi, mme);
+        LinkId linkId = LinkId.valueOf(ecgi, ueId);
         return linkMap.get(linkId);
     }
 
@@ -267,25 +270,19 @@
 
     @Override
     public void storeUe(RnibUe ue) {
-        if (ue.getMmeS1apId() != null) {
-            ueMap.putIfAbsent(ue.getMmeS1apId(), ue);
-        }
+        long newId = ueIdGenerator.getNewId();
+        ue.setId(newId);
+        ueMap.put(newId, ue);
     }
 
     @Override
-    public boolean removeUe(MMEUES1APID mme) {
-        return ueMap.remove(mme) != null;
+    public boolean removeUe(long ueId) {
+        return ueMap.remove(ueId) != null;
     }
 
     @Override
-    public RnibUe getUe(long euId) {
-        MMEUES1APID mme = new MMEUES1APID(euId);
-        return ueMap.get(mme);
-    }
-
-    @Override
-    public RnibUe getUe(MMEUES1APID mme) {
-        return ueMap.get(mme);
+    public RnibUe getUe(long ueId) {
+        return ueMap.get(ueId);
     }
 
     private EUTRANCellIdentifier hexToECI(String eciHex) {
diff --git a/src/main/java/org.onosproject.xran/providers/UeProvider.java b/src/main/java/org.onosproject.xran/providers/UeProvider.java
index 2205c60..435c78a 100644
--- a/src/main/java/org.onosproject.xran/providers/UeProvider.java
+++ b/src/main/java/org.onosproject.xran/providers/UeProvider.java
@@ -97,7 +97,7 @@
                 ecgiSet.forEach(ecgi -> hostLocations.add(new HostLocation(deviceId(uri(ecgi)), PortNumber.portNumber(0), 0)));
 
                 SparseAnnotations annotations = DefaultAnnotations.builder()
-                        .set(AnnotationKeys.NAME, "UE " + ue.getMmeS1apId())
+                        .set(AnnotationKeys.NAME, "UE " + ue.getId())
                         .build();
 
                 DefaultHostDescription desc = new DefaultHostDescription(
diff --git a/src/main/java/org.onosproject.xran/rest/CellWebResource.java b/src/main/java/org.onosproject.xran/rest/CellWebResource.java
index 566e8b9..86438d5 100644
--- a/src/main/java/org.onosproject.xran/rest/CellWebResource.java
+++ b/src/main/java/org.onosproject.xran/rest/CellWebResource.java
@@ -120,7 +120,7 @@
 
                     queue[0] = get(XranController.class).sendModifiedRRMConf(cell.getRrmConfig(),
                             cell.getVersion() <= 3);
-                    String poll = queue[0].poll(get(XranControllerImpl.class).northbound_timeout, TimeUnit.MILLISECONDS);
+                    String poll = queue[0].poll(get(XranController.class).getNorthbound_timeout(), TimeUnit.MILLISECONDS);
 
                     if (poll != null) {
                         return ResponseHelper.getResponse(
diff --git a/src/main/java/org.onosproject.xran/rest/LinkWebResource.java b/src/main/java/org.onosproject.xran/rest/LinkWebResource.java
index 0213beb..20780b3 100644
--- a/src/main/java/org.onosproject.xran/rest/LinkWebResource.java
+++ b/src/main/java/org.onosproject.xran/rest/LinkWebResource.java
@@ -215,7 +215,7 @@
             );
         }
 
-        if (get(XranStore.class).getLink(cell.getEcgi(), ue.getMmeS1apId()) != null) {
+        if (get(XranStore.class).getLink(cell.getEcgi(), ue.getId()) != null) {
             return ResponseHelper.getResponse(
                     mapper(),
                     ResponseHelper.statusCode.BAD_REQUEST,
@@ -284,14 +284,14 @@
                 case SERVING_SECONDARY_CA:
                 case SERVING_SECONDARY_DC:
                 case NON_SERVING: {
-                    List<RnibLink> linksByUeId = get(XranStore.class).getLinksByUeId(link.getLinkId().getMmeues1apid().longValue());
+                    List<RnibLink> linksByUeId = get(XranStore.class).getLinksByUeId(link.getLinkId().getUeId());
 
                     Optional<RnibLink> primary = linksByUeId.stream()
                             .filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY))
                             .findFirst();
                     if (primary.isPresent()) {
                         queue[0] = get(XranController.class).sendHORequest(link, primary.get());
-                        String poll = queue[0].poll(get(XranControllerImpl.class).northbound_timeout, TimeUnit.MILLISECONDS);
+                        String poll = queue[0].poll(get(XranController.class).getNorthbound_timeout(), TimeUnit.MILLISECONDS);
 
                         if (poll != null) {
                             return ResponseHelper.getResponse(
@@ -365,7 +365,7 @@
                 case SERVING_SECONDARY_DC:
                 case NON_SERVING:
                     queue[0] = get(XranController.class).sendScellAdd(link);
-                    String poll = queue[0].poll(get(XranControllerImpl.class).northbound_timeout, TimeUnit.MILLISECONDS);
+                    String poll = queue[0].poll(get(XranController.class).getNorthbound_timeout(), TimeUnit.MILLISECONDS);
                     if (poll != null) {
                         return ResponseHelper.getResponse(
                                 mapper(),
@@ -434,7 +434,7 @@
                     "xICIC was sent successfully"
             );
         } else {
-            String poll = queue[0].poll(get(XranControllerImpl.class).northbound_timeout, TimeUnit.MILLISECONDS);
+            String poll = queue[0].poll(get(XranController.class).getNorthbound_timeout(), TimeUnit.MILLISECONDS);
 
             if (poll != null) {
                 return ResponseHelper.getResponse(
diff --git a/src/main/java/org.onosproject.xran/rest/ResponseHelper.java b/src/main/java/org.onosproject.xran/rest/ResponseHelper.java
index 826adc1..5e2f1dd 100644
--- a/src/main/java/org.onosproject.xran/rest/ResponseHelper.java
+++ b/src/main/java/org.onosproject.xran/rest/ResponseHelper.java
@@ -29,7 +29,16 @@
         ObjectNode rootNode = mapper.createObjectNode();
 
         switch (status) {
-            case OK:
+            case OK: {
+                ArrayNode data = rootNode.putArray("data");
+                ObjectNode addObject = data.addObject();
+                addObject.put("status", status.status);
+                addObject.put("title", title);
+                addObject.put("detail", detail);
+                return Response.status(status.status)
+                        .entity(rootNode.toString())
+                        .build();
+            }
             case BAD_REQUEST:
             case NOT_IMPLEMENTED:
             case REQUEST_TIMEOUT:
diff --git a/src/main/java/org.onosproject.xran/wrapper/LinkMap.java b/src/main/java/org.onosproject.xran/wrapper/LinkMap.java
index 5e62271..ed7b4f1 100644
--- a/src/main/java/org.onosproject.xran/wrapper/LinkMap.java
+++ b/src/main/java/org.onosproject.xran/wrapper/LinkMap.java
@@ -19,7 +19,6 @@
 import org.onosproject.xran.XranStore;
 import org.onosproject.xran.codecs.api.CRNTI;
 import org.onosproject.xran.codecs.api.ECGI;
-import org.onosproject.xran.codecs.api.MMEUES1APID;
 import org.onosproject.xran.entities.RnibCell;
 import org.onosproject.xran.entities.RnibLink;
 import org.onosproject.xran.entities.RnibUe;
@@ -63,7 +62,20 @@
         return link;
     }
 
-    public RnibLink get(ECGI src, MMEUES1APID dst) {
+    public RnibLink putNonServingLink(RnibCell cell, Long ueId) {
+        RnibLink link = null;
+        RnibUe ue = ueMap.get(ueId);
+
+        if (ue != null) {
+            link = new RnibLink(cell, ue);
+            xranStore.storeLink(link);
+        } else {
+            log.error("Could not find mapping for CRNTI to UE. Aborting creation of non-serving link");
+        }
+        return link;
+    }
+
+    public RnibLink get(ECGI src, Long dst) {
         if (src != null && dst != null) {
             return xranStore.getLink(src, dst);
         }
@@ -74,17 +86,17 @@
         RnibUe ue = ueMap.get(src, dst);
 
         if (ue != null) {
-            return xranStore.getLink(src, ue.getMmeS1apId());
+            return xranStore.getLink(src, ue.getId());
         }
         return null;
     }
 
-    public CRNTI getCrnti(MMEUES1APID mme) {
-        return ueMap.getCrntUe().inverse().get(mme).getValue();
+    public CRNTI getCrnti(Long ueId) {
+        return ueMap.getCrntUe().inverse().get(ueId).getValue();
     }
 
     public RnibCell getPrimaryCell(RnibUe ue) {
-        List<RnibLink> linksByUeId = xranStore.getLinksByUeId(ue.getMmeS1apId().longValue());
+        List<RnibLink> linksByUeId = xranStore.getLinksByUeId(ue.getId());
         Optional<RnibLink> primary = linksByUeId.stream()
                 .filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY))
                 .findFirst();
diff --git a/src/main/java/org.onosproject.xran/wrapper/UeMap.java b/src/main/java/org.onosproject.xran/wrapper/UeMap.java
index 1938a79..8b2110d 100644
--- a/src/main/java/org.onosproject.xran/wrapper/UeMap.java
+++ b/src/main/java/org.onosproject.xran/wrapper/UeMap.java
@@ -16,25 +16,18 @@
 
 package org.onosproject.xran.wrapper;
 
-import com.google.common.base.Objects;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
-import io.netty.channel.ChannelHandlerContext;
-import javafx.util.Pair;
-import org.onosproject.net.HostId;
 import org.onosproject.xran.XranStore;
 import org.onosproject.xran.codecs.api.CRNTI;
 import org.onosproject.xran.codecs.api.ECGI;
-import org.onosproject.xran.codecs.api.ENBUES1APID;
 import org.onosproject.xran.codecs.api.MMEUES1APID;
 import org.onosproject.xran.entities.RnibCell;
 import org.onosproject.xran.entities.RnibUe;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import org.onosproject.xran.identifiers.EcgiCrntiPair;
 
 public class UeMap {
-    private BiMap<EcgiCrntiPair, MMEUES1APID> crntUe = HashBiMap.create();
+    private BiMap<EcgiCrntiPair, Long> crntUe = HashBiMap.create();
 
     private XranStore xranStore;
 
@@ -42,75 +35,44 @@
         this.xranStore = xranStore;
     }
 
-    public BiMap<EcgiCrntiPair, MMEUES1APID> getCrntUe() {
+    public BiMap<EcgiCrntiPair, Long> getCrntUe() {
         return crntUe;
     }
 
     public void putCrnti(RnibCell cell, RnibUe ue) {
-        CRNTI ranId = ue.getRanId();
+        CRNTI ranId = ue.getCrnti();
         ECGI ecgi = cell.getEcgi();
         if (ranId != null && ecgi != null) {
-            crntUe.put(EcgiCrntiPair.valueOf(cell.getEcgi(),ue.getRanId()), ue.getMmeS1apId());
+            EcgiCrntiPair oldPair = crntUe.inverse().get(ue.getId()),
+                    newPair = EcgiCrntiPair.valueOf(cell.getEcgi(), ue.getCrnti());
+            if (oldPair == null) {
+                crntUe.put(newPair, ue.getId());
+            } else {
+                crntUe.inverse().remove(ue.getId());
+                crntUe.put(newPair, ue.getId());
+            }
         }
     }
 
     public void put(RnibCell cell, RnibUe ue) {
-
-        MMEUES1APID mmeS1apId = ue.getMmeS1apId();
-        if (mmeS1apId != null) {
-            xranStore.storeUe(ue);
-            putCrnti(cell, ue);
-        }
+        xranStore.storeUe(ue);
+        putCrnti(cell, ue);
     }
 
     public RnibUe get(ECGI ecgi, CRNTI crnti) {
-        MMEUES1APID mme = crntUe.get(EcgiCrntiPair.valueOf(ecgi, crnti));
-        if (mme != null) {
-            return xranStore.getUe(mme);
+        Long aLong = crntUe.get(EcgiCrntiPair.valueOf(ecgi, crnti));
+        if (aLong != null) {
+            return xranStore.getUe(aLong);
         }
         return null;
     }
 
-    public RnibUe get(MMEUES1APID mme) {
-        if (mme != null) {
-            return xranStore.getUe(mme);
-        }
-        return null;
+    public RnibUe get(Long ueId) {
+        return xranStore.getUe(ueId);
     }
 
-    public boolean remove(MMEUES1APID id) {
-        crntUe.inverse().remove(id);
-        return xranStore.removeUe(id);
-    }
-
-    public static class EcgiCrntiPair extends Pair<ECGI, CRNTI> {
-
-        /**
-         * Creates a new pair
-         *
-         * @param key   The key for this pair
-         * @param value The value to use for this pair
-         */
-        public EcgiCrntiPair(ECGI key, CRNTI value) {
-            super(key, value);
-        }
-
-        public static EcgiCrntiPair valueOf(ECGI key, CRNTI value) {
-            return new EcgiCrntiPair(key, value);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(getKey(), getValue());
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (o instanceof EcgiCrntiPair) {
-                return ((EcgiCrntiPair) o).getKey().equals(getKey()) &&
-                        ((EcgiCrntiPair) o).getValue().equals(getValue());
-            }
-            return super.equals(o);
-        }
+    public boolean remove(Long ueId) {
+        crntUe.inverse().remove(ueId);
+        return xranStore.removeUe(ueId);
     }
 }
diff --git a/xran-cfg.json b/xran-cfg.json
index b1787a7..03fa720 100644
--- a/xran-cfg.json
+++ b/xran-cfg.json
@@ -6,12 +6,12 @@
           {
             "plmn_id": "000001",
             "eci": "00000010",
-            "ip_addr": "1.1.1.1"
+            "ip_addr": "10.10.10.1"
           },
           {
             "plmn_id": "000002",
             "eci": "00000020",
-            "ip_addr": "1.1.1.2"
+            "ip_addr": "172.16.27.100"
           },
           {
             "plmn_id": "000003",
@@ -19,7 +19,7 @@
             "ip_addr": "1.1.1.3"
           }
         ],
-        "l2_meas_report_interval_ms": 30000,
+        "l2_meas_report_interval_ms": 5000,
         "rx_signal_meas_report_interval_ms": 7000,
         "xranc_cellconfigrequest_interval_seconds": 10,
         "xranc_port": 7891,