Skip to content

Commit

Permalink
fix OVS bridge with bond port in mode 6
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangzujian committed Feb 28, 2022
1 parent 4ead779 commit f662890
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
3 changes: 3 additions & 0 deletions docs/vlan.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ In Vlan mode, packets from pods will be sent directly to physical switches with
![topology](vlan-topolgy.png "vlan network topology")

To enable Vlan mode, a ~~dedicated~~ network interface is required by container network. Mac address, MTU, IP addresses and routes attached to the interface will be copied/transferred to an OVS bridge named `br-PROVIDER` where `PROVIDER` is name of the provider network.

> NOTICE: If the provided interface is a bond device in mode 6 (a.k.a. balance-alb or adaptive load balancing), the OVS bridge will NOT contain the same Mac address. Instead, Kube-OVN assigns a generated Mac address with prefix `00:00:00` to the bridge.
The related switch port must work in trunk mode to accept 802.1q packets. For underlay network with no vlan tag, you need
to set the VLAN ID to 0.

Expand Down
47 changes: 45 additions & 2 deletions pkg/daemon/ovs.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,22 @@ func configureNic(link, ip string, macAddr net.HardwareAddr, mtu int) error {
}

func configExternalBridge(provider, bridge, nic string) error {
brExists, err := ovs.BridgeExists(bridge)
if err != nil {
return fmt.Errorf("failed to check OVS bridge existence: %v", err)
}
output, err := ovs.Exec(ovs.MayExist, "add-br", bridge,
"--", "set", "bridge", bridge, "external_ids:vendor="+util.CniTypeName)
if err != nil {
return fmt.Errorf("failed to create OVS bridge %s, %v: %q", bridge, err, output)
}
if !brExists {
// assign a new generated mac address only when the bridge is newly created
output, err = ovs.Exec("set", "bridge", bridge, fmt.Sprintf(`other-config:hwaddr="%s"`, util.GenerateMac()))
if err != nil {
return fmt.Errorf("failed to set hwaddr of OVS bridge %s, %v: %q", bridge, err, output)
}
}
if output, err = ovs.Exec("list-ports", bridge); err != nil {
return fmt.Errorf("failed to list ports of OVS birdge %s, %v: %q", bridge, err, output)
}
Expand Down Expand Up @@ -583,9 +594,18 @@ func configProviderNic(nicName, brName string) (int, error) {
}
}

if _, err = ovs.Exec("set", "bridge", brName, fmt.Sprintf(`other-config:hwaddr="%s"`, nic.Attrs().HardwareAddr.String())); err != nil {
return 0, fmt.Errorf("failed to set MAC address of OVS bridge %s: %v", brName, err)
// keep mac address the same with the provider nic,
// unless the provider nic is a bond in mode 6, or a vlan interface of a bond in mode 6
albBond, err := linkIsAlbBond(nic)
if err != nil {
return 0, err
}
if !albBond {
if _, err = ovs.Exec("set", "bridge", brName, fmt.Sprintf(`other-config:hwaddr="%s"`, nic.Attrs().HardwareAddr.String())); err != nil {
return 0, fmt.Errorf("failed to set MAC address of OVS bridge %s: %v", brName, err)
}
}

if err = netlink.LinkSetMTU(bridge, nic.Attrs().MTU); err != nil {
return 0, fmt.Errorf("failed to set MTU of OVS bridge %s: %v", brName, err)
}
Expand Down Expand Up @@ -620,6 +640,29 @@ func configProviderNic(nicName, brName string) (int, error) {
return nic.Attrs().MTU, nil
}

func linkIsAlbBond(link netlink.Link) (bool, error) {
check := func(link netlink.Link) bool {
bond, ok := link.(*netlink.Bond)
return ok && bond.Mode == netlink.BOND_MODE_BALANCE_ALB
}

if check(link) {
return true, nil
}

vlan, ok := link.(*netlink.Vlan)
if !ok {
return false, nil
}
parent, err := netlink.LinkByIndex(vlan.ParentIndex)
if err != nil {
klog.Errorf("failed to get link by index %d: %v", vlan.ParentIndex, err)
return false, err
}

return check(parent), nil
}

// Remove host nic from external bridge
// IP addresses & routes will be transferred to the host nic
func removeProviderNic(nicName, brName string) error {
Expand Down
9 changes: 9 additions & 0 deletions pkg/ovs/ovs-vsctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ func Bridges() ([]string, error) {
return ovsFind("bridge", "name", fmt.Sprintf("external-ids:vendor=%s", util.CniTypeName))
}

// BridgeExists checks whether the bridge already exists
func BridgeExists(name string) (bool, error) {
bridges, err := Bridges()
if err != nil {
return false, err
}
return util.ContainsString(bridges, name), nil
}

// ClearPodBandwidth remove qos related to this pod. Only used when remove pod.
func ClearPodBandwidth(podName, podNamespace string) error {
qosList, err := ovsFind("qos", "_uuid", fmt.Sprintf(`external-ids:iface-id="%s.%s"`, podName, podNamespace))
Expand Down

0 comments on commit f662890

Please sign in to comment.