github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/osl/interface_linux.go (about) 1 package osl 2 3 import ( 4 "fmt" 5 "net" 6 "regexp" 7 "sync" 8 "syscall" 9 "time" 10 11 log "github.com/Sirupsen/logrus" 12 "github.com/docker/libnetwork/ns" 13 "github.com/docker/libnetwork/types" 14 "github.com/vishvananda/netlink" 15 "github.com/vishvananda/netns" 16 ) 17 18 // IfaceOption is a function option type to set interface options 19 type IfaceOption func(i *nwIface) 20 21 type nwIface struct { 22 srcName string 23 dstName string 24 master string 25 dstMaster string 26 mac net.HardwareAddr 27 address *net.IPNet 28 addressIPv6 *net.IPNet 29 ipAliases []*net.IPNet 30 llAddrs []*net.IPNet 31 routes []*net.IPNet 32 bridge bool 33 ns *networkNamespace 34 sync.Mutex 35 } 36 37 func (i *nwIface) SrcName() string { 38 i.Lock() 39 defer i.Unlock() 40 41 return i.srcName 42 } 43 44 func (i *nwIface) DstName() string { 45 i.Lock() 46 defer i.Unlock() 47 48 return i.dstName 49 } 50 51 func (i *nwIface) DstMaster() string { 52 i.Lock() 53 defer i.Unlock() 54 55 return i.dstMaster 56 } 57 58 func (i *nwIface) Bridge() bool { 59 i.Lock() 60 defer i.Unlock() 61 62 return i.bridge 63 } 64 65 func (i *nwIface) Master() string { 66 i.Lock() 67 defer i.Unlock() 68 69 return i.master 70 } 71 72 func (i *nwIface) MacAddress() net.HardwareAddr { 73 i.Lock() 74 defer i.Unlock() 75 76 return types.GetMacCopy(i.mac) 77 } 78 79 func (i *nwIface) Address() *net.IPNet { 80 i.Lock() 81 defer i.Unlock() 82 83 return types.GetIPNetCopy(i.address) 84 } 85 86 func (i *nwIface) AddressIPv6() *net.IPNet { 87 i.Lock() 88 defer i.Unlock() 89 90 return types.GetIPNetCopy(i.addressIPv6) 91 } 92 93 func (i *nwIface) LinkLocalAddresses() []*net.IPNet { 94 i.Lock() 95 defer i.Unlock() 96 97 return i.llAddrs 98 } 99 100 func (i *nwIface) IPAliases() []*net.IPNet { 101 i.Lock() 102 defer i.Unlock() 103 104 return i.ipAliases 105 } 106 107 func (i *nwIface) Routes() []*net.IPNet { 108 i.Lock() 109 defer i.Unlock() 110 111 routes := make([]*net.IPNet, len(i.routes)) 112 for index, route := range i.routes { 113 r := types.GetIPNetCopy(route) 114 routes[index] = r 115 } 116 117 return routes 118 } 119 120 func (n *networkNamespace) Interfaces() []Interface { 121 n.Lock() 122 defer n.Unlock() 123 124 ifaces := make([]Interface, len(n.iFaces)) 125 126 for i, iface := range n.iFaces { 127 ifaces[i] = iface 128 } 129 130 return ifaces 131 } 132 133 func (i *nwIface) Remove() error { 134 i.Lock() 135 n := i.ns 136 i.Unlock() 137 138 n.Lock() 139 isDefault := n.isDefault 140 nlh := n.nlHandle 141 n.Unlock() 142 143 // Find the network interface identified by the DstName attribute. 144 iface, err := nlh.LinkByName(i.DstName()) 145 if err != nil { 146 return err 147 } 148 149 // Down the interface before configuring 150 if err := nlh.LinkSetDown(iface); err != nil { 151 return err 152 } 153 154 err = nlh.LinkSetName(iface, i.SrcName()) 155 if err != nil { 156 log.Debugf("LinkSetName failed for interface %s: %v", i.SrcName(), err) 157 return err 158 } 159 160 // if it is a bridge just delete it. 161 if i.Bridge() { 162 if err := nlh.LinkDel(iface); err != nil { 163 return fmt.Errorf("failed deleting bridge %q: %v", i.SrcName(), err) 164 } 165 } else if !isDefault { 166 // Move the network interface to caller namespace. 167 if err := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); err != nil { 168 log.Debugf("LinkSetNsPid failed for interface %s: %v", i.SrcName(), err) 169 return err 170 } 171 } 172 173 n.Lock() 174 for index, intf := range n.iFaces { 175 if intf == i { 176 n.iFaces = append(n.iFaces[:index], n.iFaces[index+1:]...) 177 break 178 } 179 } 180 n.Unlock() 181 182 return nil 183 } 184 185 // Returns the sandbox's side veth interface statistics 186 func (i *nwIface) Statistics() (*types.InterfaceStatistics, error) { 187 i.Lock() 188 n := i.ns 189 i.Unlock() 190 191 l, err := n.nlHandle.LinkByName(i.DstName()) 192 if err != nil { 193 return nil, fmt.Errorf("failed to retrieve the statistics for %s in netns %s: %v", i.DstName(), n.path, err) 194 } 195 196 stats := l.Attrs().Statistics 197 if stats == nil { 198 return nil, fmt.Errorf("no statistics were returned") 199 } 200 201 return &types.InterfaceStatistics{ 202 RxBytes: uint64(stats.RxBytes), 203 TxBytes: uint64(stats.TxBytes), 204 RxPackets: uint64(stats.RxPackets), 205 TxPackets: uint64(stats.TxPackets), 206 RxDropped: uint64(stats.RxDropped), 207 TxDropped: uint64(stats.TxDropped), 208 }, nil 209 } 210 211 func (n *networkNamespace) findDst(srcName string, isBridge bool) string { 212 n.Lock() 213 defer n.Unlock() 214 215 for _, i := range n.iFaces { 216 // The master should match the srcname of the interface and the 217 // master interface should be of type bridge, if searching for a bridge type 218 if i.SrcName() == srcName && (!isBridge || i.Bridge()) { 219 return i.DstName() 220 } 221 } 222 223 return "" 224 } 225 226 func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error { 227 i := &nwIface{srcName: srcName, dstName: dstPrefix, ns: n} 228 i.processInterfaceOptions(options...) 229 230 if i.master != "" { 231 i.dstMaster = n.findDst(i.master, true) 232 if i.dstMaster == "" { 233 return fmt.Errorf("could not find an appropriate master %q for %q", 234 i.master, i.srcName) 235 } 236 } 237 238 n.Lock() 239 if n.isDefault { 240 i.dstName = i.srcName 241 } else { 242 i.dstName = fmt.Sprintf("%s%d", i.dstName, n.nextIfIndex) 243 n.nextIfIndex++ 244 } 245 246 path := n.path 247 isDefault := n.isDefault 248 nlh := n.nlHandle 249 nlhHost := ns.NlHandle() 250 n.Unlock() 251 252 // If it is a bridge interface we have to create the bridge inside 253 // the namespace so don't try to lookup the interface using srcName 254 if i.bridge { 255 link := &netlink.Bridge{ 256 LinkAttrs: netlink.LinkAttrs{ 257 Name: i.srcName, 258 }, 259 } 260 if err := nlh.LinkAdd(link); err != nil { 261 return fmt.Errorf("failed to create bridge %q: %v", i.srcName, err) 262 } 263 } else { 264 // Find the network interface identified by the SrcName attribute. 265 iface, err := nlhHost.LinkByName(i.srcName) 266 if err != nil { 267 return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err) 268 } 269 270 // Move the network interface to the destination 271 // namespace only if the namespace is not a default 272 // type 273 if !isDefault { 274 newNs, err := netns.GetFromPath(path) 275 if err != nil { 276 return fmt.Errorf("failed get network namespace %q: %v", path, err) 277 } 278 defer newNs.Close() 279 if err := nlhHost.LinkSetNsFd(iface, int(newNs)); err != nil { 280 return fmt.Errorf("failed to set namespace on link %q: %v", i.srcName, err) 281 } 282 } 283 } 284 285 // Find the network interface identified by the SrcName attribute. 286 iface, err := nlh.LinkByName(i.srcName) 287 if err != nil { 288 return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err) 289 } 290 291 // Down the interface before configuring 292 if err := nlh.LinkSetDown(iface); err != nil { 293 return fmt.Errorf("failed to set link down: %v", err) 294 } 295 296 // Configure the interface now this is moved in the proper namespace. 297 if err := configureInterface(nlh, iface, i); err != nil { 298 return err 299 } 300 301 // Up the interface. 302 cnt := 0 303 for err = nlh.LinkSetUp(iface); err != nil && cnt < 3; cnt++ { 304 log.Debugf("retrying link setup because of: %v", err) 305 time.Sleep(10 * time.Millisecond) 306 err = nlh.LinkSetUp(iface) 307 } 308 if err != nil { 309 return fmt.Errorf("failed to set link up: %v", err) 310 } 311 312 // Set the routes on the interface. This can only be done when the interface is up. 313 if err := setInterfaceRoutes(nlh, iface, i); err != nil { 314 return fmt.Errorf("error setting interface %q routes to %q: %v", iface.Attrs().Name, i.Routes(), err) 315 } 316 317 n.Lock() 318 n.iFaces = append(n.iFaces, i) 319 n.Unlock() 320 321 return nil 322 } 323 324 func configureInterface(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 325 ifaceName := iface.Attrs().Name 326 ifaceConfigurators := []struct { 327 Fn func(*netlink.Handle, netlink.Link, *nwIface) error 328 ErrMessage string 329 }{ 330 {setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, i.DstName())}, 331 {setInterfaceMAC, fmt.Sprintf("error setting interface %q MAC to %q", ifaceName, i.MacAddress())}, 332 {setInterfaceIP, fmt.Sprintf("error setting interface %q IP to %v", ifaceName, i.Address())}, 333 {setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())}, 334 {setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())}, 335 {setInterfaceLinkLocalIPs, fmt.Sprintf("error setting interface %q link local IPs to %v", ifaceName, i.LinkLocalAddresses())}, 336 {setInterfaceIPAliases, fmt.Sprintf("error setting interface %q IP Aliases to %v", ifaceName, i.IPAliases())}, 337 } 338 339 for _, config := range ifaceConfigurators { 340 if err := config.Fn(nlh, iface, i); err != nil { 341 return fmt.Errorf("%s: %v", config.ErrMessage, err) 342 } 343 } 344 return nil 345 } 346 347 func setInterfaceMaster(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 348 if i.DstMaster() == "" { 349 return nil 350 } 351 352 return nlh.LinkSetMaster(iface, &netlink.Bridge{ 353 LinkAttrs: netlink.LinkAttrs{Name: i.DstMaster()}}) 354 } 355 356 func setInterfaceMAC(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 357 if i.MacAddress() == nil { 358 return nil 359 } 360 return nlh.LinkSetHardwareAddr(iface, i.MacAddress()) 361 } 362 363 func setInterfaceIP(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 364 if i.Address() == nil { 365 return nil 366 } 367 368 ipAddr := &netlink.Addr{IPNet: i.Address(), Label: ""} 369 return nlh.AddrAdd(iface, ipAddr) 370 } 371 372 func setInterfaceIPv6(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 373 if i.AddressIPv6() == nil { 374 return nil 375 } 376 ipAddr := &netlink.Addr{IPNet: i.AddressIPv6(), Label: "", Flags: syscall.IFA_F_NODAD} 377 return nlh.AddrAdd(iface, ipAddr) 378 } 379 380 func setInterfaceLinkLocalIPs(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 381 for _, llIP := range i.LinkLocalAddresses() { 382 ipAddr := &netlink.Addr{IPNet: llIP} 383 if err := nlh.AddrAdd(iface, ipAddr); err != nil { 384 return err 385 } 386 } 387 return nil 388 } 389 390 func setInterfaceIPAliases(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 391 for _, si := range i.IPAliases() { 392 ipAddr := &netlink.Addr{IPNet: si} 393 if err := nlh.AddrAdd(iface, ipAddr); err != nil { 394 return err 395 } 396 } 397 return nil 398 } 399 400 func setInterfaceName(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 401 return nlh.LinkSetName(iface, i.DstName()) 402 } 403 404 func setInterfaceRoutes(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error { 405 for _, route := range i.Routes() { 406 err := nlh.RouteAdd(&netlink.Route{ 407 Scope: netlink.SCOPE_LINK, 408 LinkIndex: iface.Attrs().Index, 409 Dst: route, 410 }) 411 if err != nil { 412 return err 413 } 414 } 415 return nil 416 } 417 418 // In older kernels (like the one in Centos 6.6 distro) sysctl does not have netns support. Therefore 419 // we cannot gather the statistics from /sys/class/net/<dev>/statistics/<counter> files. Per-netns stats 420 // are naturally found in /proc/net/dev in kernels which support netns (ifconfig relies on that). 421 const ( 422 netStatsFile = "/proc/net/dev" 423 base = "[ ]*%s:([ ]+[0-9]+){16}" 424 ) 425 426 func scanInterfaceStats(data, ifName string, i *types.InterfaceStatistics) error { 427 var ( 428 bktStr string 429 bkt uint64 430 ) 431 432 regex := fmt.Sprintf(base, ifName) 433 re := regexp.MustCompile(regex) 434 line := re.FindString(data) 435 436 _, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", 437 &bktStr, &i.RxBytes, &i.RxPackets, &i.RxErrors, &i.RxDropped, &bkt, &bkt, &bkt, 438 &bkt, &i.TxBytes, &i.TxPackets, &i.TxErrors, &i.TxDropped, &bkt, &bkt, &bkt, &bkt) 439 440 return err 441 }