setup_device_linux.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package bridge
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "github.com/containerd/log"
  8. "github.com/docker/docker/libnetwork/netutils"
  9. "github.com/vishvananda/netlink"
  10. )
  11. // SetupDevice create a new bridge interface/
  12. func setupDevice(config *networkConfiguration, i *bridgeInterface) error {
  13. // We only attempt to create the bridge when the requested device name is
  14. // the default one. The default bridge name can be overridden with the
  15. // DOCKER_TEST_CREATE_DEFAULT_BRIDGE env var. It should be used only for
  16. // test purpose.
  17. var defaultBridgeName string
  18. if defaultBridgeName = os.Getenv("DOCKER_TEST_CREATE_DEFAULT_BRIDGE"); defaultBridgeName == "" {
  19. defaultBridgeName = DefaultBridgeName
  20. }
  21. if config.BridgeName != defaultBridgeName && config.DefaultBridge {
  22. return NonDefaultBridgeExistError(config.BridgeName)
  23. }
  24. // Set the bridgeInterface netlink.Bridge.
  25. i.Link = &netlink.Bridge{
  26. LinkAttrs: netlink.LinkAttrs{
  27. Name: config.BridgeName,
  28. },
  29. }
  30. // Set the bridge's MAC address. Requires kernel version 3.3 or up.
  31. hwAddr := netutils.GenerateRandomMAC()
  32. i.Link.Attrs().HardwareAddr = hwAddr
  33. log.G(context.TODO()).Debugf("Setting bridge mac address to %s", hwAddr)
  34. if err := i.nlh.LinkAdd(i.Link); err != nil {
  35. log.G(context.TODO()).WithError(err).Errorf("Failed to create bridge %s via netlink", config.BridgeName)
  36. return err
  37. }
  38. return nil
  39. }
  40. func setupMTU(config *networkConfiguration, i *bridgeInterface) error {
  41. if err := i.nlh.LinkSetMTU(i.Link, config.Mtu); err != nil {
  42. log.G(context.TODO()).WithError(err).Errorf("Failed to set bridge MTU %s via netlink", config.BridgeName)
  43. return err
  44. }
  45. return nil
  46. }
  47. func setupDefaultSysctl(config *networkConfiguration, i *bridgeInterface) error {
  48. // Disable IPv6 router advertisements originating on the bridge
  49. sysPath := filepath.Join("/proc/sys/net/ipv6/conf/", config.BridgeName, "accept_ra")
  50. if _, err := os.Stat(sysPath); err != nil {
  51. log.G(context.TODO()).
  52. WithField("bridge", config.BridgeName).
  53. WithField("syspath", sysPath).
  54. Info("failed to read ipv6 net.ipv6.conf.<bridge>.accept_ra")
  55. return nil
  56. }
  57. if err := os.WriteFile(sysPath, []byte{'0', '\n'}, 0o644); err != nil {
  58. log.G(context.TODO()).WithError(err).Warn("unable to disable IPv6 router advertisement")
  59. }
  60. return nil
  61. }
  62. // SetupDeviceUp ups the given bridge interface.
  63. func setupDeviceUp(config *networkConfiguration, i *bridgeInterface) error {
  64. err := i.nlh.LinkSetUp(i.Link)
  65. if err != nil {
  66. return fmt.Errorf("Failed to set link up for %s: %v", config.BridgeName, err)
  67. }
  68. // Attempt to update the bridge interface to refresh the flags status,
  69. // ignoring any failure to do so.
  70. if lnk, err := i.nlh.LinkByName(config.BridgeName); err == nil {
  71. i.Link = lnk
  72. } else {
  73. log.G(context.TODO()).Warnf("Failed to retrieve link for interface (%s): %v", config.BridgeName, err)
  74. }
  75. return nil
  76. }