diff --git a/scapy/fields.py b/scapy/fields.py
index 0a92c3f5e5290c7c5a9ff2b09f0765a30b173620..0dbe6910eba412c44c8f5ead1712f173fc499e3b 100644
--- a/scapy/fields.py
+++ b/scapy/fields.py
@@ -554,6 +554,30 @@ class StrLenField(StrField):
         l = self.length_from(pkt)
         return s[l:], self.m2i(pkt,s[:l])
     
+class XStrField(StrField):
+    """
+    StrField which value is printed as hexadecimal.
+    """
+
+    def i2repr(self, pkt, x):
+        return x.encode("hex")
+
+class XStrLenField(StrLenField):
+    """
+    StrLenField which value is printed as hexadecimal.
+    """
+
+    def i2repr(self, pkt, x):
+        return x[:self.length_from(pkt)].encode("hex")
+
+class XStrFixedLenField(StrFixedLenField):
+    """
+    StrFixedLenField which value is printed as hexadecimal.
+    """
+
+    def i2repr(self, pkt, x):
+        return x[:self.length_from(pkt)].encode("hex")
+
 class StrLenFieldUtf16(StrLenField):
     def h2i(self, pkt, x):
         return x.encode('utf-16')[2:]
diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py
index b26ff106b90580cb5853a282aaec881cad4f5684..40f44518b641cde92fae5af56dbf31d214170a55 100644
--- a/scapy/layers/l2.py
+++ b/scapy/layers/l2.py
@@ -543,6 +543,366 @@ class EAP_FAST(Packet):
     ]
 
 
+#############################################################################
+##### IEEE 802.1X-2010 - MACsec Key Agreement (MKA) protocol
+#############################################################################
+
+#________________________________________________________________________
+#
+# IEEE 802.1X-2010 standard
+# Section 11.11.1
+#________________________________________________________________________
+#
+
+_parameter_set_types = {
+    1:   "Live Peer List",
+    2:   "Potential Peer List",
+    3:   "MACsec SAK Use",
+    4:   "Distributed SAK",
+    5:   "Distributed CAK",
+    6:   "KMD",
+    7:   "Announcement",
+    255: "ICV Indicator"
+}
+
+
+# Used by MKAParamSet::dispatch_hook() to instantiate the appropriate class
+_param_set_cls = {
+    1:   "MKALivePeerListParamSet",
+    2:   "MKAPotentialPeerListParamSet",
+    3:   "MKASAKUseParamSet",
+    4:   "MKADistributedSAKParamSet",
+    255: "MKAICVSet",
+}
+
+
+class MACsecSCI(Packet):
+    """
+    Secure Channel Identifier.
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1AE-2006 standard
+    # Section 9.9
+    #________________________________________________________________________
+    #
+
+    name = "SCI"
+    fields_desc = [
+        SourceMACField("system_identifier"),
+        ShortField("port_identifier", 0)
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class MKAParamSet(Packet):
+    """
+    Class from which every parameter set class inherits (except
+    MKABasicParamSet, which has no "Parameter set type" field, and must
+    come first in the list of parameter sets).
+    """
+
+    MACSEC_DEFAULT_ICV_LEN = 16
+    EAPOL_MKA_DEFAULT_KEY_WRAP_LEN = 24
+
+    @classmethod
+    def dispatch_hook(cls, _pkt=None, *args, **kargs):
+        """
+        Returns the right parameter set class.
+        """
+
+        cls = conf.raw_layer
+        if _pkt is not None:
+            ptype = struct.unpack("!B", _pkt[0])[0]
+            return globals().get(_param_set_cls.get(ptype), conf.raw_layer)
+
+        return cls
+
+
+class MKABasicParamSet(Packet):
+    """
+    Basic Parameter Set (802.1X-2010, section 11.11).
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "Basic Parameter Set"
+    fields_desc = [
+        ByteField("mka_version_id", 0),
+        ByteField("key_server_priority", 0),
+        BitField("key_server", 0, 1),
+        BitField("macsec_desired", 0, 1),
+        BitField("macsec_capability", 0, 2),
+        BitField("param_set_body_len", 0, 12),
+        PacketField("SCI", MACsecSCI(), MACsecSCI),
+        XStrFixedLenField("actor_member_id", "", length=12),
+        XIntField("actor_message_number", 0),
+        XIntField("algorithm_agility", 0),
+        PadField(
+            XStrLenField(
+                "cak_name",
+                "",
+                length_from=lambda pkt: (pkt.param_set_body_len - 28)
+            ),
+            4,
+            padwith="\x00"
+        )
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
+
+class MKAPeerListTuple(Packet):
+    """
+    Live / Potential Peer List parameter sets tuples (802.1X-2010, section 11.11).
+    """
+
+    name = "Peer List Tuple"
+    fields_desc = [
+        XStrFixedLenField("member_id", "", length=12),
+        XStrFixedLenField("message_number", "", length=4),
+    ]
+
+
+class MKALivePeerListParamSet(MKAParamSet):
+    """
+    Live Peer List parameter sets (802.1X-2010, section 11.11).
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "Live Peer List Parameter Set"
+    fields_desc = [
+        PadField(
+            ByteEnumField(
+                "param_set_type",
+                1,
+                _parameter_set_types
+            ),
+            2,
+            padwith="\x00"
+        ),
+        ShortField("param_set_body_len", 0),
+        PacketListField("member_id_message_num", [], MKAPeerListTuple)
+    ]
+
+
+class MKAPotentialPeerListParamSet(MKAParamSet):
+    """
+    Potential Peer List parameter sets (802.1X-2010, section 11.11).
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "Potential Peer List Parameter Set"
+    fields_desc = [
+        PadField(
+            ByteEnumField(
+                "param_set_type",
+                2,
+                _parameter_set_types
+            ),
+            2,
+            padwith="\x00"
+        ),
+        ShortField("param_set_body_len", 0),
+        PacketListField("member_id_message_num", [], MKAPeerListTuple)
+    ]
+
+
+class MKASAKUseParamSet(MKAParamSet):
+    """
+    SAK Use Parameter Set (802.1X-2010, section 11.11).
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "SAK Use Parameter Set"
+    fields_desc = [
+        ByteEnumField("param_set_type", 3, _parameter_set_types),
+        BitField("latest_key_an", 0, 2),
+        BitField("latest_key_tx", 0, 1),
+        BitField("latest_key_rx", 0, 1),
+        BitField("old_key_an", 0, 2),
+        BitField("old_key_tx", 0, 1),
+        BitField("old_key_rx", 0, 1),
+        BitField("plain_tx", 0, 1),
+        BitField("plain_rx", 0, 1),
+        BitField("X", 0, 1),
+        BitField("delay_protect", 0, 1),
+        BitField("param_set_body_len", 0, 12),
+        XStrFixedLenField("latest_key_key_server_member_id", "", length=12),
+        XStrFixedLenField("latest_key_key_number", "", length=4),
+        XStrFixedLenField("latest_key_lowest_acceptable_pn", "", length=4),
+        XStrFixedLenField("old_key_key_server_member_id", "", length=12),
+        XStrFixedLenField("old_key_key_number", "", length=4),
+        XStrFixedLenField("old_key_lowest_acceptable_pn", "", length=4)
+    ]
+
+
+class MKADistributedSAKParamSet(MKAParamSet):
+    """
+    Distributed SAK parameter set (802.1X-2010, section 11.11).
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "Distributed SAK parameter set"
+    fields_desc = [
+        ByteEnumField("param_set_type", 4, _parameter_set_types),
+        BitField("distributed_an", 0, 2),
+        BitField("confidentiality_offset", 0, 2),
+        BitField("unused", 0, 4),
+        ShortField("param_set_body_len", 0),
+        XStrFixedLenField("key_number", "", length=4),
+        ConditionalField(
+            XStrFixedLenField("macsec_cipher_suite", "", length=8),
+            lambda pkt: pkt.param_set_body_len > 28
+        ),
+        XStrFixedLenField(
+            "sak_aes_key_wrap",
+            "",
+            length=MKAParamSet.EAPOL_MKA_DEFAULT_KEY_WRAP_LEN
+        )
+    ]
+
+
+class MKADistributedCAKParamSet(MKAParamSet):
+    """
+    Distributed CAK Parameter Set (802.1X-2010, section 11.11).
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "Distributed CAK parameter set"
+    fields_desc = [
+        PadField(
+            ByteEnumField(
+                "param_set_type",
+                5,
+                _parameter_set_types
+            ),
+            2,
+            padwith="\x00"
+        ),
+        ShortField("param_set_body_len", 0),
+        XStrFixedLenField(
+            "cak_aes_key_wrap",
+            "",
+            length=MKAParamSet.EAPOL_MKA_DEFAULT_KEY_WRAP_LEN
+        ),
+        XStrField("cak_key_name", "")
+    ]
+
+
+class MKAICVSet(MKAParamSet):
+    """
+    ICV (802.1X-2010, section 11.11).
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "ICV"
+    fields_desc = [
+        PadField(
+            ByteEnumField(
+                "param_set_type",
+                255,
+                _parameter_set_types
+            ),
+            2,
+            padwith="\x00"
+        ),
+        ShortField("param_set_body_len", 0),
+        XStrFixedLenField("icv", "", length=MKAParamSet.MACSEC_DEFAULT_ICV_LEN)
+    ]
+
+
+class MKAParamSetPacketListField(PacketListField):
+    """
+    PacketListField that handles the parameter sets.
+    """
+
+    PARAM_SET_LEN_MASK = 0b0000111111111111
+
+    def m2i(self, pkt, m):
+        return MKAParamSet(m)
+
+    def getfield(self, pkt, s):
+        lst = []
+        remain = s
+
+        while remain:
+            len_bytes = struct.unpack("!H", remain[2:4])[0]
+            param_set_len = self.__class__.PARAM_SET_LEN_MASK & len_bytes
+            current = remain[:4 + param_set_len]
+            remain = remain[4 + param_set_len:]
+            current_packet = self.m2i(pkt, current)
+            lst.append(current_packet)
+
+        return remain, lst
+
+
+class MKAPDU(Packet):
+    """
+    MACsec Key Agreement Protocol Data Unit.
+    """
+
+    #________________________________________________________________________
+    #
+    # IEEE 802.1X-2010 standard
+    # Section 11.11
+    #________________________________________________________________________
+    #
+
+    name = "MKPDU"
+    fields_desc = [
+        PacketField("basic_param_set", "", MKABasicParamSet),
+        MKAParamSetPacketListField("parameter_sets", [], MKAParamSet),
+    ]
+
+    def extract_padding(self, s):
+        return "", s
+
 
 class ARP(Packet):
     name = "ARP"
@@ -668,9 +1028,10 @@ bind_layers( GRE,           GRErouting,    { "routing_present" : 1 } )
 bind_layers( GRErouting,    conf.raw_layer,{ "address_family" : 0, "SRE_len" : 0 })
 bind_layers( GRErouting,    GRErouting,    { } )
 bind_layers( EAPOL,         EAP,           type=0)
-bind_layers( EAP,           EAP_MD5,       type=4)
+bind_layers( EAPOL,         MKAPDU,        type=5)
 bind_layers(EAP,           EAP_TLS,       type=13)
 bind_layers(EAP,           EAP_FAST,      type=43)
+bind_layers( EAP,           EAP_MD5,       type=4)
 bind_layers( LLC,           STP,           dsap=66, ssap=66, ctrl=3)
 bind_layers( LLC,           SNAP,          dsap=170, ssap=170, ctrl=3)
 bind_layers( SNAP,          Dot1Q,         code=33024)
diff --git a/test/regression.uts b/test/regression.uts
index b6fd6f085f4da75dd96bd65ebda4a6aecc6d37f8..a6ca36aedc5e66e8bfc646e4a2fe9d99f380b85e 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -5597,6 +5597,87 @@ assert(eapol.len == 60)
 assert(eapol.haslayer(EAP_FAST))
 
 
+############
+############
++ EAPOL-MKA class tests
+
+= EAPOL-MKA - With Basic parameter set - Dissection
+eapol = None
+s = '\x03\x05\x00T\x01\xff\xf0<\x00Bh\xa8\x1e\x03\x00\n\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7\x00\x00\x00\x01\x00\x80\xc2\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\xff\x00\x00\x10\xe5\xf5j\x86V\\\xb1\xcc\xa9\xb95\x04m*Cj'
+eapol = EAPOL(s)
+assert(eapol.version == 3)
+assert(eapol.type == 5)
+assert(eapol.len == 84)
+assert(eapol.haslayer(MKAPDU))
+assert(eapol[MKAPDU].basic_param_set.actor_member_id == "\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7")
+assert(eapol[MKAPDU].haslayer(MKAICVSet))
+assert(eapol[MKAPDU][MKAICVSet].icv == "\xe5\xf5j\x86V\\\xb1\xcc\xa9\xb95\x04m*Cj")
+
+
+= EAPOL-MKA - With Potential Peer List parameter set - Dissection
+eapol = None
+s = '\x03\x05\x00h\x01\x10\xe0<\xccN$\xc4\xf7\x7f\x00\x80q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6\x00\x00\x00}\x00\x80\xc2\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x02\x00\x00\x10\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7\x00\x00\x00\x01\xff\x00\x00\x105\x01\xdc)\xfd\xd1\xff\xd55\x9c_o\xc9\x9c\xca\xc0'
+eapol = EAPOL(s)
+assert(eapol.version == 3)
+assert(eapol.type == 5)
+assert(eapol.len == 104)
+assert(eapol.haslayer(MKAPDU))
+assert(eapol[MKAPDU].basic_param_set.actor_member_id == "q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6")
+assert(eapol.haslayer(MKAPotentialPeerListParamSet))
+assert(eapol[MKAPDU][MKAPotentialPeerListParamSet].member_id_message_num[0].member_id == "\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7")
+assert(eapol[MKAPDU].haslayer(MKAICVSet))
+assert(eapol[MKAPDU][MKAICVSet].icv == "5\x01\xdc)\xfd\xd1\xff\xd55\x9c_o\xc9\x9c\xca\xc0")
+
+= EAPOL-MKA - With Live Peer List parameter set - Dissection
+eapol = None
+s = "\x03\x05\x00h\x01\xffp<\x00Bh\xa8\x1e\x03\x00\n\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7\x00\x00\x00\x02\x00\x80\xc2\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x01\x00\x00\x10q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6\x00\x00\x00\x80\xff\x00\x00\x10\xf4\xa1d\x18\tD\xa2}\x8e'\x0c/\xda,\xea\xb7"
+eapol = EAPOL(s)
+assert(eapol.version == 3)
+assert(eapol.type == 5)
+assert(eapol.len == 104)
+assert(eapol.haslayer(MKAPDU))
+assert(eapol[MKAPDU].basic_param_set.actor_member_id == '\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7')
+assert(eapol.haslayer(MKALivePeerListParamSet))
+assert(eapol[MKAPDU][MKALivePeerListParamSet].member_id_message_num[0].member_id == "q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6")
+assert(eapol[MKAPDU].haslayer(MKAICVSet))
+assert(eapol[MKAPDU][MKAICVSet].icv == "\xf4\xa1d\x18\tD\xa2}\x8e'\x0c/\xda,\xea\xb7")
+
+= EAPOL-MKA - With SAK Use parameter set - Dissection
+eapol = None
+s = '\x03\x05\x00\x94\x01\xffp<\x00Bh\xa8\x1e\x03\x00\n\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7\x00\x00\x00\x03\x00\x80\xc2\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x03\x10\x00(q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6\x00\x00\x00\x01\x00\x00\x00\x00q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x10q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6\x00\x00\x00\x83\xff\x00\x00\x10OF\x84\xf1@%\x95\xe6Fw9\x1a\xfa\x03(\xae'
+eapol = EAPOL(s)
+assert(eapol.version == 3)
+assert(eapol.type == 5)
+assert(eapol.len == 148)
+assert(eapol.haslayer(MKAPDU))
+assert(eapol[MKAPDU].basic_param_set.actor_member_id == '\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7')
+assert(eapol.haslayer(MKASAKUseParamSet))
+assert(eapol[MKAPDU][MKASAKUseParamSet].latest_key_key_server_member_id == "q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6")
+assert(eapol.haslayer(MKALivePeerListParamSet))
+assert(eapol[MKAPDU][MKALivePeerListParamSet].member_id_message_num[0].member_id == "q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6")
+assert(eapol[MKAPDU].haslayer(MKAICVSet))
+assert(eapol[MKAPDU][MKAICVSet].icv == "OF\x84\xf1@%\x95\xe6Fw9\x1a\xfa\x03(\xae")
+
+= EAPOL-MKA - With Distributed SAK parameter set - Dissection
+eapol = None
+s = "\x03\x05\x00\xb4\x01\x10\xe0<\xccN$\xc4\xf7\x7f\x00\x80q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6\x00\x00\x00\x81\x00\x80\xc2\x01\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x01\x00\x00\x10\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7\x00\x00\x00\x02\x03\x10\x00(q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x10\x00\x1c\x00\x00\x00\x01Cz\x05\x88\x9f\xe8-\x94W+?\x13~\xfb\x016yVB?\xbd\xa1\x9fu\xff\x00\x00\x10\xb0H\xcf\xe0:\xa1\x94RD'\x03\xe67\xe1Ur"
+eapol = EAPOL(s)
+assert(eapol.version == 3)
+assert(eapol.type == 5)
+assert(eapol.len == 180)
+assert(eapol.haslayer(MKAPDU))
+assert(eapol[MKAPDU].basic_param_set.actor_member_id == "q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6")
+assert(eapol.haslayer(MKASAKUseParamSet))
+assert(eapol[MKAPDU][MKASAKUseParamSet].latest_key_key_server_member_id == "q\x8b\x8a9\x86k/X\x14\xc9\xdc\xf6")
+assert(eapol.haslayer(MKALivePeerListParamSet))
+assert(eapol[MKAPDU][MKALivePeerListParamSet].member_id_message_num[0].member_id == "\xbcj\x00\x96Ywz\x82:\x90\xd9\xe7")
+assert(eapol.haslayer(MKADistributedSAKParamSet))
+assert(eapol[MKADistributedSAKParamSet].sak_aes_key_wrap == "Cz\x05\x88\x9f\xe8-\x94W+?\x13~\xfb\x016yVB?\xbd\xa1\x9fu")
+assert(eapol[MKAPDU].haslayer(MKAICVSet))
+assert(eapol[MKAPDU][MKAICVSet].icv == "\xb0H\xcf\xe0:\xa1\x94RD'\x03\xe67\xe1Ur")
+
+
+############
 ############
 ############
 + EAP class tests