IEEE 802.1x EAPOL-MKA packet support.

Change-Id: I61bc45226d5b84445d4fafa969150c4a707ab3bc
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOL.java b/utils/misc/src/main/java/org/onlab/packet/EAPOL.java
index 741d302..3d7d7c4 100644
--- a/utils/misc/src/main/java/org/onlab/packet/EAPOL.java
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOL.java
@@ -29,7 +29,8 @@
  */
 public class EAPOL extends BasePacket {
 
-    private byte version = 0x01;
+    // private byte version = 0x01;
+    private byte version = 0x03;
     private byte eapolType;
     private short packetLength;
 
@@ -37,12 +38,13 @@
 
     // EAPOL Packet Type
     public static final byte EAPOL_PACKET = 0x0;
-    public static final byte EAPOL_START  = 0x1;
+    public static final byte EAPOL_START = 0x1;
     public static final byte EAPOL_LOGOFF = 0x2;
-    public static final byte EAPOL_KEY    = 0x3;
-    public static final byte EAPOL_ASF    = 0x4;
+    public static final byte EAPOL_KEY = 0x3;
+    public static final byte EAPOL_ASF = 0x4;
+    public static final byte EAPOL_MKA = 0X5;
 
-    public static final MacAddress PAE_GROUP_ADDR = MacAddress.valueOf(new byte[] {
+    public static final MacAddress PAE_GROUP_ADDR = MacAddress.valueOf(new byte[]{
             (byte) 0x01, (byte) 0x80, (byte) 0xc2, (byte) 0x00, (byte) 0x00, (byte) 0x03
     });
 
@@ -187,13 +189,16 @@
 
             if (eapol.packetLength > 0) {
                 checkHeaderLength(length, HEADER_LENGTH + eapol.packetLength);
-                // deserialize the EAP Payload
-                eapol.payload = EAP.deserializer().deserialize(data,
-                        bb.position(), bb.limit() - bb.position());
-
+                if (eapol.getEapolType() == EAPOL_MKA) {
+                    eapol.payload = EAPOLMkpdu.deserializer().deserialize(data,
+                            bb.position(), bb.limit() - bb.position());
+                } else {
+                    // deserialize the EAP Payload
+                    eapol.payload = EAP.deserializer().deserialize(data,
+                            bb.position(), bb.limit() - bb.position());
+                }
                 eapol.payload.setParent(eapol);
             }
-
             return eapol;
         };
     }
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpdu.java b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpdu.java
new file mode 100644
index 0000000..fb67401
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpdu.java
@@ -0,0 +1,226 @@
+
+/*
+ * Copyright 2017-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.onlab.packet;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+/**
+ * EAPOL MKA (EAPOL MAC Key Agreement Protocol) header.
+ */
+public class EAPOLMkpdu extends BasePacket {
+
+    // Parameter Sets.
+    protected Map<Byte, IPacket> parameterSets = new LinkedHashMap<>();
+
+    /*
+     * Parameter Serialization Order.
+     * IEEE 802.1x Clause 11.11.3.
+     */
+    public static byte[] parametersetSerializerKeyList = new byte[]{
+            EAPOLMkpduParameterSet.PARAMETERSET_TYPE_BASIC,
+            EAPOLMkpduParameterSet.PARAMETERSET_TYPE_LIVE_PEER_LIST,
+            EAPOLMkpduParameterSet.PARAMETERSET_TYPE_POTENTIAL_PEER_LIST,
+            EAPOLMkpduParameterSet.PARAMETERSET_TYPE_MACSEC_SAK_USE,
+            EAPOLMkpduParameterSet.PARAMETERSET_TYPE_DISTRIBUTED_SAK,
+            // TODO: Fill other types.
+            EAPOLMkpduParameterSet.PARAMETERSET_TYPE_ICV_INDICATOR
+    };
+
+
+     // Various Parameter Set Deserializers.
+
+    public static final Map<Byte, Deserializer<? extends IPacket>> PARAMETERSET_DESERIALIZER_MAP =
+            new LinkedHashMap<>();
+
+    static {
+        EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_BASIC,
+                EAPOLMkpduBasicParameterSet.deserializer());
+        EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_LIVE_PEER_LIST,
+                EAPOLMkpduPeerListParameterSet.deserializer());
+        EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_POTENTIAL_PEER_LIST,
+                EAPOLMkpduPeerListParameterSet.deserializer());
+        EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_MACSEC_SAK_USE,
+                EAPOLMkpduMACSecUseParameterSet.deserializer());
+        EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_DISTRIBUTED_SAK,
+                EAPOLMkpduDistributedSAKParameterSet.deserializer());
+        EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_ICV_INDICATOR,
+                EAPOLMkpduICVIndicatorParameterSet.deserializer());
+    }
+
+    @Override
+    public byte[] serialize() {
+        int payloadLength = packetLength();
+        ByteBuffer payload = ByteBuffer.wrap(new byte[payloadLength]);
+
+
+        //Serialize Parameter Sets.
+        for (byte b : parametersetSerializerKeyList) {
+            IPacket packet = parameterSets.get(b);
+            if (packet != null) {
+                byte[] data = packet.serialize();
+                if (data != null) {
+                    payload.put(data);
+                }
+            }
+        }
+        return payload.array();
+    }
+
+    /**
+     * Static deserializer for EAPOL-MKA packets.
+     *
+     * @return deserializer function
+     */
+    public static Deserializer<EAPOLMkpdu> deserializer() {
+        return (data, offset, length) -> {
+            byte parameterSetType;
+            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            EAPOLMkpdu mkpdu = new EAPOLMkpdu();
+
+                /* Extract Basic ParameterSet;
+                   Special care needed, MKA Version & Peer Type difficult to distinguish. */
+            Deserializer<? extends IPacket> psDeserializer =
+                    EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.get(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_BASIC);
+            EAPOLMkpduParameterSet ps = (EAPOLMkpduParameterSet) (psDeserializer.deserialize(bb.array(),
+                    bb.position(), bb.remaining()));
+            if (!mkpdu.addParameterSet(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_BASIC, ps)) {
+                throw new DeserializationException("Error in deserializing packets");
+            }
+                // Update buffer position.
+            bb.position(bb.position() + ps.getTotalLength());
+
+                // Extract various remaining Parameter Sets.
+            while (bb.hasRemaining()) {
+                parameterSetType = bb.get();
+                psDeserializer = EAPOLMkpdu.PARAMETERSET_DESERIALIZER_MAP.get(parameterSetType);
+                ps = (EAPOLMkpduParameterSet) (psDeserializer.deserialize(bb.array(), bb.position(),
+                        bb.remaining()));
+                    // Specially handle Peer List Parameter Sets .
+                if ((parameterSetType == EAPOLMkpduParameterSet.PARAMETERSET_TYPE_LIVE_PEER_LIST) ||
+                        (parameterSetType == EAPOLMkpduParameterSet.PARAMETERSET_TYPE_POTENTIAL_PEER_LIST)) {
+                    EAPOLMkpduPeerListParameterSet peerList =
+                            (EAPOLMkpduPeerListParameterSet) ps;
+                    peerList.setPeerListType(parameterSetType);
+                }
+                if (!mkpdu.addParameterSet(parameterSetType, ps)) {
+                    throw new DeserializationException("Error in deserializing packets");
+                }
+
+                    // Update buffer.
+                short consumed = ps.getTotalLength();
+                short remaining = (short) bb.remaining();
+                    // Already one byte shifted, only "consumed-1" is to be shifted.
+                bb.position(bb.position() + ((remaining > consumed) ? (consumed - 1) : remaining));
+            }
+            return mkpdu;
+        };
+    }
+
+    /**
+     * Populate various Parameter Sets to store.
+     *
+     * @param type short
+     * @param ps EAPOLMkpduParameterSet
+     * @return boolean
+     */
+    public boolean addParameterSet(short type, EAPOLMkpduParameterSet ps) {
+        if (ps == null) {
+            return false;
+        }
+
+        // Ensure type is valid.
+        if (!((EAPOLMkpduParameterSet.PARAMETERSET_TYPE_BASIC <= type &&
+                type <= EAPOLMkpduParameterSet.PARAMETERSET_TYPE_DISTRIBUTED_SAK) ||
+                (type == EAPOLMkpduParameterSet.PARAMETERSET_TYPE_ICV_INDICATOR))) {
+            return false;
+        }
+
+
+        // Update store.
+        parameterSets.put((byte) type, (IPacket) ps);
+
+        return true;
+    }
+
+    /**
+     * Provide Basic Parameter Set details.
+     *
+     * @return EAPOLMkpduBasicParameterSet
+     */
+    public EAPOLMkpduBasicParameterSet getBasicParameterSet() {
+        IPacket parameterSet = null;
+        if (parameterSets.containsKey(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_BASIC)) {
+            parameterSet = parameterSets.get(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_BASIC);
+        }
+        return (EAPOLMkpduBasicParameterSet) parameterSet;
+    }
+
+    /**
+     * Provide Live/Potential Peer List details.
+     *
+     * @return EAPOLMkpduPeerListParameterSet
+     */
+    public EAPOLMkpduPeerListParameterSet getPeerListParameterSet() {
+        IPacket parameterSet;
+        if (parameterSets.containsKey(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_LIVE_PEER_LIST)) {
+            parameterSet = parameterSets.get(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_LIVE_PEER_LIST);
+        } else {
+            parameterSet = parameterSets.get(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_POTENTIAL_PEER_LIST);
+        }
+        return (EAPOLMkpduPeerListParameterSet) parameterSet;
+    }
+
+    /**
+     * Total EAPOL-MKPDU packet length. Cumulative length of Parameter Sets.
+     *
+     * @return length
+     */
+    public short packetLength() {
+        short length = 0;
+        for (byte k : parameterSets.keySet()) {
+            EAPOLMkpduParameterSet p = (EAPOLMkpduParameterSet) parameterSets.get(k);
+            length += p.getTotalLength();
+        }
+        return length;
+    }
+
+    /**
+     * Retrieve Parameter Set based on type.
+     *
+     * @param type byte
+     * @return EAPOLMkpduParameterSet
+     */
+    public EAPOLMkpduParameterSet getParameterSet(byte type) {
+        EAPOLMkpduParameterSet ps = null;
+        Map.Entry<Byte, IPacket> entry = parameterSets.entrySet().stream()
+                .filter((i) -> {
+                    return i.getKey().equals(new Byte(type));
+                })
+                .findFirst()
+                .orElse(null);
+        if (entry != null) {
+            ps = (EAPOLMkpduParameterSet) entry.getValue();
+        }
+        return ps;
+    }
+
+}
+
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduBasicParameterSet.java b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduBasicParameterSet.java
new file mode 100644
index 0000000..9efe64b
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduBasicParameterSet.java
@@ -0,0 +1,548 @@
+/*
+ * Copyright 2017-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.onlab.packet;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * Class representing EAPOL MKPDU Basic Parameter Set.
+ * IEEE 802.1X Clause 11; Figure 11-8
+ */
+public class EAPOLMkpduBasicParameterSet extends BasePacket implements EAPOLMkpduParameterSet {
+
+    // Parameter Set fields.
+    private byte mkaVersion;
+    private byte keyServerPriority;
+    private boolean keyServer;
+    private boolean macSecDesired;
+    private byte capability;
+    private short bodyLength;
+    private SCI sci;
+    private byte[] mi;
+    private int mn;
+    private byte[] algAgility;
+    private byte[] ckn;
+    private byte[] padding;
+
+    // Various fixed parameter widths. IEEE 802.1X Table 11-6.
+    public static final int FIELD_ALGAG_LENGTH = 4;
+    public static final int TOTAL_BPS_BODY_LENGTH = 32;
+
+
+    // Basic Parameter Set field masks.
+    public static final byte KEYSERVER_MASK = (byte) 0x80;
+    public static final byte KEYSERVER_OFFSET = (byte) 0x07;
+    public static final byte MACSEC_DESIRED_MASK = (byte) 0x70;
+    public static final byte MACSEC_DESIRED_OFFSET = (byte) 0x06;
+    public static final byte MACSEC_CAPABILITY_MASK = (byte) 0x30;
+    public static final byte MACSEC_CAPABILITY_OFFSET = (byte) 0x04;
+
+    /**
+     * MKA Secure Channel Identifier.
+     */
+    public static class SCI {
+        private byte[] address;
+        private short port;
+
+        public static final int SYSTEM_IDENTIFIER_LENGTH = 6;
+        public static final int PORT_OFFSET = 6;
+
+
+        /**
+         * Validate SCI has <MAC (6 bytes)><Port (2 bytes)> length.
+         *
+         * @param sci ,byte[]
+         * @return true ,boolean
+         */
+        private boolean validateSCI(byte[] sci) {
+            if (sci != null && sci.length < EAPOLMkpduBasicParameterSet.FIELD_SCI_LENGTH) {
+                throw new IllegalArgumentException(
+                        "Invalid SCI argument. Enough bytes are not provided."
+                );
+            }
+            return true;
+        }
+
+        /**
+         * Validate System Identifier.
+         *
+         * @param address , byte[]
+         * @return true , boolean
+         */
+        private boolean validateAddress(byte[] address) {
+            if (address != null && address.length < SCI.SYSTEM_IDENTIFIER_LENGTH) {
+                throw new IllegalArgumentException(
+                        "Invalid System Identifier argument. Expects 6 bytes eg. MAC address.");
+            }
+            return true;
+        }
+
+        /**
+         * To set SCI from MAC address and port stream.
+         *
+         * @param sci , type byte[]
+         */
+
+        public SCI(byte[] sci) {
+            validateSCI(sci);
+            address = Arrays.copyOfRange(sci, 0, SYSTEM_IDENTIFIER_LENGTH);
+            port = (short) ((((short) (sci[PORT_OFFSET] & 0xFF)) << 8)
+                    | ((short) (sci[PORT_OFFSET + 1] & 0xFF)));
+        }
+
+        /**
+         * To set SCI from MAC address and port number.
+         *
+         * @param address ,type byte[]
+         * @param port    ,type short
+         * @throws IllegalArgumentException Exceptions
+         */
+        public SCI(byte[] address, short port) throws IllegalArgumentException {
+            validateAddress(address);
+            this.address = address;
+            this.port = port;
+        }
+
+        /**
+         * To set address.
+         *
+         * @param address , type byte[]
+         * @throws IllegalArgumentException if address is not set
+         */
+        public void setAdddress(byte[] address) throws IllegalArgumentException {
+            validateAddress(address);
+            this.address = address;
+        }
+
+        /**
+         * To return address.
+         *
+         * @return address , type byte[]
+         */
+        public byte[] address() {
+            return address;
+        }
+
+        /**
+         * TO set Port.
+         *
+         * @param port , type short
+         */
+        public void setPort(short port) {
+            this.port = port;
+        }
+
+        /**
+         * To return Port.
+         *
+         * @return port , type short
+         */
+        public short port() {
+            return port;
+        }
+
+        /**
+         * Convert to byte array.
+         *
+         * @return bb.array() ,type byte[]
+         */
+        public byte[] array() {
+            byte[] data = new byte[address.length + 2];
+            ByteBuffer bb = ByteBuffer.wrap(data);
+            bb.put(address);
+            bb.putShort(port);
+            return bb.array();
+        }
+    }
+
+    // Basic Parameter Set fixed header portion size.
+    public static final short BPS_FIXED_PART_SIZE_UPTO_LENGTH_FIELD = 4;
+    public static final short BPS_FIXED_PART_TOTAL_SIZE = 32;
+
+    /**
+     * To set MKA Version.
+     *
+     * @param version , type byte
+     */
+    public void setMkaVersion(byte version) {
+        this.mkaVersion = version;
+    }
+
+    /**
+     * To get MKA Version.
+     *
+     * @return mkaVersion , type byte
+     */
+    public byte getMkaVersion() {
+        return mkaVersion;
+    }
+
+    /**
+     * To set Key Server Priority.
+     *
+     * @param priority  , type byte
+     */
+
+    public void setKeyServerPriority(byte priority) {
+        this.keyServerPriority = priority;
+    }
+
+    /**
+     * To get Key Server Priority.
+     *
+     * @return keyServerPriority, type byte
+     */
+    public byte getKeyServerPriority() {
+        return keyServerPriority;
+    }
+
+    /**
+     * To set Key Server.
+     *
+     * @param isKeyServer , type boolean
+     */
+    public void setKeyServer(boolean isKeyServer) {
+        this.keyServer = isKeyServer;
+    }
+
+    /**
+     * To get Key Server.
+     *
+     * @return keyServer, type boolean
+     */
+    public boolean getKeyServer() {
+        return keyServer;
+    }
+
+    /**
+     * To set MACSec Desired.
+     *
+     * @param desired , type boolean
+     */
+    public void setMacSecDesired(boolean desired) {
+        this.macSecDesired = desired;
+    }
+
+    /**
+     * To get MACSec Desired.
+     *
+     * @return macSecDesired , type boolean
+     */
+    public boolean getMacSecDesired() {
+        return macSecDesired;
+    }
+
+    /**
+     * To set MACSec Capacity.
+     *
+     * @param capability ,type byte
+     */
+    public void setMacSecCapability(byte capability) {
+        this.capability = capability;
+    }
+
+    /**
+     * To get MACSec Capacity.
+     *
+     * @return capability, type byte
+     */
+    public byte getMacSecCapacity() {
+        return capability;
+    }
+
+    /**
+     * To set body length.
+     *
+     * @param length , type short
+     */
+    public void setBodyLength(short length) {
+        this.bodyLength = length;
+    }
+
+    public short getBodyLength() {
+        return bodyLength;
+    }
+
+    /**
+     * To set SCI.
+     *
+     * @param sci , byte[]
+     */
+    public void setSci(byte[] sci) {
+        this.sci = new SCI(sci);
+    }
+
+    /**
+     * To set SCI.
+     *
+     * @param sci , SCI
+     */
+    public void setSci(SCI sci) {
+        // TODO: Ensure sci valid.
+        this.sci = sci;
+    }
+
+    /**
+     * To get SCI.
+     *
+     * @return sci, type SCI
+     */
+    public SCI getSci() {
+        return sci;
+    }
+
+    /**
+     * To set Member Identifier.
+     *
+     * @param mi , type byte[]
+     * @throws IllegalArgumentException if mi is not set.
+     */
+
+    public void setActorMI(byte[] mi) throws IllegalArgumentException {
+        if (mi != null && mi.length < EAPOLMkpduParameterSet.FIELD_MI_LENGTH) {
+            throw new IllegalArgumentException("Actor Message Identifier doesn't have enough length.");
+        }
+        this.mi = mi;
+    }
+
+    /**
+     * To get Member Identifier.
+     *
+     * @return mi, type byte[]
+     */
+    public byte[] getActorMI() {
+        return mi;
+    }
+
+    /**
+     * To set Member Identifier.
+     *
+     * @param mn , type byte[]
+     * @throws IllegalArgumentException if mn is not set.
+     */
+    public void setActorMN(byte[] mn) throws IllegalArgumentException {
+        if (mn != null && mn.length < EAPOLMkpduParameterSet.FIELD_MN_LENGTH) {
+            throw new IllegalArgumentException("Actor Message Number doesn't have enough length.");
+        }
+        final ByteBuffer bf = ByteBuffer.wrap(mn);
+        this.mn = bf.getInt();
+    }
+
+    /**
+     * To set Member Identifier.
+     *
+     * @param mn , type int
+     */
+    public void setActorMN(int mn) {
+        this.mn = mn;
+    }
+
+    /**
+     * To get Member Identifier.
+     *
+     * @return mn, type int
+     */
+    public int getActorMN() {
+        return mn;
+    }
+
+    /**
+     * To set Algorithm Agility.
+     *
+     * @param algAgility , type byte[]
+     * @throws IllegalArgumentException if algAgility is not set or in incorrect format
+     */
+    public void setAlgAgility(byte[] algAgility) throws IllegalArgumentException {
+        if (algAgility != null && algAgility.length < EAPOLMkpduBasicParameterSet.FIELD_ALGAG_LENGTH) {
+            throw new IllegalArgumentException("Algorithm Agility doesn't have enough length.");
+        }
+        this.algAgility = algAgility;
+    }
+
+    /**
+     * To get Algorithm Agility.
+     *
+     * @return algAgility, type byte[]
+     */
+    public byte[] getAlgAgility() {
+        return algAgility;
+    }
+
+    /**
+     * To set CAK name.
+     *
+     * @param ckn , type byte[]
+     */
+    public void setCKN(byte[] ckn) {
+        int cakNameLength = bodyLength - EAPOLMkpduBasicParameterSet.TOTAL_BPS_BODY_LENGTH;
+        if (ckn != null && ckn.length < cakNameLength) {
+            throw new IllegalArgumentException("CAK name doesn't have enough length.");
+        }
+        this.ckn = ckn;
+    }
+
+    /**
+     * To get CAK name.
+     *
+     * @return ckn , type byte[]
+     */
+    public byte[] getCKN() {
+        return ckn;
+    }
+
+    /**
+     * To set padding.
+     *
+     * @param padding , type byte[]
+     */
+    public void setPadding(byte[] padding) {
+        this.padding = padding;
+    }
+
+    /**
+     * Deserializer function for Basic Parameter Set.
+     *
+     * @return deserializer function
+     */
+    public static Deserializer<EAPOLMkpduBasicParameterSet> deserializer() {
+        return (data, offset, length) -> {
+
+            // Ensure buffer has enough details.
+            if (length < TOTAL_BPS_BODY_LENGTH) {
+                return null;
+            }
+
+            // Various tools for deserialization.
+            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            EAPOLMkpduBasicParameterSet basicParameterSet = new EAPOLMkpduBasicParameterSet();
+
+            // Deserialize Basic Parameter Set fields.
+            basicParameterSet.setMkaVersion(bb.get());
+            basicParameterSet.setKeyServerPriority(bb.get());
+
+            byte[] mbField = new byte[1];
+            mbField[0] = bb.get();
+            basicParameterSet.setKeyServer(((mbField[0] & EAPOLMkpduBasicParameterSet.KEYSERVER_MASK) > 0) ?
+                    true : false);
+            basicParameterSet.setMacSecDesired(((mbField[0]
+                    & EAPOLMkpduBasicParameterSet.MACSEC_DESIRED_MASK) > 0) ?
+                    true : false);
+            basicParameterSet.setMacSecCapability((byte) ((mbField[0]
+                    & EAPOLMkpduBasicParameterSet.MACSEC_CAPABILITY_MASK)
+                    >> EAPOLMkpduBasicParameterSet.MACSEC_CAPABILITY_OFFSET));
+
+            short bodyLength = (short) (((short) (mbField[0] & EAPOLMkpduParameterSet.BODY_LENGTH_MSB_MASK))
+                    << EAPOLMkpduBasicParameterSet.BODY_LENGTH_MSB_SHIFT);
+            bodyLength |= (short) (bb.get());
+            basicParameterSet.setBodyLength(bodyLength);
+
+            mbField = new byte[EAPOLMkpduParameterSet.FIELD_SCI_LENGTH];
+            bb.get(mbField, 0, EAPOLMkpduParameterSet.FIELD_SCI_LENGTH);
+            basicParameterSet.setSci(mbField);
+
+            mbField = new byte[EAPOLMkpduParameterSet.FIELD_MI_LENGTH];
+            bb.get(mbField, 0, EAPOLMkpduParameterSet.FIELD_MI_LENGTH);
+            basicParameterSet.setActorMI(mbField);
+
+            mbField = new byte[EAPOLMkpduParameterSet.FIELD_MN_LENGTH];
+            bb.get(mbField, 0, EAPOLMkpduParameterSet.FIELD_MN_LENGTH);
+            basicParameterSet.setActorMN(mbField);
+
+            mbField = new byte[EAPOLMkpduBasicParameterSet.FIELD_ALGAG_LENGTH];
+            bb.get(mbField, 0, EAPOLMkpduBasicParameterSet.FIELD_ALGAG_LENGTH);
+            basicParameterSet.setAlgAgility(mbField);
+
+            int cakNameLength = basicParameterSet.getBodyLength() + EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET -
+                    EAPOLMkpduBasicParameterSet.TOTAL_BPS_BODY_LENGTH;
+            mbField = new byte[cakNameLength];
+            bb.get(mbField, 0, cakNameLength);
+            basicParameterSet.setCKN(mbField);
+
+            int padLength = basicParameterSet.getBodyLength() + EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET -
+                    (EAPOLMkpduBasicParameterSet.TOTAL_BPS_BODY_LENGTH + cakNameLength);
+            if (padLength > 0) {
+                mbField = new byte[padLength];
+                bb.get(mbField, 0, padLength);
+                basicParameterSet.setPadding(mbField);
+            }
+            return basicParameterSet;
+        };
+    }
+
+    @Override
+    public byte[] serialize() {
+        short paddedLength = getTotalLength();
+
+        // Serialize Basic Parameter Set. IEEE 802.1x, Figure 11.8
+        ByteBuffer data = ByteBuffer.wrap(new byte[paddedLength]);
+
+        // Octet 1,2
+        data.put(mkaVersion);
+        data.put(keyServerPriority);
+
+        // Octet 3
+        byte octet3 = (byte) ((byte) ((keyServer) ? 0x01 : 0x00) << KEYSERVER_OFFSET);
+        octet3 |= (byte) ((byte) ((macSecDesired) ? 0x01 : 0x00) << MACSEC_DESIRED_OFFSET);
+        octet3 |= capability << MACSEC_CAPABILITY_OFFSET;
+
+        // Remove header length upto "Length" field from total packet length.
+        paddedLength -= BPS_FIXED_PART_SIZE_UPTO_LENGTH_FIELD;
+        octet3 |= (byte) (paddedLength >> BODY_LENGTH_MSB_SHIFT & BODY_LENGTH_MSB_MASK);
+        data.put(octet3);
+
+        // Octet 4
+        data.put((byte) paddedLength);
+
+        // Octet 5-12
+        data.put(sci.array());
+
+        // Octet 13-24
+        data.put(mi);
+
+        // Octet 25-28
+        data.putInt(mn);
+
+        // Octet 29-32
+        data.put(algAgility);
+
+        // Octet 33-
+        data.put(ckn);
+
+        // TODO: Filling Padding if needed.
+
+        return data.array();
+    }
+
+
+    @Override
+    public byte getParameterSetType() {
+        return PARAMETERSET_TYPE_BASIC;
+    }
+
+    @Override
+    public short getTotalLength() {
+        /*
+         *  Total size calculation.
+         *    4 byte aligned padded length calculation.
+         *    ie. padded_length = (length + 3) & ~3
+         */
+        short paddedLength = (short) (((BPS_FIXED_PART_TOTAL_SIZE + ckn.length) + 0x03) & ~0x03);
+        return paddedLength;
+    }
+
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduDistributedSAKParameterSet.java b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduDistributedSAKParameterSet.java
new file mode 100644
index 0000000..a893e40
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduDistributedSAKParameterSet.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2017-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.onlab.packet;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Class representing MKPDU MACSec SAK Use Parameter Set (GCM-AES 128).
+ * IEEE 802.1X Clause 11; Figure 11-11
+ */
+public class EAPOLMkpduDistributedSAKParameterSet extends BasePacket implements EAPOLMkpduParameterSet {
+
+    // Various fields.
+    private byte distributedAN;
+    private byte confidentialityOffset;
+    private int keyNumber;
+    private byte[] sak;
+
+    /* Body Length is fixed in Distribute SAK Parameter Set.
+     * Still variable kept for de-serialization purpose.
+     */
+    private short bodyLength;
+
+    // Various Constants.
+    public static final short TOTAL_DSAKPS_BODY_LENGTH = 32;
+    public static final short SAK_FIELD_LENGTH = 24;
+    public static final byte DSAKPS_GENERAL_MASK = 0x03;
+    public static final byte DISTRIBUTED_AN_OFFSET = (byte) 0x06;
+    public static final byte CONFIDENTIALITY_OFFSET = (byte) 0x04;
+
+    // Key wrapping support.
+    @FunctionalInterface
+    public interface KeyWrapper {
+        byte[] wrap(byte[] message);
+    }
+
+    KeyWrapper sakWrapper;
+
+    @Override
+    public byte getParameterSetType() {
+        return PARAMETERSET_TYPE_DISTRIBUTED_SAK;
+    }
+
+    @Override
+    public short getTotalLength() {
+        return TOTAL_DSAKPS_BODY_LENGTH;
+    }
+
+    @Override
+    public short getBodyLength() {
+        return bodyLength;
+    }
+
+    public void setBodyLength(short bodyLength) {
+        this.bodyLength = bodyLength;
+    }
+
+    @Override
+    public byte[] serialize() {
+        short length = getTotalLength();
+
+        // Serialize Distribute SAK Parameter Set. IEEE 802.1x, Figure 11.10
+        ByteBuffer data = ByteBuffer.wrap(new byte[length]);
+
+        /*
+         *Populate fields
+         * Octet 1
+         */
+        data.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_DISTRIBUTED_SAK);
+
+        // Octet 2
+        byte octet = 0x00;
+        octet = (byte) ((DSAKPS_GENERAL_MASK & distributedAN) << DISTRIBUTED_AN_OFFSET);
+        octet |= (byte) ((DSAKPS_GENERAL_MASK & confidentialityOffset) << CONFIDENTIALITY_OFFSET);
+        data.put(octet);
+
+        // Octet 3 & 4
+        length -= EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET;
+        octet |= (byte) (length >> BODY_LENGTH_MSB_SHIFT & BODY_LENGTH_MSB_MASK);
+        data.put(octet);
+        data.put((byte) length);
+
+        // Octet 5
+        data.putInt(keyNumber);
+
+        // AES Key Wrap of SAK
+        data.put(sakWrapper.wrap(sak));
+
+        return data.array();
+    }
+
+    /**
+     * Deserializer function for Distributed SAK Parameter Set.
+     *
+     * @return deserializer function
+     */
+    public static Deserializer<EAPOLMkpduDistributedSAKParameterSet> deserializer() {
+        return (data, offset, length) -> {
+
+            // Needed components.
+            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            EAPOLMkpduDistributedSAKParameterSet dps = new EAPOLMkpduDistributedSAKParameterSet();
+
+            /*
+             * Extract fields.
+             * Octet 2
+             */
+            byte[] mbField = new byte[1];
+            mbField[0] = bb.get();
+            dps.setDistributedAN((byte) ((mbField[0] >> DISTRIBUTED_AN_OFFSET) & DSAKPS_GENERAL_MASK));
+            dps.setConfidentialityOffset((byte) ((mbField[0] >> CONFIDENTIALITY_OFFSET) & DSAKPS_GENERAL_MASK));
+
+            // Octet 3 & 4
+            mbField[0] = bb.get();
+            short bodyLength = (short) (((short) (mbField[0] & EAPOLMkpduParameterSet.BODY_LENGTH_MSB_MASK))
+                    << EAPOLMkpduParameterSet.BODY_LENGTH_MSB_SHIFT);
+            bodyLength |= (short) (bb.get());
+            dps.setBodyLength(bodyLength);
+
+            // Octet 5
+            dps.setKeyNumber(bb.getInt());
+
+            // SAK
+            mbField = new byte[EAPOLMkpduDistributedSAKParameterSet.SAK_FIELD_LENGTH];
+            bb.get(mbField, 0, EAPOLMkpduDistributedSAKParameterSet.SAK_FIELD_LENGTH);
+            dps.setSAK(mbField);
+
+            return dps;
+        };
+    }
+
+    // Distributed AN
+    public void setDistributedAN(byte distributedAN) {
+        this.distributedAN = distributedAN;
+    }
+
+    // Confidentiality Offset
+    public void setConfidentialityOffset(byte confidentialityOffset) {
+        this.confidentialityOffset = confidentialityOffset;
+    }
+
+    // Key Number
+    public void setKeyNumber(int keyNumber) {
+        this.keyNumber = keyNumber;
+    }
+
+    // SAK
+    public void setSAK(byte[] sak) {
+        this.sak = sak;
+    }
+
+    // Key Wrapper
+    public void setKeyWrapper(KeyWrapper sakWrapper) {
+        this.sakWrapper = sakWrapper;
+    }
+
+}
+
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduICVIndicatorParameterSet.java b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduICVIndicatorParameterSet.java
new file mode 100644
index 0000000..8ae1705
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduICVIndicatorParameterSet.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017-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.onlab.packet;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Class representing MKPDU ICV Indicator.
+ * IEEE 802.1X Clause 11; Figure 11-16
+ */
+public class EAPOLMkpduICVIndicatorParameterSet extends BasePacket implements EAPOLMkpduParameterSet {
+
+    // Variables for Hash Generation.
+    private byte[] icv;
+
+    /*
+     * Body Length is fixed in SAK Use Parameter Set.
+     * Still variable kept for de-serialization purpose.
+     */
+    private short bodyLength;
+
+    // Total packet length. Currently only 128bit ICV is supported.
+    public static final short TOTAL_ICVPS_BODY_LENGTH = 20;
+
+
+    @Override
+    public byte[] serialize() {
+        short length = getTotalLength();
+
+        // Serialize ICV Indicator Parameter Set. IEEE 802.1x, Figure 11.16 .
+        ByteBuffer data = ByteBuffer.wrap(new byte[length]);
+
+        /*
+         * Populate fields
+         * Octet 1
+         */
+        data.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_ICV_INDICATOR);
+
+        // Octet 2. Reserved.
+        byte octet = 0x00;
+        data.put(octet);
+
+        // Octet 3
+        length -= EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET;
+        octet |= (byte) (length >> BODY_LENGTH_MSB_SHIFT & BODY_LENGTH_MSB_MASK);
+        data.put(octet);
+
+        // Octet 4
+        data.put((byte) length);
+
+        // Note : ICV generation excluded from serialization.
+        //        Should be done at the level where ethernet packet is being created.
+
+        return data.array();
+    }
+
+    /**
+     * Deserializer function for ICV Indicator Parameter Set.
+     *
+     * @return deserializer function
+     */
+    public static Deserializer<EAPOLMkpduICVIndicatorParameterSet> deserializer() {
+        return (data, offset, length) -> {
+            // TODO : Ensure buffer has enough details.
+
+            // Deserialize Basic Parameter Set.
+            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            EAPOLMkpduICVIndicatorParameterSet icvps = new EAPOLMkpduICVIndicatorParameterSet();
+
+            // Extract fields. Skip type, reserved fields.
+            byte[] mbField = new byte[2];
+            bb.get(mbField, 0, 2);
+            short bodyLength = (short) (((short) (mbField[1] & EAPOLMkpduParameterSet.BODY_LENGTH_MSB_MASK))
+                    << EAPOLMkpduParameterSet.BODY_LENGTH_MSB_SHIFT);
+            bodyLength |= (short) (bb.get());
+            icvps.setBodyLength(bodyLength);
+
+            // SAK
+            byte[] icv = new byte[bodyLength];
+            bb.get(icv);
+            icvps.setICV(icv);
+
+            return icvps;
+        };
+    }
+
+    @Override
+    public byte getParameterSetType() {
+        return PARAMETERSET_TYPE_ICV_INDICATOR;
+    }
+
+    @Override
+    public short getTotalLength() {
+        return TOTAL_ICVPS_BODY_LENGTH;
+    }
+
+    @Override
+    public short getBodyLength() {
+        return TOTAL_ICVPS_BODY_LENGTH - BODY_LENGTH_OCTET_OFFSET;
+    }
+
+    /**
+     * To set body length.
+     *
+     * @param bodyLength  ,type short
+     */
+    public void setBodyLength(short bodyLength) {
+        this.bodyLength = bodyLength;
+    }
+
+    /**
+     * To set ICV.
+     *
+     * @param icv , type byte[]
+     */
+    public void setICV(byte[] icv) {
+        this.icv = icv;
+    }
+
+}
+
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduMACSecUseParameterSet.java b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduMACSecUseParameterSet.java
new file mode 100644
index 0000000..2085c27
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduMACSecUseParameterSet.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2017-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.onlab.packet;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Class representing MKPDU MACSec SAK Use Parameter Set.
+ * IEEE 802.1X Clause 11; Figure 11-10
+ */
+public class EAPOLMkpduMACSecUseParameterSet extends BasePacket implements EAPOLMkpduParameterSet {
+
+    // Various Header Fields
+    private boolean delayProtect = false;
+    private boolean plainTX = false;
+    private boolean plainRX = false;
+    private byte[] latestKI;
+    private int latestKN;
+    private byte latestAN;
+    private int latestLAPN;
+    private boolean latestTX;
+    private boolean latestRX;
+    private byte[] oldKI;
+    private int oldKN;
+    private byte oldAN;
+    private int oldLAPN;
+    private boolean oldTX;
+    private boolean oldRX;
+
+    /* Body Length is fixed in SAK Use Parameter Set.
+     * Still variable kept for de-serialization purpose.
+     * */
+    private short bodyLength;
+
+    // Various constants.
+    public static final short TOTAL_SUPS_BODY_LENGTH = 44;
+    public static final short LATEST_KEY_AN_OFFSET = 6;
+    public static final short OLD_KEY_AN_OFFSET = 2;
+
+    public static final byte LATEST_KEY_RX_MASK = 0x10;
+    public static final byte LATEST_KEY_TX_MASK = 0X20;
+    public static final byte OLD_KEY_RX_MASK = 0x01;
+    public static final byte OLD_KEY_TX_MASK = 0x02;
+    public static final byte KEY_AN_MASK = 0x02;
+    public static final byte PLAIN_TX_MASK = (byte) 0x80;
+    public static final byte PLAIN_RX_MASK = 0x40;
+    public static final byte DELAY_PROTECT_MASK = 0x10;
+    public static final short SUPS_FIXED_PART_TOTAL_SIZE = 44;
+
+    @Override
+    public byte[] serialize() {
+        short length = getTotalLength();
+
+        // Serialize SAK Use Parameter Set. IEEE 802.1x, Figure 11.10
+        ByteBuffer data = ByteBuffer.wrap(new byte[length]);
+
+        /*
+         *Populate fields
+         * Octet 1
+         * */
+        data.put(EAPOLMkpduParameterSet.PARAMETERSET_TYPE_MACSEC_SAK_USE);
+
+        // Octet 2
+        byte octet = 0x00;
+        octet = (byte) ((latestRX) ? octet | LATEST_KEY_RX_MASK : octet & (byte) (~LATEST_KEY_RX_MASK));
+        octet = (byte) ((latestTX) ? octet | LATEST_KEY_TX_MASK : octet & (byte) (~LATEST_KEY_TX_MASK));
+        octet = (byte) ((oldRX) ? octet | OLD_KEY_RX_MASK : octet & (byte) (~OLD_KEY_RX_MASK));
+        octet = (byte) ((oldTX) ? octet | OLD_KEY_TX_MASK : octet & (byte) (~OLD_KEY_TX_MASK));
+        octet |= latestAN << LATEST_KEY_AN_OFFSET;
+        octet |= oldAN << OLD_KEY_AN_OFFSET;
+        data.put(octet);
+
+        // Octet 3
+        octet = 0x00;
+        octet = (byte) ((plainTX) ? octet | (byte) PLAIN_TX_MASK : octet & (byte) (~PLAIN_TX_MASK));
+        octet = (byte) ((plainRX) ? octet | (byte) PLAIN_RX_MASK : octet & (byte) (~PLAIN_RX_MASK));
+        octet = (byte) ((delayProtect) ? octet | DELAY_PROTECT_MASK : octet & (byte) (~DELAY_PROTECT_MASK));
+        length -= EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET;
+        octet |= (byte) (length >> BODY_LENGTH_MSB_SHIFT & BODY_LENGTH_MSB_MASK);
+        data.put(octet);
+
+        // Octet 4
+        data.put((byte) length);
+
+        // Latest & Old Key Server Details
+        data.put(latestKI);
+        data.putInt(latestKN);
+        data.putInt(latestLAPN);
+        data.put(oldKI);
+        data.putInt(oldKN);
+        data.putInt(oldLAPN);
+
+        return data.array();
+    }
+
+    /**
+     * Deserializer function for MACSec SAK Use Parameter Set.
+     *
+     * @return deserializer function
+     */
+    public static Deserializer<EAPOLMkpduMACSecUseParameterSet> deserializer() {
+        return (data, offset, length) -> {
+
+            // Needed components.
+            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            EAPOLMkpduMACSecUseParameterSet macSecUsePS = new EAPOLMkpduMACSecUseParameterSet();
+
+            /*
+             *Extract fields.
+             *Octet 2
+            **/
+            byte[] mbField = new byte[1];
+            mbField[0] = bb.get();
+            macSecUsePS.setOldRX((mbField[0] & OLD_KEY_RX_MASK) != 0);
+            macSecUsePS.setOldTX((mbField[0] & OLD_KEY_TX_MASK) != 0);
+            macSecUsePS.setLatestRX((mbField[0] & OLD_KEY_RX_MASK) != 0);
+            macSecUsePS.setLatestTX((mbField[0] & OLD_KEY_TX_MASK) != 0);
+            macSecUsePS.setLatestAN((byte) ((mbField[0] >> LATEST_KEY_AN_OFFSET) & KEY_AN_MASK));
+            macSecUsePS.setOldAN((byte) ((mbField[0] >> OLD_KEY_AN_OFFSET) & KEY_AN_MASK));
+
+            // Octet 3 & 4
+            mbField[0] = bb.get();
+            macSecUsePS.setPlainRX((mbField[0] & PLAIN_RX_MASK) != 0);
+            macSecUsePS.setPlainTX((mbField[0] & PLAIN_TX_MASK) != 0);
+            macSecUsePS.setDelayProtect((mbField[0] & DELAY_PROTECT_MASK) != 0);
+
+            short bodyLength = (short) (((short) (mbField[0] & EAPOLMkpduParameterSet.BODY_LENGTH_MSB_MASK))
+                    << EAPOLMkpduParameterSet.BODY_LENGTH_MSB_SHIFT);
+            bodyLength |= (short) (bb.get());
+            macSecUsePS.setBodyLength(bodyLength);
+
+            // Latest Key Server details.
+            mbField = new byte[EAPOLMkpduParameterSet.FIELD_MI_LENGTH];
+            bb.get(mbField, 0, EAPOLMkpduParameterSet.FIELD_MI_LENGTH);
+            macSecUsePS.setLatestKI(mbField);
+            macSecUsePS.setLatestKN(bb.getInt());
+            macSecUsePS.setLatestLAPN(bb.getInt());
+
+            // Old Key Server details.
+            mbField = new byte[EAPOLMkpduParameterSet.FIELD_MI_LENGTH];
+            bb.get(mbField, 0, EAPOLMkpduParameterSet.FIELD_MI_LENGTH);
+            macSecUsePS.setOldKI(mbField);
+            macSecUsePS.setOldKN(bb.getInt());
+            macSecUsePS.setOldLAPN(bb.getInt());
+
+            return macSecUsePS;
+        };
+    }
+
+    @Override
+    public byte getParameterSetType() {
+        return PARAMETERSET_TYPE_MACSEC_SAK_USE;
+    }
+
+    @Override
+    public short getTotalLength() {
+        return TOTAL_SUPS_BODY_LENGTH;
+    }
+
+    @Override
+    public short getBodyLength() {
+        return bodyLength;
+    }
+
+    public void setBodyLength(short bodyLength) {
+        this.bodyLength = bodyLength;
+    }
+
+    /**
+     * To set Delay Protect.
+     *
+     * @param delayProtect , type boolean
+     */
+    public void setDelayProtect(boolean delayProtect) {
+        this.delayProtect = delayProtect;
+    }
+
+    /**
+     * To set Plain TX supported or not.
+     *
+     * @param plainTX , type boolean
+     */
+    public void setPlainTX(boolean plainTX) {
+        this.plainTX = plainTX;
+    }
+
+    /**
+     * Plain RX supported or not.
+     *
+     * @param plainRX , type boolean
+     */
+    public void setPlainRX(boolean plainRX) {
+        this.plainRX = plainRX;
+    }
+
+    /**
+     * Lowest Acceptable Packet Number for Latest Key Server.
+     *
+     * @param latestLAPN ,type int
+     */
+    public void setLatestLAPN(int latestLAPN) {
+        this.latestLAPN = latestLAPN;
+    }
+
+    /**
+     * Latest Key Server Association Number.
+     *
+     * @param latestAN , type byte
+     */
+    public void setLatestAN(byte latestAN) {
+        this.latestAN = latestAN;
+    }
+
+    /**
+     * Latest Key Server Identifier.
+     *
+     * @param latestKI ,type byte[]
+     */
+    public void setLatestKI(byte[] latestKI) {
+        this.latestKI = latestKI;
+    }
+
+    /**
+     * Latest Key Server Key Number.
+     *
+     * @param latestKN ,type int
+     */
+    public void setLatestKN(int latestKN) {
+        this.latestKN = latestKN;
+    }
+
+    /**
+     * Latest Key Server used for TX protection.
+     *
+     * @param latestTX ,type boolean
+     */
+    public void setLatestTX(boolean latestTX) {
+        this.latestTX = latestTX;
+    }
+
+    /**
+     * Latest Key Server used for RX protection .
+     *
+     * @param latestRX ,type boolean.
+     */
+    public void setLatestRX(boolean latestRX) {
+        this.latestRX = latestRX;
+    }
+
+    /**
+     * Lowest Acceptable Packet Number for Old Key Server.
+     *
+     * @param oldLAPN , type int
+     */
+    public void setOldLAPN(int oldLAPN) {
+        this.oldLAPN = oldLAPN;
+    }
+
+    /**
+     * Old Key Server Association Number.
+     *
+     * @param oldAN , type byte
+     */
+    public void setOldAN(byte oldAN) {
+        this.oldAN = oldAN;
+    }
+
+    /**
+     * Old Key Server Identifier.
+     *
+     * @param oldKI , type byte[]
+     */
+    public void setOldKI(byte[] oldKI) {
+        this.oldKI = oldKI;
+    }
+
+    /**
+     * Old Key Server Number.
+     *
+     * @param oldKN , type int
+     */
+    public void setOldKN(int oldKN) {
+        this.oldKN = oldKN;
+    }
+
+    /**
+     * Old Key Server used for TX protection.
+     *
+     * @param oldTX ,type boolean
+     */
+    public void setOldTX(boolean oldTX) {
+        this.oldTX = oldTX;
+    }
+
+    /**
+     * Old Key Server used for RX protection.
+     *
+     * @param oldRX , type boolean
+     */
+    public void setOldRX(boolean oldRX) {
+        this.oldRX = oldRX;
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduParameterSet.java b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduParameterSet.java
new file mode 100644
index 0000000..ba630d2
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduParameterSet.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017-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.onlab.packet;
+
+/**
+ * Class representing EAPOL MKPDU Parameter Set.
+ * IEEE 802.1X Clause 11; Figure 11-7, Table 11-6
+ */
+public interface EAPOLMkpduParameterSet {
+    // Parameter Set Types.
+    public static final byte PARAMETERSET_TYPE_BASIC = 0;
+    public static final byte PARAMETERSET_TYPE_LIVE_PEER_LIST = 1;
+    public static final byte PARAMETERSET_TYPE_POTENTIAL_PEER_LIST = 2;
+    public static final byte PARAMETERSET_TYPE_MACSEC_SAK_USE = 3;
+    public static final byte PARAMETERSET_TYPE_DISTRIBUTED_SAK = 4;
+    public static final byte PARAMETERSET_TYPE_ICV_INDICATOR = (byte) 255;
+
+    // Member Identifier & Number fields.
+    public static final int FIELD_MI_LENGTH = 12;
+    public static final int FIELD_MN_LENGTH = 4;
+
+    // SCI field details.
+    public static final int FIELD_SCI_LENGTH = 8;
+
+    // Body Length field details.
+    public static final byte BODY_LENGTH_MSB_MASK = (byte) 0x0F;
+    public static final byte BODY_LENGTH_MSB_SHIFT = (byte) 0x08;
+    public static final byte BODY_LENGTH_OCTET_OFFSET = (byte) 0x04;
+
+    /**
+     * Retrieve Type of Parameter Set.
+     *
+     * @return parameter set type.
+     */
+    public byte getParameterSetType();
+
+    /**
+     * Total length; ie. including header and body length.
+     *
+     * @return short value.
+     */
+    public short getTotalLength();
+
+    /**
+     * Retrieve Body Length field of Parameter Set.
+     *
+     * @return body length of parameter set.
+     */
+    public short getBodyLength();
+
+    /**
+     * Utility function for Serializing Parameter Set.
+     *
+     * @return byte[] value
+     */
+    public byte[] serialize();
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduPeerListParameterSet.java b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduPeerListParameterSet.java
new file mode 100644
index 0000000..793b638
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/EAPOLMkpduPeerListParameterSet.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2017-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.onlab.packet;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Class representing MKPDU Live/Potential Peer List Parameter Set.
+ * IEEE 802.1X Clause 11; Figure 11-9
+ */
+public class EAPOLMkpduPeerListParameterSet extends BasePacket implements EAPOLMkpduParameterSet {
+
+    // Member Details
+    public static class MemberDetails {
+        byte[] memberID;
+        int messageNo;
+
+        public MemberDetails(byte[] memberID, int messageNo) {
+            this.memberID = memberID;
+            this.messageNo = messageNo;
+        }
+
+        public byte[] getMemberID() {
+            return memberID;
+        }
+
+        public int getMessageNo() {
+            return messageNo;
+        }
+    }
+
+    // Peer List Types
+    public static byte peerListTypeLive = 1;
+    public static byte peerListTypePotential = 2;
+
+    // Type for distinguishing Live & Potential Lists.
+    protected byte peerListType = 1;
+    protected short bodyLength;
+
+    //Members
+    protected List<MemberDetails> members = new ArrayList<>();
+
+    @Override
+    public byte[] serialize() {
+
+        // Don't Serialize if no members are available.
+        if (members.size() == 0) {
+            return null;
+        }
+
+        // Serialize PeerList Parameter Set. IEEE 802.1x, Figure 11.9
+        short length = getTotalLength();
+        ByteBuffer data = ByteBuffer.wrap(new byte[length]);
+
+        /*
+         *Populate fields
+         * Octet 1
+         */
+        data.put(peerListType);
+
+        // Octet 2. Reserved.
+        byte octet = 0x00;
+        data.put(octet);
+
+        // Octet 3
+        length -= EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET;
+        octet |= (byte) (length >> BODY_LENGTH_MSB_SHIFT & BODY_LENGTH_MSB_MASK);
+        data.put(octet);
+
+        // Octet 4
+        data.put((byte) length);
+
+        // Member details.
+        members.forEach(a -> {
+                    data.put(a.getMemberID());
+                    data.putInt(a.getMessageNo());
+                }
+        );
+
+        return data.array();
+    }
+
+
+    /**
+     * Deserializer function for Peer List Parameter Set.
+     *
+     * @return deserializer function
+     */
+    public static Deserializer<EAPOLMkpduPeerListParameterSet> deserializer() {
+        return (data, offset, length) -> {
+
+            // Ensure buffer has enough details.
+            if (data == null) {
+                return null;
+            }
+
+            // Deserialize Basic Parameter Set.
+            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+            EAPOLMkpduPeerListParameterSet peerListParameterSet =
+                    new EAPOLMkpduPeerListParameterSet();
+
+            // Parse Peer List Fields/
+            byte[] mbField = new byte[1];
+            // mbField[0] = bb.get(); // Skip Type. Already processed in EAPOL-MKPDU de-serializer.
+            bb.get(); // Skip Reserved.
+
+            // Length
+            mbField[0] = bb.get();
+            short bodyLength = (short) (((short) (mbField[0] & EAPOLMkpduParameterSet.BODY_LENGTH_MSB_MASK))
+                    << EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET);
+            bodyLength |= (short) (bb.get());
+            peerListParameterSet.setBodyLength(bodyLength);
+
+            // Member details
+            while (bodyLength > 0) {
+                mbField = new byte[FIELD_MI_LENGTH];
+                bb.get(mbField, 0, FIELD_MI_LENGTH);
+                peerListParameterSet.addMember(mbField, bb.getInt());
+                bodyLength -= FIELD_MI_LENGTH + FIELD_MN_LENGTH;
+            }
+            return peerListParameterSet;
+        };
+    }
+
+    /**
+     * Setting List Type.
+     *
+     * @param peerListType type - PEERLIST_TYPE_LIVE or PEERLIST_TYPE_POTENTIAL for live
+     *                     and potential peer lists
+     */
+    public void setPeerListType(byte peerListType) {
+        if ((peerListType != EAPOLMkpduPeerListParameterSet.peerListTypeLive) &&
+                (peerListType != EAPOLMkpduPeerListParameterSet.peerListTypePotential)) {
+            throw new IllegalArgumentException("Unknown PeerList Type specified.");
+        }
+        this.peerListType = peerListType;
+    }
+
+    /**
+     * Member details adding.
+     *
+     * @param mi ,type byte[]
+     * @param mn , type int
+     */
+    public void addMember(byte[] mi, int mn) {
+        if (mi != null) {
+            members.add(new MemberDetails(mi, mn));
+        }
+        return;
+    }
+
+    /**
+     * Searching Member details.
+     *
+     * @param mi ,type byte[]
+     * @return boolean based on the value of member.
+     */
+    public boolean memberExists(byte[] mi) {
+        MemberDetails member = members.stream()
+                .filter(m -> Arrays.equals(m.getMemberID(), mi))
+                .findAny()
+                .orElse(null);
+        return (member != null) ? true : false;
+    }
+
+    /**
+     * Member details.
+     *
+     * @return members
+     */
+    public List<MemberDetails> getMembers() {
+        return members;
+    }
+
+    @Override
+    public byte getParameterSetType() {
+        return peerListType;
+    }
+
+    @Override
+    public short getTotalLength() {
+        return (short) (EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET +
+                members.size() * (EAPOLMkpduParameterSet.FIELD_MI_LENGTH +
+                        EAPOLMkpduParameterSet.FIELD_MN_LENGTH));
+    }
+
+    @Override
+    public short getBodyLength() {
+        return bodyLength;
+    }
+
+    /**
+     * Body Length.
+     *
+     * @param length ,type short
+     */
+    public void setBodyLength(short length) {
+        this.bodyLength = length;
+    }
+}
+