Layer 2 and Layer 3 protocols of switches and their detailed solutions

Overview

A switch is a type of network device, which is mainly used to connect multiple network devices to realize network communication and data transmission. The protocol of the switch is divided into two-layer and three-layer protocols.

Layer 2 protocol

Layer 2 protocols are also called data link layer protocols, common ones include:

  • Ethernet Protocol: Ethernet is a widely used local area network (LAN) technology that defines how to transmit data at the physical layer and the data link layer.
  • Token Ring Protocol: Token Ring is another LAN technology that uses a token passing mechanism to control access to the network and prevent conflicts and collisions.
  • MAC-Based Switching Protocol (MAC-Based Switching Protocol): A protocol for switching based on MAC addresses, which can improve the efficiency of data packet forwarding.

Layer 3 protocol

The three-layer protocol is also called the network layer protocol, and the common ones include:

  • IP protocol (Internet Protocol): IP is the basic protocol of data communication on the Internet, which is used to transmit data packets from source address to destination address.
  • ARP protocol (Address Resolution Protocol): The ARP protocol is used to resolve the mapping relationship between MAC addresses and IP addresses so that data packets can be correctly sent to the target device.
  • ICMP protocol (Internet Control Message Protocol): ICMP protocol is used for network error detection and diagnosis. For example, the ping command is implemented using ICMP protocol.
  • OSPF protocol (Open Shortest Path First): OSPF is a routing protocol used to select the shortest path among multiple available paths for data packet transmission.

Ethernet protocol

Ethernet is a local area network protocol that defines how computers communicate on a local area network. Here are some detailed descriptions of the Ethernet protocol:

physical layer
The Ethernet physical layer defines the characteristics of cables, connectors, and signals. Commonly used Ethernet cables include twisted pair, coaxial cable, and optical fiber, and connectors include RJ45, BNC, and SC.

data link layer
The Ethernet data link layer consists of two sublayers: the Logical Link Control (LLC) sublayer and the Media Access Control (MAC) sublayer. The LLC sublayer provides a unified interface that enables upper-layer protocols to communicate with different types of networks. The MAC sublayer is the core of the Ethernet protocol, which defines how to send data frames to the LAN.

data frame format
The data frame of the Ethernet protocol consists of the following parts:

Preamble: Used to synchronize the data frame clock.
Destination address and source address: Each Ethernet adapter has a unique MAC address, which is used to identify the sender and receiver of the data packet.
Type/Length Field: Specifies the type or length of the data in the data frame.
Data section: The actual data in the data frame.
Frame Check Sequence (FCS): It is used to detect whether there is an error in the data frame during transmission.
MAC address
Every Ethernet adapter has a unique MAC address, which consists of 6 bytes, usually expressed as 12 hexadecimal digits. The first three bytes represent the vendor ID, and the last three bytes represent the serial number of the adapter.

data transmission
In Ethernet, the data transmission adopts the CSMA/CD protocol, that is, the carrier sense multipoint access/collision detection protocol. When a node wants to send data, it first listens to the network, and if no other nodes are sending data, it can send data. If two nodes send data at the same time causing a collision, they stop sending and wait a random amount of time before retrying sending data.

The above are some detailed descriptions of the Ethernet protocol, which provides a reliable communication method for the local area network.

Example code

Here’s a simple Ethernet protocol example implemented in Python that includes frame generation, parsing, and sending:

python
copy code

import struct

# generate ethernet frame
def create_ethernet_frame(dest_mac, src_mac, data):
    # Ethernet frame format: destination MAC address + source MAC address + type + data + checksum
    frame = struct.pack("!6s6sH", dest_mac, src_mac, len(data)) + data
    return frame

# parse ethernet frame
def parse_ethernet_frame(frame):
    dest_mac, src_mac, length = struct.unpack("!6s6sH", frame[:14])
    data = frame[14:]
    return (dest_mac, src_mac, length, data)

# send ethernet frame

```bash
def send_ethernet_frame(frame):
    print("Sending ethernet frame:", frame)

# test code
def test():
    dest_mac = b"\x00\x11\x22\x33\x44\x55"
    src_mac = b"\x66\x77\x88\x99\xaa\xbb"
    data = b"Hello, world!"
    # generate frame
    frame = create_ethernet_frame(dest_mac, src_mac, data)
    print("Created ethernet frame:", frame)
    # parse frame
    dest_mac, src_mac, length, data = parse_ethernet_frame(frame)
    print("Parsed ethernet frame: dest_mac =", dest_mac.hex(), ", src_mac =", src_mac.hex(), ", length =", length, ", data =" , data)
    # send frame
    send_ethernet_frame(frame)

test()

In the above code,
The create_ethernet_frame() function generates an Ethernet frame that includes the destination MAC address, source MAC address, data length, and data.
The parse_ethernet_frame() function parses an Ethernet frame and returns the destination MAC address, source MAC address, data length and data. The send_ethernet_frame() function is used to send Ethernet frames.
We used Python’s struct module to handle packing and unpacking of binary data. In the create_ethernet_frame() function, we use the struct.pack() function to pack the various fields of the Ethernet frame into a binary string, and then stitch them together to get a complete Ethernet frame. In the parse_ethernet_frame() function, we use the struct.unpack() function to unpack the fields of the Ethernet frame and return their values.

In the test() function, we generate an Ethernet frame containing the destination MAC address, source MAC address and data, and print it out. Then, we parse the Ethernet frame and print out the parsed result. Finally, we send this Ethernet frame, and print it out.

Note that the above code is just a simple example, it does not implement the full Ethernet protocol. If you need to use the Ethernet protocol in a real project, please use a more complete and reliable implementation.

CSMA/CD protocol

CSMA/CD is a multi-point access protocol for local area networks, which is used to control collisions when multiple nodes send data at the same time. Below are some detailed descriptions of the CSMA/CD protocol, as well as a simple Python code example:

Carrier Sense (CS)
When a node wants to send data, it first listens to the network to see if other nodes are sending data. If there is no data transmission on the network, the node can start sending data.

Collision Detection (CD)
If two or more nodes start sending data at the same time, they will collide on the network. When a node detects a collision on the network, it stops sending data and waits a random amount of time before retrying.

backoff algorithm
The backoff algorithm is used to prevent nodes from sending data again at the same time when a network conflict occurs. Each node waits a random amount of time before resending data to reduce the chance of collisions.

Example code

Here is an example of a simple CSMA/CD algorithm implemented in Python, which includes carrier sense, collision detection, and backoff algorithms:

import random

# Carrier Sense
def cs(listening):
    if listening:
        print("No other nodes transmitting data, start transmitting...")
    else:
        print("Network is busy, wait until idle.")

# Impact checking
def cd():
    print("Collision detected, stop transmitting and wait for random time...")
    # Generate a random number between 1-10
    random_time = random.randint(1, 10)
    print("Wait for", random_time, "seconds before retrying...")

# backoff algorithm
def backoff(time):
    print("Wait for another", time, "seconds before retrying...")
    # generate a longer wait time
    new_time = 2 * time
    return new_time

# test data transfer
def test():
    # generate a random 0 or 1
    node1 = random. randint(0, 1)
    node2 = random. randint(0, 1)
    # If neither node 1 nor node 2 is sending data, start sending data
    if node1 == 0 and node2 == 0:
        cs(True)
    # If only one node is sending data, the node can continue to send data
    elif node1 == 0:
        cs(False)
    elif node2 == 0:
        cs(False)
    # Collision occurs if both nodes are sending data
    else:
        cd()
        # After waiting for a random time, use the backoff algorithm to calculate the next waiting time
        time = backoff(random. randint(1, 10))
        # Wait for the next time period and try sending data again
        test(time)

test()

In the above code, the test() function simulates the situation when two nodes transmit data, including carrier sense, collision detection and backoff calculation.

IP protocol

The IP (Internet Protocol) protocol is one of the basic protocols for data transmission on the Internet, and it is mainly responsible for the transmission and routing of data packets.

The IP protocol is a connectionless and unreliable protocol. It only provides the most basic data transmission service without any data transmission guarantee. During the data transmission process, the IP protocol ensures that the data can reach the destination by adding the source address and destination address to the data packet. This process is called routing.

The address of the IP protocol is a 32-bit number, usually written as 4 numbers, and each number is separated by a dot. For example: 192.168.0.1.

The IP protocol defines how to send a data packet from the source address to the destination address. During this process, the intermediate router will decide how to forward the data packet according to the destination address in the data packet. If the router cannot determine the routing path for the packet, it sends the packet to the default gateway.

The IP protocol can also expand its functions through some options. For example, the IP protocol can support different transmission protocols (such as TCP, UDP, ICMP, etc.) through the protocol number field. The IP protocol can also use some flag fields to support functions such as packet fragmentation, reassembly, and time stamping.

Generally speaking, the IP protocol is one of the basic protocols of the Internet. It provides data transmission and routing services, and provides basic services for high-level protocols.

Example code

The following is a simple example of the IP protocol implemented in Python, including the generation, parsing and sending of packets:

import struct
import socket

# Generate IP packets
def create_ip_packet(source_ip, dest_ip, data):
    # IP packet format: version + header length + differentiated services + total length + identification + flag + slice offset + time to live + protocol + checksum + source IP address + destination IP address + data
    version = 4
    ihl = 5
    tos = 0
    total_length = len(data) + 20
    identification = 0
    flags = 0
    fragment_offset = 0
    ttl = 255
    protocol = socket.IPPROTO_TCP
    header_checksum = 0
    ip_header = struct.pack("!BBHHHBBH4s4s", (version << 4) + ihl, tos, total_length, identification, (flags << 13) + fragment_offset, ttl, protocol, header_checksum, socket.inet_aton(source_ip), socket.inet_aton(dest_ip))
    header_checksum = calculate_checksum(ip_header)
    ip_header = struct.pack("!BBHHHBBH4s4s", (version << 4) + ihl, tos, total_length, identification, (flags << 13) + fragment_offset, ttl, protocol, header_checksum, socket.inet_aton(source_ip), socket.inet_aton(dest_ip))
    packet = ip_header + data
    return packet

# parse IP packets
def parse_ip_packet(packet):
    ip_header = packet[:20]
    version_ihl, tos, total_length, identification, flags_fragment_offset, ttl, protocol, header_checksum, source_ip, dest_ip = struct.unpack("!BBHHHBBH4s4s", ip_header)
    version = version_ihl >> 4
    ihl = version_ihl & 0x0f
    flags = flags_fragment_offset >> 13
    fragment_offset = flags

ip_header_length = ihl * 4
data = packet[ip_header_length:]
return version, ihl, tos, total_length, identification, flags, fragment_offset, ttl, protocol, header_checksum, socket.inet_ntoa(source_ip), socket.inet_ntoa(dest_ip), data
Calculate IP packet header checksum
def calculate_checksum(header):
length = len(header)
if length % 2 == 1:
header + = b'\0'
length + = 1
checksum = 0
for i in range(0, length, 2):
word = (header[i] << 8) + header[i + 1]
checksum += word
while checksum >> 16:
checksum = (checksum & amp; 0xffff) + (checksum >> 16)
checksum = ~checksum & 0xffff
return checksum

Send IP packets
def send_ip_packet(packet, dest_ip):
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s. sendto(packet, (dest_ip, 0))

Test IP protocol code
def test():
source_ip = "192.168.1.100"
dest_ip = "192.168.1.1"
data = b"Hello, world!"
packet = create_ip_packet(source_ip, dest_ip, data)
print("IP packet:", packet)
version, ihl, tos, total_length, identification, flags, fragment_offset, ttl, protocol, header_checksum, source_ip, dest_ip, data = parse_ip_packet(packet)
print("Version:", version)
print("IHL:", ihl)
print("TOS:", tos)
print("Total Length:", total_length)
print("Identification:", identification)
print("Flags:", flags)
print("Fragment Offset:", fragment_offset)
print("TTL:", ttl)
print("Protocol:", protocol)
print("Header Checksum:", header_checksum)
print("Source IP:", source_ip)
print("Destination IP:", dest_ip)
print("Data:", data)
send_ip_packet(packet, dest_ip)
print("Packet sent.")

test()

In the above code, we use Python’s socket module to send and receive IP packets. In the create_ip_packet() function, we first define the value of each field according to the format of the IP packet, and then use the struct.pack() function to pack them into a binary string and calculate the header checksum. Finally, we splice the IP header and data together to get a complete IP packet.

In the parse_ip_packet() function, we use the struct.unpack() function to unpack the various fields of the IP packet and return their values. In the calculate_checksum() function, we calculate the header checksum of the IP packet to ensure the integrity of the packet. In the send_ip_packet() function, we use the raw socket of the socket module to send the IP packet.

In the test() function, we generate an IP packet containing source IP address, destination IP address and data and print it out. Then, we parse the IP packet and print out the parsed result. Finally, we send this IP packet, and