EnsureBridge used to skip creation and initialization of the weave bridge and friends if such existed. This caused problems when EnsureBridge failed before completing all init steps and so, subsequent weaver could not work without "weave reset". This change makes EnsureBridge idempotent.
104 lines
2.2 KiB
Go
104 lines
2.2 KiB
Go
package odp
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"syscall"
|
|
|
|
"github.com/weaveworks/go-odp/odp"
|
|
)
|
|
|
|
// ODP admin functionality
|
|
|
|
func CreateDatapath(dpname string) (supported bool, err error) {
|
|
dpif, err := odp.NewDpif()
|
|
if err != nil {
|
|
if odp.IsKernelLacksODPError(err) {
|
|
return false, nil
|
|
}
|
|
return true, err
|
|
}
|
|
defer dpif.Close()
|
|
|
|
dp, err := dpif.CreateDatapath(dpname)
|
|
if err != nil {
|
|
if !odp.IsDatapathNameAlreadyExistsError(err) {
|
|
return true, err
|
|
}
|
|
if dp, err = dpif.LookupDatapath(dpname); err != nil {
|
|
return true, err
|
|
}
|
|
}
|
|
|
|
// Pick an ephemeral port number to use in probing for vxlan
|
|
// support.
|
|
udpconn, err := net.ListenUDP("udp4", nil)
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
defer udpconn.Close()
|
|
|
|
// we leave the UDP socket open, so creating a vxlan vport on
|
|
// the same port number should fail. But that's fine: It's
|
|
// still sufficient to probe for support.
|
|
portno := uint16(udpconn.LocalAddr().(*net.UDPAddr).Port)
|
|
vpid, err := dp.CreateVport(odp.NewVxlanVportSpec(fmt.Sprintf("vxlan-%d", portno), portno))
|
|
if nlerr, ok := err.(odp.NetlinkError); ok {
|
|
if syscall.Errno(nlerr) == syscall.EAFNOSUPPORT {
|
|
dp.Delete()
|
|
return false, fmt.Errorf("kernel does not have Open vSwitch VXLAN support")
|
|
}
|
|
}
|
|
if err == nil {
|
|
dp.DeleteVport(vpid)
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func DeleteDatapath(dpname string) error {
|
|
dpif, err := odp.NewDpif()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer dpif.Close()
|
|
|
|
dp, err := dpif.LookupDatapath(dpname)
|
|
if err != nil {
|
|
if odp.IsNoSuchDatapathError(err) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
return dp.Delete()
|
|
}
|
|
|
|
func AddDatapathInterface(dpname string, ifname string) error {
|
|
return addDatapathInterface(dpname, ifname, false)
|
|
}
|
|
|
|
func AddDatapathInterfaceIfNotExist(dpname string, ifname string) error {
|
|
return addDatapathInterface(dpname, ifname, true)
|
|
}
|
|
|
|
func addDatapathInterface(dpname, ifname string, ignoreIfExist bool) error {
|
|
dpif, err := odp.NewDpif()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer dpif.Close()
|
|
|
|
dp, err := dpif.LookupDatapath(dpname)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = dp.CreateVport(odp.NewNetdevVportSpec(ifname))
|
|
if ignoreIfExist && err == odp.NetlinkError(syscall.EEXIST) {
|
|
return nil
|
|
}
|
|
|
|
return err
|
|
}
|