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  }