Updated Adapter to support to handle DHCP trap on NNI and packet-in/out and Bug Fixing.
Tested EAPOL/DHCP/HSIA functionality E2E with EdgeCore OLT and TWSH ONU KIT.
patch: PON port is derived from platform and sent to core and bug fixes
Retested EAPOL/DHCP/HSIA use case end to end with EdgeCore OLT and TWSH ONU KIT
Change-Id: I99df82fd7a1385c10878f6fe09ce0d30c48d8e99
diff --git a/vendor/github.com/mdlayher/ethernet/ethernet.go b/vendor/github.com/mdlayher/ethernet/ethernet.go
new file mode 100644
index 0000000..d150d8e
--- /dev/null
+++ b/vendor/github.com/mdlayher/ethernet/ethernet.go
@@ -0,0 +1,301 @@
+// Package ethernet implements marshaling and unmarshaling of IEEE 802.3
+// Ethernet II frames and IEEE 802.1Q VLAN tags.
+package ethernet
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "hash/crc32"
+ "io"
+ "net"
+)
+
+//go:generate stringer -output=string.go -type=EtherType
+
+const (
+ // minPayload is the minimum payload size for an Ethernet frame, assuming
+ // that no 802.1Q VLAN tags are present.
+ minPayload = 46
+)
+
+var (
+ // Broadcast is a special hardware address which indicates a Frame should
+ // be sent to every device on a given LAN segment.
+ Broadcast = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+)
+
+var (
+ // ErrInvalidFCS is returned when Frame.UnmarshalFCS detects an incorrect
+ // Ethernet frame check sequence in a byte slice for a Frame.
+ ErrInvalidFCS = errors.New("invalid frame check sequence")
+)
+
+// An EtherType is a value used to identify an upper layer protocol
+// encapsulated in a Frame.
+//
+// A list of IANA-assigned EtherType values may be found here:
+// http://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml.
+type EtherType uint16
+
+// Common EtherType values frequently used in a Frame.
+const (
+ EtherTypeIPv4 EtherType = 0x0800
+ EtherTypeARP EtherType = 0x0806
+ EtherTypeIPv6 EtherType = 0x86DD
+
+ // EtherTypeVLAN and EtherTypeServiceVLAN are used as 802.1Q Tag Protocol
+ // Identifiers (TPIDs).
+ EtherTypeVLAN EtherType = 0x8100
+ EtherTypeServiceVLAN EtherType = 0x88a8
+)
+
+// A Frame is an IEEE 802.3 Ethernet II frame. A Frame contains information
+// such as source and destination hardware addresses, zero or more optional
+// 802.1Q VLAN tags, an EtherType, and payload data.
+type Frame struct {
+ // Destination specifies the destination hardware address for this Frame.
+ //
+ // If this address is set to Broadcast, the Frame will be sent to every
+ // device on a given LAN segment.
+ Destination net.HardwareAddr
+
+ // Source specifies the source hardware address for this Frame.
+ //
+ // Typically, this is the hardware address of the network interface used to
+ // send this Frame.
+ Source net.HardwareAddr
+
+ // ServiceVLAN specifies an optional 802.1Q service VLAN tag, for use with
+ // 802.1ad double tagging, or "Q-in-Q". If ServiceVLAN is not nil, VLAN must
+ // not be nil as well.
+ //
+ // Most users should leave this field set to nil and use VLAN instead.
+ ServiceVLAN *VLAN
+
+ // VLAN specifies an optional 802.1Q customer VLAN tag, which may or may
+ // not be present in a Frame. It is important to note that the operating
+ // system may automatically strip VLAN tags before they can be parsed.
+ VLAN *VLAN
+
+ // EtherType is a value used to identify an upper layer protocol
+ // encapsulated in this Frame.
+ EtherType EtherType
+
+ // Payload is a variable length data payload encapsulated by this Frame.
+ Payload []byte
+}
+
+// MarshalBinary allocates a byte slice and marshals a Frame into binary form.
+func (f *Frame) MarshalBinary() ([]byte, error) {
+ b := make([]byte, f.length())
+ _, err := f.read(b)
+ return b, err
+}
+
+// MarshalFCS allocates a byte slice, marshals a Frame into binary form, and
+// finally calculates and places a 4-byte IEEE CRC32 frame check sequence at
+// the end of the slice.
+//
+// Most users should use MarshalBinary instead. MarshalFCS is provided as a
+// convenience for rare occasions when the operating system cannot
+// automatically generate a frame check sequence for an Ethernet frame.
+func (f *Frame) MarshalFCS() ([]byte, error) {
+ // Frame length with 4 extra bytes for frame check sequence
+ b := make([]byte, f.length()+4)
+ if _, err := f.read(b); err != nil {
+ return nil, err
+ }
+
+ // Compute IEEE CRC32 checksum of frame bytes and place it directly
+ // in the last four bytes of the slice
+ binary.BigEndian.PutUint32(b[len(b)-4:], crc32.ChecksumIEEE(b[0:len(b)-4]))
+ return b, nil
+}
+
+// read reads data from a Frame into b. read is used to marshal a Frame
+// into binary form, but does not allocate on its own.
+func (f *Frame) read(b []byte) (int, error) {
+ // S-VLAN must also have accompanying C-VLAN.
+ if f.ServiceVLAN != nil && f.VLAN == nil {
+ return 0, ErrInvalidVLAN
+ }
+
+ copy(b[0:6], f.Destination)
+ copy(b[6:12], f.Source)
+
+ // Marshal each non-nil VLAN tag into bytes, inserting the appropriate
+ // EtherType/TPID before each, so devices know that one or more VLANs
+ // are present.
+ vlans := []struct {
+ vlan *VLAN
+ tpid EtherType
+ }{
+ {vlan: f.ServiceVLAN, tpid: EtherTypeServiceVLAN},
+ {vlan: f.VLAN, tpid: EtherTypeVLAN},
+ }
+
+ n := 12
+ for _, vt := range vlans {
+ if vt.vlan == nil {
+ continue
+ }
+
+ // Add VLAN EtherType and VLAN bytes.
+ binary.BigEndian.PutUint16(b[n:n+2], uint16(vt.tpid))
+ if _, err := vt.vlan.read(b[n+2 : n+4]); err != nil {
+ return 0, err
+ }
+ n += 4
+ }
+
+ // Marshal actual EtherType after any VLANs, copy payload into
+ // output bytes.
+ binary.BigEndian.PutUint16(b[n:n+2], uint16(f.EtherType))
+ copy(b[n+2:], f.Payload)
+
+ return len(b), nil
+}
+
+// UnmarshalBinary unmarshals a byte slice into a Frame.
+func (f *Frame) UnmarshalBinary(b []byte) error {
+ // Verify that both hardware addresses and a single EtherType are present
+ if len(b) < 14 {
+ return io.ErrUnexpectedEOF
+ }
+
+ // Track offset in packet for reading data
+ n := 14
+
+ // Continue looping and parsing VLAN tags until no more VLAN EtherType
+ // values are detected
+ et := EtherType(binary.BigEndian.Uint16(b[n-2 : n]))
+ switch et {
+ case EtherTypeServiceVLAN, EtherTypeVLAN:
+ // VLAN type is hinted for further parsing. An index is returned which
+ // indicates how many bytes were consumed by VLAN tags.
+ nn, err := f.unmarshalVLANs(et, b[n:])
+ if err != nil {
+ return err
+ }
+
+ n += nn
+ default:
+ // No VLANs detected.
+ f.EtherType = et
+ }
+
+ // Allocate single byte slice to store destination and source hardware
+ // addresses, and payload
+ bb := make([]byte, 6+6+len(b[n:]))
+ copy(bb[0:6], b[0:6])
+ f.Destination = bb[0:6]
+ copy(bb[6:12], b[6:12])
+ f.Source = bb[6:12]
+
+ // There used to be a minimum payload length restriction here, but as
+ // long as two hardware addresses and an EtherType are present, it
+ // doesn't really matter what is contained in the payload. We will
+ // follow the "robustness principle".
+ copy(bb[12:], b[n:])
+ f.Payload = bb[12:]
+
+ return nil
+}
+
+// UnmarshalFCS computes the IEEE CRC32 frame check sequence of a Frame,
+// verifies it against the checksum present in the byte slice, and finally,
+// unmarshals a byte slice into a Frame.
+//
+// Most users should use UnmarshalBinary instead. UnmarshalFCS is provided as
+// a convenience for rare occasions when the operating system cannot
+// automatically verify a frame check sequence for an Ethernet frame.
+func (f *Frame) UnmarshalFCS(b []byte) error {
+ // Must contain enough data for FCS, to avoid panics
+ if len(b) < 4 {
+ return io.ErrUnexpectedEOF
+ }
+
+ // Verify checksum in slice versus newly computed checksum
+ want := binary.BigEndian.Uint32(b[len(b)-4:])
+ got := crc32.ChecksumIEEE(b[0 : len(b)-4])
+ if want != got {
+ return ErrInvalidFCS
+ }
+
+ return f.UnmarshalBinary(b[0 : len(b)-4])
+}
+
+// length calculates the number of bytes required to store a Frame.
+func (f *Frame) length() int {
+ // If payload is less than the required minimum length, we zero-pad up to
+ // the required minimum length
+ pl := len(f.Payload)
+ if pl < minPayload {
+ pl = minPayload
+ }
+
+ // Add additional length if VLAN tags are needed.
+ var vlanLen int
+ switch {
+ case f.ServiceVLAN != nil && f.VLAN != nil:
+ vlanLen = 8
+ case f.VLAN != nil:
+ vlanLen = 4
+ }
+
+ // 6 bytes: destination hardware address
+ // 6 bytes: source hardware address
+ // N bytes: VLAN tags (if present)
+ // 2 bytes: EtherType
+ // N bytes: payload length (may be padded)
+ return 6 + 6 + vlanLen + 2 + pl
+}
+
+// unmarshalVLANs unmarshals S/C-VLAN tags. It is assumed that tpid
+// is a valid S/C-VLAN TPID.
+func (f *Frame) unmarshalVLANs(tpid EtherType, b []byte) (int, error) {
+ // 4 or more bytes must remain for valid S/C-VLAN tag and EtherType.
+ if len(b) < 4 {
+ return 0, io.ErrUnexpectedEOF
+ }
+
+ // Track how many bytes are consumed by VLAN tags.
+ var n int
+
+ switch tpid {
+ case EtherTypeServiceVLAN:
+ vlan := new(VLAN)
+ if err := vlan.UnmarshalBinary(b[n : n+2]); err != nil {
+ return 0, err
+ }
+ f.ServiceVLAN = vlan
+
+ // Assume that a C-VLAN immediately trails an S-VLAN.
+ if EtherType(binary.BigEndian.Uint16(b[n+2:n+4])) != EtherTypeVLAN {
+ return 0, ErrInvalidVLAN
+ }
+
+ // 4 or more bytes must remain for valid C-VLAN tag and EtherType.
+ n += 4
+ if len(b[n:]) < 4 {
+ return 0, io.ErrUnexpectedEOF
+ }
+
+ // Continue to parse the C-VLAN.
+ fallthrough
+ case EtherTypeVLAN:
+ vlan := new(VLAN)
+ if err := vlan.UnmarshalBinary(b[n : n+2]); err != nil {
+ return 0, err
+ }
+
+ f.VLAN = vlan
+ f.EtherType = EtherType(binary.BigEndian.Uint16(b[n+2 : n+4]))
+ n += 4
+ default:
+ panic(fmt.Sprintf("unknown VLAN TPID: %04x", tpid))
+ }
+
+ return n, nil
+}