2015-02-22 20:24:22 -05:00
|
|
|
package bridge
|
|
|
|
|
2015-04-10 12:02:25 -04:00
|
|
|
import (
|
2016-01-06 21:13:08 -05:00
|
|
|
"fmt"
|
2015-04-10 12:02:25 -04:00
|
|
|
"net"
|
|
|
|
|
2016-05-16 14:51:40 -04:00
|
|
|
"github.com/Sirupsen/logrus"
|
2015-04-10 12:02:25 -04:00
|
|
|
"github.com/vishvananda/netlink"
|
|
|
|
)
|
2015-02-22 20:24:22 -05:00
|
|
|
|
2015-02-22 20:58:52 -05:00
|
|
|
const (
|
2015-03-04 16:25:43 -05:00
|
|
|
// DefaultBridgeName is the default name for the bridge interface managed
|
|
|
|
// by the driver when unspecified by the caller.
|
2015-02-22 20:58:52 -05:00
|
|
|
DefaultBridgeName = "docker0"
|
|
|
|
)
|
|
|
|
|
2015-03-04 16:25:43 -05:00
|
|
|
// Interface models the bridge network device.
|
|
|
|
type bridgeInterface struct {
|
2015-04-24 18:13:44 -04:00
|
|
|
Link netlink.Link
|
|
|
|
bridgeIPv4 *net.IPNet
|
|
|
|
bridgeIPv6 *net.IPNet
|
|
|
|
gatewayIPv4 net.IP
|
|
|
|
gatewayIPv6 net.IP
|
2016-05-16 14:51:40 -04:00
|
|
|
nlh *netlink.Handle
|
2015-02-22 20:24:22 -05:00
|
|
|
}
|
|
|
|
|
2015-04-20 13:08:09 -04:00
|
|
|
// newInterface creates a new bridge interface structure. It attempts to find
|
2015-05-22 13:56:36 -04:00
|
|
|
// an already existing device identified by the configuration BridgeName field,
|
2016-05-22 22:55:17 -04:00
|
|
|
// or the default bridge name when unspecified, but doesn't attempt to create
|
2015-04-20 13:08:09 -04:00
|
|
|
// one when missing
|
2016-09-05 07:36:59 -04:00
|
|
|
func newInterface(nlh *netlink.Handle, config *networkConfiguration) (*bridgeInterface, error) {
|
2016-05-16 14:51:40 -04:00
|
|
|
var err error
|
|
|
|
i := &bridgeInterface{nlh: nlh}
|
2015-02-22 20:24:22 -05:00
|
|
|
|
2015-02-22 20:58:52 -05:00
|
|
|
// Initialize the bridge name to the default if unspecified.
|
2015-04-15 01:25:42 -04:00
|
|
|
if config.BridgeName == "" {
|
|
|
|
config.BridgeName = DefaultBridgeName
|
2015-02-22 20:58:52 -05:00
|
|
|
}
|
|
|
|
|
2015-02-22 20:24:22 -05:00
|
|
|
// Attempt to find an existing bridge named with the specified name.
|
2016-05-16 14:51:40 -04:00
|
|
|
i.Link, err = nlh.LinkByName(config.BridgeName)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Debugf("Did not find any interface with name %s: %v", config.BridgeName, err)
|
2016-09-05 07:36:59 -04:00
|
|
|
} else if _, ok := i.Link.(*netlink.Bridge); !ok {
|
|
|
|
return nil, fmt.Errorf("existing interface %s is not a bridge", i.Link.Attrs().Name)
|
2016-05-16 14:51:40 -04:00
|
|
|
}
|
2016-09-05 07:36:59 -04:00
|
|
|
return i, nil
|
2015-02-22 20:24:22 -05:00
|
|
|
}
|
|
|
|
|
2015-04-20 13:08:09 -04:00
|
|
|
// exists indicates if the existing bridge interface exists on the system.
|
2015-03-04 16:25:43 -05:00
|
|
|
func (i *bridgeInterface) exists() bool {
|
2015-02-22 20:24:22 -05:00
|
|
|
return i.Link != nil
|
|
|
|
}
|
2015-02-23 00:32:48 -05:00
|
|
|
|
2016-09-17 01:40:44 -04:00
|
|
|
// addresses returns all IPv4 addresses and all IPv6 addresses for the bridge interface.
|
|
|
|
func (i *bridgeInterface) addresses() ([]netlink.Addr, []netlink.Addr, error) {
|
2016-05-16 14:51:40 -04:00
|
|
|
v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4)
|
2015-02-23 00:32:48 -05:00
|
|
|
if err != nil {
|
2016-09-17 01:40:44 -04:00
|
|
|
return nil, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
|
2015-02-23 00:32:48 -05:00
|
|
|
}
|
|
|
|
|
2016-05-16 14:51:40 -04:00
|
|
|
v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6)
|
2015-02-23 00:32:48 -05:00
|
|
|
if err != nil {
|
2016-09-17 01:40:44 -04:00
|
|
|
return nil, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
|
2015-02-23 00:32:48 -05:00
|
|
|
}
|
|
|
|
|
2015-02-24 21:41:17 -05:00
|
|
|
if len(v4addr) == 0 {
|
2016-09-17 01:40:44 -04:00
|
|
|
return nil, v6addr, nil
|
2015-02-24 21:41:17 -05:00
|
|
|
}
|
2016-09-17 01:40:44 -04:00
|
|
|
return v4addr, v6addr, nil
|
2015-02-23 00:32:48 -05:00
|
|
|
}
|
2016-01-06 21:13:08 -05:00
|
|
|
|
|
|
|
func (i *bridgeInterface) programIPv6Address() error {
|
|
|
|
_, nlAddressList, err := i.addresses()
|
|
|
|
if err != nil {
|
|
|
|
return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: fmt.Errorf("failed to retrieve address list: %v", err)}
|
|
|
|
}
|
|
|
|
nlAddr := netlink.Addr{IPNet: i.bridgeIPv6}
|
|
|
|
if findIPv6Address(nlAddr, nlAddressList) {
|
|
|
|
return nil
|
|
|
|
}
|
2016-05-16 14:51:40 -04:00
|
|
|
if err := i.nlh.AddrAdd(i.Link, &nlAddr); err != nil {
|
2016-01-06 21:13:08 -05:00
|
|
|
return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: err}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|