github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/libnetwork/drivers/bridge/interface.go (about)

     1  // +build linux
     2  
     3  package bridge
     4  
     5  import (
     6  	"fmt"
     7  	"net"
     8  
     9  	"github.com/sirupsen/logrus"
    10  	"github.com/vishvananda/netlink"
    11  )
    12  
    13  const (
    14  	// DefaultBridgeName is the default name for the bridge interface managed
    15  	// by the driver when unspecified by the caller.
    16  	DefaultBridgeName = "docker0"
    17  )
    18  
    19  // Interface models the bridge network device.
    20  type bridgeInterface struct {
    21  	Link        netlink.Link
    22  	bridgeIPv4  *net.IPNet
    23  	bridgeIPv6  *net.IPNet
    24  	gatewayIPv4 net.IP
    25  	gatewayIPv6 net.IP
    26  	nlh         *netlink.Handle
    27  }
    28  
    29  // newInterface creates a new bridge interface structure. It attempts to find
    30  // an already existing device identified by the configuration BridgeName field,
    31  // or the default bridge name when unspecified, but doesn't attempt to create
    32  // one when missing
    33  func newInterface(nlh *netlink.Handle, config *networkConfiguration) (*bridgeInterface, error) {
    34  	var err error
    35  	i := &bridgeInterface{nlh: nlh}
    36  
    37  	// Initialize the bridge name to the default if unspecified.
    38  	if config.BridgeName == "" {
    39  		config.BridgeName = DefaultBridgeName
    40  	}
    41  
    42  	// Attempt to find an existing bridge named with the specified name.
    43  	i.Link, err = nlh.LinkByName(config.BridgeName)
    44  	if err != nil {
    45  		logrus.Debugf("Did not find any interface with name %s: %v", config.BridgeName, err)
    46  	} else if _, ok := i.Link.(*netlink.Bridge); !ok {
    47  		return nil, fmt.Errorf("existing interface %s is not a bridge", i.Link.Attrs().Name)
    48  	}
    49  	return i, nil
    50  }
    51  
    52  // exists indicates if the existing bridge interface exists on the system.
    53  func (i *bridgeInterface) exists() bool {
    54  	return i.Link != nil
    55  }
    56  
    57  // addresses returns all IPv4 addresses and all IPv6 addresses for the bridge interface.
    58  func (i *bridgeInterface) addresses() ([]netlink.Addr, []netlink.Addr, error) {
    59  	v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4)
    60  	if err != nil {
    61  		return nil, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
    62  	}
    63  
    64  	v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6)
    65  	if err != nil {
    66  		return nil, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
    67  	}
    68  
    69  	if len(v4addr) == 0 {
    70  		return nil, v6addr, nil
    71  	}
    72  	return v4addr, v6addr, nil
    73  }
    74  
    75  func (i *bridgeInterface) programIPv6Address() error {
    76  	_, nlAddressList, err := i.addresses()
    77  	if err != nil {
    78  		return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: fmt.Errorf("failed to retrieve address list: %v", err)}
    79  	}
    80  	nlAddr := netlink.Addr{IPNet: i.bridgeIPv6}
    81  	if findIPv6Address(nlAddr, nlAddressList) {
    82  		return nil
    83  	}
    84  	if err := i.nlh.AddrAdd(i.Link, &nlAddr); err != nil {
    85  		return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: err}
    86  	}
    87  	return nil
    88  }