1. 程式人生 > >Network Protocol Breakdown: Ethernet and Go

Network Protocol Breakdown: Ethernet and Go

Network Protocol Breakdown: Ethernet and Go

If you’re reading this article right now, chances are pretty good that there’s an Ethernet (IEEE 802.3) link somewhere between your device and the server hosting this blog. The Ethernet family of networking technologies are a fundamental building block in many of today’s computer networks.

There is a great deal to be said about how Ethernet works at the physical level, but this post will focus on Ethernet II frames (“Ethernet frames”): the Layer 2 frames that enable communication between two machines over an Ethernet link.

This post will break down the structure of Ethernet II frames in detail, explaining the significance of each item within the frame. We will also discuss how to make use of Ethernet frames in the Go programming language, using .

Introduction to Ethernet frames

The fundamental unit of Layer 2 data transmission for Ethernet networks is an Ethernet frame. The frame’s structure is rather straightforward, compared to some more complex protocols built on top of it.

The first two fields in an Ethernet frame are the destination and source MAC addresses. A

MAC address is a unique identifier for a network interface on given Layer 2 network segment. Ethernet MAC addresses are 48 bits (6 bytes) in length.

The destination address indicates the MAC address of the network interface which should receive a given frame. In some cases, this may be the Ethernet broadcast address: FF:FF:FF:FF:FF:FF. Some protocols, such as ARP, send frames with a broadcast destination in order to send a message to all machines on a given network segment. When a network switch receives a frame with the broadcast address, it duplicates the frame to each port attached to the switch.

The source address indicates the MAC address of the network interface which sent the frame. This enables other machines on the network to identify and reply to messages received from this machine.

The next field is a 16 bit integer called the EtherType. The EtherType indicates which protocol is encapsulated in the payload portion of a given frame. Some typical examples include Layer 3 protocols such as ARP, IPv4, and IPv6.

The payload of an Ethernet frame can contain anywhere from 46 to 1500 (or more!) bytes of data, depending on how the machines on a Layer 2 network segment are configured. The payload can carry arbitrary data, including the headers for Layer 3 and above protocols (which may even encapsulate traffic at higher layers).

The last element of an Ethernet frame is the frame check sequence (“FCS”): a CRC32 checksum using the IEEE polynomial which enables detection of corrupted data within the frame. Once the frame is assembled, the checksum is computed and stored in the final 4 bytes of the frame. Typically, this is done automatically by the operating system or network interface, but in some circumstances, it is necessary to compute the FCS in userspace software.

Crafting an Ethernet frame in Go

Using the package, Ethernet frames can be created in Go and used to send and receive data over a network.

In this example, we will create a frame that carries a minimal “hello world” payload with a custom EtherType. The frame will be broadcast to all machines on the same Layer 2 network segment, using the Ethernet broadcast address: FF:FF:FF:FF:FF:FF.

// The frame to be sent over the network.
f := &ethernet.Frame{
// Broadcast frame to all machines on same network segment.
Destination: ethernet.Broadcast,
    // Identify our machine as the sender.
Source: net.HardwareAddr{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad},
    // Identify frame with an unused EtherType.
EtherType: 0xcccc,
    // Send a simple message.
Payload: []byte("hello world"),
}
// Marshal the Go representation of a frame to
// the Ethernet frame format.
b, err := f.MarshalBinary()
if err != nil {
log.Fatalf("failed to marshal frame: %v", err)
}
// Send the marshaled frame to the network.
sendEthernetFrame(b)

As mentioned earlier, the operating system or network interface will typically handle the FCS calculation for the Ethernet frame. In unusual cases where this cannot be done automatically, ethernet.Frame.MarshalFCS can be invoked to append a calculated FCS to the marshaled frame.

Introduction to VLAN tags

If you’ve worked with computer networks in the past, you may be familiar with the concept of a VLAN: a Virtual LAN segment. VLANs (IEEE 802.1Q) enable splitting a single network segment into many different segments, through clever re-use of the EtherType field in an Ethernet frame.

When a VLAN tag is added, the 16 bit EtherType field becomes the Tag Protocol Identifier field. This indicates that a VLAN tag is present, using a reserved EtherType value such as 0x8100.

When a VLAN tag is present, the 16 bits immediately following it designate three fields:

  • Priority (3 bits): an IEEE P8021.p class of service level.
  • Drop Eligible Indicator (DEI; formerly CFI) (1 bit): indicates if a frame may be dropped in the presence of network congestion.
  • VLAN ID (VID) (12 bits): specifies the VLAN to which the frame belongs. Each VID creates a unique network segment.

After the VLAN tag, the EtherType which indicates the encapsulated traffic is present, as normal.

In some circumstances, multiple VLAN tags may be present (IEEE 802.1ad, also known as “Q-in-Q”). As an example, this enables an internet provider to encapsulate a customer’s traffic in a single VLAN, while the customer may also encapsulate their own traffic in many different VLANs.

Specifying VLAN tags for Ethernet frames in Go

Often, the network interface will take care of VLAN tagging for Ethernet frames, but in some circumstances, it can be useful to apply this tag in software as well. Let’s specify a VLAN tag manually, using the frame from our prior example.

// The frame to be sent over the network.
f := &ethernet.Frame{
// Broadcast frame to all machines on same network segment.
Destination: ethernet.Broadcast,
    // Identify our machine as the sender.
Source: net.HardwareAddr{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad},
    // Tag traffic to VLAN 10. If needed, multiple tags
// can be applied for Q-in-Q.
VLAN: []*ethernet.VLAN{{
ID: 10,
}},
    // Identify frame with an unused EtherType.
EtherType: 0xcccc,
    // Send a simple message.
Payload: []byte("hello world"),
}

In my (admittedly limited) experience, the Priority and DEI fields in the VLAN tag are not generally needed. If in doubt, leave them set to zero.

Sending and receiving Ethernet frames over the network

Most network applications typically build upon TCP or UDP, but since Ethernet frames operate at a much lower level in the stack, some special APIs and permissions are required to make use of them directly.

These APIs are typically referred to as “raw sockets” (or “packet sockets” on Linux). These low level sockets enable sending and receiving Ethernet frames directly, using elevated privileges from the operating system.

On Linux and BSD, can be used to send and receive Ethernet frames over a network interface. Here’s an example that shows how to broadcast our crafted Ethernet frame with its “hello world” message:

// Select the eth0 interface to use for Ethernet traffic.
ifi, err := net.InterfaceByName("eth0")
if err != nil {
log.Fatalf("failed to open interface: %v", err)
}
// Open a raw socket using same EtherType as our frame.
c, err := raw.ListenPacket(ifi, 0xcccc)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
defer c.Close()
// Marshal a frame to its binary format.
f := newEthernetFrame("hello world")
b, err := f.MarshalBinary()
if err != nil {
log.Fatalf("failed to marshal frame: %v", err)
}
// Broadcast the frame to all devices on our network segment.
addr := &raw.Addr{HardwareAddr: ethernet.Broadcast}
if _, err := c.WriteTo(b, addr); err != nil {
log.Fatalf("failed to write frame: %v", err)
}

On a different machine, we can use a similar program to listen for incoming Ethernet frames using our specified EtherType.

// Select the eth0 interface to use for Ethernet traffic.
ifi, err := net.InterfaceByName("eth0")
if err != nil {
log.Fatalf("failed to open interface: %v", err)
}
// Open a raw socket using same EtherType as our frame.
c, err := raw.ListenPacket(ifi, 0xcccc)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
defer c.Close()
// Accept frames up to interface's MTU in size.
b := make([]byte, ifi.MTU)
var f ethernet.Frame
// Keep reading frames.
for {
n, addr, err := c.ReadFrom(b)
if err != nil {
log.Fatalf("failed to receive message: %v", err)
}
    // Unpack Ethernet frame into Go representation.
if err := (&f).UnmarshalBinary(b[:n]); err != nil {
log.Fatalf("failed to unmarshal ethernet frame: %v", err)
}
    // Display source of message and message itself.
log.Printf("[%s] %s", addr.String(), string(f.Payload))
}

That’s it! If you’d like to give this a try at home and have two or more Linux or BSD machines available, you can try out my demo binary.

Summary

Low-level networking primitives like Ethernet frames and raw sockets are very powerful. Using these primitives, you can have complete control over the traffic sent and received by your application.

If you find these types of programs as exciting as I do, I highly encourage you to take my and raw packages for a spin. In future posts, I’ll discuss some of the protocols you can build directly on top of Ethernet frames and raw sockets.

Thank you very much for reading this post. I hope you’ve enjoyed it and learned something new along the way. If you have, you may also be interested in some of my other posts about using low-level networking primitives with the Go programming language.

Finally, if you have questions or comments, feel free to reach out via the comments, Twitter, or Gophers Slack (username: mdlayher).

Thanks again for your time!

Links

References

相關推薦

Network Protocol Breakdown: Ethernet and Go

Network Protocol Breakdown: Ethernet and GoIf you’re reading this article right now, chances are pretty good that there’s an Ethernet (IEEE 802.3) link som

Network Protocol Breakdown: NDP and Go

An introduction to NDPNDP is specified in IETF RFC 4861. In many ways, NDP is the spiritual successor to ARP for IPv6. It is used to help computers find th

19 Error handling and Go

art internal acc writer generate cloud inspect new distinct Error handling and Go 12 July 2011 Introduction If you have written any Go c

21 JSON and Go

with pick pat change nco previous lar ont mes JSON and Go 25 January 2011 Introduction JSON (JavaScript Object Notation) is a simple dat

論文閱讀筆記《Gated Context Aggregation Network for Image Dehazing and Deraining》WACV19

輸出 每一個 為什麽 作用 導致 作者 ont 而不是 簡單的 目錄: 相關鏈接 方法亮點 方法細節 實驗結果 總結與收獲 相關鏈接: 論文:https://arxiv.org/abs/1811.08747 源碼:暫無 方法亮點: 提出端到端的去霧網絡,不

【文藝學生】Learning with exploration, and go ahead with learning. Let's progress together! :)

文藝學生 Learning with exploration, and go ahead with learning. Let's progress together! :)

Namespaces and Go Part 1

Linux provides the following namespaces and we will see how we can demonstrate these with Go Namespace Constant Isolates Cgroup

Namespaces and Go Part 3

In Part 2 we executed a shell with modified hostname using UTS namespace. In this article, we will explain how we can use PID and Mount namespaces. By is

Namespaces and Go Part 2

In Part 1 of Namespace article series ,we were unable to set hostname from a shell even though the user was root That program was missing UTS namespace w

Building a Network Command Line Interface in Go

In this article, we are going to be building a very simple Command Line Interface in Go using the urfave/cli package available on Github here: http

Writing a Frontend Web Framework with WebAssembly And Go

JavaScript Frontend frameworks have undoubtedly helped to push the boundaries of what was previously possible in the context of a browser. Ever mor

論文閱讀:Deep MANTA: A Coarse-to-fine Many-Task Network for joint 2D and 3D vehicle analysis

這篇論文是在2017年3月22日發表在CVPR上的,作者在這篇論文中提出了一個叫做深度從粗糙到精細化的多工卷積神經網路(Deep MANTA),該模型可以用於對一張圖片中的車輛進行多工的分析。該網路同時執行的多工包括:車輛檢測、部件定位、可見性描述和三維形

Error handling and Go

12 July 2011 Introduction If you have written any Go code you have probably encountered the built-in error type.

Version Constraints and Go

Constants, Variables, Build Tags, oh my!At this point our code is failing to build, which means we’ve met the minimum requirements to prevent our code to b

Linux, Netlink, and Go — Part 2: generic netlink

Linux, Netlink, and Go — Part 2: generic netlinkIn Part 1 of this series, I described some of the fundamental concepts of netlink sockets, messages, and at

Linux, Netlink, and Go — Part 1: netlink

Linux, Netlink, and Go — Part 1: netlinkI’m a big fan of Prometheus. I use it quite a lot at both home and work, and greatly enjoy having insight into what

11838 Come and Go && UVA

連結 :  11838 :求一張圖可否任意兩點可達 。直接判斷整個圖是否強連通。 #pragma comment(linker, "/STACK:10240000,10240000") #include <algorithm> #include &l

Chapter 1 Securing Your Server and Network(7):禁用SQL Server Browse

tcp/ip blog splay 響應 otto 屬性 you src 安裝 原文出處:http://blog.csdn.net/dba_huangzj/article/details/38227187,專題文件夾:http://blog.csdn.net/dba_hu

Mastering the game of Go with deep neural networks and tree search

深度 策略 參數初始化 技術 以及 -1 簡單 cpu 網絡 Silver, David, et al. "Mastering the game of Go with deep neural networks and tree search." Nature 529.758

Network subsystem Of Linux Performance and Tuning Guidelines

network subsystem linux網絡子系統本文出自 “庭前夜末空看雪” 博客,請務必保留此出處http://12550795.blog.51cto.com/12540795/1946086Network subsystem Of Linux Performance and Tuning Guid