在 Linux 系统中可以使用命令行工具来创建和测试 VXLAN 网络
- 确定物理网卡
首先要明确 VXLAN 隧道所基于的物理网卡,一般可以使用 ip addr 命令查看当前系统的网络接口信息。例如,假设物理网卡名为 eth0。 创建 VXLAN 接口
ip link add vxlan100 type vxlan id 100 dev eth0 dstport 4789
- vxlan100:这是新创建的 VXLAN 接口的名称,你可以根据需求自定义。
- id 100:指定 VXLAN 的网络标识符(VNI)为 100,VNI 用于区分不同的 VXLAN 网络,取值范围是 0 - 16777215。
- dev eth0:指定 VXLAN 隧道所基于的物理网卡为 eth0。
- dstport 4789:指定 VXLAN 数据包使用的目的 UDP 端口为 4789,这是 VXLAN 的标准端口。
- 启用 VXLAN 接口
ip link set up vxlan100
- 配置 IP 地址
ip addr add 192.168.100.1/24 dev vxlan100
测试 VXLAN 网络
# 创建 VXLAN 接口
ip link add vxlan100 type vxlan id 100 dev eth0 dstport 4789
# 启用 VXLAN 接口
ip link set up vxlan100
# 配置 IP 地址
ip addr add 192.168.100.2/24 dev vxlan100
测试连通性
ping 192.168.100.2
端口检查
ss -uln | grep 4789
数据传输测试
nc -u -l 8080
echo "Hello, VXLAN!" | nc -u 192.168.100.1 8080
go的代码实现
- 安装依赖
go get github.com/vishvananda/netlink
- 创建 VXLAN 接口及配置 IP 地址
package main
import (
"fmt"
"github.com/vishvananda/netlink"
"net"
)
func createVXLAN() error {
// 定义 VXLAN 接口名称和 VNI
vxlanName := "vxlan0"
vxlanID := uint32(100)
// 假设物理网卡为 eth0,可根据实际情况修改
parentIfaceName := "eth0"
// 获取物理网卡信息
parentIface, err := netlink.LinkByName(parentIfaceName)
if err != nil {
return fmt.Errorf("failed to get parent interface: %w", err)
}
// 创建 VXLAN 接口配置
vxlan := &netlink.Vxlan{
LinkAttrs: netlink.LinkAttrs{
Name: vxlanName,
},
VxlanId: vxlanID,
Port: 4789,
Learning: true,
Group: nil,
TTL: 64,
Ageing: 300,
Limit: 0,
PortLow: 0,
PortHigh: 0,
Parent: parentIface,
}
// 添加 VXLAN 接口
err = netlink.LinkAdd(vxlan)
if err != nil {
return fmt.Errorf("failed to add VXLAN interface: %w", err)
}
fmt.Printf("VXLAN interface %s created successfully.\n", vxlanName)
// 启用 VXLAN 接口
err = netlink.LinkSetUp(vxlan)
if err != nil {
return fmt.Errorf("failed to bring up VXLAN interface: %w", err)
}
fmt.Printf("VXLAN interface %s is up.\n", vxlanName)
// 配置 IP 地址
ipAddr, err := netlink.ParseAddr("192.168.100.1/24")
if err != nil {
return fmt.Errorf("failed to parse IP address: %w", err)
}
err = netlink.AddrAdd(vxlan, ipAddr)
if err != nil {
return fmt.Errorf("failed to add IP address to VXLAN interface: %w", err)
}
fmt.Printf("IP address %s added to VXLAN interface %s.\n", ipAddr.IPNet, vxlanName)
return nil
}
- 实现数据收发功能
// 服务器端
func server() {
// 监听本地地址和端口
localAddr, err := net.ResolveUDPAddr("udp", "192.168.100.1:8080")
if err != nil {
fmt.Printf("Failed to resolve local address: %v\n", err)
return
}
conn, err := net.ListenUDP("udp", localAddr)
if err != nil {
fmt.Printf("Failed to listen on UDP socket: %v\n", err)
return
}
defer conn.Close()
fmt.Println("Listening on UDP socket...")
buffer := make([]byte, 1024)
n, addr, err := conn.ReadFromUDP(buffer)
if err != nil {
fmt.Printf("Failed to read from UDP socket: %v\n", err)
return
}
fmt.Printf("Received %d bytes from %s: %s\n", n, addr, string(buffer[:n]))
// 发送响应
response := []byte("Hello, client!")
_, err = conn.WriteToUDP(response, addr)
if err != nil {
fmt.Printf("Failed to send response to UDP client: %v\n", err)
return
}
fmt.Println("Response sent to client.")
}
// 客户端
func client() {
serverAddr, err := net.ResolveUDPAddr("udp", "192.168.100.1:8080")
if err != nil {
fmt.Printf("Failed to resolve server address: %v\n", err)
return
}
conn, err := net.DialUDP("udp", nil, serverAddr)
if err != nil {
fmt.Printf("Failed to connect to server: %v\n", err)
return
}
defer conn.Close()
message := []byte("Hello from client!")
_, err = conn.Write(message)
if err != nil {
fmt.Printf("Failed to send message: %v\n", err)
return
}
buffer := make([]byte, 1024)
n, _, err := conn.ReadFromUDP(buffer)
if err != nil {
fmt.Printf("Failed to receive response: %v\n", err)
return
}
fmt.Printf("Received response: %s\n", string(buffer[:n]))
}
- 主函数调用
func main() {
err := createVXLAN()
if err != nil {
fmt.Println(err)
return
}
// 启动服务器
go server()
// 启动客户端
client()
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。