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