func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) { fastdp.lock.Lock() defer fastdp.lock.Unlock() if vxlanVportID, present := fastdp.vxlanVportIDs[udpPort]; present { return vxlanVportID, nil } vxlanVportID, err := fastdp.dp.CreateVport( odp.NewVxlanVportSpec(fmt.Sprintf("vxlan-%d", udpPort), uint16(udpPort))) if err != nil { return 0, err } fastdp.vxlanVportIDs[udpPort] = vxlanVportID fastdp.missHandlers[vxlanVportID] = func(fks odp.FlowKeys, lock *fastDatapathLock) FlowOp { tunnel := fks[odp.OVS_KEY_ATTR_TUNNEL].(odp.TunnelFlowKey) tunKey := tunnel.Key() lock.relock() consumer := fastdp.overlayConsumer if consumer == nil { return vetoFlowCreationFlowOp{} } srcPeer, dstPeer := fastdp.extractPeers(tunKey.TunnelId) if srcPeer == nil || dstPeer == nil { return vetoFlowCreationFlowOp{} } lock.unlock() pk := flowKeysToPacketKey(fks) var zeroMAC MAC if pk.SrcMAC == zeroMAC && pk.DstMAC == zeroMAC { return vxlanSpecialPacketFlowOp{ fastdp: fastdp, srcPeer: srcPeer, sender: &net.UDPAddr{ IP: net.IP(tunKey.Ipv4Src[:]), Port: udpPort, }, } } key := ForwardPacketKey{ SrcPeer: srcPeer, DstPeer: dstPeer, PacketKey: pk, } var tunnelFlowKey odp.TunnelFlowKey tunnelFlowKey.SetTunnelId(tunKey.TunnelId) tunnelFlowKey.SetIpv4Src(tunKey.Ipv4Src) tunnelFlowKey.SetIpv4Dst(tunKey.Ipv4Dst) return NewMultiFlowOp(false, odpFlowKey(tunnelFlowKey), consumer(key)) } return vxlanVportID, nil }
func addVxlanVport(f Flags) bool { var port uint // 4789 is the IANA assigned port number for VXLAN f.UintVar(&port, "port", 4789, "UDP port number") args := f.Parse(2, 2) if port > 65535 { return printErr("port number too large") } return addVport(args[0], odp.NewVxlanVportSpec(args[1], uint16(port))) }
func CreateDatapath(dpname string) (err error, supported bool) { dpif, err := odp.NewDpif() if err != nil { if odp.IsKernelLacksODPError(err) { return nil, false } return err, true } defer dpif.Close() dp, err := dpif.CreateDatapath(dpname) if err != nil && !odp.IsDatapathNameAlreadyExistsError(err) { return err, true } // Pick an ephemeral port number to use in probing for vxlan // support. udpconn, err := net.ListenUDP("udp4", nil) if err != nil { return err, true } // 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 fmt.Errorf("kernel does not have Open vSwitch VXLAN support"), false } } if err == nil { dp.DeleteVport(vpid) } udpconn.Close() return nil, true }
func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) { fastdp.lock.Lock() defer fastdp.lock.Unlock() if vxlanVportID, present := fastdp.vxlanVportIDs[udpPort]; present { return vxlanVportID, nil } name := fmt.Sprintf("vxlan-%d", udpPort) vxlanVportID, err := fastdp.dp.CreateVport( odp.NewVxlanVportSpec(name, uint16(udpPort))) if err != nil { return 0, err } // If a netdev for the vxlan vport exists, we need to do an extra check // to bypass the kernel bug which makes the vxlan creation to complete // successfully regardless whether there were any errors when binding // to the given UDP port. if link, err := netlink.LinkByName(name); err == nil { if link.Attrs().Flags&net.FlagUp == 0 { // The netdev interface is down, so most likely bringing it up // has failed due to the UDP port being in use. if err := fastdp.dp.DeleteVport(vxlanVportID); err != nil { log.Warning("Unable to remove vxlan vport %d: %s", vxlanVportID, err) } return 0, odp.NetlinkError(syscall.EADDRINUSE) } } fastdp.vxlanVportIDs[udpPort] = vxlanVportID fastdp.missHandlers[vxlanVportID] = func(fks odp.FlowKeys, lock *fastDatapathLock) FlowOp { log.Debug("ODP miss: ", fks, " on port ", vxlanVportID) tunnel := fks[odp.OVS_KEY_ATTR_TUNNEL].(odp.TunnelFlowKey) tunKey := tunnel.Key() lock.relock() consumer := fastdp.overlayConsumer if consumer == nil { return vetoFlowCreationFlowOp{} } srcPeer, dstPeer := fastdp.extractPeers(tunKey.TunnelId) if srcPeer == nil || dstPeer == nil { return vetoFlowCreationFlowOp{} } lock.unlock() pk := flowKeysToPacketKey(fks) var zeroMAC MAC if pk.SrcMAC == zeroMAC && pk.DstMAC == zeroMAC { return vxlanSpecialPacketFlowOp{ fastdp: fastdp, srcPeer: srcPeer, sender: &net.UDPAddr{ IP: net.IP(tunKey.Ipv4Src[:]), Port: udpPort, }, } } key := ForwardPacketKey{ SrcPeer: srcPeer, DstPeer: dstPeer, PacketKey: pk, } var tunnelFlowKey odp.TunnelFlowKey tunnelFlowKey.SetTunnelId(tunKey.TunnelId) tunnelFlowKey.SetIpv4Src(tunKey.Ipv4Src) tunnelFlowKey.SetIpv4Dst(tunKey.Ipv4Dst) return NewMultiFlowOp(false, odpFlowKey(tunnelFlowKey), consumer(key)) } return vxlanVportID, nil }