func (fastdp *FastDatapath) getVxlanVportIDHarder(udpPort int, retries int, duration time.Duration) (odp.VportID, error) { var vxlanVportID odp.VportID var err error for try := 0; try < retries; try++ { vxlanVportID, err = fastdp.getVxlanVportID(udpPort) if err == nil || err != odp.NetlinkError(syscall.EADDRINUSE) { return vxlanVportID, err } log.Warning("Address already in use creating vxlan vport ", udpPort, " - retrying") time.Sleep(duration) } return 0, err }
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 }