Skip to content

Commit

Permalink
Merge pull request #2164 from xiaoxubeii/failto-update-bridge
Browse files Browse the repository at this point in the history
bugfix: Fix that cannot update bridge when restart pouchd
  • Loading branch information
rudyfly authored Sep 18, 2018
2 parents 651bc7a + 23627d5 commit 6189f26
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 59 deletions.
109 changes: 55 additions & 54 deletions network/mode/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/alibaba/pouch/daemon/mgr"
"github.com/alibaba/pouch/network"
"github.com/alibaba/pouch/pkg/errtypes"
"github.com/alibaba/pouch/pkg/utils"

"github.com/docker/libnetwork/drivers/bridge"
"github.com/docker/libnetwork/netlabel"
Expand All @@ -30,86 +31,52 @@ func New(ctx context.Context, config network.BridgeConfig, manager mgr.NetworkMg
}
}

// set bridge name
// get bridge name
bridgeName := DefaultBridge
if config.Name != "" {
bridgeName = config.Name
}

// init host bridge network.
br, err := initBridgeDevice(bridgeName)
// get bridge ip
bridgeIP := utils.StringDefault(config.IP, DefaultIPNet)
ipNet, err := netlink.ParseIPNet(bridgeIP)
if err != nil {
return err
return fmt.Errorf("failed to parse ip %v", bridgeIP)
}
logrus.Debugf("initialize bridge network, bridge ip: %s.", ipNet)

var (
bridgeIPv4Address string
)
Addrs, err := netlink.AddrList(br, netlink.FAMILY_V4)
// init host bridge network.
_, err = initBridgeDevice(bridgeName, ipNet)
if err != nil {
return errors.Wrap(err, "failed to get bridge addr")
}
for _, addr := range Addrs {
cidr := addr.String()
if strings.Contains(cidr, ":") {
continue
}

parts := strings.Split(cidr, " ")
if len(parts) != 2 {
continue
}

bridgeIPv4Address = parts[0]
break
return err
}

// get subnet
subnet := DefaultSubnet
if config.IP != "" {
subnet = config.IP
} else if bridgeIPv4Address != "" {
subnet = bridgeIPv4Address
// get bridge subnet
_, subnet, err := net.ParseCIDR(bridgeIP)
if err != nil {
return fmt.Errorf("failted to parse subnet %v", bridgeIP)
}
logrus.Debugf("initialize bridge network, subnet: %s", subnet)
logrus.Debugf("initialize bridge network, bridge network: %s", subnet)

// get ip range
ipRange := DefaultIPRange
if config.FixedCIDR != "" {
ipRange = config.FixedCIDR
} else {
ipRange = subnet
ipRange = subnet.String()
}
logrus.Debugf("initialize bridge network, bridge ip range in subnet: %s", ipRange)

// get gateway
gateway := DefaultGateway
if config.GatewayIPv4 != "" {
gateway = config.GatewayIPv4
} else {
// get the default route set as gateway.
routes, err := netlink.RouteList(br, netlink.FAMILY_V4)
if err != nil {
return errors.Wrap(err, "failed to get route list")
}
for _, route := range routes {
gw := route.Gw.String()
if gw != "" && gw != "<nil>" {
gateway = gw
break
}
}

// nat mode bridge have no default route, so let the bridge ip as gateway.
if bridgeIPv4Address != "" {
gateway = strings.Split(bridgeIPv4Address, "/")[0]
}
}
logrus.Debugf("initialize bridge network, gateway: %s", gateway)

ipamV4Conf := types.IPAMConfig{
AuxAddress: make(map[string]string),
Subnet: subnet,
Subnet: subnet.String(),
IPRange: ipRange,
Gateway: gateway,
}
Expand Down Expand Up @@ -148,15 +115,49 @@ func New(ctx context.Context, config network.BridgeConfig, manager mgr.NetworkMg
return err
}

func initBridgeDevice(name string) (netlink.Link, error) {
func containIP(ip net.IPNet, br netlink.Link) bool {
addrs, err := netlink.AddrList(br, netlink.FAMILY_V4)
if err == nil {
for _, addr := range addrs {
if ip.IP.Equal(addr.IP) {
sizea, _ := ip.Mask.Size()
sizeb, _ := addr.Mask.Size()
if sizea == sizeb {
return true
}
}
}
}
return false
}

func existVethPair(br netlink.Link) bool {
allLinks, err := netlink.LinkList()
if err == nil {
for _, l := range allLinks {
if l.Type() == "veth" && l.Attrs().MasterIndex == br.Attrs().Index {
return true
}
}
}
return false
}

func initBridgeDevice(name string, ipNet *net.IPNet) (netlink.Link, error) {
br, err := netlink.LinkByName(name)
if err == nil && br != nil {
return br, nil
if containIP(*ipNet, br) { // do nothing if ip exists
return br, nil
}
if existVethPair(br) {
return nil, fmt.Errorf("failed to remove old bridge device due to existing veth pair")
}
netlink.LinkDel(br)
}

// generate mac address for bridge.
var ip []int
for _, v := range strings.Split(DefaultBridgeIP, ".") {
for _, v := range strings.Split(ipNet.IP.String(), ".") {
tmp, _ := strconv.Atoi(v)
ip = append(ip, tmp)
}
Expand Down Expand Up @@ -184,7 +185,7 @@ func initBridgeDevice(name string) (netlink.Link, error) {
}
}()

addr, err := netlink.ParseAddr(DefaultSubnet)
addr, err := netlink.ParseAddr(ipNet.String())
if err != nil {
return nil, errors.Wrap(err, "failed to parse ip address")
}
Expand Down
7 changes: 2 additions & 5 deletions network/mode/bridge/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@ const (
// DefaultBridge defines the default bridge name.
DefaultBridge = "p0"

// DefaultBridgeIP defines the default bridge ip.
DefaultBridgeIP = "192.168.5.1"

// DefaultSubnet defines the default bridge subnet.
DefaultSubnet = "192.168.5.1/24"
// DefaultIPNet defines the default bridge ip.
DefaultIPNet = "192.168.5.1/24"

// DefaultIPRange defines the default bridge ip range in ipam.
DefaultIPRange = "192.168.5.1/24"
Expand Down
8 changes: 8 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,3 +353,11 @@ func MergeMap(m1 map[string]interface{}, m2 map[string]interface{}) (map[string]

return m1, nil
}

// StringDefault return default value if s is empty, otherwise return s.
func StringDefault(s string, val string) string {
if s != "" {
return s
}
return val
}

0 comments on commit 6189f26

Please sign in to comment.