funcNewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {returnnewHandle(ns, netns.None(), nlFamilies...)}// NewHandleAtFrom works as NewHandle but allows client to specify the// new and the origin netns Handle.funcNewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {returnnewHandle(newNs, curNs)}funcnewHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) { h :=&Handle{sockets: map[int]*nl.SocketHandle{}} fams := nl.SupportedNlFamiliesiflen(nlFamilies) !=0 { fams = nlFamilies }for _, f :=range fams { s, err := nl.GetNetlinkSocketAt(newNs, curNs, f)if err !=nil {returnnil, err } h.sockets[f] =&nl.SocketHandle{Socket: s} }return h, nil}
Add Interface
Bridge Network
Create Network
根据配置文件中 BridgeName 查找系统中已存在的 Link 实例,如果 BridgeName 为空,使用默认网桥 docker0。
funcnewInterface(nlh *netlink.Handle, config *networkConfiguration) (*bridgeInterface, error) {var err error i :=&bridgeInterface{nlh: nlh}// Initialize the bridge name to the default if unspecified.if config.BridgeName =="" { config.BridgeName = DefaultBridgeName }// Attempt to find an existing bridge named with the specified name. i.Link, err = nlh.LinkByName(config.BridgeName)if err !=nil { logrus.Debugf("Did not find any interface with name %s: %v", config.BridgeName, err) } elseif _, ok := i.Link.(*netlink.Bridge); !ok {returnnil, fmt.Errorf("existing interface %s is not a bridge", i.Link.Attrs().Name) }return i, nil}
创建 bridgeNetwork 实例,并存入 networks
// Create and set network handler in drivernetwork :=&bridgeNetwork{ id: config.ID, endpoints: make(map[string]*bridgeEndpoint), config: config, portMapper: portmapper.New(d.config.UserlandProxyPath), bridge: bridgeIface, driver: d,}d.Lock()d.networks[config.ID] = networkd.Unlock()
bridgeAlreadyExists := bridgeIface.exists()if!bridgeAlreadyExists { bridgeSetup.queueStep(setupDevice) bridgeSetup.queueStep(setupDefaultSysctl)}// For the default bridge, set expected sysctlsif config.DefaultBridge { bridgeSetup.queueStep(setupDefaultSysctl)}
根据配置文件参数,将对应的设置方法加入设置队列
for _, step :=range []struct { Condition bool Fn setupStep}{// Enable IPv6 on the bridge if required. We do this even for a// previously existing bridge, as it may be here from a previous// installation where IPv6 wasn't supported yet and needs to be// assigned an IPv6 link-local address. {config.EnableIPv6, setupBridgeIPv6},// We ensure that the bridge has the expectedIPv4 and IPv6 addresses in// the case of a previously existing device. {bridgeAlreadyExists &&!config.InhibitIPv4, setupVerifyAndReconcile},// Enable IPv6 Forwarding {enableIPv6Forwarding, setupIPv6Forwarding},// Setup Loopback Addresses Routing {!d.config.EnableUserlandProxy, setupLoopbackAddressesRouting},// Setup IPTables. {d.config.EnableIPTables, network.setupIPTables},//We want to track firewalld configuration so that//if it is started/reloaded, the rules can be applied correctly {d.config.EnableIPTables, network.setupFirewalld},// Setup DefaultGatewayIPv4 {config.DefaultGatewayIPv4 !=nil, setupGatewayIPv4},// Setup DefaultGatewayIPv6 {config.DefaultGatewayIPv6 !=nil, setupGatewayIPv6},// Add inter-network communication rules. {d.config.EnableIPTables, setupNetworkIsolationRules},//Configure bridge networking filtering if ICC is off and IP tables are enabled {!config.EnableICC && d.config.EnableIPTables, setupBridgeNetFiltering},} {if step.Condition { bridgeSetup.queueStep(step.Fn) }}
创建 netlink.Bridge 结构体,LinkAttrs 中使用配置中的 BridgeName,然后,使用 netlink 方法创建网桥设备,如果需要设置 MAC 则随机生成 MAC 地址。
funcsetupDevice(config *networkConfiguration, i *bridgeInterface) error {var setMac bool// We only attempt to create the bridge when the requested device name is// the default one.if config.BridgeName != DefaultBridgeName && config.DefaultBridge {returnNonDefaultBridgeExistError(config.BridgeName) }// Set the bridgeInterface netlink.Bridge. i.Link =&netlink.Bridge{ LinkAttrs: netlink.LinkAttrs{ Name: config.BridgeName, }, }// Only set the bridge's MAC address if the kernel version is > 3.3, as it// was not supported before that. kv, err := kernel.GetKernelVersion()if err !=nil { logrus.Errorf("Failed to check kernel versions: %v. Will not assign a MAC address to the bridge interface", err)
} else { setMac = kv.Kernel >3|| (kv.Kernel ==3&& kv.Major >=3) }if setMac { hwAddr := netutils.GenerateRandomMAC() i.Link.Attrs().HardwareAddr = hwAddr logrus.Debugf("Setting bridge mac address to %s", hwAddr) }if err = i.nlh.LinkAdd(i.Link); err !=nil { logrus.Debugf("Failed to create bridge %s via netlink. Trying ioctl", config.BridgeName)returnioctlCreateBridge(config.BridgeName, setMac) }return err}