blob: a75da25745fc1d96ec9104cec079a4efdefcb8a7 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.resource.impl;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import org.onlab.util.Bandwidth;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.resource.BandwidthCapacity;
import org.onosproject.net.resource.ResourceAdminService;
import org.onosproject.net.resource.Resources;
import org.slf4j.Logger;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableSet;
// TODO Consider merging this with ResourceDeviceListener.
/**
* Handler for NetworkConfiguration changes.
*/
@Beta
final class ResourceNetworkConfigListener implements NetworkConfigListener {
/**
* Config classes relevant to this listener.
*/
private static final Set<Class<?>> CONFIG_CLASSES = ImmutableSet.of(BandwidthCapacity.class);
private final Logger log = getLogger(getClass());
private final ResourceAdminService adminService;
private final NetworkConfigService cfgService;
private final MastershipService mastershipService;
private final ExecutorService executor;
/**
* Creates an instance of listener.
*
* @param adminService {@link ResourceAdminService}
* @param cfgService {@link NetworkConfigService}
* @param mastershipService {@link MastershipService}
* @param executor Executor to use.
*/
ResourceNetworkConfigListener(ResourceAdminService adminService, NetworkConfigService cfgService,
MastershipService mastershipService, ExecutorService executor) {
this.adminService = checkNotNull(adminService);
this.cfgService = checkNotNull(cfgService);
this.mastershipService = checkNotNull(mastershipService);
this.executor = checkNotNull(executor);
}
@Override
public boolean isRelevant(NetworkConfigEvent event) {
switch (event.type()) {
case CONFIG_ADDED:
case CONFIG_REMOVED:
case CONFIG_UPDATED:
return CONFIG_CLASSES.contains(event.configClass());
case CONFIG_REGISTERED:
case CONFIG_UNREGISTERED:
default:
return false;
}
}
@Override
public void event(NetworkConfigEvent event) {
if (event.configClass() == BandwidthCapacity.class) {
executor.execute(() -> {
try {
handleBandwidthCapacity(event);
} catch (Exception e) {
log.error("Exception handling BandwidthCapacity", e);
}
});
}
}
private void handleBandwidthCapacity(NetworkConfigEvent event) {
checkArgument(event.configClass() == BandwidthCapacity.class);
ConnectPoint cp = (ConnectPoint) event.subject();
if (!mastershipService.isLocalMaster(cp.deviceId())) {
return;
}
BandwidthCapacity bwCapacity = cfgService.getConfig(cp, BandwidthCapacity.class);
switch (event.type()) {
case CONFIG_ADDED:
if (!adminService.register(Resources.continuous(cp.deviceId(),
cp.port(), Bandwidth.class)
.resource(bwCapacity.capacity().bps()))) {
log.info("Failed to register Bandwidth for {}, attempting update", cp);
// Bandwidth based on port speed, was probably already registered.
// need to update to the valued based on configuration
if (!updateRegistration(cp, bwCapacity)) {
log.warn("Failed to update Bandwidth for {}", cp);
}
}
break;
case CONFIG_UPDATED:
if (!updateRegistration(cp, bwCapacity)) {
log.warn("Failed to update Bandwidth for {}", cp);
}
break;
case CONFIG_REMOVED:
// FIXME Following should be an update to the value based on port speed
if (!adminService.unregister(Resources.continuous(cp.deviceId(),
cp.port(),
Bandwidth.class).id())) {
log.warn("Failed to unregister Bandwidth for {}", cp);
}
break;
case CONFIG_REGISTERED:
case CONFIG_UNREGISTERED:
// no-op
break;
default:
break;
}
}
private boolean updateRegistration(ConnectPoint cp, BandwidthCapacity bwCapacity) {
// FIXME workaround until replace/update semantics become available
// this potentially blows up existing registration
// or end up as no-op
//
// Current code end up in situation like below:
// PortNumber: 2
// MplsLabel: [[16‥240)]
// VlanId: [[0‥4095)]
// Bandwidth: 2000000.000000
// Bandwidth: 20000000.000000
//
// but both unregisterResources(..) and registerResources(..)
// returns true (success)
if (!adminService.unregister(
Resources.continuous(cp.deviceId(), cp.port(), Bandwidth.class).id())) {
log.warn("unregisterResources for {} failed", cp);
}
return adminService.register(Resources.continuous(cp.deviceId(),
cp.port(),
Bandwidth.class).resource(bwCapacity.capacity().bps()));
}
}