Search in sources :

Example 6 with ProviderId

use of org.onosproject.net.provider.ProviderId in project onos by opennetworkinglab.

the class GossipDeviceStore method createOrUpdateDeviceInternal.

private DeviceEvent createOrUpdateDeviceInternal(ProviderId providerId, DeviceId deviceId, Timestamped<DeviceDescription> deltaDesc) {
    // Collection of DeviceDescriptions for a Device
    Map<ProviderId, DeviceDescriptions> device = getOrCreateDeviceDescriptionsMap(deviceId);
    synchronized (device) {
        if (isDeviceRemoved(deviceId, deltaDesc.timestamp())) {
            log.debug("Ignoring outdated event: {}", deltaDesc);
            return null;
        }
        DeviceDescriptions descs = getOrCreateProviderDeviceDescriptions(device, providerId, deltaDesc);
        final Device oldDevice = devices.get(deviceId);
        final Device newDevice;
        if (deltaDesc == descs.getDeviceDesc() || deltaDesc.isNewer(descs.getDeviceDesc())) {
            // on new device or valid update
            descs.putDeviceDesc(deltaDesc);
            newDevice = composeDevice(deviceId, device);
        } else {
            // outdated event, ignored.
            return null;
        }
        if (oldDevice == null) {
            // REGISTER
            if (!deltaDesc.value().isDefaultAvailable()) {
                return registerDevice(providerId, newDevice, deltaDesc.timestamp());
            }
            // ADD
            return createDevice(providerId, newDevice, deltaDesc.timestamp());
        } else {
            // UPDATE or ignore (no change or stale)
            return updateDevice(providerId, oldDevice, newDevice, deltaDesc.timestamp(), deltaDesc.value().isDefaultAvailable());
        }
    }
}
Also used : ProviderId(org.onosproject.net.provider.ProviderId) DefaultDevice(org.onosproject.net.DefaultDevice) Device(org.onosproject.net.Device)

Example 7 with ProviderId

use of org.onosproject.net.provider.ProviderId in project onos by opennetworkinglab.

the class GossipDeviceStore method composePort.

/**
 * Returns a Port, merging description given from multiple Providers.
 *
 * @param device   device the port is on
 * @param number   port number
 * @param descsMap Collection of Descriptions from multiple providers
 * @return Port instance
 */
private Port composePort(Device device, PortNumber number, Map<ProviderId, DeviceDescriptions> descsMap) {
    ProviderId primary = pickPrimaryPid(descsMap);
    DeviceDescriptions primDescs = descsMap.get(primary);
    // if no primary, assume not enabled
    boolean isEnabled = false;
    DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
    Timestamp newest = null;
    final Timestamped<PortDescription> portDesc = primDescs.getPortDesc(number);
    if (portDesc != null) {
        isEnabled = portDesc.value().isEnabled();
        annotations.putAll(portDesc.value().annotations());
        newest = portDesc.timestamp();
    }
    Port updated = null;
    for (Entry<ProviderId, DeviceDescriptions> e : descsMap.entrySet()) {
        if (e.getKey().equals(primary)) {
            continue;
        }
        // Note: should keep track of Description timestamp in the future
        // and only merge conflicting keys when timestamp is newer.
        // Currently assuming there will never be a key conflict between
        // providers
        // annotation merging. not so efficient, should revisit later
        final Timestamped<PortDescription> otherPortDesc = e.getValue().getPortDesc(number);
        if (otherPortDesc != null) {
            if (newest != null && newest.isNewerThan(otherPortDesc.timestamp())) {
                continue;
            }
            annotations.putAll(otherPortDesc.value().annotations());
            PortDescription other = otherPortDesc.value();
            updated = buildTypedPort(device, number, isEnabled, other, annotations.build());
            newest = otherPortDesc.timestamp();
        }
    }
    if (portDesc == null) {
        return updated == null ? new DefaultPort(device, number, false, annotations.build()) : updated;
    }
    PortDescription current = portDesc.value();
    return updated == null ? buildTypedPort(device, number, isEnabled, current, annotations.build()) : updated;
}
Also used : ProviderId(org.onosproject.net.provider.ProviderId) DefaultAnnotations(org.onosproject.net.DefaultAnnotations) Port(org.onosproject.net.Port) DefaultPort(org.onosproject.net.DefaultPort) PortDescription(org.onosproject.net.device.PortDescription) WallClockTimestamp(org.onosproject.store.service.WallClockTimestamp) Timestamp(org.onosproject.store.Timestamp) MastershipBasedTimestamp(org.onosproject.store.impl.MastershipBasedTimestamp) MultiValuedTimestamp(org.onosproject.store.service.MultiValuedTimestamp) DefaultPort(org.onosproject.net.DefaultPort)

Example 8 with ProviderId

use of org.onosproject.net.provider.ProviderId in project onos by opennetworkinglab.

the class GossipDeviceStore method updatePortStatus.

@Override
public synchronized DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId, PortDescription portDescription) {
    final Timestamp newTimestamp;
    try {
        newTimestamp = deviceClockService.getTimestamp(deviceId);
    } catch (IllegalStateException e) {
        log.info("Timestamp was not available for device {}", deviceId);
        log.debug("  discarding {}", portDescription);
        // See updatePorts comment
        return null;
    }
    final Timestamped<PortDescription> deltaDesc = new Timestamped<>(portDescription, newTimestamp);
    final DeviceEvent event;
    Timestamped<PortDescription> mergedDesc;
    final Map<ProviderId, DeviceDescriptions> device = getOrCreateDeviceDescriptionsMap(deviceId);
    synchronized (device) {
        event = updatePortStatusInternal(providerId, deviceId, deltaDesc);
        mergedDesc = device.get(providerId).getPortDesc(portDescription.portNumber());
        // on delete the port is removed, thus using latest known description
        if (mergedDesc == null) {
            mergedDesc = new Timestamped<>(portDescription, newTimestamp);
        }
    }
    if (event != null) {
        log.debug("Notifying peers of a port status update topology event for providerId: {} and deviceId: {}", providerId, deviceId);
        notifyPeers(new InternalPortStatusEvent(providerId, deviceId, mergedDesc));
    }
    return event;
}
Also used : ProviderId(org.onosproject.net.provider.ProviderId) DeviceEvent(org.onosproject.net.device.DeviceEvent) PortDescription(org.onosproject.net.device.PortDescription) Timestamped(org.onosproject.store.impl.Timestamped) WallClockTimestamp(org.onosproject.store.service.WallClockTimestamp) Timestamp(org.onosproject.store.Timestamp) MastershipBasedTimestamp(org.onosproject.store.impl.MastershipBasedTimestamp) MultiValuedTimestamp(org.onosproject.store.service.MultiValuedTimestamp)

Example 9 with ProviderId

use of org.onosproject.net.provider.ProviderId in project onos by opennetworkinglab.

the class GossipDeviceStore method handleAdvertisement.

/**
 * Responds to anti-entropy advertisement message.
 * <p>
 * Notify sender about out-dated information using regular replication message.
 * Send back advertisement to sender if not in sync.
 *
 * @param advertisement to respond to
 */
private void handleAdvertisement(DeviceAntiEntropyAdvertisement advertisement) {
    /*
         * NOTE that when an instance rejoins the cluster, it will generate
         * device events and send to the local apps through the delegate. This
         * approach might be not the best if the apps are not enough robust or
         * if there is no proper coordination in the cluster. Also, note that
         * any ECMap will act on the same way during the bootstrap process
         */
    final NodeId sender = advertisement.sender();
    Map<DeviceFragmentId, Timestamp> devAds = new HashMap<>(advertisement.deviceFingerPrints());
    Map<PortFragmentId, Timestamp> portAds = new HashMap<>(advertisement.ports());
    Map<DeviceId, Timestamp> offlineAds = new HashMap<>(advertisement.offline());
    // Fragments to request
    Collection<DeviceFragmentId> reqDevices = new ArrayList<>();
    Collection<PortFragmentId> reqPorts = new ArrayList<>();
    for (Entry<DeviceId, Map<ProviderId, DeviceDescriptions>> de : deviceDescs.entrySet()) {
        final DeviceId deviceId = de.getKey();
        final Map<ProviderId, DeviceDescriptions> lDevice = de.getValue();
        synchronized (lDevice) {
            // latestTimestamp across provider
            // Note: can be null initially
            Timestamp localLatest = offline.get(deviceId);
            // handle device Ads
            for (Entry<ProviderId, DeviceDescriptions> prov : lDevice.entrySet()) {
                final ProviderId provId = prov.getKey();
                final DeviceDescriptions lDeviceDescs = prov.getValue();
                final DeviceFragmentId devFragId = new DeviceFragmentId(deviceId, provId);
                Timestamped<DeviceDescription> lProvDevice = lDeviceDescs.getDeviceDesc();
                Timestamp advDevTimestamp = devAds.get(devFragId);
                if (advDevTimestamp == null || lProvDevice.isNewerThan(advDevTimestamp)) {
                    // remote does not have it or outdated, suggest
                    log.trace("send to {} device update {} for {}", sender, lProvDevice, deviceId);
                    notifyPeer(sender, new InternalDeviceEvent(provId, deviceId, lProvDevice));
                } else if (!lProvDevice.timestamp().equals(advDevTimestamp)) {
                    // local is outdated, request
                    log.trace("need update {} < {} for device {} from {}", lProvDevice.timestamp(), advDevTimestamp, deviceId, sender);
                    reqDevices.add(devFragId);
                }
                // handle port Ads
                for (Entry<PortNumber, Timestamped<PortDescription>> pe : lDeviceDescs.getPortDescs().entrySet()) {
                    final PortNumber num = pe.getKey();
                    final Timestamped<PortDescription> lPort = pe.getValue();
                    final PortFragmentId portFragId = new PortFragmentId(deviceId, provId, num);
                    Timestamp advPortTimestamp = portAds.get(portFragId);
                    if (advPortTimestamp == null || lPort.isNewerThan(advPortTimestamp)) {
                        // remote does not have it or outdated, suggest
                        log.trace("send to {} port update {} for {}/{}", sender, lPort, deviceId, num);
                        notifyPeer(sender, new InternalPortStatusEvent(provId, deviceId, lPort));
                    } else if (!lPort.timestamp().equals(advPortTimestamp)) {
                        // local is outdated, request
                        log.trace("need update {} < {} for port {} from {}", lPort.timestamp(), advPortTimestamp, num, sender);
                        reqPorts.add(portFragId);
                    }
                    // remove port Ad already processed
                    portAds.remove(portFragId);
                }
                // end local port loop
                // remove device Ad already processed
                devAds.remove(devFragId);
                // find latest and update
                final Timestamp providerLatest = lDeviceDescs.getLatestTimestamp();
                if (localLatest == null || providerLatest.compareTo(localLatest) > 0) {
                    localLatest = providerLatest;
                }
            }
            // end local provider loop
            // checking if remote timestamp is more recent.
            Timestamp rOffline = offlineAds.get(deviceId);
            if (localLatest == null || (rOffline != null && rOffline.compareTo(localLatest) > 0)) {
                // remote offline timestamp suggests that the
                // device is off-line
                log.trace("remote offline timestamp from {} suggests that the device {} is off-line", sender, deviceId);
                markOfflineInternal(deviceId, rOffline);
            }
            Timestamp lOffline = offline.get(deviceId);
            if (lOffline != null && rOffline == null) {
                // locally offline, but remote is online, suggest offline
                log.trace("suggest to {} sthat the device {} is off-line", sender, deviceId);
                notifyPeer(sender, new InternalDeviceStatusChangeEvent(deviceId, lOffline, false));
            }
            // remove device offline Ad already processed
            offlineAds.remove(deviceId);
        }
    // end local device loop
    }
    // device lock
    // If there is any Ads left, request them
    log.trace("Ads left {}, {}", devAds, portAds);
    reqDevices.addAll(devAds.keySet());
    reqPorts.addAll(portAds.keySet());
    if (reqDevices.isEmpty() && reqPorts.isEmpty()) {
        log.trace("Nothing to request to remote peer {}", sender);
        return;
    }
    log.debug("Need to sync {} {}", reqDevices, reqPorts);
    // 2-way Anti-Entropy for now
    try {
        unicastMessage(sender, DEVICE_ADVERTISE, createAdvertisement());
    } catch (IOException e) {
        log.error("Failed to send response advertisement to " + sender, e);
    }
// Sketch of 3-way Anti-Entropy
// DeviceAntiEntropyRequest request = new DeviceAntiEntropyRequest(self, reqDevices, reqPorts);
// ClusterMessage message = new ClusterMessage(
// clusterService.getLocalNode().id(),
// GossipDeviceStoreMessageSubjects.DEVICE_REQUEST,
// SERIALIZER.encode(request));
// 
// try {
// clusterCommunicator.unicast(message, advertisement.sender());
// } catch (IOException e) {
// log.error("Failed to send advertisement reply to "
// + advertisement.sender(), e);
// }
}
Also used : ProviderId(org.onosproject.net.provider.ProviderId) DeviceDescription(org.onosproject.net.device.DeviceDescription) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) DeviceId(org.onosproject.net.DeviceId) ArrayList(java.util.ArrayList) WallClockTimestamp(org.onosproject.store.service.WallClockTimestamp) Timestamp(org.onosproject.store.Timestamp) MastershipBasedTimestamp(org.onosproject.store.impl.MastershipBasedTimestamp) MultiValuedTimestamp(org.onosproject.store.service.MultiValuedTimestamp) Timestamped(org.onosproject.store.impl.Timestamped) PortDescription(org.onosproject.net.device.PortDescription) IOException(java.io.IOException) ControllerNodeToNodeId.toNodeId(org.onosproject.cluster.ControllerNodeToNodeId.toNodeId) NodeId(org.onosproject.cluster.NodeId) PortNumber(org.onosproject.net.PortNumber) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) EventuallyConsistentMap(org.onosproject.store.service.EventuallyConsistentMap)

Example 10 with ProviderId

use of org.onosproject.net.provider.ProviderId in project onos by opennetworkinglab.

the class GossipDeviceStore method handleDeviceEvent.

private void handleDeviceEvent(InternalDeviceEvent event) {
    ProviderId providerId = event.providerId();
    DeviceId deviceId = event.deviceId();
    Timestamped<DeviceDescription> deviceDescription = event.deviceDescription();
    try {
        notifyDelegateIfNotNull(createOrUpdateDeviceInternal(providerId, deviceId, deviceDescription));
    } catch (Exception e) {
        log.warn("Exception thrown handling device update", e);
    }
}
Also used : ProviderId(org.onosproject.net.provider.ProviderId) DeviceDescription(org.onosproject.net.device.DeviceDescription) DeviceId(org.onosproject.net.DeviceId) IOException(java.io.IOException)

Aggregations

ProviderId (org.onosproject.net.provider.ProviderId)62 DefaultDevice (org.onosproject.net.DefaultDevice)15 DeviceId (org.onosproject.net.DeviceId)13 Tunnel (org.onosproject.incubator.net.tunnel.Tunnel)12 DefaultAnnotations (org.onosproject.net.DefaultAnnotations)12 Device (org.onosproject.net.Device)12 PortDescription (org.onosproject.net.device.PortDescription)12 TunnelProvider (org.onosproject.incubator.net.tunnel.TunnelProvider)10 DefaultPort (org.onosproject.net.DefaultPort)10 Port (org.onosproject.net.Port)10 DeviceEvent (org.onosproject.net.device.DeviceEvent)10 MastershipBasedTimestamp (org.onosproject.store.impl.MastershipBasedTimestamp)10 PortNumber (org.onosproject.net.PortNumber)9 DeviceDescription (org.onosproject.net.device.DeviceDescription)9 Timestamp (org.onosproject.store.Timestamp)9 MultiValuedTimestamp (org.onosproject.store.service.MultiValuedTimestamp)9 WallClockTimestamp (org.onosproject.store.service.WallClockTimestamp)9 DefaultTunnel (org.onosproject.incubator.net.tunnel.DefaultTunnel)7 TunnelId (org.onosproject.incubator.net.tunnel.TunnelId)7 DefaultLinkDescription (org.onosproject.net.link.DefaultLinkDescription)7