[VOL-1349] EPON OLT adapter (package B)

Change-Id: I634ef62c53813dcf4456f54948f13e06358e263c
diff --git a/vendor/github.com/google/gopacket/layers/ospf.go b/vendor/github.com/google/gopacket/layers/ospf.go
new file mode 100644
index 0000000..f3f2ca9
--- /dev/null
+++ b/vendor/github.com/google/gopacket/layers/ospf.go
@@ -0,0 +1,680 @@
+// Copyright 2017 Google, Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree.
+
+package layers
+
+import (
+	"encoding/binary"
+	"fmt"
+
+	"github.com/google/gopacket"
+)
+
+// OSPFType denotes what kind of OSPF type it is
+type OSPFType uint8
+
+// Potential values for OSPF.Type.
+const (
+	OSPFHello                   OSPFType = 1
+	OSPFDatabaseDescription     OSPFType = 2
+	OSPFLinkStateRequest        OSPFType = 3
+	OSPFLinkStateUpdate         OSPFType = 4
+	OSPFLinkStateAcknowledgment OSPFType = 5
+)
+
+// LSA Function Codes for LSAheader.LSType
+const (
+	RouterLSAtypeV2         = 0x1
+	RouterLSAtype           = 0x2001
+	NetworkLSAtypeV2        = 0x2
+	NetworkLSAtype          = 0x2002
+	SummaryLSANetworktypeV2 = 0x3
+	InterAreaPrefixLSAtype  = 0x2003
+	SummaryLSAASBRtypeV2    = 0x4
+	InterAreaRouterLSAtype  = 0x2004
+	ASExternalLSAtypeV2     = 0x5
+	ASExternalLSAtype       = 0x4005
+	NSSALSAtype             = 0x2007
+	LinkLSAtype             = 0x0008
+	IntraAreaPrefixLSAtype  = 0x2009
+)
+
+// String conversions for OSPFType
+func (i OSPFType) String() string {
+	switch i {
+	case OSPFHello:
+		return "Hello"
+	case OSPFDatabaseDescription:
+		return "Database Description"
+	case OSPFLinkStateRequest:
+		return "Link State Request"
+	case OSPFLinkStateUpdate:
+		return "Link State Update"
+	case OSPFLinkStateAcknowledgment:
+		return "Link State Acknowledgment"
+	default:
+		return ""
+	}
+}
+
+// Prefix extends IntraAreaPrefixLSA
+type Prefix struct {
+	PrefixLength  uint8
+	PrefixOptions uint8
+	Metric        uint16
+	AddressPrefix []byte
+}
+
+// IntraAreaPrefixLSA is the struct from RFC 5340  A.4.10.
+type IntraAreaPrefixLSA struct {
+	NumOfPrefixes  uint16
+	RefLSType      uint16
+	RefLinkStateID uint32
+	RefAdvRouter   uint32
+	Prefixes       []Prefix
+}
+
+// LinkLSA is the struct from RFC 5340  A.4.9.
+type LinkLSA struct {
+	RtrPriority      uint8
+	Options          uint32
+	LinkLocalAddress []byte
+	NumOfPrefixes    uint32
+	Prefixes         []Prefix
+}
+
+// ASExternalLSAV2 is the struct from RFC 2328  A.4.5.
+type ASExternalLSAV2 struct {
+	NetworkMask       uint32
+	ExternalBit       uint8
+	Metric            uint32
+	ForwardingAddress uint32
+	ExternalRouteTag  uint32
+}
+
+// ASExternalLSA is the struct from RFC 5340  A.4.7.
+type ASExternalLSA struct {
+	Flags             uint8
+	Metric            uint32
+	PrefixLength      uint8
+	PrefixOptions     uint8
+	RefLSType         uint16
+	AddressPrefix     []byte
+	ForwardingAddress []byte
+	ExternalRouteTag  uint32
+	RefLinkStateID    uint32
+}
+
+// InterAreaRouterLSA is the struct from RFC 5340  A.4.6.
+type InterAreaRouterLSA struct {
+	Options             uint32
+	Metric              uint32
+	DestinationRouterID uint32
+}
+
+// InterAreaPrefixLSA is the struct from RFC 5340  A.4.5.
+type InterAreaPrefixLSA struct {
+	Metric        uint32
+	PrefixLength  uint8
+	PrefixOptions uint8
+	AddressPrefix []byte
+}
+
+// NetworkLSA is the struct from RFC 5340  A.4.4.
+type NetworkLSA struct {
+	Options        uint32
+	AttachedRouter []uint32
+}
+
+// RouterV2 extends RouterLSAV2
+type RouterV2 struct {
+	Type     uint8
+	LinkID   uint32
+	LinkData uint32
+	Metric   uint16
+}
+
+// RouterLSAV2 is the struct from RFC 2328  A.4.2.
+type RouterLSAV2 struct {
+	Flags   uint8
+	Links   uint16
+	Routers []RouterV2
+}
+
+// Router extends RouterLSA
+type Router struct {
+	Type                uint8
+	Metric              uint16
+	InterfaceID         uint32
+	NeighborInterfaceID uint32
+	NeighborRouterID    uint32
+}
+
+// RouterLSA is the struct from RFC 5340  A.4.3.
+type RouterLSA struct {
+	Flags   uint8
+	Options uint32
+	Routers []Router
+}
+
+// LSAheader is the struct from RFC 5340  A.4.2 and RFC 2328 A.4.1.
+type LSAheader struct {
+	LSAge       uint16
+	LSType      uint16
+	LinkStateID uint32
+	AdvRouter   uint32
+	LSSeqNumber uint32
+	LSChecksum  uint16
+	Length      uint16
+	LSOptions   uint8
+}
+
+// LSA links LSAheader with the structs from RFC 5340  A.4.
+type LSA struct {
+	LSAheader
+	Content interface{}
+}
+
+// LSUpdate is the struct from RFC 5340  A.3.5.
+type LSUpdate struct {
+	NumOfLSAs uint32
+	LSAs      []LSA
+}
+
+// LSReq is the struct from RFC 5340  A.3.4.
+type LSReq struct {
+	LSType    uint16
+	LSID      uint32
+	AdvRouter uint32
+}
+
+// DbDescPkg is the struct from RFC 5340  A.3.3.
+type DbDescPkg struct {
+	Options      uint32
+	InterfaceMTU uint16
+	Flags        uint16
+	DDSeqNumber  uint32
+	LSAinfo      []LSAheader
+}
+
+// HelloPkg  is the struct from RFC 5340  A.3.2.
+type HelloPkg struct {
+	InterfaceID              uint32
+	RtrPriority              uint8
+	Options                  uint32
+	HelloInterval            uint16
+	RouterDeadInterval       uint32
+	DesignatedRouterID       uint32
+	BackupDesignatedRouterID uint32
+	NeighborID               []uint32
+}
+
+// HelloPkgV2 extends the HelloPkg struct with OSPFv2 information
+type HelloPkgV2 struct {
+	HelloPkg
+	NetworkMask uint32
+}
+
+// OSPF is a basic OSPF packet header with common fields of Version 2 and Version 3.
+type OSPF struct {
+	Version      uint8
+	Type         OSPFType
+	PacketLength uint16
+	RouterID     uint32
+	AreaID       uint32
+	Checksum     uint16
+	Content      interface{}
+}
+
+//OSPFv2 extend the OSPF head with version 2 specific fields
+type OSPFv2 struct {
+	BaseLayer
+	OSPF
+	AuType         uint16
+	Authentication uint64
+}
+
+// OSPFv3 extend the OSPF head with version 3 specific fields
+type OSPFv3 struct {
+	BaseLayer
+	OSPF
+	Instance uint8
+	Reserved uint8
+}
+
+// getLSAsv2 parses the LSA information from the packet for OSPFv2
+func getLSAsv2(num uint32, data []byte) ([]LSA, error) {
+	var lsas []LSA
+	var i uint32 = 0
+	var offset uint32 = 0
+	for ; i < num; i++ {
+		lstype := uint16(data[offset+3])
+		lsalength := binary.BigEndian.Uint16(data[offset+18 : offset+20])
+		content, err := extractLSAInformation(lstype, lsalength, data[offset:])
+		if err != nil {
+			return nil, fmt.Errorf("Could not extract Link State type.")
+		}
+		lsa := LSA{
+			LSAheader: LSAheader{
+				LSAge:       binary.BigEndian.Uint16(data[offset : offset+2]),
+				LSOptions:   data[offset+2],
+				LSType:      lstype,
+				LinkStateID: binary.BigEndian.Uint32(data[offset+4 : offset+8]),
+				AdvRouter:   binary.BigEndian.Uint32(data[offset+8 : offset+12]),
+				LSSeqNumber: binary.BigEndian.Uint32(data[offset+12 : offset+16]),
+				LSChecksum:  binary.BigEndian.Uint16(data[offset+16 : offset+18]),
+				Length:      lsalength,
+			},
+			Content: content,
+		}
+		lsas = append(lsas, lsa)
+		offset += uint32(lsalength)
+	}
+	return lsas, nil
+}
+
+// extractLSAInformation extracts all the LSA information
+func extractLSAInformation(lstype, lsalength uint16, data []byte) (interface{}, error) {
+	if lsalength < 20 {
+		return nil, fmt.Errorf("Link State header length %v too short, %v required", lsalength, 20)
+	}
+	if len(data) < int(lsalength) {
+		return nil, fmt.Errorf("Link State header length %v too short, %v required", len(data), lsalength)
+	}
+	var content interface{}
+	switch lstype {
+	case RouterLSAtypeV2:
+		var routers []RouterV2
+		links := binary.BigEndian.Uint16(data[22:24])
+		content = RouterLSAV2{
+			Flags:   data[20],
+			Links:   links,
+			Routers: routers,
+		}
+	case ASExternalLSAtypeV2:
+		content = ASExternalLSAV2{
+			NetworkMask:       binary.BigEndian.Uint32(data[20:24]),
+			ExternalBit:       data[24] & 0x80,
+			Metric:            binary.BigEndian.Uint32(data[24:28]) & 0x00FFFFFF,
+			ForwardingAddress: binary.BigEndian.Uint32(data[28:32]),
+			ExternalRouteTag:  binary.BigEndian.Uint32(data[32:36]),
+		}
+	case RouterLSAtype:
+		var routers []Router
+		var j uint32
+		for j = 24; j < uint32(lsalength); j += 16 {
+			router := Router{
+				Type:                uint8(data[j]),
+				Metric:              binary.BigEndian.Uint16(data[j+2 : j+4]),
+				InterfaceID:         binary.BigEndian.Uint32(data[j+4 : j+8]),
+				NeighborInterfaceID: binary.BigEndian.Uint32(data[j+8 : j+12]),
+				NeighborRouterID:    binary.BigEndian.Uint32(data[j+12 : j+16]),
+			}
+			routers = append(routers, router)
+		}
+		content = RouterLSA{
+			Flags:   uint8(data[20]),
+			Options: binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
+			Routers: routers,
+		}
+	case NetworkLSAtype:
+		var routers []uint32
+		var j uint32
+		for j = 24; j < uint32(lsalength); j += 4 {
+			routers = append(routers, binary.BigEndian.Uint32(data[j:j+4]))
+		}
+		content = NetworkLSA{
+			Options:        binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
+			AttachedRouter: routers,
+		}
+	case InterAreaPrefixLSAtype:
+		content = InterAreaPrefixLSA{
+			Metric:        binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
+			PrefixLength:  uint8(data[24]),
+			PrefixOptions: uint8(data[25]),
+			AddressPrefix: data[28:uint32(lsalength)],
+		}
+	case InterAreaRouterLSAtype:
+		content = InterAreaRouterLSA{
+			Options:             binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
+			Metric:              binary.BigEndian.Uint32(data[24:28]) & 0x00FFFFFF,
+			DestinationRouterID: binary.BigEndian.Uint32(data[28:32]),
+		}
+	case ASExternalLSAtype:
+		fallthrough
+	case NSSALSAtype:
+
+		flags := uint8(data[20])
+		prefixLen := uint8(data[24]) / 8
+		var forwardingAddress []byte
+		if (flags & 0x02) == 0x02 {
+			forwardingAddress = data[28+uint32(prefixLen) : 28+uint32(prefixLen)+16]
+		}
+		content = ASExternalLSA{
+			Flags:             flags,
+			Metric:            binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
+			PrefixLength:      prefixLen,
+			PrefixOptions:     uint8(data[25]),
+			RefLSType:         binary.BigEndian.Uint16(data[26:28]),
+			AddressPrefix:     data[28 : 28+uint32(prefixLen)],
+			ForwardingAddress: forwardingAddress,
+		}
+	case LinkLSAtype:
+		var prefixes []Prefix
+		var prefixOffset uint32 = 44
+		var j uint32
+		numOfPrefixes := binary.BigEndian.Uint32(data[40:44])
+		for j = 0; j < numOfPrefixes; j++ {
+			prefixLen := uint8(data[prefixOffset])
+			prefix := Prefix{
+				PrefixLength:  prefixLen,
+				PrefixOptions: uint8(data[prefixOffset+1]),
+				AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
+			}
+			prefixes = append(prefixes, prefix)
+			prefixOffset = prefixOffset + 4 + uint32(prefixLen)/8
+		}
+		content = LinkLSA{
+			RtrPriority:      uint8(data[20]),
+			Options:          binary.BigEndian.Uint32(data[20:24]) & 0x00FFFFFF,
+			LinkLocalAddress: data[24:40],
+			NumOfPrefixes:    numOfPrefixes,
+			Prefixes:         prefixes,
+		}
+	case IntraAreaPrefixLSAtype:
+		var prefixes []Prefix
+		var prefixOffset uint32 = 32
+		var j uint16
+		numOfPrefixes := binary.BigEndian.Uint16(data[20:22])
+		for j = 0; j < numOfPrefixes; j++ {
+			prefixLen := uint8(data[prefixOffset])
+			prefix := Prefix{
+				PrefixLength:  prefixLen,
+				PrefixOptions: uint8(data[prefixOffset+1]),
+				Metric:        binary.BigEndian.Uint16(data[prefixOffset+2 : prefixOffset+4]),
+				AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
+			}
+			prefixes = append(prefixes, prefix)
+			prefixOffset = prefixOffset + 4 + uint32(prefixLen)
+		}
+		content = IntraAreaPrefixLSA{
+			NumOfPrefixes:  numOfPrefixes,
+			RefLSType:      binary.BigEndian.Uint16(data[22:24]),
+			RefLinkStateID: binary.BigEndian.Uint32(data[24:28]),
+			RefAdvRouter:   binary.BigEndian.Uint32(data[28:32]),
+			Prefixes:       prefixes,
+		}
+	default:
+		return nil, fmt.Errorf("Unknown Link State type.")
+	}
+	return content, nil
+}
+
+// getLSAs parses the LSA information from the packet for OSPFv3
+func getLSAs(num uint32, data []byte) ([]LSA, error) {
+	var lsas []LSA
+	var i uint32 = 0
+	var offset uint32 = 0
+	for ; i < num; i++ {
+		var content interface{}
+		lstype := binary.BigEndian.Uint16(data[offset+2 : offset+4])
+		lsalength := binary.BigEndian.Uint16(data[offset+18 : offset+20])
+
+		content, err := extractLSAInformation(lstype, lsalength, data[offset:])
+		if err != nil {
+			return nil, fmt.Errorf("Could not extract Link State type.")
+		}
+		lsa := LSA{
+			LSAheader: LSAheader{
+				LSAge:       binary.BigEndian.Uint16(data[offset : offset+2]),
+				LSType:      lstype,
+				LinkStateID: binary.BigEndian.Uint32(data[offset+4 : offset+8]),
+				AdvRouter:   binary.BigEndian.Uint32(data[offset+8 : offset+12]),
+				LSSeqNumber: binary.BigEndian.Uint32(data[offset+12 : offset+16]),
+				LSChecksum:  binary.BigEndian.Uint16(data[offset+16 : offset+18]),
+				Length:      lsalength,
+			},
+			Content: content,
+		}
+		lsas = append(lsas, lsa)
+		offset += uint32(lsalength)
+	}
+	return lsas, nil
+}
+
+// DecodeFromBytes decodes the given bytes into the OSPF layer.
+func (ospf *OSPFv2) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
+	if len(data) < 24 {
+		return fmt.Errorf("Packet too smal for OSPF Version 2")
+	}
+
+	ospf.Version = uint8(data[0])
+	ospf.Type = OSPFType(data[1])
+	ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
+	ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
+	ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
+	ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
+	ospf.AuType = binary.BigEndian.Uint16(data[14:16])
+	ospf.Authentication = binary.BigEndian.Uint64(data[16:24])
+
+	switch ospf.Type {
+	case OSPFHello:
+		var neighbors []uint32
+		for i := 44; uint16(i+4) <= ospf.PacketLength; i += 4 {
+			neighbors = append(neighbors, binary.BigEndian.Uint32(data[i:i+4]))
+		}
+		ospf.Content = HelloPkgV2{
+			NetworkMask: binary.BigEndian.Uint32(data[24:28]),
+			HelloPkg: HelloPkg{
+				HelloInterval:            binary.BigEndian.Uint16(data[28:30]),
+				Options:                  uint32(data[30]),
+				RtrPriority:              uint8(data[31]),
+				RouterDeadInterval:       binary.BigEndian.Uint32(data[32:36]),
+				DesignatedRouterID:       binary.BigEndian.Uint32(data[36:40]),
+				BackupDesignatedRouterID: binary.BigEndian.Uint32(data[40:44]),
+				NeighborID:               neighbors,
+			},
+		}
+	case OSPFDatabaseDescription:
+		var lsas []LSAheader
+		for i := 32; uint16(i+20) <= ospf.PacketLength; i += 20 {
+			lsa := LSAheader{
+				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
+				LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
+				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
+				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
+				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
+				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
+				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
+			}
+			lsas = append(lsas, lsa)
+		}
+		ospf.Content = DbDescPkg{
+			InterfaceMTU: binary.BigEndian.Uint16(data[24:26]),
+			Options:      uint32(data[26]),
+			Flags:        uint16(data[27]),
+			DDSeqNumber:  binary.BigEndian.Uint32(data[28:32]),
+			LSAinfo:      lsas,
+		}
+	case OSPFLinkStateRequest:
+		var lsrs []LSReq
+		for i := 24; uint16(i+12) <= ospf.PacketLength; i += 12 {
+			lsr := LSReq{
+				LSType:    binary.BigEndian.Uint16(data[i+2 : i+4]),
+				LSID:      binary.BigEndian.Uint32(data[i+4 : i+8]),
+				AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
+			}
+			lsrs = append(lsrs, lsr)
+		}
+		ospf.Content = lsrs
+	case OSPFLinkStateUpdate:
+		num := binary.BigEndian.Uint32(data[24:28])
+
+		lsas, err := getLSAsv2(num, data[28:])
+		if err != nil {
+			return fmt.Errorf("Cannot parse Link State Update packet: %v", err)
+		}
+		ospf.Content = LSUpdate{
+			NumOfLSAs: num,
+			LSAs:      lsas,
+		}
+	case OSPFLinkStateAcknowledgment:
+		var lsas []LSAheader
+		for i := 24; uint16(i+20) <= ospf.PacketLength; i += 20 {
+			lsa := LSAheader{
+				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
+				LSOptions:   data[i+2],
+				LSType:      uint16(data[i+3]),
+				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
+				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
+				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
+				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
+				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
+			}
+			lsas = append(lsas, lsa)
+		}
+		ospf.Content = lsas
+	}
+	return nil
+}
+
+// DecodeFromBytes decodes the given bytes into the OSPF layer.
+func (ospf *OSPFv3) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
+
+	if len(data) < 16 {
+		return fmt.Errorf("Packet too smal for OSPF Version 3")
+	}
+
+	ospf.Version = uint8(data[0])
+	ospf.Type = OSPFType(data[1])
+	ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
+	ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
+	ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
+	ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
+	ospf.Instance = uint8(data[14])
+	ospf.Reserved = uint8(data[15])
+
+	switch ospf.Type {
+	case OSPFHello:
+		var neighbors []uint32
+		for i := 36; uint16(i+4) <= ospf.PacketLength; i += 4 {
+			neighbors = append(neighbors, binary.BigEndian.Uint32(data[i:i+4]))
+		}
+		ospf.Content = HelloPkg{
+			InterfaceID:              binary.BigEndian.Uint32(data[16:20]),
+			RtrPriority:              uint8(data[20]),
+			Options:                  binary.BigEndian.Uint32(data[21:25]) >> 8,
+			HelloInterval:            binary.BigEndian.Uint16(data[24:26]),
+			RouterDeadInterval:       uint32(binary.BigEndian.Uint16(data[26:28])),
+			DesignatedRouterID:       binary.BigEndian.Uint32(data[28:32]),
+			BackupDesignatedRouterID: binary.BigEndian.Uint32(data[32:36]),
+			NeighborID:               neighbors,
+		}
+	case OSPFDatabaseDescription:
+		var lsas []LSAheader
+		for i := 28; uint16(i+20) <= ospf.PacketLength; i += 20 {
+			lsa := LSAheader{
+				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
+				LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
+				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
+				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
+				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
+				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
+				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
+			}
+			lsas = append(lsas, lsa)
+		}
+		ospf.Content = DbDescPkg{
+			Options:      binary.BigEndian.Uint32(data[16:20]) & 0x00FFFFFF,
+			InterfaceMTU: binary.BigEndian.Uint16(data[20:22]),
+			Flags:        binary.BigEndian.Uint16(data[22:24]),
+			DDSeqNumber:  binary.BigEndian.Uint32(data[24:28]),
+			LSAinfo:      lsas,
+		}
+	case OSPFLinkStateRequest:
+		var lsrs []LSReq
+		for i := 16; uint16(i+12) <= ospf.PacketLength; i += 12 {
+			lsr := LSReq{
+				LSType:    binary.BigEndian.Uint16(data[i+2 : i+4]),
+				LSID:      binary.BigEndian.Uint32(data[i+4 : i+8]),
+				AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
+			}
+			lsrs = append(lsrs, lsr)
+		}
+		ospf.Content = lsrs
+	case OSPFLinkStateUpdate:
+		num := binary.BigEndian.Uint32(data[16:20])
+		lsas, err := getLSAs(num, data[20:])
+		if err != nil {
+			return fmt.Errorf("Cannot parse Link State Update packet: %v", err)
+		}
+		ospf.Content = LSUpdate{
+			NumOfLSAs: num,
+			LSAs:      lsas,
+		}
+
+	case OSPFLinkStateAcknowledgment:
+		var lsas []LSAheader
+		for i := 16; uint16(i+20) <= ospf.PacketLength; i += 20 {
+			lsa := LSAheader{
+				LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
+				LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
+				LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
+				AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
+				LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
+				LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
+				Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
+			}
+			lsas = append(lsas, lsa)
+		}
+		ospf.Content = lsas
+	default:
+	}
+
+	return nil
+}
+
+// LayerType returns LayerTypeOSPF
+func (ospf *OSPFv2) LayerType() gopacket.LayerType {
+	return LayerTypeOSPF
+}
+func (ospf *OSPFv3) LayerType() gopacket.LayerType {
+	return LayerTypeOSPF
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (ospf *OSPFv2) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypeZero
+}
+func (ospf *OSPFv3) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypeZero
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode.
+func (ospf *OSPFv2) CanDecode() gopacket.LayerClass {
+	return LayerTypeOSPF
+}
+func (ospf *OSPFv3) CanDecode() gopacket.LayerClass {
+	return LayerTypeOSPF
+}
+
+func decodeOSPF(data []byte, p gopacket.PacketBuilder) error {
+	if len(data) < 14 {
+		return fmt.Errorf("Packet too smal for OSPF")
+	}
+
+	switch uint8(data[0]) {
+	case 2:
+		ospf := &OSPFv2{}
+		return decodingLayerDecoder(ospf, data, p)
+	case 3:
+		ospf := &OSPFv3{}
+		return decodingLayerDecoder(ospf, data, p)
+	default:
+	}
+
+	return fmt.Errorf("Unable to determine OSPF type.")
+}