macvlan L2 和 L3 的区别

33 阅读3分钟



  // Layer 2 模式 (macvlan.go:364-380)
  if isLayer3 {
      // ... Layer 3 配置
  } else {
      // Layer 2 模式:只设置接口 UP
      err = netns.Do(func(_ ns.NetNS) error {
          macvlanInterfaceLink, err := netlinksafe.LinkByName(args.IfName)
          if err != nil {
              return fmt.Errorf("failed to find interface name %q: %v", macvlanInterface.Name, err)
          }

          // 只做这一件事:设置 UP
          if err := netlink.LinkSetUp(macvlanInterfaceLink); err != nil {
              return fmt.Errorf("failed to set %q UP: %v", args.IfName, err)
          }

          return nil
      })
  }

  // Layer 3 模式 (macvlan.go:323-363)
  if isLayer3 {
      // 调用 IPAM 获取 IP 配置
      r, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData)

      // 检查必须有 IP
      if len(ipamResult.IPs) == 0 {
          return errors.New("IPAM plugin returned missing IP config")
      }

      // 保存 IP 和路由
      result.IPs = ipamResult.IPs
      result.Routes = ipamResult.Routes

      // 配置 IP 和路由到接口
      err = netns.Do(func(_ ns.NetNS) error {
          return ipam.ConfigureIface(args.IfName, result)
      })
  }





  Layer 2 配置(无 IPAM):
  {
    "cniVersion": "1.0.0",
    "name": "mynet",
    "type": "macvlan",
    "master": "eth0",
    "mode": "bridge"
  }
  结果:容器内有 eth0 接口,但没有 IP 地址

  Layer 3 配置(有 IPAM):
  {
    "cniVersion": "1.0.0",
    "name": "mynet",
    "type": "macvlan",
    "master": "eth0",
    "mode": "bridge",
    "ipam": {
      "type": "host-local",
      "subnet": "10.1.2.0/24",
      "routes": [
        { "dst": "0.0.0.0/0" }
      ]
    }
  }



在 macvlan 的实现中, Layer 2 模式 和 Layer 3 模式 的 macvlan 的网卡有不同之处么? 除了 ip 和路由这些可以后续配置上的东西

⏺ 非常好的问题!让我仔细分析代码中 macvlan 网卡本身的创建过程。


⏺ Read(plugins/main/macvlan/macvlan.go)
  ⎿  Read 100 lines

⏺ 答案:网卡本身完全一样,只有一个配置上的细微差异

看代码执行顺序:

  1. 第 295 行:判断是否是 Layer 3 模式
  2. 第 303 行:创建 macvlan 网卡(在判断 isLayer3 之前!)
  3. 第 323-381 行:根据模式做不同的后续配置

macvlan 网卡本身:完全一样

createMacvlan() 函数(macvlan.go:202-287)创建的 macvlan 设备完全一样,不管是否配置了 IPAM。

创建时只依赖这些参数:

  • Master: 父接口
  • Mode: macvlan 模式(bridge/private/vepa/passthru)
  • MTU: 最大传输单元
  • Mac: MAC 地址(可选)
  • BCQueueLen: 广播队列长度

网卡的内核属性(device type, mode, parent 等)完全相同。

唯一的差异:sysctl 内核参数

虽然网卡本身一样,但 Layer 3 模式会设置额外的内核参数:

  Layer 3 模式(macvlan.go:355-360):
  err = netns.Do(func(_ ns.NetNS) error {
      // 📌 设置 ARP 和 NDP 通知
      _, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1")
      _, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv6/conf/%s/ndisc_notify", args.IfName), "1")

      return ipam.ConfigureIface(args.IfName, result)  // 这里也会设置 UP
  })

  Layer 2 模式(macvlan.go:366-377):
  err = netns.Do(func(_ ns.NetNS) error {
      macvlanInterfaceLink, err := netlinksafe.LinkByName(args.IfName)
      if err != nil {
          return fmt.Errorf("failed to find interface name %q: %v", macvlanInterface.Name, err)
      }

      // 只设置 UP,没有 sysctl 设置
      if err := netlink.LinkSetUp(macvlanInterfaceLink); err != nil {
          return fmt.Errorf("failed to set %q UP: %v", args.IfName, err)
      }

      return nil
  })

这两个 sysctl 参数的作用

net/ipv4/conf//arp_notify = 1:

  • 当 IP 地址配置到接口时,自动发送 Gratuitous ARP(免费 ARP)
  • 让同网段的设备快速更新 ARP 缓存,学习新的 MAC-IP 映射
  • 避免通信延迟(否则需要等待 ARP 超时)

net/ipv6/conf//ndisc_notify = 1:

  • IPv6 的等价功能
  • 发送 Unsolicited Neighbor Advertisement(主动邻居通告)
  • 让 IPv6 网络快速学习新的 MAC-IP 映射

实际影响

你可以验证这个差异:

Layer 2 模式(无 IPAM):

# 容器内查看
$ sysctl net.ipv4.conf.eth1.arp_notify
net.ipv4.conf.eth1.arp_notify = 0  # 默认值

Layer 3 模式(有 IPAM):

容器内查看

 $ sysctl net.ipv4.conf.eth1.arp_notify
 net.ipv4.conf.eth1.arp_notify = 1  # 已设置

但这个差异可以手动补齐

即使是 Layer 2 模式创建的网卡,你后续也可以:

# 手动设置这些参数
sysctl -w net.ipv4.conf.eth1.arp_notify=1
sysctl -w net.ipv6.conf.eth1.ndisc_notify=1

手动配置 IP 和路由

ip addr add 192.168.1.10/24 dev eth1
ip route add default via 192.168.1.1 dev eth1
ip link set eth1 up

最终效果和 Layer 3 模式完全一样。

总结

项目Layer 2 模式Layer 3 模式
macvlan 设备本身✅ 完全相同✅ 完全相同
device typemacvlanmacvlan
mode/parent/MTU✅ 相同✅ 相同
arp_notify0(默认)1
ndisc_notify0(默认)1
IP 地址有(IPAM 分配)
路由有(IPAM 提供)
接口状态UPUP

结论:除了两个 sysctl 内核参数(arp_notify 和 ndisc_notify),macvlan 网卡设备本身没有任何区别。这两个参数也只是配置层面的优化,可以后续手动设置。