mirror of
https://github.com/soypat/lneto.git
synced 2026-07-26 10:38:47 +00:00
remove legacy remnants and move ip,udp,ethernet logic into subpackages
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package ethernet
|
||||
|
||||
const (
|
||||
sizeHeaderNoVLAN = 14
|
||||
)
|
||||
|
||||
//go:generate stringer -type=Type -linecomment -output stringers.go .
|
||||
|
||||
type Type uint16
|
||||
|
||||
// IsSize returns true if the EtherType is actually the size of the payload
|
||||
// and should NOT be interpreted as an EtherType.
|
||||
func (et Type) IsSize() bool { return et <= 1500 }
|
||||
|
||||
// Ethernet type flags
|
||||
const (
|
||||
TypeIPv4 Type = 0x0800 // IPv4
|
||||
TypeARP Type = 0x0806 // ARP
|
||||
TypeWakeOnLAN Type = 0x0842 // wake on LAN
|
||||
TypeTRILL Type = 0x22F3 // TRILL
|
||||
TypeDECnetPhase4 Type = 0x6003 // DECnetPhase4
|
||||
TypeRARP Type = 0x8035 // RARP
|
||||
TypeAppleTalk Type = 0x809B // AppleTalk
|
||||
TypeAARP Type = 0x80F3 // AARP
|
||||
TypeIPX1 Type = 0x8137 // IPx1
|
||||
TypeIPX2 Type = 0x8138 // IPx2
|
||||
TypeQNXQnet Type = 0x8204 // QNXQnet
|
||||
TypeIPv6 Type = 0x86DD // IPv6
|
||||
TypeEthernetFlowControl Type = 0x8808 // EthernetFlowCtl
|
||||
TypeIEEE802_3 Type = 0x8809 // IEEE802.3
|
||||
TypeCobraNet Type = 0x8819 // CobraNet
|
||||
TypeMPLSUnicast Type = 0x8847 // MPLS Unicast
|
||||
TypeMPLSMulticast Type = 0x8848 // MPLS Multicast
|
||||
TypePPPoEDiscovery Type = 0x8863 // PPPoE discovery
|
||||
TypePPPoESession Type = 0x8864 // PPPoE session
|
||||
TypeJumboFrames Type = 0x8870 // jumbo frames
|
||||
TypeHomePlug1_0MME Type = 0x887B // home plug 1 0mme
|
||||
TypeIEEE802_1X Type = 0x888E // IEEE 802.1x
|
||||
TypePROFINET Type = 0x8892 // profinet
|
||||
TypeHyperSCSI Type = 0x889A // hyper SCSI
|
||||
TypeAoE Type = 0x88A2 // AoE
|
||||
TypeEtherCAT Type = 0x88A4 // EtherCAT
|
||||
TypeEthernetPowerlink Type = 0x88AB // Ethernet powerlink
|
||||
TypeLLDP Type = 0x88CC // LLDP
|
||||
TypeSERCOS3 Type = 0x88CD // SERCOS3
|
||||
TypeHomePlugAVMME Type = 0x88E1 // home plug AVMME
|
||||
TypeMRP Type = 0x88E3 // MRP
|
||||
TypeIEEE802_1AE Type = 0x88E5 // IEEE 802.1ae
|
||||
TypeIEEE1588 Type = 0x88F7 // IEEE 1588
|
||||
TypeIEEE802_1ag Type = 0x8902 // IEEE 802.1ag
|
||||
TypeFCoE Type = 0x8906 // FCoE
|
||||
TypeFCoEInit Type = 0x8914 // FCoE init
|
||||
TypeRoCE Type = 0x8915 // RoCE
|
||||
TypeCTP Type = 0x9000 // CTP
|
||||
TypeVeritasLLT Type = 0xCAFE // Veritas LLT
|
||||
TypeVLAN Type = 0x8100 // VLAN
|
||||
TypeServiceVLAN Type = 0x88a8 // service VLAN
|
||||
// minEthPayload is the minimum payload size for an Ethernet frame, assuming
|
||||
// that no 802.1Q VLAN tags are present.
|
||||
minEthPayload = 46
|
||||
)
|
||||
|
||||
// VLANTag holds priority (PCP) Drop indicator (DEI) and VLAN ID bits of the VLAN tag field.
|
||||
type VLANTag uint16
|
||||
|
||||
// DropEligibleIndicator returns true if the DEI bit is set.
|
||||
// DEI may be used separately or in conjunction with PCP to indicate frames eligible to be dropped in the presence of congestion.
|
||||
func (vt VLANTag) DropEligibleIndicator() bool { return vt&(1<<3) != 0 }
|
||||
|
||||
// PriorityCodePoint is 3-bit field which refers to the IEEE 802.1p class of service (CoS) and maps to the frame priority level. Different PCP values can be used to prioritize different classes of traffic
|
||||
func (vt VLANTag) PriorityCodePoint() uint8 { return uint8(vt & 0b111) }
|
||||
|
||||
// VLANIdentifier 12 bit field which specifies which VLAN the frame belongs to. Values of 0 and 4095 are reserved.
|
||||
func (vt VLANTag) VLANIdentifier() uint16 { return uint16(vt) >> 4 }
|
||||
@@ -0,0 +1,131 @@
|
||||
package ethernet
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/soypat/lneto/lneto2"
|
||||
)
|
||||
|
||||
// NewFrame returns a EthFrame with data set to buf.
|
||||
// An error is returned if the buffer size is smaller than 14.
|
||||
// Users should still call [EthFrame.ValidateSize] before working
|
||||
// with payload/options of frames to avoid panics.
|
||||
func NewFrame(buf []byte) (Frame, error) {
|
||||
if len(buf) < sizeHeaderNoVLAN {
|
||||
return Frame{buf: nil}, errShort
|
||||
}
|
||||
return Frame{buf: buf}, nil
|
||||
}
|
||||
|
||||
// Frame encapsulates the raw data of an Ethernet frame
|
||||
// without including preamble (first byte is start of destination address)
|
||||
// and provides methods for manipulating, validating and
|
||||
// retrieving fields and payload data. See [IEEE 802.3].
|
||||
//
|
||||
// [IEEE 802.3]: https://standards.ieee.org/ieee/802.3/7071/
|
||||
type Frame struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// RawData returns the underlying slice with which the frame was created.
|
||||
func (efrm Frame) RawData() []byte { return efrm.buf }
|
||||
|
||||
// HeaderLength returns the length of the ethernet packet header. Nominally returns 14; or 18 for VLAN packets.
|
||||
func (efrm Frame) HeaderLength() int {
|
||||
if efrm.IsVLAN() {
|
||||
return 18
|
||||
}
|
||||
return sizeHeaderNoVLAN
|
||||
}
|
||||
|
||||
// Payload returns the data portion of the ethernet packet with handling of VLAN packets.
|
||||
func (efrm Frame) Payload() []byte {
|
||||
hl := efrm.HeaderLength()
|
||||
et := efrm.EtherTypeOrSize()
|
||||
if et.IsSize() {
|
||||
return efrm.buf[hl:et]
|
||||
}
|
||||
return efrm.buf[hl:]
|
||||
}
|
||||
|
||||
// DestinationHardwareAddr returns the target's MAC/hardware address for the ethernet packet.
|
||||
func (efrm Frame) DestinationHardwareAddr() (dst *[6]byte) {
|
||||
return (*[6]byte)(efrm.buf[0:6])
|
||||
}
|
||||
|
||||
// IsBroadcast returns true if the destination is the broadcast address ff:ff:ff:ff:ff:ff, false otherwise.
|
||||
func (efrm Frame) IsBroadcast() bool {
|
||||
return efrm.buf[0] == 0xff && efrm.buf[1] == 0xff && efrm.buf[2] == 0xff &&
|
||||
efrm.buf[3] == 0xff && efrm.buf[4] == 0xff && efrm.buf[5] == 0xff
|
||||
}
|
||||
|
||||
// SourceHardwareAddr returns the sender's MAC/hardware address of the ethernet packet.
|
||||
func (efrm Frame) SourceHardwareAddr() (src *[6]byte) {
|
||||
return (*[6]byte)(efrm.buf[6:12])
|
||||
}
|
||||
|
||||
// EtherTypeOrSize returns the EtherType/Size field of the ethernet packet.
|
||||
// Caller should check if the field is actually a valid EtherType or if it represents the Ethernet payload size with [EtherType.IsSize].
|
||||
func (efrm Frame) EtherTypeOrSize() Type {
|
||||
return Type(binary.BigEndian.Uint16(efrm.buf[12:14]))
|
||||
}
|
||||
|
||||
// SetEtherType sets the EtherType field of the ethernet packet. See [EtherType] and [Frame.EtherTypeOrSize].
|
||||
func (efrm Frame) SetEtherType(v Type) {
|
||||
binary.BigEndian.PutUint16(efrm.buf[12:14], uint16(v))
|
||||
}
|
||||
|
||||
// VLANTag returns the VLAN tag field following the TPID=0x8100. See [VLANTag]. Call [Frame.ValidateSize] to ensure this function does not panic.
|
||||
func (efrm Frame) VLANTag() VLANTag { return VLANTag(binary.BigEndian.Uint16(efrm.buf[14:16])) }
|
||||
|
||||
// SetVLANTag sets the VLAN tag field of the Ethernet Header. See [VLANTag]. Call [Frame.ValidateSize] to ensure this function does not panic.
|
||||
func (efrm Frame) SetVLANTag(vt VLANTag) { binary.BigEndian.PutUint16(efrm.buf[14:16], uint16(vt)) }
|
||||
|
||||
// VLANEtherType returns the [EtherType] for a VLAN ethernet frame (octet position 16). Call [Frame.ValidateSize] to ensure this function does not panic.
|
||||
func (efrm Frame) VLANEtherType() Type {
|
||||
return Type(binary.BigEndian.Uint16(efrm.buf[16:18]))
|
||||
}
|
||||
|
||||
// SetVLANEtherType sets the [EtherType] for a VLAN ethernet frame (octet position 16). Call [Frame.ValidateSize] to ensure this function does not panic.
|
||||
func (efrm Frame) SetVLANEtherType(vt Type) {
|
||||
binary.BigEndian.PutUint16(efrm.buf[16:18], uint16(vt))
|
||||
}
|
||||
|
||||
// IsVLAN returns true if the SizeOrEtherType is set to the VLAN tag 0x8100. This
|
||||
// indicates the EthernetHeader is invalid as-is and instead of EtherType the field
|
||||
// contains the first two octets of a 4 octet 802.1Q VLAN tag. In this case 4 more bytes
|
||||
// must be read from the wire, of which the last 2 of these bytes contain the actual
|
||||
// SizeOrEtherType field, which needs to be validated yet again in case the packet is
|
||||
// a VLAN double-tap packet.
|
||||
func (efrm Frame) IsVLAN() bool {
|
||||
return efrm.EtherTypeOrSize() == TypeVLAN
|
||||
}
|
||||
|
||||
// ClearHeader zeros out the fixed(non-variable) header contents.
|
||||
func (frm Frame) ClearHeader() {
|
||||
for i := range frm.buf[:sizeHeaderNoVLAN] {
|
||||
frm.buf[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Validation API.
|
||||
//
|
||||
|
||||
var (
|
||||
errShort = errors.New("ethernet: too short")
|
||||
errShortVLAN = errors.New("ethernet: short VLAN")
|
||||
)
|
||||
|
||||
// ValidateSize checks the frame's size fields and compares with the actual buffer
|
||||
// the frame. It returns a non-nil error on finding an inconsistency.
|
||||
func (efrm Frame) ValidateSize(v *lneto2.Validator) {
|
||||
sz := efrm.EtherTypeOrSize()
|
||||
if sz.IsSize() && len(efrm.buf) < int(sz) {
|
||||
v.AddError(errShort)
|
||||
}
|
||||
if sz == TypeVLAN && len(efrm.buf) < 18 {
|
||||
v.AddError(errShortVLAN)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// Code generated by "stringer -type=Type -linecomment -output stringers.go ."; DO NOT EDIT.
|
||||
|
||||
package ethernet
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[TypeIPv4-2048]
|
||||
_ = x[TypeARP-2054]
|
||||
_ = x[TypeWakeOnLAN-2114]
|
||||
_ = x[TypeTRILL-8947]
|
||||
_ = x[TypeDECnetPhase4-24579]
|
||||
_ = x[TypeRARP-32821]
|
||||
_ = x[TypeAppleTalk-32923]
|
||||
_ = x[TypeAARP-33011]
|
||||
_ = x[TypeIPX1-33079]
|
||||
_ = x[TypeIPX2-33080]
|
||||
_ = x[TypeQNXQnet-33284]
|
||||
_ = x[TypeIPv6-34525]
|
||||
_ = x[TypeEthernetFlowControl-34824]
|
||||
_ = x[TypeIEEE802_3-34825]
|
||||
_ = x[TypeCobraNet-34841]
|
||||
_ = x[TypeMPLSUnicast-34887]
|
||||
_ = x[TypeMPLSMulticast-34888]
|
||||
_ = x[TypePPPoEDiscovery-34915]
|
||||
_ = x[TypePPPoESession-34916]
|
||||
_ = x[TypeJumboFrames-34928]
|
||||
_ = x[TypeHomePlug1_0MME-34939]
|
||||
_ = x[TypeIEEE802_1X-34958]
|
||||
_ = x[TypePROFINET-34962]
|
||||
_ = x[TypeHyperSCSI-34970]
|
||||
_ = x[TypeAoE-34978]
|
||||
_ = x[TypeEtherCAT-34980]
|
||||
_ = x[TypeEthernetPowerlink-34987]
|
||||
_ = x[TypeLLDP-35020]
|
||||
_ = x[TypeSERCOS3-35021]
|
||||
_ = x[TypeHomePlugAVMME-35041]
|
||||
_ = x[TypeMRP-35043]
|
||||
_ = x[TypeIEEE802_1AE-35045]
|
||||
_ = x[TypeIEEE1588-35063]
|
||||
_ = x[TypeIEEE802_1ag-35074]
|
||||
_ = x[TypeFCoE-35078]
|
||||
_ = x[TypeFCoEInit-35092]
|
||||
_ = x[TypeRoCE-35093]
|
||||
_ = x[TypeCTP-36864]
|
||||
_ = x[TypeVeritasLLT-51966]
|
||||
_ = x[TypeVLAN-33024]
|
||||
_ = x[TypeServiceVLAN-34984]
|
||||
}
|
||||
|
||||
const _Type_name = "IPv4ARPwake on LANTRILLDECnetPhase4RARPAppleTalkAARPVLANIPx1IPx2QNXQnetIPv6EthernetFlowCtlIEEE802.3CobraNetMPLS UnicastMPLS MulticastPPPoE discoveryPPPoE sessionjumbo frameshome plug 1 0mmeIEEE 802.1xprofinethyper SCSIAoEEtherCATservice VLANEthernet powerlinkLLDPSERCOS3home plug AVMMEMRPIEEE 802.1aeIEEE 1588IEEE 802.1agFCoEFCoE initRoCECTPVeritas LLT"
|
||||
|
||||
var _Type_map = map[Type]string{
|
||||
2048: _Type_name[0:4],
|
||||
2054: _Type_name[4:7],
|
||||
2114: _Type_name[7:18],
|
||||
8947: _Type_name[18:23],
|
||||
24579: _Type_name[23:35],
|
||||
32821: _Type_name[35:39],
|
||||
32923: _Type_name[39:48],
|
||||
33011: _Type_name[48:52],
|
||||
33024: _Type_name[52:56],
|
||||
33079: _Type_name[56:60],
|
||||
33080: _Type_name[60:64],
|
||||
33284: _Type_name[64:71],
|
||||
34525: _Type_name[71:75],
|
||||
34824: _Type_name[75:90],
|
||||
34825: _Type_name[90:99],
|
||||
34841: _Type_name[99:107],
|
||||
34887: _Type_name[107:119],
|
||||
34888: _Type_name[119:133],
|
||||
34915: _Type_name[133:148],
|
||||
34916: _Type_name[148:161],
|
||||
34928: _Type_name[161:173],
|
||||
34939: _Type_name[173:189],
|
||||
34958: _Type_name[189:200],
|
||||
34962: _Type_name[200:208],
|
||||
34970: _Type_name[208:218],
|
||||
34978: _Type_name[218:221],
|
||||
34980: _Type_name[221:229],
|
||||
34984: _Type_name[229:241],
|
||||
34987: _Type_name[241:259],
|
||||
35020: _Type_name[259:263],
|
||||
35021: _Type_name[263:270],
|
||||
35041: _Type_name[270:285],
|
||||
35043: _Type_name[285:288],
|
||||
35045: _Type_name[288:300],
|
||||
35063: _Type_name[300:309],
|
||||
35074: _Type_name[309:321],
|
||||
35078: _Type_name[321:325],
|
||||
35092: _Type_name[325:334],
|
||||
35093: _Type_name[334:338],
|
||||
36864: _Type_name[338:341],
|
||||
51966: _Type_name[341:352],
|
||||
}
|
||||
|
||||
func (i Type) String() string {
|
||||
if str, ok := _Type_map[i]; ok {
|
||||
return str
|
||||
}
|
||||
return "Type(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
Reference in New Issue
Block a user