mirror of
https://github.com/soypat/lneto.git
synced 2026-08-20 22:49:11 +00:00
remove legacy remnants and move ip,udp,ethernet logic into subpackages
This commit is contained in:
+1
-118
@@ -1,115 +1,6 @@
|
||||
package lneto2
|
||||
|
||||
//go:generate stringer -type=EtherType,IPProto,ARPOp -linecomment -output stringers.go .
|
||||
|
||||
type EtherType uint16
|
||||
|
||||
// IsSize returns true if the EtherType is actually the size of the payload
|
||||
// and should NOT be interpreted as an EtherType.
|
||||
func (et EtherType) IsSize() bool { return et <= 1500 }
|
||||
|
||||
// Ethernet type flags
|
||||
const (
|
||||
EtherTypeIPv4 EtherType = 0x0800 // IPv4
|
||||
EtherTypeARP EtherType = 0x0806 // ARP
|
||||
EtherTypeWakeOnLAN EtherType = 0x0842 // wake on LAN
|
||||
EtherTypeTRILL EtherType = 0x22F3 // TRILL
|
||||
EtherTypeDECnetPhase4 EtherType = 0x6003 // DECnetPhase4
|
||||
EtherTypeRARP EtherType = 0x8035 // RARP
|
||||
EtherTypeAppleTalk EtherType = 0x809B // AppleTalk
|
||||
EtherTypeAARP EtherType = 0x80F3 // AARP
|
||||
EtherTypeIPX1 EtherType = 0x8137 // IPx1
|
||||
EtherTypeIPX2 EtherType = 0x8138 // IPx2
|
||||
EtherTypeQNXQnet EtherType = 0x8204 // QNXQnet
|
||||
EtherTypeIPv6 EtherType = 0x86DD // IPv6
|
||||
EtherTypeEthernetFlowControl EtherType = 0x8808 // EthernetFlowCtl
|
||||
EtherTypeIEEE802_3 EtherType = 0x8809 // IEEE802.3
|
||||
EtherTypeCobraNet EtherType = 0x8819 // CobraNet
|
||||
EtherTypeMPLSUnicast EtherType = 0x8847 // MPLS Unicast
|
||||
EtherTypeMPLSMulticast EtherType = 0x8848 // MPLS Multicast
|
||||
EtherTypePPPoEDiscovery EtherType = 0x8863 // PPPoE discovery
|
||||
EtherTypePPPoESession EtherType = 0x8864 // PPPoE session
|
||||
EtherTypeJumboFrames EtherType = 0x8870 // jumbo frames
|
||||
EtherTypeHomePlug1_0MME EtherType = 0x887B // home plug 1 0mme
|
||||
EtherTypeIEEE802_1X EtherType = 0x888E // IEEE 802.1x
|
||||
EtherTypePROFINET EtherType = 0x8892 // profinet
|
||||
EtherTypeHyperSCSI EtherType = 0x889A // hyper SCSI
|
||||
EtherTypeAoE EtherType = 0x88A2 // AoE
|
||||
EtherTypeEtherCAT EtherType = 0x88A4 // EtherCAT
|
||||
EtherTypeEthernetPowerlink EtherType = 0x88AB // Ethernet powerlink
|
||||
EtherTypeLLDP EtherType = 0x88CC // LLDP
|
||||
EtherTypeSERCOS3 EtherType = 0x88CD // SERCOS3
|
||||
EtherTypeHomePlugAVMME EtherType = 0x88E1 // home plug AVMME
|
||||
EtherTypeMRP EtherType = 0x88E3 // MRP
|
||||
EtherTypeIEEE802_1AE EtherType = 0x88E5 // IEEE 802.1ae
|
||||
EtherTypeIEEE1588 EtherType = 0x88F7 // IEEE 1588
|
||||
EtherTypeIEEE802_1ag EtherType = 0x8902 // IEEE 802.1ag
|
||||
EtherTypeFCoE EtherType = 0x8906 // FCoE
|
||||
EtherTypeFCoEInit EtherType = 0x8914 // FCoE init
|
||||
EtherTypeRoCE EtherType = 0x8915 // RoCE
|
||||
EtherTypeCTP EtherType = 0x9000 // CTP
|
||||
EtherTypeVeritasLLT EtherType = 0xCAFE // Veritas LLT
|
||||
EtherTypeVLAN EtherType = 0x8100 // VLAN
|
||||
EtherTypeServiceVLAN EtherType = 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 }
|
||||
|
||||
// IPToS represents the Traffic Class (a.k.a Type of Service).
|
||||
type IPToS uint8
|
||||
|
||||
// DS returns the top 6 bits of the IPv4 ToS holding the Differentiated Services field
|
||||
// which is used to classify packets.
|
||||
func (tos IPToS) DS() uint8 { return uint8(tos) >> 2 }
|
||||
|
||||
// ECN is the Explicit Congestion Notification which provides congestion control and non-congestion control traffic.
|
||||
func (tos IPToS) ECN() uint8 { return uint8(tos & 0b11) }
|
||||
|
||||
// IPv4Flags holds fragmentation field data of an IPv4 header.
|
||||
type IPv4Flags uint16
|
||||
|
||||
// IsEvil returns true if evil bit set as per [RFC3514].
|
||||
//
|
||||
// [RFC3514]: https://datatracker.ietf.org/doc/html/rfc3514
|
||||
func (f IPv4Flags) IsEvil() bool { return f&2000 != 0 }
|
||||
|
||||
// DontFragment specifies whether the datagram can not be fragmented.
|
||||
// This can be used when sending packets to a host that does not have resources to perform reassembly of fragments.
|
||||
// If the DontFragment(DF) flag is set, and fragmentation is required to route the packet, then the packet is dropped.
|
||||
func (f IPv4Flags) DontFragment() bool { return f&0x4000 != 0 }
|
||||
|
||||
// MoreFragments is cleared for unfragmented packets.
|
||||
// For fragmented packets, all fragments except the last have the MF flag set.
|
||||
// The last fragment has a non-zero Fragment Offset field, so it can still be differentiated from an unfragmented packet.
|
||||
func (f IPv4Flags) MoreFragments() bool { return f&0x8000 != 0 }
|
||||
|
||||
// FragmentOffset specifies the offset of a particular fragment relative to the beginning of the original unfragmented IP datagram.
|
||||
// Fragments are specified in units of 8 bytes, which is why fragment lengths are always a multiple of 8; except the last, which may be smaller.
|
||||
// The fragmentation offset value for the first fragment is always 0.
|
||||
func (f IPv4Flags) FragmentOffset() uint16 { return uint16(f) & 0x1fff }
|
||||
|
||||
const (
|
||||
sizeHeaderIPv4 = 20
|
||||
sizeHeaderTCP = 20
|
||||
sizeHeaderEthNoVLAN = 14
|
||||
sizeHeaderUDP = 8
|
||||
sizeHeaderARPv4 = 28
|
||||
sizeHeaderIPv6 = 40
|
||||
)
|
||||
//go:generate stringer -type=IPProto -linecomment -output stringers.go .
|
||||
|
||||
// IPProto represents the IP protocol number.
|
||||
type IPProto uint8
|
||||
@@ -258,11 +149,3 @@ const (
|
||||
IPProtoAGGFRAG IPProto = 144 // AGGFRAG Encapsulation payload for ESP
|
||||
IPProtoNSH IPProto = 145 // Network Service Header
|
||||
)
|
||||
|
||||
// ARPOp represents the type of ARP packet, either request or reply/response.
|
||||
type ARPOp uint8
|
||||
|
||||
const (
|
||||
ARPRequest ARPOp = 1 // request
|
||||
ARPReply ARPOp = 2 // reply
|
||||
)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package lneto2_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/soypat/lneto/ethernet"
|
||||
"github.com/soypat/lneto/internal/ltesto"
|
||||
"github.com/soypat/lneto/ipv4"
|
||||
"github.com/soypat/lneto/tcp"
|
||||
)
|
||||
|
||||
func TestTCPMarshalUnmarshal(t *testing.T) {
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
var gen ltesto.PacketGen
|
||||
gen.RandomizeAddrs(rng)
|
||||
const maxSize = 4096
|
||||
src := make([]byte, maxSize)
|
||||
dst := make([]byte, maxSize)
|
||||
for i := 0; i < 512; i++ {
|
||||
src = gen.AppendRandomIPv4TCPPacket(src[:0], rng, tcp.Segment{
|
||||
SEQ: tcp.Value(rng.Int()),
|
||||
ACK: tcp.Value(rng.Int()),
|
||||
DATALEN: tcp.Size(rng.Intn(256)),
|
||||
WND: tcp.Size(rng.Intn(1024)),
|
||||
Flags: tcp.FlagACK,
|
||||
})
|
||||
dst = dst[:len(src)]
|
||||
testMoveTCPPacket(t, src, dst)
|
||||
if !bytes.Equal(src, dst) {
|
||||
t.Fatal("mismatching data")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testMoveTCPPacket(t *testing.T, src, dst []byte) {
|
||||
if len(src) != len(dst) {
|
||||
panic("expect src and dst same length")
|
||||
}
|
||||
efrm, err := ethernet.NewFrame(src)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
epl := efrm.Payload()
|
||||
ifrm, err := ipv4.NewFrame(epl)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ipl := ifrm.Payload()
|
||||
tfrm, err := tcp.NewFrame(ipl)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
efrm2, _ := ethernet.NewFrame(dst)
|
||||
*efrm2.DestinationHardwareAddr() = *efrm.DestinationHardwareAddr()
|
||||
*efrm2.SourceHardwareAddr() = *efrm.SourceHardwareAddr()
|
||||
efrm2.SetEtherType(efrm.EtherTypeOrSize())
|
||||
if efrm.EtherTypeOrSize() == ethernet.TypeVLAN {
|
||||
efrm2.SetVLANTag(efrm.VLANTag())
|
||||
efrm2.SetVLANEtherType(efrm.VLANEtherType())
|
||||
}
|
||||
|
||||
ifrm2, _ := ipv4.NewFrame(efrm2.Payload())
|
||||
ifrm2.SetVersionAndIHL(ifrm.VersionAndIHL())
|
||||
ifrm2.SetToS(ifrm.ToS())
|
||||
ifrm2.SetFlags(ifrm.Flags())
|
||||
ifrm2.SetTotalLength(ifrm.TotalLength())
|
||||
ifrm2.SetID(ifrm.ID())
|
||||
ifrm2.SetTTL(ifrm.TTL())
|
||||
ifrm2.SetProtocol(ifrm.Protocol())
|
||||
ifrm2.SetCRC(ifrm.CRC())
|
||||
*ifrm2.SourceAddr() = *ifrm.SourceAddr()
|
||||
*ifrm2.DestinationAddr() = *ifrm.DestinationAddr()
|
||||
|
||||
tfrm2, _ := tcp.NewFrame(ifrm2.Payload())
|
||||
tfrm2.SetSourcePort(tfrm.SourcePort())
|
||||
tfrm2.SetDestinationPort(tfrm.DestinationPort())
|
||||
tfrm2.SetSeq(tfrm.Seq())
|
||||
tfrm2.SetAck(tfrm.Ack())
|
||||
tfrm2.SetOffsetAndFlags(tfrm.OffsetAndFlags())
|
||||
tfrm2.SetWindowSize(tfrm.WindowSize())
|
||||
tfrm2.SetCRC(tfrm.CRC())
|
||||
tfrm2.SetUrgentPtr(tfrm.UrgentPtr())
|
||||
|
||||
copy(ifrm2.Options(), ifrm.Options())
|
||||
copy(tfrm2.Options(), tfrm.Options())
|
||||
copy(tfrm2.Payload(), tfrm.Payload())
|
||||
|
||||
elen := efrm.HeaderLength()
|
||||
if !bytes.Equal(src[:elen], dst[:elen]) {
|
||||
t.Fatalf("Ethernet header mismatch\n%x\n%x", src[:elen], dst[:elen])
|
||||
}
|
||||
ilen := ifrm.HeaderLength()
|
||||
if !bytes.Equal(src[elen:elen+20], dst[elen:elen+20]) {
|
||||
t.Fatalf("IPv4 header mismatch\n%x\n%x", src[elen:elen+20], dst[elen:elen+20])
|
||||
}
|
||||
ipoptLen := len(ifrm.Options())
|
||||
if !bytes.Equal(ifrm.Options(), ifrm2.Options()) {
|
||||
t.Fatalf("IPv4 options mismatch\n%x\n%x", ifrm.Options(), ifrm2.Options())
|
||||
} else if ipoptLen > 0 && &ifrm.Options()[0] != &src[elen+20] {
|
||||
t.Fatal("IPv4 options start pointer mismatch")
|
||||
}
|
||||
|
||||
tlen := tfrm.HeaderLength()
|
||||
toff := elen + ilen + ipoptLen
|
||||
if !bytes.Equal(src[toff:toff+tlen], dst[toff:toff+tlen]) {
|
||||
t.Fatalf("TCP header mismatch\n%x\n%x", src[toff:toff+tlen], dst[toff:toff+tlen])
|
||||
}
|
||||
payload := tfrm.Payload()
|
||||
|
||||
if !bytes.Equal(payload, tfrm2.Payload()) {
|
||||
t.Fatalf("payload mismatch %d %d", len(payload), len(tfrm2.Payload()))
|
||||
}
|
||||
}
|
||||
+1
-119
@@ -1,108 +1,9 @@
|
||||
// Code generated by "stringer -type=EtherType,IPProto,ARPOp -linecomment -output stringers.go ."; DO NOT EDIT.
|
||||
// Code generated by "stringer -type=IPProto -linecomment -output stringers.go ."; DO NOT EDIT.
|
||||
|
||||
package lneto2
|
||||
|
||||
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[EtherTypeIPv4-2048]
|
||||
_ = x[EtherTypeARP-2054]
|
||||
_ = x[EtherTypeWakeOnLAN-2114]
|
||||
_ = x[EtherTypeTRILL-8947]
|
||||
_ = x[EtherTypeDECnetPhase4-24579]
|
||||
_ = x[EtherTypeRARP-32821]
|
||||
_ = x[EtherTypeAppleTalk-32923]
|
||||
_ = x[EtherTypeAARP-33011]
|
||||
_ = x[EtherTypeIPX1-33079]
|
||||
_ = x[EtherTypeIPX2-33080]
|
||||
_ = x[EtherTypeQNXQnet-33284]
|
||||
_ = x[EtherTypeIPv6-34525]
|
||||
_ = x[EtherTypeEthernetFlowControl-34824]
|
||||
_ = x[EtherTypeIEEE802_3-34825]
|
||||
_ = x[EtherTypeCobraNet-34841]
|
||||
_ = x[EtherTypeMPLSUnicast-34887]
|
||||
_ = x[EtherTypeMPLSMulticast-34888]
|
||||
_ = x[EtherTypePPPoEDiscovery-34915]
|
||||
_ = x[EtherTypePPPoESession-34916]
|
||||
_ = x[EtherTypeJumboFrames-34928]
|
||||
_ = x[EtherTypeHomePlug1_0MME-34939]
|
||||
_ = x[EtherTypeIEEE802_1X-34958]
|
||||
_ = x[EtherTypePROFINET-34962]
|
||||
_ = x[EtherTypeHyperSCSI-34970]
|
||||
_ = x[EtherTypeAoE-34978]
|
||||
_ = x[EtherTypeEtherCAT-34980]
|
||||
_ = x[EtherTypeEthernetPowerlink-34987]
|
||||
_ = x[EtherTypeLLDP-35020]
|
||||
_ = x[EtherTypeSERCOS3-35021]
|
||||
_ = x[EtherTypeHomePlugAVMME-35041]
|
||||
_ = x[EtherTypeMRP-35043]
|
||||
_ = x[EtherTypeIEEE802_1AE-35045]
|
||||
_ = x[EtherTypeIEEE1588-35063]
|
||||
_ = x[EtherTypeIEEE802_1ag-35074]
|
||||
_ = x[EtherTypeFCoE-35078]
|
||||
_ = x[EtherTypeFCoEInit-35092]
|
||||
_ = x[EtherTypeRoCE-35093]
|
||||
_ = x[EtherTypeCTP-36864]
|
||||
_ = x[EtherTypeVeritasLLT-51966]
|
||||
_ = x[EtherTypeVLAN-33024]
|
||||
_ = x[EtherTypeServiceVLAN-34984]
|
||||
}
|
||||
|
||||
const _EtherType_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 _EtherType_map = map[EtherType]string{
|
||||
2048: _EtherType_name[0:4],
|
||||
2054: _EtherType_name[4:7],
|
||||
2114: _EtherType_name[7:18],
|
||||
8947: _EtherType_name[18:23],
|
||||
24579: _EtherType_name[23:35],
|
||||
32821: _EtherType_name[35:39],
|
||||
32923: _EtherType_name[39:48],
|
||||
33011: _EtherType_name[48:52],
|
||||
33024: _EtherType_name[52:56],
|
||||
33079: _EtherType_name[56:60],
|
||||
33080: _EtherType_name[60:64],
|
||||
33284: _EtherType_name[64:71],
|
||||
34525: _EtherType_name[71:75],
|
||||
34824: _EtherType_name[75:90],
|
||||
34825: _EtherType_name[90:99],
|
||||
34841: _EtherType_name[99:107],
|
||||
34887: _EtherType_name[107:119],
|
||||
34888: _EtherType_name[119:133],
|
||||
34915: _EtherType_name[133:148],
|
||||
34916: _EtherType_name[148:161],
|
||||
34928: _EtherType_name[161:173],
|
||||
34939: _EtherType_name[173:189],
|
||||
34958: _EtherType_name[189:200],
|
||||
34962: _EtherType_name[200:208],
|
||||
34970: _EtherType_name[208:218],
|
||||
34978: _EtherType_name[218:221],
|
||||
34980: _EtherType_name[221:229],
|
||||
34984: _EtherType_name[229:241],
|
||||
34987: _EtherType_name[241:259],
|
||||
35020: _EtherType_name[259:263],
|
||||
35021: _EtherType_name[263:270],
|
||||
35041: _EtherType_name[270:285],
|
||||
35043: _EtherType_name[285:288],
|
||||
35045: _EtherType_name[288:300],
|
||||
35063: _EtherType_name[300:309],
|
||||
35074: _EtherType_name[309:321],
|
||||
35078: _EtherType_name[321:325],
|
||||
35092: _EtherType_name[325:334],
|
||||
35093: _EtherType_name[334:338],
|
||||
36864: _EtherType_name[338:341],
|
||||
51966: _EtherType_name[341:352],
|
||||
}
|
||||
|
||||
func (i EtherType) String() string {
|
||||
if str, ok := _EtherType_map[i]; ok {
|
||||
return str
|
||||
}
|
||||
return "EtherType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
@@ -289,22 +190,3 @@ func (i IPProto) String() string {
|
||||
return "IPProto(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
}
|
||||
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[ARPRequest-1]
|
||||
_ = x[ARPReply-2]
|
||||
}
|
||||
|
||||
const _ARPOp_name = "requestreply"
|
||||
|
||||
var _ARPOp_index = [...]uint8{0, 7, 12}
|
||||
|
||||
func (i ARPOp) String() string {
|
||||
i -= 1
|
||||
if i >= ARPOp(len(_ARPOp_index)-1) {
|
||||
return "ARPOp(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||
}
|
||||
return _ARPOp_name[_ARPOp_index[i]:_ARPOp_index[i+1]]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user