added HO and RRMConf NB api
diff --git a/src/main/java/org.onosproject.xran/XranStore.java b/src/main/java/org.onosproject.xran/XranStore.java
index e925cf0..00c4a81 100644
--- a/src/main/java/org.onosproject.xran/XranStore.java
+++ b/src/main/java/org.onosproject.xran/XranStore.java
@@ -71,7 +71,7 @@
 
     RnibCell getCell(ECGI cellId);
 
-    boolean modifyCellRrmConf(String eci, JsonNode rrmConf);
+    boolean modifyCellRrmConf(RnibCell cell, JsonNode rrmConf);
 
     void storeCell(RnibCell cell);
 
diff --git a/src/main/java/org.onosproject.xran/codecs/api/PLMNIdentity.java b/src/main/java/org.onosproject.xran/codecs/api/PLMNIdentity.java
index 5fe0d69..5279ed6 100644
--- a/src/main/java/org.onosproject.xran/codecs/api/PLMNIdentity.java
+++ b/src/main/java/org.onosproject.xran/codecs/api/PLMNIdentity.java
@@ -6,16 +6,36 @@
 
 import org.openmuc.jasn1.ber.types.BerOctetString;
 
+import javax.xml.bind.DatatypeConverter;
+import java.util.Arrays;
+
 
 public class PLMNIdentity extends BerOctetString {
 
-	private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
-	public PLMNIdentity() {
-	}
+    public PLMNIdentity() {
+    }
 
-	public PLMNIdentity(byte[] value) {
-		super(value);
-	}
+    public PLMNIdentity(byte[] value) {
+        super(value);
+    }
 
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(value);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof PLMNIdentity) {
+            return Arrays.equals(value, ((PLMNIdentity) obj).value);
+        }
+        return super.equals(obj);
+    }
+
+    @Override
+    public String toString() {
+        return "\"" + DatatypeConverter.printHexBinary(value) + "\"";
+    }
 }
diff --git a/src/main/java/org.onosproject.xran/codecs/package-info.java b/src/main/java/org.onosproject.xran/codecs/package-info.java
new file mode 100644
index 0000000..07f89fa
--- /dev/null
+++ b/src/main/java/org.onosproject.xran/codecs/package-info.java
@@ -0,0 +1 @@
+package org.onosproject.xran.codecs;
\ No newline at end of file
diff --git a/src/main/java/org.onosproject.xran/codecs/pdu/RRMConfig.java b/src/main/java/org.onosproject.xran/codecs/pdu/RRMConfig.java
index 4de355d..e7ff333 100644
--- a/src/main/java/org.onosproject.xran/codecs/pdu/RRMConfig.java
+++ b/src/main/java/org.onosproject.xran/codecs/pdu/RRMConfig.java
@@ -7,1579 +7,1620 @@
 import org.onosproject.xran.codecs.api.CRNTI;
 import org.onosproject.xran.codecs.api.ECGI;
 import org.onosproject.xran.codecs.api.XICICPA;
+import org.onosproject.xran.entities.RnibCell;
 import org.openmuc.jasn1.ber.BerByteArrayOutputStream;
 import org.openmuc.jasn1.ber.BerLength;
 import org.openmuc.jasn1.ber.BerTag;
 import org.openmuc.jasn1.ber.types.BerBitString;
 import org.openmuc.jasn1.ber.types.BerInteger;
+import org.openmuc.jasn1.ber.types.string.BerUTF8String;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
 public class RRMConfig implements Serializable {
 
-	private static final long serialVersionUID = 1L;
+    public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+    private static final long serialVersionUID = 1L;
+    public byte[] code = null;
+    private ECGI ecgi = null;
+    private Crnti crnti = null;
+    private Pa pa = null;
+    private StartPrbDl startPrbDl = null;
+    private EndPrbDl endPrbDl = null;
+    private SubframeBitmaskDl subframeBitmaskDl = null;
+    private P0UePusch p0UePusch = null;
+    private StartPrbUl startPrbUl = null;
+    private EndPrbUl endPrbUl = null;
+    private SubframeBitmaskUl subframeBitmaskUl = null;
 
-	public static class Crnti implements Serializable {
+    public RRMConfig() {
+    }
 
-		private static final long serialVersionUID = 1L;
+    public RRMConfig(byte[] code) {
+        this.code = code;
+    }
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<CRNTI> seqOf = null;
+    public ECGI getEcgi() {
+        return ecgi;
+    }
 
-		public Crnti() {
-			seqOf = new ArrayList<CRNTI>();
-		}
+    public void setEcgi(ECGI ecgi) {
+        this.ecgi = ecgi;
+    }
 
-		public Crnti(byte[] code) {
-			this.code = code;
-		}
+    public Crnti getCrnti() {
+        return crnti;
+    }
 
-		public List<CRNTI> getCRNTI() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<CRNTI>();
-			}
-			return seqOf;
-		}
+    public void setCrnti(Crnti crnti) {
+        this.crnti = crnti;
+    }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+    public Pa getPa() {
+        return pa;
+    }
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+    public void setPa(Pa pa) {
+        this.pa = pa;
+    }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+    public StartPrbDl getStartPrbDl() {
+        return startPrbDl;
+    }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+    public void setStartPrbDl(StartPrbDl startPrbDl) {
+        this.startPrbDl = startPrbDl;
+    }
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+    public EndPrbDl getEndPrbDl() {
+        return endPrbDl;
+    }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+    public void setEndPrbDl(EndPrbDl endPrbDl) {
+        this.endPrbDl = endPrbDl;
+    }
 
-			return codeLength;
-		}
+    public SubframeBitmaskDl getSubframeBitmaskDl() {
+        return subframeBitmaskDl;
+    }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+    public void setSubframeBitmaskDl(SubframeBitmaskDl subframeBitmaskDl) {
+        this.subframeBitmaskDl = subframeBitmaskDl;
+    }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+    public P0UePusch getP0UePusch() {
+        return p0UePusch;
+    }
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+    public void setP0UePusch(P0UePusch p0UePusch) {
+        this.p0UePusch = p0UePusch;
+    }
 
-			while (subCodeLength < totalLength) {
-				CRNTI element = new CRNTI();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+    public StartPrbUl getStartPrbUl() {
+        return startPrbUl;
+    }
 
-			}
-			codeLength += subCodeLength;
+    public void setStartPrbUl(StartPrbUl startPrbUl) {
+        this.startPrbUl = startPrbUl;
+    }
 
-			return codeLength;
-		}
+    public EndPrbUl getEndPrbUl() {
+        return endPrbUl;
+    }
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+    public void setEndPrbUl(EndPrbUl endPrbUl) {
+        this.endPrbUl = endPrbUl;
+    }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+    public SubframeBitmaskUl getSubframeBitmaskUl() {
+        return subframeBitmaskUl;
+    }
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
+    public void setSubframeBitmaskUl(SubframeBitmaskUl subframeBitmaskUl) {
+        this.subframeBitmaskUl = subframeBitmaskUl;
+    }
 
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+    public int encode(BerByteArrayOutputStream os) throws IOException {
+        return encode(os, true);
+    }
+
+    public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+
+        if (code != null) {
+            for (int i = code.length - 1; i >= 0; i--) {
+                os.write(code[i]);
+            }
+            if (withTag) {
+                return tag.encode(os) + code.length;
+            }
+            return code.length;
+        }
+
+        int codeLength = 0;
+        if (subframeBitmaskUl != null) {
+            codeLength += subframeBitmaskUl.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 9
+            os.write(0xA9);
+            codeLength += 1;
+        }
+
+        if (endPrbUl != null) {
+            codeLength += endPrbUl.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 8
+            os.write(0xA8);
+            codeLength += 1;
+        }
+
+        if (startPrbUl != null) {
+            codeLength += startPrbUl.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 7
+            os.write(0xA7);
+            codeLength += 1;
+        }
+
+        if (p0UePusch != null) {
+            codeLength += p0UePusch.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 6
+            os.write(0xA6);
+            codeLength += 1;
+        }
+
+        if (subframeBitmaskDl != null) {
+            codeLength += subframeBitmaskDl.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 5
+            os.write(0xA5);
+            codeLength += 1;
+        }
+
+        if (endPrbDl != null) {
+            codeLength += endPrbDl.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 4
+            os.write(0xA4);
+            codeLength += 1;
+        }
+
+        if (startPrbDl != null) {
+            codeLength += startPrbDl.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 3
+            os.write(0xA3);
+            codeLength += 1;
+        }
+
+        if (pa != null) {
+            codeLength += pa.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 2
+            os.write(0xA2);
+            codeLength += 1;
+        }
+
+        if (crnti != null) {
+            codeLength += crnti.encode(os, false);
+            // write tag: CONTEXT_CLASS, CONSTRUCTED, 1
+            os.write(0xA1);
+            codeLength += 1;
+        }
+
+        codeLength += ecgi.encode(os, false);
+        // write tag: CONTEXT_CLASS, CONSTRUCTED, 0
+        os.write(0xA0);
+        codeLength += 1;
+
+        codeLength += BerLength.encodeLength(os, codeLength);
+
+        if (withTag) {
+            codeLength += tag.encode(os);
+        }
+
+        return codeLength;
+
+    }
+
+    public int decode(InputStream is) throws IOException {
+        return decode(is, true);
+    }
+
+    public int decode(InputStream is, boolean withTag) throws IOException {
+        int codeLength = 0;
+        int subCodeLength = 0;
+        BerTag berTag = new BerTag();
+
+        if (withTag) {
+            codeLength += tag.decodeAndCheck(is);
+        }
+
+        BerLength length = new BerLength();
+        codeLength += length.decode(is);
+
+        int totalLength = length.val;
+        codeLength += totalLength;
+
+        subCodeLength += berTag.decode(is);
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 0)) {
+            ecgi = new ECGI();
+            subCodeLength += ecgi.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        } else {
+            throw new IOException("Tag does not match the mandatory sequence element tag.");
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 1)) {
+            crnti = new Crnti();
+            subCodeLength += crnti.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 2)) {
+            pa = new Pa();
+            subCodeLength += pa.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 3)) {
+            startPrbDl = new StartPrbDl();
+            subCodeLength += startPrbDl.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 4)) {
+            endPrbDl = new EndPrbDl();
+            subCodeLength += endPrbDl.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 5)) {
+            subframeBitmaskDl = new SubframeBitmaskDl();
+            subCodeLength += subframeBitmaskDl.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 6)) {
+            p0UePusch = new P0UePusch();
+            subCodeLength += p0UePusch.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 7)) {
+            startPrbUl = new StartPrbUl();
+            subCodeLength += startPrbUl.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 8)) {
+            endPrbUl = new EndPrbUl();
+            subCodeLength += endPrbUl.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+            subCodeLength += berTag.decode(is);
+        }
+
+        if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 9)) {
+            subframeBitmaskUl = new SubframeBitmaskUl();
+            subCodeLength += subframeBitmaskUl.decode(is, false);
+            if (subCodeLength == totalLength) {
+                return codeLength;
+            }
+        }
+        throw new IOException("Unexpected end of sequence, length tag: " + totalLength + ", actual sequence length: " + subCodeLength);
+
+
+    }
+
+    public void encodeAndSave(int encodingSizeGuess) throws IOException {
+        BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+        encode(os, false);
+        code = os.getArray();
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        appendAsString(sb, 0);
+        return sb.toString();
+    }
+
+    public void appendAsString(StringBuilder sb, int indentLevel) {
+
+        sb.append("{");
+        sb.append("\n");
+        for (int i = 0; i < indentLevel + 1; i++) {
+            sb.append("\t");
+        }
+        if (ecgi != null) {
+            sb.append("\"ecgi\": ");
+            ecgi.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (crnti != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"crnti\": ");
+            crnti.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (pa != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"pa\": ");
+            pa.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (startPrbDl != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"startPrbDl\": ");
+            startPrbDl.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (endPrbDl != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"endPrbDl\": ");
+            endPrbDl.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (subframeBitmaskDl != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"subframeBitmaskDl\": ");
+            subframeBitmaskDl.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (p0UePusch != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"p0UePusch\": ");
+            p0UePusch.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (startPrbUl != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"startPrbUl\": ");
+            startPrbUl.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (endPrbUl != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"endPrbUl\": ");
+            endPrbUl.appendAsString(sb, indentLevel + 1);
+        }
+
+        if (subframeBitmaskUl != null) {
+            sb.append(",\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            sb.append("\"subframeBitmaskUl\": ");
+            subframeBitmaskUl.appendAsString(sb, indentLevel + 1);
+        }
+
+        sb.append("\n");
+        for (int i = 0; i < indentLevel; i++) {
+            sb.append("\t");
+        }
+        sb.append("}");
+    }
+
+    public static class Crnti implements Serializable {
+
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<CRNTI> seqOf = null;
+
+        public Crnti() {
+            seqOf = new ArrayList<CRNTI>();
+        }
+
+        public Crnti(byte[] code) {
+            this.code = code;
+        }
+
+        public List<CRNTI> getCRNTI() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<CRNTI>();
+            }
+            return seqOf;
+        }
+
+        public void addCRNTI(CRNTI crnti) {
+            seqOf.add(crnti);
+        }
+
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
+
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
+
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
+
+            codeLength += BerLength.encodeLength(os, codeLength);
+
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
+
+            return codeLength;
+        }
+
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
+
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
+
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
+
+            while (subCodeLength < totalLength) {
+                CRNTI element = new CRNTI();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+
+            }
+            codeLength += subCodeLength;
+
+            return codeLength;
+        }
+
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
+
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
+
+        public void appendAsString(StringBuilder sb, int indentLevel) {
+
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<CRNTI> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<CRNTI> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+    }
 
-	public static class Pa implements Serializable {
+    public static class Pa implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<XICICPA> seqOf = null;
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<XICICPA> seqOf = null;
+        public Pa() {
+            seqOf = new ArrayList<XICICPA>();
+        }
 
-		public Pa() {
-			seqOf = new ArrayList<XICICPA>();
-		}
+        public Pa(byte[] code) {
+            this.code = code;
+        }
 
-		public Pa(byte[] code) {
-			this.code = code;
-		}
+        public List<XICICPA> getXICICPA() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<XICICPA>();
+            }
+            return seqOf;
+        }
 
-		public List<XICICPA> getXICICPA() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<XICICPA>();
-			}
-			return seqOf;
-		}
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+            while (subCodeLength < totalLength) {
+                XICICPA element = new XICICPA();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-			while (subCodeLength < totalLength) {
-				XICICPA element = new XICICPA();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+            }
+            codeLength += subCodeLength;
 
-			}
-			codeLength += subCodeLength;
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+        public void appendAsString(StringBuilder sb, int indentLevel) {
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
-
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<XICICPA> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<XICICPA> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+    }
 
-	public static class StartPrbDl implements Serializable {
+    public static class StartPrbDl implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<BerInteger> seqOf = null;
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<BerInteger> seqOf = null;
+        public StartPrbDl() {
+            seqOf = new ArrayList<BerInteger>();
+        }
 
-		public StartPrbDl() {
-			seqOf = new ArrayList<BerInteger>();
-		}
+        public StartPrbDl(byte[] code) {
+            this.code = code;
+        }
 
-		public StartPrbDl(byte[] code) {
-			this.code = code;
-		}
+        public List<BerInteger> getSeqOf() {
+            return seqOf;
+        }
 
-		public List<BerInteger> getBerInteger() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<BerInteger>();
-			}
-			return seqOf;
-		}
+        public void setSeqOf(List<BerInteger> seqOf) {
+            this.seqOf = seqOf;
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public List<BerInteger> getBerInteger() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<BerInteger>();
+            }
+            return seqOf;
+        }
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-			return codeLength;
-		}
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+            return codeLength;
+        }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-			while (subCodeLength < totalLength) {
-				BerInteger element = new BerInteger();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			}
-			codeLength += subCodeLength;
+            while (subCodeLength < totalLength) {
+                BerInteger element = new BerInteger();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-			return codeLength;
-		}
+            }
+            codeLength += subCodeLength;
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+            return codeLength;
+        }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
 
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+        public void appendAsString(StringBuilder sb, int indentLevel) {
+
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<BerInteger> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<BerInteger> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+        public void addBerInteger(BerInteger berInteger) {
+            seqOf.add(berInteger);
+        }
+    }
 
-	public static class EndPrbDl implements Serializable {
+    public static class EndPrbDl implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<BerInteger> seqOf = null;
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<BerInteger> seqOf = null;
+        public EndPrbDl() {
+            seqOf = new ArrayList<BerInteger>();
+        }
 
-		public EndPrbDl() {
-			seqOf = new ArrayList<BerInteger>();
-		}
+        public EndPrbDl(byte[] code) {
+            this.code = code;
+        }
 
-		public EndPrbDl(byte[] code) {
-			this.code = code;
-		}
+        public List<BerInteger> getBerInteger() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<BerInteger>();
+            }
+            return seqOf;
+        }
 
-		public List<BerInteger> getBerInteger() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<BerInteger>();
-			}
-			return seqOf;
-		}
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+            while (subCodeLength < totalLength) {
+                BerInteger element = new BerInteger();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-			while (subCodeLength < totalLength) {
-				BerInteger element = new BerInteger();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+            }
+            codeLength += subCodeLength;
 
-			}
-			codeLength += subCodeLength;
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+        public void appendAsString(StringBuilder sb, int indentLevel) {
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
-
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<BerInteger> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<BerInteger> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+        public void addBerInteger(BerInteger berInteger) {
+            seqOf.add(berInteger);
+        }
 
-	public static class SubframeBitmaskDl implements Serializable {
+        public List<BerInteger> getSeqOf() {
+            return seqOf;
+        }
 
-		private static final long serialVersionUID = 1L;
+        public void setSeqOf(List<BerInteger> seqOf) {
+            this.seqOf = seqOf;
+        }
+    }
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<BerBitString> seqOf = null;
+    public static class SubframeBitmaskDl implements Serializable {
 
-		public SubframeBitmaskDl() {
-			seqOf = new ArrayList<BerBitString>();
-		}
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<BerBitString> seqOf = null;
 
-		public SubframeBitmaskDl(byte[] code) {
-			this.code = code;
-		}
+        public SubframeBitmaskDl() {
+            seqOf = new ArrayList<BerBitString>();
+        }
 
-		public List<BerBitString> getBerBitString() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<BerBitString>();
-			}
-			return seqOf;
-		}
+        public SubframeBitmaskDl(byte[] code) {
+            this.code = code;
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public List<BerBitString> getBerBitString() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<BerBitString>();
+            }
+            return seqOf;
+        }
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+        public void addBerBitString(BerBitString berBitString) {
+            seqOf.add(berBitString);
+        }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			return codeLength;
-		}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+            return codeLength;
+        }
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-			while (subCodeLength < totalLength) {
-				BerBitString element = new BerBitString();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-			}
-			codeLength += subCodeLength;
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			return codeLength;
-		}
+            while (subCodeLength < totalLength) {
+                BerBitString element = new BerBitString();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+            }
+            codeLength += subCodeLength;
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+            return codeLength;
+        }
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
+
+        public void appendAsString(StringBuilder sb, int indentLevel) {
+
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<BerBitString> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<BerBitString> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append("\"" + it.next() + "\"");
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append("\"" + it.next() + "\"");
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+    }
 
-	public static class P0UePusch implements Serializable {
+    public static class P0UePusch implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<BerInteger> seqOf = null;
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<BerInteger> seqOf = null;
+        public P0UePusch() {
+            seqOf = new ArrayList<BerInteger>();
+        }
 
-		public P0UePusch() {
-			seqOf = new ArrayList<BerInteger>();
-		}
+        public P0UePusch(byte[] code) {
+            this.code = code;
+        }
 
-		public P0UePusch(byte[] code) {
-			this.code = code;
-		}
+        public List<BerInteger> getBerInteger() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<BerInteger>();
+            }
+            return seqOf;
+        }
 
-		public List<BerInteger> getBerInteger() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<BerInteger>();
-			}
-			return seqOf;
-		}
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+            while (subCodeLength < totalLength) {
+                BerInteger element = new BerInteger();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-			while (subCodeLength < totalLength) {
-				BerInteger element = new BerInteger();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+            }
+            codeLength += subCodeLength;
 
-			}
-			codeLength += subCodeLength;
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+        public void appendAsString(StringBuilder sb, int indentLevel) {
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
-
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<BerInteger> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<BerInteger> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+    }
 
-	public static class StartPrbUl implements Serializable {
+    public static class StartPrbUl implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<BerInteger> seqOf = null;
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<BerInteger> seqOf = null;
+        public StartPrbUl() {
+            seqOf = new ArrayList<BerInteger>();
+        }
 
-		public StartPrbUl() {
-			seqOf = new ArrayList<BerInteger>();
-		}
+        public StartPrbUl(byte[] code) {
+            this.code = code;
+        }
 
-		public StartPrbUl(byte[] code) {
-			this.code = code;
-		}
+        public List<BerInteger> getBerInteger() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<BerInteger>();
+            }
+            return seqOf;
+        }
 
-		public List<BerInteger> getBerInteger() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<BerInteger>();
-			}
-			return seqOf;
-		}
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+            while (subCodeLength < totalLength) {
+                BerInteger element = new BerInteger();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-			while (subCodeLength < totalLength) {
-				BerInteger element = new BerInteger();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+            }
+            codeLength += subCodeLength;
 
-			}
-			codeLength += subCodeLength;
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+        public void appendAsString(StringBuilder sb, int indentLevel) {
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
-
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<BerInteger> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<BerInteger> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+        public void addBerInteger(BerInteger berInteger) {
+            seqOf.add(berInteger);
+        }
+    }
 
-	public static class EndPrbUl implements Serializable {
+    public static class EndPrbUl implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<BerInteger> seqOf = null;
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<BerInteger> seqOf = null;
+        public EndPrbUl() {
+            seqOf = new ArrayList<BerInteger>();
+        }
 
-		public EndPrbUl() {
-			seqOf = new ArrayList<BerInteger>();
-		}
+        public EndPrbUl(byte[] code) {
+            this.code = code;
+        }
 
-		public EndPrbUl(byte[] code) {
-			this.code = code;
-		}
+        public List<BerInteger> getBerInteger() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<BerInteger>();
+            }
+            return seqOf;
+        }
 
-		public List<BerInteger> getBerInteger() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<BerInteger>();
-			}
-			return seqOf;
-		}
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+            while (subCodeLength < totalLength) {
+                BerInteger element = new BerInteger();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-			while (subCodeLength < totalLength) {
-				BerInteger element = new BerInteger();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+            }
+            codeLength += subCodeLength;
 
-			}
-			codeLength += subCodeLength;
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+        public void appendAsString(StringBuilder sb, int indentLevel) {
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
-
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<BerInteger> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<BerInteger> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+        public void addBerInteger(BerInteger berInteger) {
+            seqOf.add(berInteger);
+        }
+    }
 
-	public static class SubframeBitmaskUl implements Serializable {
+    public static class SubframeBitmaskUl implements Serializable {
 
-		private static final long serialVersionUID = 1L;
+        public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+        private static final long serialVersionUID = 1L;
+        public byte[] code = null;
+        private List<BerBitString> seqOf = null;
 
-		public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
-		public byte[] code = null;
-		private List<BerBitString> seqOf = null;
+        public SubframeBitmaskUl() {
+            seqOf = new ArrayList<BerBitString>();
+        }
 
-		public SubframeBitmaskUl() {
-			seqOf = new ArrayList<BerBitString>();
-		}
+        public SubframeBitmaskUl(byte[] code) {
+            this.code = code;
+        }
 
-		public SubframeBitmaskUl(byte[] code) {
-			this.code = code;
-		}
+        public List<BerBitString> getBerBitString() {
+            if (seqOf == null) {
+                seqOf = new ArrayList<BerBitString>();
+            }
+            return seqOf;
+        }
 
-		public List<BerBitString> getBerBitString() {
-			if (seqOf == null) {
-				seqOf = new ArrayList<BerBitString>();
-			}
-			return seqOf;
-		}
+        public int encode(BerByteArrayOutputStream os) throws IOException {
+            return encode(os, true);
+        }
 
-		public int encode(BerByteArrayOutputStream os) throws IOException {
-			return encode(os, true);
-		}
+        public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
 
-		public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
+            if (code != null) {
+                for (int i = code.length - 1; i >= 0; i--) {
+                    os.write(code[i]);
+                }
+                if (withTag) {
+                    return tag.encode(os) + code.length;
+                }
+                return code.length;
+            }
 
-			if (code != null) {
-				for (int i = code.length - 1; i >= 0; i--) {
-					os.write(code[i]);
-				}
-				if (withTag) {
-					return tag.encode(os) + code.length;
-				}
-				return code.length;
-			}
+            int codeLength = 0;
+            for (int i = (seqOf.size() - 1); i >= 0; i--) {
+                codeLength += seqOf.get(i).encode(os, true);
+            }
 
-			int codeLength = 0;
-			for (int i = (seqOf.size() - 1); i >= 0; i--) {
-				codeLength += seqOf.get(i).encode(os, true);
-			}
+            codeLength += BerLength.encodeLength(os, codeLength);
 
-			codeLength += BerLength.encodeLength(os, codeLength);
+            if (withTag) {
+                codeLength += tag.encode(os);
+            }
 
-			if (withTag) {
-				codeLength += tag.encode(os);
-			}
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public int decode(InputStream is) throws IOException {
+            return decode(is, true);
+        }
 
-		public int decode(InputStream is) throws IOException {
-			return decode(is, true);
-		}
+        public int decode(InputStream is, boolean withTag) throws IOException {
+            int codeLength = 0;
+            int subCodeLength = 0;
+            if (withTag) {
+                codeLength += tag.decodeAndCheck(is);
+            }
 
-		public int decode(InputStream is, boolean withTag) throws IOException {
-			int codeLength = 0;
-			int subCodeLength = 0;
-			if (withTag) {
-				codeLength += tag.decodeAndCheck(is);
-			}
+            BerLength length = new BerLength();
+            codeLength += length.decode(is);
+            int totalLength = length.val;
 
-			BerLength length = new BerLength();
-			codeLength += length.decode(is);
-			int totalLength = length.val;
+            while (subCodeLength < totalLength) {
+                BerBitString element = new BerBitString();
+                subCodeLength += element.decode(is, true);
+                seqOf.add(element);
+            }
+            if (subCodeLength != totalLength) {
+                throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
 
-			while (subCodeLength < totalLength) {
-				BerBitString element = new BerBitString();
-				subCodeLength += element.decode(is, true);
-				seqOf.add(element);
-			}
-			if (subCodeLength != totalLength) {
-				throw new IOException("Decoded SequenceOf or SetOf has wrong length. Expected " + totalLength + " but has " + subCodeLength);
+            }
+            codeLength += subCodeLength;
 
-			}
-			codeLength += subCodeLength;
+            return codeLength;
+        }
 
-			return codeLength;
-		}
+        public void encodeAndSave(int encodingSizeGuess) throws IOException {
+            BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
+            encode(os, false);
+            code = os.getArray();
+        }
 
-		public void encodeAndSave(int encodingSizeGuess) throws IOException {
-			BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-			encode(os, false);
-			code = os.getArray();
-		}
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendAsString(sb, 0);
+            return sb.toString();
+        }
 
-		public String toString() {
-			StringBuilder sb = new StringBuilder();
-			appendAsString(sb, 0);
-			return sb.toString();
-		}
+        public void appendAsString(StringBuilder sb, int indentLevel) {
 
-		public void appendAsString(StringBuilder sb, int indentLevel) {
-
-			sb.append("[\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			if (seqOf == null) {
+            sb.append("[\n");
+            for (int i = 0; i < indentLevel + 1; i++) {
+                sb.append("\t");
+            }
+            if (seqOf == null) {
 //				sb.append("null");
-			}
-			else {
-				Iterator<BerBitString> it = seqOf.iterator();
-				if (it.hasNext()) {
-					sb.append(it.next());
-					while (it.hasNext()) {
-						sb.append(",\n");
-						for (int i = 0; i < indentLevel + 1; i++) {
-							sb.append("\t");
-						}
-						sb.append(it.next());
-					}
-				}
-			}
+            } else {
+                Iterator<BerBitString> it = seqOf.iterator();
+                if (it.hasNext()) {
+                    sb.append(it.next());
+                    while (it.hasNext()) {
+                        sb.append(",\n");
+                        for (int i = 0; i < indentLevel + 1; i++) {
+                            sb.append("\t");
+                        }
+                        sb.append(it.next());
+                    }
+                }
+            }
 
-			sb.append("\n");
-			for (int i = 0; i < indentLevel; i++) {
-				sb.append("\t");
-			}
-			sb.append("]");
-		}
+            sb.append("\n");
+            for (int i = 0; i < indentLevel; i++) {
+                sb.append("\t");
+            }
+            sb.append("]");
+        }
 
-	}
+    }
 
-	public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
+    public static XrancPdu constructPacket(RnibCell cell) {
+        XrancPduBody body = new XrancPduBody();
+        body.setRRMConfig(cell.getRrmConfig());
 
-	public byte[] code = null;
-	private ECGI ecgi = null;
-	private Crnti crnti = null;
-	private Pa pa = null;
-	private StartPrbDl startPrbDl = null;
-	private EndPrbDl endPrbDl = null;
-	private SubframeBitmaskDl subframeBitmaskDl = null;
-	private P0UePusch p0UePusch = null;
-	private StartPrbUl startPrbUl = null;
-	private EndPrbUl endPrbUl = null;
-	private SubframeBitmaskUl subframeBitmaskUl = null;
-	
-	public RRMConfig() {
-	}
+        BerUTF8String ver = null;
+        try {
+            ver = new BerUTF8String("4");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
 
-	public RRMConfig(byte[] code) {
-		this.code = code;
-	}
+        XrancApiID apiID = new XrancApiID(26);
+        XrancPduHdr hdr = new XrancPduHdr();
+        hdr.setVer(ver);
+        hdr.setApiId(apiID);
 
-	public void setEcgi(ECGI ecgi) {
-		this.ecgi = ecgi;
-	}
-
-	public ECGI getEcgi() {
-		return ecgi;
-	}
-
-	public void setCrnti(Crnti crnti) {
-		this.crnti = crnti;
-	}
-
-	public Crnti getCrnti() {
-		return crnti;
-	}
-
-	public void setPa(Pa pa) {
-		this.pa = pa;
-	}
-
-	public Pa getPa() {
-		return pa;
-	}
-
-	public void setStartPrbDl(StartPrbDl startPrbDl) {
-		this.startPrbDl = startPrbDl;
-	}
-
-	public StartPrbDl getStartPrbDl() {
-		return startPrbDl;
-	}
-
-	public void setEndPrbDl(EndPrbDl endPrbDl) {
-		this.endPrbDl = endPrbDl;
-	}
-
-	public EndPrbDl getEndPrbDl() {
-		return endPrbDl;
-	}
-
-	public void setSubframeBitmaskDl(SubframeBitmaskDl subframeBitmaskDl) {
-		this.subframeBitmaskDl = subframeBitmaskDl;
-	}
-
-	public SubframeBitmaskDl getSubframeBitmaskDl() {
-		return subframeBitmaskDl;
-	}
-
-	public void setP0UePusch(P0UePusch p0UePusch) {
-		this.p0UePusch = p0UePusch;
-	}
-
-	public P0UePusch getP0UePusch() {
-		return p0UePusch;
-	}
-
-	public void setStartPrbUl(StartPrbUl startPrbUl) {
-		this.startPrbUl = startPrbUl;
-	}
-
-	public StartPrbUl getStartPrbUl() {
-		return startPrbUl;
-	}
-
-	public void setEndPrbUl(EndPrbUl endPrbUl) {
-		this.endPrbUl = endPrbUl;
-	}
-
-	public EndPrbUl getEndPrbUl() {
-		return endPrbUl;
-	}
-
-	public void setSubframeBitmaskUl(SubframeBitmaskUl subframeBitmaskUl) {
-		this.subframeBitmaskUl = subframeBitmaskUl;
-	}
-
-	public SubframeBitmaskUl getSubframeBitmaskUl() {
-		return subframeBitmaskUl;
-	}
-
-	public int encode(BerByteArrayOutputStream os) throws IOException {
-		return encode(os, true);
-	}
-
-	public int encode(BerByteArrayOutputStream os, boolean withTag) throws IOException {
-
-		if (code != null) {
-			for (int i = code.length - 1; i >= 0; i--) {
-				os.write(code[i]);
-			}
-			if (withTag) {
-				return tag.encode(os) + code.length;
-			}
-			return code.length;
-		}
-
-		int codeLength = 0;
-		if (subframeBitmaskUl != null) {
-			codeLength += subframeBitmaskUl.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 9
-			os.write(0xA9);
-			codeLength += 1;
-		}
-		
-		if (endPrbUl != null) {
-			codeLength += endPrbUl.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 8
-			os.write(0xA8);
-			codeLength += 1;
-		}
-		
-		if (startPrbUl != null) {
-			codeLength += startPrbUl.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 7
-			os.write(0xA7);
-			codeLength += 1;
-		}
-		
-		if (p0UePusch != null) {
-			codeLength += p0UePusch.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 6
-			os.write(0xA6);
-			codeLength += 1;
-		}
-		
-		if (subframeBitmaskDl != null) {
-			codeLength += subframeBitmaskDl.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 5
-			os.write(0xA5);
-			codeLength += 1;
-		}
-		
-		if (endPrbDl != null) {
-			codeLength += endPrbDl.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 4
-			os.write(0xA4);
-			codeLength += 1;
-		}
-		
-		if (startPrbDl != null) {
-			codeLength += startPrbDl.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 3
-			os.write(0xA3);
-			codeLength += 1;
-		}
-		
-		if (pa != null) {
-			codeLength += pa.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 2
-			os.write(0xA2);
-			codeLength += 1;
-		}
-		
-		if (crnti != null) {
-			codeLength += crnti.encode(os, false);
-			// write tag: CONTEXT_CLASS, CONSTRUCTED, 1
-			os.write(0xA1);
-			codeLength += 1;
-		}
-		
-		codeLength += ecgi.encode(os, false);
-		// write tag: CONTEXT_CLASS, CONSTRUCTED, 0
-		os.write(0xA0);
-		codeLength += 1;
-		
-		codeLength += BerLength.encodeLength(os, codeLength);
-
-		if (withTag) {
-			codeLength += tag.encode(os);
-		}
-
-		return codeLength;
-
-	}
-
-	public int decode(InputStream is) throws IOException {
-		return decode(is, true);
-	}
-
-	public int decode(InputStream is, boolean withTag) throws IOException {
-		int codeLength = 0;
-		int subCodeLength = 0;
-		BerTag berTag = new BerTag();
-
-		if (withTag) {
-			codeLength += tag.decodeAndCheck(is);
-		}
-
-		BerLength length = new BerLength();
-		codeLength += length.decode(is);
-
-		int totalLength = length.val;
-		codeLength += totalLength;
-
-		subCodeLength += berTag.decode(is);
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 0)) {
-			ecgi = new ECGI();
-			subCodeLength += ecgi.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		else {
-			throw new IOException("Tag does not match the mandatory sequence element tag.");
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 1)) {
-			crnti = new Crnti();
-			subCodeLength += crnti.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 2)) {
-			pa = new Pa();
-			subCodeLength += pa.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 3)) {
-			startPrbDl = new StartPrbDl();
-			subCodeLength += startPrbDl.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 4)) {
-			endPrbDl = new EndPrbDl();
-			subCodeLength += endPrbDl.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 5)) {
-			subframeBitmaskDl = new SubframeBitmaskDl();
-			subCodeLength += subframeBitmaskDl.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 6)) {
-			p0UePusch = new P0UePusch();
-			subCodeLength += p0UePusch.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 7)) {
-			startPrbUl = new StartPrbUl();
-			subCodeLength += startPrbUl.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 8)) {
-			endPrbUl = new EndPrbUl();
-			subCodeLength += endPrbUl.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-			subCodeLength += berTag.decode(is);
-		}
-		
-		if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 9)) {
-			subframeBitmaskUl = new SubframeBitmaskUl();
-			subCodeLength += subframeBitmaskUl.decode(is, false);
-			if (subCodeLength == totalLength) {
-				return codeLength;
-			}
-		}
-		throw new IOException("Unexpected end of sequence, length tag: " + totalLength + ", actual sequence length: " + subCodeLength);
-
-		
-	}
-
-	public void encodeAndSave(int encodingSizeGuess) throws IOException {
-		BerByteArrayOutputStream os = new BerByteArrayOutputStream(encodingSizeGuess);
-		encode(os, false);
-		code = os.getArray();
-	}
-
-	public String toString() {
-		StringBuilder sb = new StringBuilder();
-		appendAsString(sb, 0);
-		return sb.toString();
-	}
-
-	public void appendAsString(StringBuilder sb, int indentLevel) {
-
-		sb.append("{");
-		sb.append("\n");
-		for (int i = 0; i < indentLevel + 1; i++) {
-			sb.append("\t");
-		}
-		if (ecgi != null) {
-			sb.append("\"ecgi\": ");
-			ecgi.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (crnti != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"crnti\": ");
-			crnti.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (pa != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"pa\": ");
-			pa.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (startPrbDl != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"startPrbDl\": ");
-			startPrbDl.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (endPrbDl != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"endPrbDl\": ");
-			endPrbDl.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (subframeBitmaskDl != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"subframeBitmaskDl\": ");
-			subframeBitmaskDl.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (p0UePusch != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"p0UePusch\": ");
-			p0UePusch.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (startPrbUl != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"startPrbUl\": ");
-			startPrbUl.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (endPrbUl != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"endPrbUl\": ");
-			endPrbUl.appendAsString(sb, indentLevel + 1);
-		}
-		
-		if (subframeBitmaskUl != null) {
-			sb.append(",\n");
-			for (int i = 0; i < indentLevel + 1; i++) {
-				sb.append("\t");
-			}
-			sb.append("\"subframeBitmaskUl\": ");
-			subframeBitmaskUl.appendAsString(sb, indentLevel + 1);
-		}
-		
-		sb.append("\n");
-		for (int i = 0; i < indentLevel; i++) {
-			sb.append("\t");
-		}
-		sb.append("}");
-	}
+        XrancPdu pdu = new XrancPdu();
+        pdu.setHdr(hdr);
+        pdu.setBody(body);
+        return pdu;
+    }
 
 }
 
diff --git a/src/main/java/org.onosproject.xran/controller/Controller.java b/src/main/java/org.onosproject.xran/controller/Controller.java
index b5b7f7d..2191f5b 100644
--- a/src/main/java/org.onosproject.xran/controller/Controller.java
+++ b/src/main/java/org.onosproject.xran/controller/Controller.java
@@ -73,7 +73,7 @@
         return b;
     }
 
-    public void start(XranDeviceAgent deviceAgent, XranHostAgent hostAgent, XranControllerImpl.InternalXranPacketAgent packetAgent, int port) {
+    public void start(XranDeviceAgent deviceAgent, XranHostAgent hostAgent, XranPacketProcessor packetAgent, int port) {
         if (isRunning && this.port != port) {
             stop();
             this.deviceAgent = deviceAgent;
diff --git a/src/main/java/org.onosproject.xran/controller/XranController.java b/src/main/java/org.onosproject.xran/controller/XranController.java
index 19b7537..9f2ae7a 100644
--- a/src/main/java/org.onosproject.xran/controller/XranController.java
+++ b/src/main/java/org.onosproject.xran/controller/XranController.java
@@ -16,14 +16,21 @@
 
 package org.onosproject.xran.controller;
 
+import org.onosproject.xran.entities.RnibCell;
+import org.onosproject.xran.entities.RnibLink;
 import org.onosproject.xran.providers.XranDeviceListener;
 import org.onosproject.xran.providers.XranHostListener;
 
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.SynchronousQueue;
+
 /**
  * Created by dimitris on 7/27/17.
  */
 public interface XranController {
 
+    SynchronousQueue<String> sendHORequest(RnibLink newLink, RnibLink oldLink);
+
     void addListener(XranDeviceListener listener);
 
     void addListener(XranHostListener listener);
@@ -31,4 +38,6 @@
     void removeListener(XranDeviceListener listener);
 
     void removeListener(XranHostListener listener);
+
+    SynchronousQueue<String> sendModifiedRRMConf(RnibCell cell);
 }
diff --git a/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java b/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java
index 36b4c07..a3740bc 100644
--- a/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java
+++ b/src/main/java/org.onosproject.xran/controller/XranControllerImpl.java
@@ -49,17 +49,16 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.xml.bind.DatatypeConverter;
 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.*;
 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.UeState;
 import static org.onosproject.xran.entities.RnibUe.hostIdtoMME;
 
 /**
@@ -107,6 +106,8 @@
     private LinkMap linkMap;
     /* MAPS */
     private ConcurrentMap<String, ECGI> legitCells = new ConcurrentHashMap<>();
+    private ConcurrentMap<CRNTI, SynchronousQueue<String>> hoQueue = new ConcurrentHashMap<CRNTI, SynchronousQueue<String>>();
+    private ConcurrentMap<ECGI, SynchronousQueue<String>> RRMCellQueue = new ConcurrentHashMap<ECGI, SynchronousQueue<String>>();
     /* AGENTS */
     private InternalXranDeviceAgent deviceAgent = new InternalXranDeviceAgent();
     private InternalXranHostAgent hostAgent = new InternalXranHostAgent();
@@ -151,6 +152,28 @@
     }
 
     @Override
+    public SynchronousQueue<String> sendHORequest(RnibLink newLink, RnibLink oldLink) {
+        ECGI newEcgi = newLink.getLinkId().getSourceId(),
+                oldEcgi = oldLink.getLinkId().getSourceId();
+        CRNTI crnti = linkMap.getCrnti(newLink.getLinkId().getDestinationId());
+        ChannelHandlerContext newCtx = cellMap.getCtx(newEcgi),
+                oldCtx = cellMap.getCtx(oldEcgi);
+
+        try {
+            XrancPdu xrancPdu = HandoffRequest.constructPacket(crnti, oldEcgi, newEcgi);
+            newCtx.writeAndFlush(getSctpMessage(xrancPdu));
+            oldCtx.writeAndFlush(getSctpMessage(xrancPdu));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        SynchronousQueue<String> queue = new SynchronousQueue<>();
+        hoQueue.put(crnti, queue);
+
+        return queue;
+    }
+
+    @Override
     public void addListener(XranDeviceListener listener) {
         xranDeviceListeners.add(listener);
     }
@@ -170,6 +193,22 @@
         xranHostListeners.remove(listener);
     }
 
+    @Override
+    public SynchronousQueue<String> sendModifiedRRMConf(RnibCell cell) {
+        ECGI ecgi = cell.getEcgi();
+        ChannelHandlerContext ctx = cellMap.getCtx(ecgi);
+        try {
+            XrancPdu pdu = RRMConfig.constructPacket(cell);
+            ctx.writeAndFlush(getSctpMessage(pdu));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        SynchronousQueue<String> queue = new SynchronousQueue<>();
+        RRMCellQueue.put(ecgi, queue);
+
+        return queue;
+    }
+
     private void restartTimer(RnibUe ue) {
         Timer timer = new Timer();
         ue.setTimer(timer);
@@ -177,7 +216,7 @@
         timer.schedule(new TimerTask() {
             @Override
             public void run() {
-                if (ue.getUeState() == UeState.IDLE) {
+                if (ue.getState() == RnibUe.State.IDLE) {
                     hostAgent.removeConnectedHost(ue);
                     log.info("UE is removed after 10 seconds of IDLE");
                 } else {
@@ -222,8 +261,8 @@
                                             if (conf == null) {
                                                 try {
                                                     ChannelHandlerContext ctx = cellMap.getCtx(ecgi);
-                                                    SctpMessage msg = XranChannelHandler.getSctpMessage(ConfigEncoderDecoder.constructPacket(ecgi));
-                                                    ctx.writeAndFlush(msg);
+                                                    XrancPdu xrancPdu = ConfigEncoderDecoder.constructPacket(ecgi);
+                                                    ctx.writeAndFlush(getSctpMessage(xrancPdu));
                                                 } catch (IOException e) {
                                                     log.error(ExceptionUtils.getFullStackTrace(e));
                                                     e.printStackTrace();
@@ -236,8 +275,7 @@
                                                             getCtx(ecgi);
                                                     XrancPdu xrancPdu = L2MeasConf.constructPacket(ecgi, xranConfig.getL2MeasInterval());
                                                     cell.setMeasConfig(xrancPdu.getBody().getL2MeasConfig());
-                                                    SctpMessage sctpMessage = XranChannelHandler.
-                                                            getSctpMessage(xrancPdu);
+                                                    SctpMessage sctpMessage = getSctpMessage(xrancPdu);
                                                     ctx.writeAndFlush(sctpMessage);
                                                 } catch (IOException e) {
                                                     log.error(ExceptionUtils.getFullStackTrace(e));
@@ -287,11 +325,10 @@
                                             if (ue.getCapability() == null) {
                                                 try {
                                                     ChannelHandlerContext ctx = cellMap.getCtx(primary.getEcgi());
-                                                    SctpMessage msg = XranChannelHandler.
-                                                            getSctpMessage(UECapabilityEnq.constructPacket(
-                                                                    primary.getEcgi(),
-                                                                    ue.getRanId()));
-                                                    ctx.writeAndFlush(msg);
+                                                    XrancPdu xrancPdu = UECapabilityEnq.constructPacket(
+                                                            primary.getEcgi(),
+                                                            ue.getRanId());
+                                                    ctx.writeAndFlush(getSctpMessage(xrancPdu));
                                                 } catch (IOException e) {
                                                     log.warn(ExceptionUtils.getFullStackTrace(e));
                                                     e.printStackTrace();
@@ -317,8 +354,7 @@
                                                                 xranConfig.getRxSignalInterval()
                                                         );
                                                         ue.setMeasConfig(xrancPdu.getBody().getRXSigMeasConfig());
-                                                        SctpMessage msg = XranChannelHandler.getSctpMessage(xrancPdu);
-                                                        ctx.writeAndFlush(msg);
+                                                        ctx.writeAndFlush(getSctpMessage(xrancPdu));
                                                     } catch (IOException e) {
                                                         log.warn(ExceptionUtils.getFullStackTrace(e));
                                                         e.printStackTrace();
@@ -400,7 +436,7 @@
 
                 Set<ECGI> ecgiSet = xranStore.getLinksByUeId(ue.getMmeS1apId().longValue())
                         .stream()
-                        .map(l -> l.getLinkId().getSource())
+                        .map(l -> l.getLinkId().getSourceId())
                         .collect(Collectors.toSet());
 
                 for (XranHostListener l : xranHostListeners) {
@@ -462,7 +498,7 @@
                     if (xranStore.getCell(ecgi) != null) {
                         CRNTI crnti = ueAdmissionRequest.getCrnti();
                         send_pdu = UEAdmEncoderDecoder.constructPacket(ecgi, crnti);
-                        ctx.writeAndFlush(XranChannelHandler.getSctpMessage(send_pdu));
+                        ctx.writeAndFlush(getSctpMessage(send_pdu));
                     } else {
                         log.warn("Could not find ECGI in registered cells: {}", ecgi);
                     }
@@ -475,9 +511,9 @@
                     RnibUe ue = ueMap.get(ueAdmissionStatus.getCrnti());
                     if (ue != null) {
                         if (ueAdmissionStatus.getAdmEstStatus().value.intValue() == 0) {
-                            ue.setUeState(UeState.ACTIVE);
+                            ue.setState(RnibUe.State.ACTIVE);
                         } else {
-                            ue.setUeState(UeState.IDLE);
+                            ue.setState(RnibUe.State.IDLE);
                         }
                     }
                     break;
@@ -518,7 +554,7 @@
                     UEReleaseInd ueReleaseInd = recv_pdu.getBody().getUEReleaseInd();
                     RnibUe ue = ueMap.get(ueReleaseInd.getCrnti());
                     if (ue != null) {
-                        ue.setUeState(UeState.IDLE);
+                        ue.setState(RnibUe.State.IDLE);
                         restartTimer(ue);
                     }
                     break;
@@ -541,7 +577,7 @@
 
                     send_pdu = BearerEncoderDecoder.constructPacket(ecgi, crnti, erabParams, numErabs);
                     // Encode and send Bearer Admission Response - API ID 9
-                    ctx.writeAndFlush(XranChannelHandler.getSctpMessage(send_pdu));
+                    ctx.writeAndFlush(getSctpMessage(send_pdu));
                     break;
                 }
                 case 10: {
@@ -582,7 +618,7 @@
                     // Encode and send UE CAPABILITY ENQUIRY
                     UECapabilityEnquiry ueCapabilityEnquiry = recv_pdu.getBody().getUECapabilityEnquiry();
                     XrancPdu xrancPdu = UECapabilityEnq.constructPacket(ueCapabilityEnquiry.getEcgi(), ueCapabilityEnquiry.getCrnti());
-                    ctx.writeAndFlush(XranChannelHandler.getSctpMessage(xrancPdu));
+                    ctx.writeAndFlush(getSctpMessage(xrancPdu));
                     break;
                 }
                 case 13: {
@@ -599,6 +635,40 @@
 
                     //14, 15, 16 are handoff
                 }
+                case 15: {
+                    HOFailure hoFailure = recv_pdu.getBody().getHOFailure();
+
+                    try {
+                        hoQueue.get(hoFailure.getCrnti())
+                                .put("Hand Over Failed with cause: " + hoFailure.getCause());
+                    } catch (InterruptedException e) {
+                        log.error(ExceptionUtils.getFullStackTrace(e));
+                        e.printStackTrace();
+                    } finally {
+                        hoQueue.remove(hoFailure.getCrnti());
+                    }
+                    break;
+                }
+                case 16: {
+                    HOComplete hoComplete = recv_pdu.getBody().getHOComplete();
+
+                    RnibLink oldLink = linkMap.get(hoComplete.getEcgiS(), hoComplete.getCrntiNew()),
+                            newLink = linkMap.get(hoComplete.getEcgiT(), hoComplete.getCrntiNew());
+
+                    oldLink.setType(RnibLink.Type.NON_SERVING);
+                    newLink.setType(RnibLink.Type.SERVING_PRIMARY);
+
+                    try {
+                        hoQueue.get(hoComplete.getCrntiNew())
+                                .put("Hand Over Completed");
+                    } catch (InterruptedException e) {
+                        log.error(ExceptionUtils.getFullStackTrace(e));
+                        e.printStackTrace();
+                    } finally {
+                        hoQueue.remove(hoComplete.getCrntiNew());
+                    }
+                    break;
+                }
                 case 18: {
                     // Decode RX Sig Meas Report.
                     RXSigMeasReport rxSigMeasReport = recv_pdu.getBody().getRXSigMeasReport();
@@ -666,7 +736,7 @@
                             log.warn("Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
                         }
                     });
-
+                    break;
                 }
                 case 21: {
                     RadioMeasReportPerCell radioMeasReportPerCell = recv_pdu.getBody().getRadioMeasReportPerCell();
@@ -723,6 +793,19 @@
                     }
                     break;
                 }
+                case 27: {
+                    RRMConfigStatus rrmConfigStatus = recv_pdu.getBody().getRRMConfigStatus();
+                    try {
+                        RRMCellQueue.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());
+                    }
+                    break;
+                }
                 case 34: {
                     TrafficSplitConfig trafficSplitConfig = recv_pdu.getBody().getTrafficSplitConfig();
 
@@ -741,9 +824,11 @@
                             log.warn("Could not find cell with ECGI: {}", trafficSplitConfig.getEcgi());
                         }
                     });
+                    break;
                 }
                 default: {
                     log.warn("Wrong API ID");
+                    break;
                 }
             }
 
diff --git a/src/main/java/org.onosproject.xran/entities/RnibCell.java b/src/main/java/org.onosproject.xran/entities/RnibCell.java
index 3aa5c89..d917f02 100644
--- a/src/main/java/org.onosproject.xran/entities/RnibCell.java
+++ b/src/main/java/org.onosproject.xran/entities/RnibCell.java
@@ -19,13 +19,14 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import org.onosproject.net.DeviceId;
 import org.onosproject.xran.codecs.api.ECGI;
-import org.onosproject.xran.codecs.api.MMEUES1APID;
 import org.onosproject.xran.codecs.api.PRBUsage;
 import org.onosproject.xran.codecs.pdu.CellConfigReport;
 import org.onosproject.xran.codecs.pdu.L2MeasConfig;
 import org.onosproject.xran.codecs.pdu.RRMConfig;
 import org.onosproject.xran.codecs.pdu.SchedMeasReportPerCell;
 import org.openmuc.jasn1.ber.BerByteArrayOutputStream;
+import org.openmuc.jasn1.ber.types.BerBitString;
+import org.openmuc.jasn1.ber.types.BerInteger;
 
 import javax.xml.bind.DatatypeConverter;
 import java.io.ByteArrayInputStream;
@@ -33,6 +34,7 @@
 import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.List;
 
 /**
  * Created by dimitris on 7/22/17.
@@ -49,6 +51,8 @@
 
     public RnibCell() {
         prbUsage = new PrbUsageContainer();
+        setDefaultRRMConf();
+
     }
 
     public static URI uri(ECGI ecgi) {
@@ -77,6 +81,65 @@
         return ecgi;
     }
 
+    public RRMConfig getRrmConfig() {
+        return rrmConfig;
+    }
+
+    public void setRrmConfig(RRMConfig rrmConfig) {
+        this.rrmConfig = rrmConfig;
+    }
+
+    public PrbUsageContainer getPrbUsage() {
+        return prbUsage;
+    }
+
+    public void setPrbUsage(PrbUsageContainer prbUsage) {
+        this.prbUsage = prbUsage;
+    }
+
+    private void setDefaultRRMConf() {
+        rrmConfig = new RRMConfig();
+
+        RRMConfig.Crnti crnti2 = new RRMConfig.Crnti();
+
+        rrmConfig.setCrnti(crnti2);
+
+        rrmConfig.setEcgi(ecgi);
+
+        RRMConfig.StartPrbDl startPrbDl = new RRMConfig.StartPrbDl();
+        startPrbDl.addBerInteger(new BerInteger(0));
+        startPrbDl.addBerInteger(new BerInteger(50));
+
+        rrmConfig.setStartPrbDl(startPrbDl);
+
+        RRMConfig.StartPrbUl startPrbUl = new RRMConfig.StartPrbUl();
+        startPrbUl.addBerInteger(new BerInteger(50));
+        startPrbUl.addBerInteger(new BerInteger(100));
+
+        rrmConfig.setStartPrbUl(startPrbUl);
+
+        RRMConfig.EndPrbDl endPrbDl = new RRMConfig.EndPrbDl();
+        endPrbDl.addBerInteger(new BerInteger(50));
+        endPrbDl.addBerInteger(new BerInteger(100));
+
+        rrmConfig.setEndPrbDl(endPrbDl);
+
+        RRMConfig.EndPrbUl endPrbUl = new RRMConfig.EndPrbUl();
+        endPrbUl.addBerInteger(new BerInteger(50));
+        endPrbUl.addBerInteger(new BerInteger(100));
+
+        rrmConfig.setEndPrbUl(endPrbUl);
+
+        RRMConfig.SubframeBitmaskDl subframeBitmaskDl = new RRMConfig.SubframeBitmaskDl();
+        BerBitString berBitString = new BerBitString(new byte[]{(byte) 0xAA, (byte) 0x80}, 10);
+        BerBitString berBitString1 = new BerBitString(new byte[]{(byte) 0x55, (byte) 0x40}, 10);
+
+        subframeBitmaskDl.addBerBitString(berBitString);
+        subframeBitmaskDl.addBerBitString(berBitString1);
+
+        rrmConfig.setSubframeBitmaskDl(subframeBitmaskDl);
+    }
+
     public ECGI getEcgi() {
         return ecgi;
     }
@@ -89,15 +152,40 @@
         return conf;
     }
 
+    /*public RRMConfig getRrmConfig() {
+        return rrmConfig;
+    }*/
+
     public void setConf(CellConfigReport conf) {
         this.conf = conf;
     }
 
-    public RRMConfig getRrmConfig() {
-        return rrmConfig;
-    }
+    public void modifyRrmConfig(JsonNode rrmConfigNode, List<RnibUe> ueList) {
+        RRMConfig.Crnti crnti = new RRMConfig.Crnti();
+        ueList.forEach(ue -> crnti.addCRNTI(ue.getRanId()));
 
-    public void modifyRrmConfig(JsonNode rrmConfig) {
+        RRMConfig.StartPrbDl startPrbDl = new RRMConfig.StartPrbDl();
+        RRMConfig.EndPrbDl endPrbDl = new RRMConfig.EndPrbDl();
+        int i = 0;
+        if (rrmConfigNode.get("start_prb_dl").isArray()) {
+            for (final JsonNode config : rrmConfigNode) {
+                startPrbDl.getSeqOf().set(i, new BerInteger(config.asInt()));
+                i++;
+            }
+        }
+        i = 0;
+        if (rrmConfigNode.get("end_prb_dl").isArray()) {
+            for (final JsonNode config : rrmConfigNode) {
+                endPrbDl.getSeqOf().set(i, new BerInteger(config.asInt()));
+                i++;
+            }
+        }
+        rrmConfig.setEndPrbDl(endPrbDl);
+        rrmConfig.setStartPrbDl(startPrbDl);
+        rrmConfig.setCrnti(crnti);
+        rrmConfig.setEcgi(ecgi);
+
+
         // TODO
     }
 
diff --git a/src/main/java/org.onosproject.xran/entities/RnibLink.java b/src/main/java/org.onosproject.xran/entities/RnibLink.java
index eb61120..d9f39cc 100644
--- a/src/main/java/org.onosproject.xran/entities/RnibLink.java
+++ b/src/main/java/org.onosproject.xran/entities/RnibLink.java
@@ -22,6 +22,8 @@
 import org.onosproject.xran.identifiers.LinkId;
 import org.openmuc.jasn1.ber.types.BerInteger;
 
+import java.util.Arrays;
+import java.util.Optional;
 import java.util.Timer;
 
 /**
@@ -42,8 +44,9 @@
     private Type type;
     private Timer timer;
 
-    public RnibLink() {
+    public RnibLink(RnibCell cell, RnibUe ue) {
         trafficPercent = new TrafficSplitPercentage();
+        trafficPercent.setEcgi(cell.getEcgi());
         trafficPercent.setTrafficPercentDl(new BerInteger(100));
         trafficPercent.setTrafficPercentUl(new BerInteger(100));
 
@@ -52,6 +55,10 @@
         pdcpPackDelay = new PDCPPacketDelay();
         resourceUsage = new ResourceUsage();
         timer = new Timer();
+
+        type = Type.NON_SERVING;
+
+        linkId = LinkId.valueOf(cell, ue);
     }
 
     public Timer getTimer() {
@@ -73,7 +80,7 @@
     }
 
     public void setLinkId(RnibCell cell, RnibUe ue) {
-        this.linkId = new LinkId(cell.getEcgi(), ue.getMmeS1apId());
+        this.linkId = LinkId.valueOf(cell, ue);
         trafficPercent.setEcgi(cell.getEcgi());
     }
 
@@ -174,24 +181,38 @@
     }
 
     public enum Type {
-        SERVING_PRIMARY {
+        SERVING_PRIMARY("serving/primary") {
             @Override
             public String toString() {
                 return "\"serving/primary\"";
             }
         },
         // TODO: Add CA/DC
-        SERVING_SECONDARY {
+        SERVING_SECONDARY("serving/secondary") {
             @Override
             public String toString() {
                 return "\"serving/secondary\"";
             }
         },
-        NON_SERVING {
+        NON_SERVING("non-serving") {
             @Override
             public String toString() {
                 return "\"non-serving\"";
             }
+        };
+
+        private String name;
+
+        Type(String name) {
+            this.name = name;
+        }
+
+        public static Type getEnum(String name) {
+            Optional<Type> any = Arrays.stream(Type.values()).filter(typeStr -> typeStr.name.equals(name)).findAny();
+            if (any.isPresent()) {
+                return any.get();
+            }
+            throw new IllegalArgumentException("No enum defined for string: " + name);
         }
     }
 
diff --git a/src/main/java/org.onosproject.xran/entities/RnibUe.java b/src/main/java/org.onosproject.xran/entities/RnibUe.java
index 2be3e01..b58e77e 100644
--- a/src/main/java/org.onosproject.xran/entities/RnibUe.java
+++ b/src/main/java/org.onosproject.xran/entities/RnibUe.java
@@ -48,13 +48,13 @@
     private ENBUES1APID enbS1apId;
     private MMEUES1APID mmeS1apId;
     private CRNTI ranId;
-    private UeState ueState;
+    private State state;
     private UECapabilityInfo capability;
     private RXSigMeasConfig measConfig;
     private Timer timer;
 
     public RnibUe() {
-        ueState = UeState.ACTIVE;
+        state = State.ACTIVE;
         timer = new Timer();
     }
 
@@ -174,12 +174,12 @@
         this.capability = capability;
     }
 
-    public UeState getUeState() {
-        return ueState;
+    public State getState() {
+        return state;
     }
 
-    public void setUeState(UeState ueState) {
-        this.ueState = ueState;
+    public void setState(State state) {
+        this.state = state;
     }
 
     @Override
@@ -190,7 +190,7 @@
                 .append(enbS1apId != null ? ",\n\"enb-s1-ap-id\":" + enbS1apId : "")
                 .append(imsi != null ? ",\"imsi\":" + imsi : "")
                 .append(ranId != null ? ",\n\"ran-id\":" + ranId : "")
-                .append(ueState != null ? ",\n\"state\":" + ueState : "")
+                .append(state != null ? ",\n\"state\":" + state : "")
                 .append(capability != null ? ",\n\"capability\":" + capability : "")
                 .append(measConfig != null ? ",\n\"meas-config\":" + measConfig : "")
                 .append("\n}\n");
@@ -214,7 +214,7 @@
         return result;
     }
 
-    public enum UeState {
+    public enum State {
         ACTIVE {
             @Override
             public String toString() {
diff --git a/src/main/java/org.onosproject.xran/identifiers/LinkId.java b/src/main/java/org.onosproject.xran/identifiers/LinkId.java
index 8531d78..9c71224 100644
--- a/src/main/java/org.onosproject.xran/identifiers/LinkId.java
+++ b/src/main/java/org.onosproject.xran/identifiers/LinkId.java
@@ -22,32 +22,57 @@
 import org.onosproject.xran.entities.RnibUe;
 
 public class LinkId {
-    private ECGI source;
-    private MMEUES1APID destination;
+    private RnibCell cell;
+    private RnibUe ue;
 
-    public LinkId(ECGI source, MMEUES1APID destination) {
-        this.source = source;
-        this.destination = destination;
+    private LinkId(RnibCell cell, RnibUe ue) {
+        this.cell = cell;
+        this.ue = ue;
     }
 
     public static LinkId valueOf(RnibCell cell, RnibUe ue) {
-        return new LinkId(cell.getEcgi(), ue.getMmeS1apId());
+        return new LinkId(cell, ue);
     }
 
-    public ECGI getSource() {
-        return source;
+    public static LinkId valueOf(ECGI ecgi, MMEUES1APID mmeues1APID) {
+        RnibCell cell = new RnibCell();
+        RnibUe ue = new RnibUe();
+
+        cell.setEcgi(ecgi);
+        ue.setMmeS1apId(mmeues1APID);
+        return new LinkId(cell, ue);
     }
 
-    public void setSource(ECGI source) {
-        this.source = source;
+    public ECGI getSourceId() {
+        return cell.getEcgi();
     }
 
-    public MMEUES1APID getDestination() {
-        return destination;
+    public void setSourceId(ECGI sourceId) {
+        cell.setEcgi(sourceId);
     }
 
-    public void setDestination(MMEUES1APID destination) {
-        this.destination = destination;
+    public MMEUES1APID getDestinationId() {
+        return ue.getMmeS1apId();
+    }
+
+    public void setDestinationId(MMEUES1APID destinationId) {
+        ue.setMmeS1apId(destinationId);
+    }
+
+    public RnibCell getCell() {
+        return cell;
+    }
+
+    public void setCell(RnibCell cell) {
+        this.cell = cell;
+    }
+
+    public RnibUe getUe() {
+        return ue;
+    }
+
+    public void setUe(RnibUe ue) {
+        this.ue = ue;
     }
 
     @Override
@@ -55,15 +80,15 @@
         return this == o ||
                 o != null &&
                         o instanceof LinkId &&
-                        destination.equals(((LinkId) o).destination) &&
-                        source.equals(((LinkId) o).source);
+                        cell.getEcgi().equals(((LinkId) o).cell.getEcgi()) &&
+                        ue.getMmeS1apId().equals(((LinkId) o).ue.getMmeS1apId());
 
     }
 
     @Override
     public int hashCode() {
-        int result = source.hashCode();
-        result = 31 * result + destination.hashCode();
+        int result = cell.getEcgi().hashCode();
+        result = 31 * result + ue.getMmeS1apId().hashCode();
         return result;
     }
 
@@ -71,8 +96,8 @@
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("{\n")
-                .append(source != null ? "\"cell\":" + source : "")
-                .append(destination != null ? ",\n\"ue\":" + destination : "")
+                .append(cell != null ? "\"cell\":" + cell : "")
+                .append(ue != null ? ",\n\"ue\":" + ue : "")
                 .append("\n}\n");
         return sb.toString();
     }
diff --git a/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java b/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java
index 7894b74..f3a9fac 100644
--- a/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java
+++ b/src/main/java/org.onosproject.xran/impl/DefaultXranStore.java
@@ -19,6 +19,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.Lists;
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.felix.scr.annotations.*;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
@@ -85,7 +86,7 @@
         list.addAll(
                 linkMap.keySet()
                         .stream()
-                        .filter(k -> k.getSource().equals(ecgi))
+                        .filter(k -> k.getSourceId().equals(ecgi))
                         .map(v -> linkMap.get(v))
                         .collect(Collectors.toList()));
 
@@ -100,7 +101,7 @@
         list.addAll(
                 linkMap.keySet()
                         .stream()
-                        .filter(k -> k.getSource().getEUTRANcellIdentifier().equals(eci))
+                        .filter(k -> k.getSourceId().getEUTRANcellIdentifier().equals(eci))
                         .map(v -> linkMap.get(v))
                         .collect(Collectors.toList()));
 
@@ -115,7 +116,7 @@
         list.addAll(
                 linkMap.keySet()
                         .stream()
-                        .filter(k -> k.getDestination().equals(mme))
+                        .filter(k -> k.getDestinationId().equals(mme))
                         .map(v -> linkMap.get(v))
                         .collect(Collectors.toList()));
 
@@ -129,8 +130,8 @@
 
         Optional<LinkId> first = linkMap.keySet()
                 .stream()
-                .filter(linkId -> linkId.getSource().getEUTRANcellIdentifier().equals(eci))
-                .filter(linkId -> linkId.getDestination().equals(mme))
+                .filter(linkId -> linkId.getSourceId().getEUTRANcellIdentifier().equals(eci))
+                .filter(linkId -> linkId.getDestinationId().equals(mme))
                 .findFirst();
 
         return first.map(linkId -> linkMap.get(linkId)).orElse(null);
@@ -142,12 +143,13 @@
         RnibUe ue = getUe(euId);
 
         if (cell != null && ue != null) {
-            RnibLink link = new RnibLink();
-            link.setLinkId(cell, ue);
+            RnibLink link = new RnibLink(cell, ue);
 
-            // TODO: string to enum mapping
-//            link.setType(type);
-
+            try {
+                link.setType(RnibLink.Type.valueOf(type));
+            } catch (Exception e) {
+                log.error(ExceptionUtils.getFullStackTrace(e));
+            }
             linkMap.put(link.getLinkId(), link);
             return true;
         }
@@ -169,7 +171,8 @@
 
     @Override
     public RnibLink getLink(ECGI ecgi, MMEUES1APID mme) {
-        LinkId linkId = new LinkId(ecgi, mme);
+
+        LinkId linkId = LinkId.valueOf(ecgi, mme);
         return linkMap.get(linkId);
     }
 
@@ -230,10 +233,12 @@
     }
 
     @Override
-    public boolean modifyCellRrmConf(String hexeci, JsonNode rrmConf) {
-        EUTRANCellIdentifier eci = hexToECI(hexeci);
-        Optional<ECGI> first = cellMap.keySet().stream().filter(ecgi -> ecgi.getEUTRANcellIdentifier().equals(eci)).findFirst();
-        first.ifPresent(ecgi -> cellMap.get(ecgi).modifyRrmConfig(rrmConf));
+    public boolean modifyCellRrmConf(RnibCell cell, JsonNode rrmConf) {
+
+        List<RnibLink> linkList = getLinksByECGI(cell.getEcgi());
+        List<RnibUe> ueList = linkList.stream().map(link -> link.getLinkId().getUe()).collect(Collectors.toList());
+
+        cell.modifyRrmConfig(rrmConf, ueList);
         return false;
     }
 
diff --git a/src/main/java/org.onosproject.xran/rest/CellWebResource.java b/src/main/java/org.onosproject.xran/rest/CellWebResource.java
index a2b0eac..336f67a 100644
--- a/src/main/java/org.onosproject.xran/rest/CellWebResource.java
+++ b/src/main/java/org.onosproject.xran/rest/CellWebResource.java
@@ -21,6 +21,9 @@
 import org.onosproject.rest.AbstractWebResource;
 import org.onosproject.xran.XranStore;
 import org.onosproject.xran.annotations.Patch;
+import org.onosproject.xran.codecs.api.ECGI;
+import org.onosproject.xran.codecs.api.EUTRANCellIdentifier;
+import org.onosproject.xran.controller.XranController;
 import org.onosproject.xran.entities.RnibCell;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -34,6 +37,8 @@
 import javax.ws.rs.core.Response;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Optional;
+import java.util.concurrent.SynchronousQueue;
 
 /**
  * Cell web resource.
@@ -79,7 +84,7 @@
      * test.
      *
      * @param eciHex test
-     * @param stream test
+     * @param stream test (body of request)
      * @return test
      */
     @Patch
@@ -88,22 +93,29 @@
     public Response patchCell(@PathParam("cellid") String eciHex, InputStream stream) {
         log.debug("PATCH CELLID {}", eciHex);
 
-        boolean b = false;
+        boolean b;
+
+        RnibCell cell = get(XranStore.class).getCell(eciHex);
+        // Check if a cell with that ECI exists. If it does, then modify its contents.
 
         try {
             ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
 
             JsonNode rrmConf = jsonTree.get("RRMConf");
             if (rrmConf != null) {
-                b = get(XranStore.class).modifyCellRrmConf(eciHex, rrmConf);
+                final SynchronousQueue<String>[] queue = new SynchronousQueue[1];
+                b = get(XranStore.class).modifyCellRrmConf(cell, rrmConf);
+                if (b) {
+                    queue[0] = get(XranController.class).sendModifiedRRMConf(cell);
+                    return Response.ok().entity(queue[0].take()).build();
+                }
             }
         } catch (Exception e) {
             log.error(ExceptionUtils.getFullStackTrace(e));
             e.printStackTrace();
+            return Response.serverError().entity(ExceptionUtils.getFullStackTrace(e)).build();
         }
-
-
-        return ok(b).build();
+        return Response.noContent().build();
     }
 
 }
diff --git a/src/main/java/org.onosproject.xran/rest/LinkWebResource.java b/src/main/java/org.onosproject.xran/rest/LinkWebResource.java
index 65772f0..370755f 100644
--- a/src/main/java/org.onosproject.xran/rest/LinkWebResource.java
+++ b/src/main/java/org.onosproject.xran/rest/LinkWebResource.java
@@ -22,7 +22,9 @@
 import org.onosproject.rest.AbstractWebResource;
 import org.onosproject.xran.XranStore;
 import org.onosproject.xran.annotations.Patch;
+import org.onosproject.xran.controller.XranController;
 import org.onosproject.xran.entities.RnibLink;
+import org.openmuc.jasn1.ber.types.BerInteger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -39,6 +41,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.SynchronousQueue;
 
 /**
  * Link web resource.
@@ -103,25 +107,48 @@
     public Response patchLinks(@PathParam("src") String src, @PathParam("dst") long dst, InputStream stream) {
         log.debug("Patch LINKS FROM {} to {}", src, dst);
 
-        boolean b = false;
         try {
-            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            RnibLink link = get(XranStore.class).getLinkBetweenCellIdUeId(src, dst);
+            if (link != null) {
 
-            JsonNode type = jsonTree.get("type");
-            if (type != null) {
+                ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
 
-            }
+                JsonNode type = jsonTree.get("type");
+                if (type != null) {
+                    final SynchronousQueue<String>[] queue = new SynchronousQueue[1];
+                    RnibLink.Type linkType = RnibLink.Type.getEnum(type.asText());
+                    if (linkType.equals(RnibLink.Type.SERVING_PRIMARY)) {
+                        List<RnibLink> linksByUeId = get(XranStore.class).getLinksByUeId(dst);
+                        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());
+                            return Response.ok().entity(queue[0].take()).build();
+                        }
+                    }
+                }
 
-            JsonNode trafficpercent = jsonTree.get("trafficpercent");
-            if (trafficpercent != null) {
-
+                JsonNode trafficpercent = jsonTree.get("trafficpercent");
+                if (trafficpercent != null) {
+                    JsonNode jsonNode = trafficpercent.get("traffic-percent-dl");
+                    if (jsonNode != null) {
+                        link.getTrafficPercent().setTrafficPercentDl(new BerInteger(jsonNode.asInt()));
+                    }
+                    jsonNode = trafficpercent.get("traffic-percent-ul");
+                    if (jsonNode != null) {
+                        link.getTrafficPercent().setTrafficPercentUl(new BerInteger(jsonNode.asInt()));
+                    }
+                    return Response.ok().build();
+                }
             }
         } catch (Exception e) {
             log.error(ExceptionUtils.getFullStackTrace(e));
             e.printStackTrace();
+            return Response.serverError().entity(ExceptionUtils.getFullStackTrace(e)).build();
         }
 
-        return ok(b).build();
+        return Response.noContent().build();
     }
 
     /**
diff --git a/src/main/java/org.onosproject.xran/samplemessages/HandoffRequest.java b/src/main/java/org.onosproject.xran/samplemessages/HandoffRequest.java
new file mode 100644
index 0000000..b8902aa
--- /dev/null
+++ b/src/main/java/org.onosproject.xran/samplemessages/HandoffRequest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015-present Open Networking Laboratory
+ *
+ * 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.samplemessages;
+
+import org.onosproject.xran.codecs.api.CRNTI;
+import org.onosproject.xran.codecs.api.ECGI;
+import org.onosproject.xran.codecs.pdu.*;
+import org.openmuc.jasn1.ber.types.string.BerUTF8String;
+
+import java.io.UnsupportedEncodingException;
+
+public class HandoffRequest {
+
+    public static XrancPdu constructPacket(CRNTI crnti, ECGI ecgis, ECGI ecgit) throws UnsupportedEncodingException {
+        HORequest hoRequest = new HORequest();
+
+        hoRequest.setCrnti(crnti);
+        hoRequest.setEcgiS(ecgis);
+        hoRequest.setEcgiT(ecgit);
+
+        BerUTF8String ver = new BerUTF8String("2a");
+
+        XrancApiID apiID = new XrancApiID(14);
+        XrancPduBody body = new XrancPduBody();
+        body.setHORequest(hoRequest);
+
+        XrancPduHdr hdr = new XrancPduHdr();
+        hdr.setVer(ver);
+        hdr.setApiId(apiID);
+
+        XrancPdu pdu = new XrancPdu();
+        pdu.setBody(body);
+        pdu.setHdr(hdr);
+
+        return pdu;
+    }
+}
diff --git a/src/main/java/org.onosproject.xran/samplemessages/RRMConf.java b/src/main/java/org.onosproject.xran/samplemessages/RRMConf.java
new file mode 100644
index 0000000..bf1e285
--- /dev/null
+++ b/src/main/java/org.onosproject.xran/samplemessages/RRMConf.java
@@ -0,0 +1,12 @@
+package org.onosproject.xran.samplemessages;
+
+import org.onosproject.xran.codecs.pdu.*;
+import org.onosproject.xran.entities.RnibCell;
+import org.openmuc.jasn1.ber.types.string.BerUTF8String;
+
+import java.io.UnsupportedEncodingException;
+
+public class RRMConf {
+
+
+}
diff --git a/src/main/java/org.onosproject.xran/samplemessages/UEAdmEncoderDecoder.java b/src/main/java/org.onosproject.xran/samplemessages/UEAdmEncoderDecoder.java
index 0ec5ce6..7110b2c 100644
--- a/src/main/java/org.onosproject.xran/samplemessages/UEAdmEncoderDecoder.java
+++ b/src/main/java/org.onosproject.xran/samplemessages/UEAdmEncoderDecoder.java
@@ -20,7 +20,7 @@
     }
 
     public static XrancPdu constructPacket(ECGI ecgi, CRNTI crnti) {
-        AdmEstResponse response = new AdmEstResponse(1);
+        AdmEstResponse response = new AdmEstResponse(0);
 
         UEAdmissionResponse ueAdmissionResponse = new UEAdmissionResponse();
         ueAdmissionResponse.setCrnti(crnti);
diff --git a/src/main/java/org.onosproject.xran/wrapper/LinkMap.java b/src/main/java/org.onosproject.xran/wrapper/LinkMap.java
index 827781f..4acf0ae 100644
--- a/src/main/java/org.onosproject.xran/wrapper/LinkMap.java
+++ b/src/main/java/org.onosproject.xran/wrapper/LinkMap.java
@@ -16,6 +16,8 @@
 
 package org.onosproject.xran.wrapper;
 
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
 import org.onosproject.xran.XranStore;
 import org.onosproject.xran.codecs.api.CRNTI;
 import org.onosproject.xran.codecs.api.ECGI;
@@ -28,29 +30,30 @@
 
 import java.util.List;
 import java.util.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 import static org.slf4j.LoggerFactory.getLogger;
 
 public class LinkMap {
     private static final Logger log = getLogger(LinkMap.class);
-
-    private ConcurrentMap<CRNTI, MMEUES1APID> crntiMme = new ConcurrentHashMap<>();
-
-    private XranStore xranStore;
+    private final XranStore xranStore;
+    private BiMap<CRNTI, MMEUES1APID> crntiMme = HashBiMap.create();
 
     public LinkMap(XranStore xranStore) {
         this.xranStore = xranStore;
     }
 
     public void putPrimaryLink(RnibCell cell, RnibUe ue) {
-        RnibLink link = new RnibLink();
-        link.setLinkId(cell, ue);
+        RnibLink link = new RnibLink(cell, ue);
         link.setType(RnibLink.Type.SERVING_PRIMARY);
-        xranStore.getLinksByUeId(ue.getMmeS1apId().longValue())
-                .forEach(l -> l.setType(RnibLink.Type.SERVING_SECONDARY));
-        xranStore.storeLink(link);
+        synchronized (xranStore) {
+            xranStore.getLinksByUeId(ue.getMmeS1apId().longValue())
+                    .forEach(l -> {
+                        if (l.getType().equals(RnibLink.Type.SERVING_PRIMARY)) {
+                            l.setType(RnibLink.Type.SERVING_SECONDARY);
+                        }
+                    });
+            xranStore.storeLink(link);
+        }
         crntiMme.put(ue.getRanId(), ue.getMmeS1apId());
     }
 
@@ -59,10 +62,8 @@
         MMEUES1APID mmeues1APID = crntiMme.get(crnti);
 
         if (mmeues1APID != null) {
-            link = new RnibLink();
             RnibUe ue = xranStore.getUe(mmeues1APID);
-            link.setLinkId(cell, ue);
-            link.setType(RnibLink.Type.NON_SERVING);
+            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");
@@ -86,6 +87,10 @@
         return null;
     }
 
+    public CRNTI getCrnti(MMEUES1APID mme) {
+        return crntiMme.inverse().get(mme);
+    }
+
     public boolean remove(ECGI src, MMEUES1APID dst) {
         RnibLink link = xranStore.getLink(src, dst);
 
@@ -116,7 +121,7 @@
         Optional<RnibLink> primary = linksByUeId.stream().filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY)).findFirst();
 
         if (primary.isPresent()) {
-            return primary.get().getLinkId().getSource();
+            return primary.get().getLinkId().getSourceId();
         }
         return null;
     }