MCPcopy
hub / github.com/opencontainers/runc / devChangeNetNamespace

Function devChangeNetNamespace

libcontainer/network_linux.go:113–232  ·  view source on GitHub ↗

devChangeNetNamespace allows to move a device given by name to a network namespace given by nsPath and optionally change the device name. The device name will be kept the same if device.Name is the zero value. This function ensures that the move and rename operations occur atomically. It preserves e

(name, nsPath string, device configs.LinuxNetDevice)

Source from the content-addressed store, hash-verified

111// This function ensures that the move and rename operations occur atomically.
112// It preserves existing interface attributes, including global IP addresses.
113func devChangeNetNamespace(name, nsPath string, device configs.LinuxNetDevice) error {
114 logrus.Debugf("attaching network device %s with attrs %+v to network namespace %s", name, device, nsPath)
115 link, err := netlink.LinkByName(name)
116 // recover same behavior on vishvananda/netlink@1.2.1 and do not fail when the kernel returns NLM_F_DUMP_INTR.
117 if err != nil && !errors.Is(err, netlink.ErrDumpInterrupted) {
118 return fmt.Errorf("link not found for interface %s on runtime namespace: %w", name, err)
119 }
120
121 // Set the interface link state to DOWN before modifying attributes like namespace or name.
122 // This prevents potential conflicts or disruptions on the host network during the transition,
123 // particularly if other host components depend on this specific interface or its properties.
124 err = netlink.LinkSetDown(link)
125 if err != nil {
126 return fmt.Errorf("fail to set link down: %w", err)
127 }
128
129 // Get the existing IP addresses on the interface.
130 addresses, err := netlink.AddrList(link, netlink.FAMILY_ALL)
131 // recover same behavior on vishvananda/netlink@1.2.1 and do not fail when the kernel returns NLM_F_DUMP_INTR.
132 if err != nil && !errors.Is(err, netlink.ErrDumpInterrupted) {
133 return fmt.Errorf("fail to get ip addresses: %w", err)
134 }
135
136 // Do interface rename and namespace change in the same operation to avoid
137 // possible conflicts with the interface name.
138 // NLM_F_REQUEST: "It must be set on all request messages."
139 // NLM_F_ACK: "Request for an acknowledgment on success."
140 // netlink(7) man page: https://man7.org/linux/man-pages/man7/netlink.7.html
141 flags := unix.NLM_F_REQUEST | unix.NLM_F_ACK
142 req := nl.NewNetlinkRequest(unix.RTM_NEWLINK, flags)
143
144 // Get a netlink socket in current namespace
145 nlSock, err := nl.GetNetlinkSocketAt(netns.None(), netns.None(), unix.NETLINK_ROUTE)
146 if err != nil {
147 return fmt.Errorf("could not get network namespace handle: %w", err)
148 }
149 defer nlSock.Close()
150
151 req.Sockets = map[int]*nl.SocketHandle{
152 unix.NETLINK_ROUTE: {Socket: nlSock},
153 }
154
155 // Set the interface index.
156 msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
157 msg.Index = int32(link.Attrs().Index)
158 req.AddData(msg)
159
160 // Set the interface name, also rename if requested.
161 newName := name
162 if device.Name != "" {
163 newName = device.Name
164 }
165 nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(newName))
166 req.AddData(nameData)
167
168 // Get the new network namespace.
169 ns, err := netns.GetFromPath(nsPath)
170 if err != nil {

Callers 1

setupNetworkDevicesMethod · 0.85

Calls 2

CloseMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…