Netlink
概述
参考:
Netlink 是 Linux 中的用户空间程序用来与内核进行通信的界面。它可以用于添加和删除接口,设置 ip 地址和路由以及配置 ipsec。
vishvananda/netlink
Netlink 通信需要提升的权限,因此在大多数情况下,此代码需要以 root 用户身份运行。由于低级 netlink 消息充其量是难以理解的,因此该库试图提供一个以 iproute2 提供的 CLI 为松散建模的 api。ip 链接添加之类的操作将通过类似名称的函数 (例如 AddLink()) 来完成。该库的生命开始于 docker/libcontainer 中的 netlink 功能分支,但经过大量重写以提高可测试性,性能并添加 ipsec xfrm 处理等新功能。
Hello World
package main
import (
"fmt"
"github.com/vishvananda/netlink"
)
func main() {
// 实例化一个 LinkAttrs,LinkAttrs 包含一个网络设备的绝大部分属性
linkAttrs := netlink.NewLinkAttrs()
// 设定 link 的名称
linkAttrs.Name = "br0"
// 将实例化的 LinkAttrs 信息赋值给 Bridge 结构体
mybridge := &netlink.Bridge{LinkAttrs: linkAttrs}
// 这里就算真正完成了一个网络设备的定义,netlink 库中包含多种网络设备结构体
// 每种网络设备结构体都实现了 Link 接口
// Link 接口只有两个方法,Attrs() 用来返回 LinkAttrs 结构体,Type() 用来返回该网络设备的类型。
// 而对各种类型的网络设备实现增删改查的函数,其接受的参数就是 Link 接口类型
// 所以 Link 接口的主要作用,就是用来区分不同类型的网络设备,以便可以在调用时统一。对网络设备的任何操作,都可以将 Link 接口作为参数互相传递。
// 使用 Bridge 结构体的信息创建一个网络设备
err := netlink.LinkAdd(mybridge)
if err != nil {
fmt.Printf("could not add %s: %v\n", linkAttrs.Name, err)
}
// eth1, _ := netlink.LinkByName("eth1")
// netlink.LinkSetMaster(eth1, mybridge)
}
实践
package main
import (
"fmt"
"github.com/vishvananda/netlink"
)
// addBridge 创建一个桥设备
func addBridge() *netlink.Bridge {
// 实例化一个 LinkAttrs,LinkAttrs 结构体包含一个网络设备的绝大部分属性。
linkAttrs := netlink.NewLinkAttrs()
// 设定 link 的名称
linkAttrs.Name = "br0"
// 将实例化的 link 信息赋值给 Bridge 结构体
myBridge := &netlink.Bridge{
LinkAttrs: linkAttrs,
}
// 使用 Bridge 结构体的信息创建一个 link
err := netlink.LinkAdd(myBridge)
if err != nil {
fmt.Printf("could not add %s: %v\n", linkAttrs.Name, err)
}
return myBridge
}
// addVeth 创建一个 veth 设备
func addVeth() *netlink.Veth {
// 实例化一个 LinkAttrs,LinkAttrs 结构体包含一个网络设备的绝大部分属性。
linkAttrs := netlink.NewLinkAttrs()
// 设定 link 的名称
linkAttrs.Name = "veth1.1"
// 将实例化的 link 信息赋值给 Veth 结构体,veth 必须指定对端设备
myVeth := &netlink.Veth{
LinkAttrs: linkAttrs,
PeerName: "veth1.2",
}
// 使用 Veth 结构体的信息创建一个 link
err := netlink.LinkAdd(myVeth)
if err != nil {
fmt.Printf("could not add %s: %v\n", linkAttrs.Name, err)
}
return myVeth
}
func main() {
// 增
// 添加 veth 和 bridge 设备,并将 veth 设备附加到 bridge 设备上。
if err := netlink.LinkSetMaster(addVeth(), addBridge()); err != nil {
fmt.Println("设置网络设备主从关系出错,原因:", err)
}
// 删除 veth 和 bridge 设备
br0, _ := netlink.LinkByName("br0")
veth, _ := netlink.LinkByName("veth1.1")
netlink.LinkDel(br0)
netlink.LinkDel(veth)
// 改
// 查
// 实例化一个 Handle,相当于在当前名称空间中创建一个 Socket 句柄。
// 呼叫者可以指定句柄应支持的netlink族。如果未指定族,则将自动添加netlink软件包支持的所有族。
handle, _ := netlink.NewHandle()
// 获取所有网络设备,等效于 `ip link show` 命令
links, _ := handle.LinkList()
// 输出网络设备信息
for _, link := range links {
fmt.Printf("设备名称为:%v\n", link.Attrs().Name)
// 获取一个网络设备的 IP 地址
addrs, _ := netlink.AddrList(link, 0)
for index, addr := range addrs {
fmt.Printf("%v 设备的第 %v 个 IP 地址为:%v\n", link.Attrs().Name, index+1, addr.IP)
}
}
}
反馈
此页是否对你有帮助?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.