blob: 52a3924cc72c90a0843dc41a4bcc0a69e74d1b48 [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.vpls;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.routing.IntentSynchronizationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Synchronizes intents between the in-memory intent store and the
* IntentService.
*/
public class IntentInstaller {
private static final String SUBMIT =
"Submitting intents to the Intent Synchronizer";
private static final String WITHDRAW =
"Withdrawing intents to the Intent Synchronizer";
private static final String SP2MP =
"Building sp2mp intent from {}";
private static final String MP2SP =
"Building mp2sp intent to {}";
private static final Logger log = LoggerFactory.getLogger(
IntentInstaller.class);
private static final int PRIORITY_OFFSET = 1000;
private static final Set<IntentState> WITHDRAWN_INTENT_STATES =
ImmutableSet.of(IntentState.WITHDRAWN,
IntentState.WITHDRAW_REQ,
IntentState.WITHDRAWING);
static final String PREFIX_BROADCAST = "brc";
static final String PREFIX_UNICAST = "uni";
static final String DASH = "-";
private final ApplicationId appId;
private final IntentSynchronizationService intentSynchronizer;
private final IntentService intentService;
/**
* Class constructor.
*
* @param appId the Application ID
* @param intentService the intent service
* @param intentSynchronizer the intent synchronizer service
*/
public IntentInstaller(ApplicationId appId, IntentService intentService,
IntentSynchronizationService intentSynchronizer) {
this.appId = appId;
this.intentService = intentService;
this.intentSynchronizer = intentSynchronizer;
}
/**
* Requests to install the intents passed as argument to the Intent Service.
*
* @param intents intents to be submitted
*/
protected void submitIntents(Collection<Intent> intents) {
log.debug(SUBMIT);
intents.forEach(intentSynchronizer::submit);
}
/**
* Requests to withdraw the intents passed as argument to the Intent Service.
*
* @param intents intents to be withdraw
*/
protected void withdrawIntents(Collection<Intent> intents) {
log.debug(WITHDRAW);
intents.forEach(intentSynchronizer::withdraw);
}
/**
* Returns list of intents belongs to a VPLS.
*
* @param name required VPLS network name
* @return list of intents belongs to a VPLS
*/
protected List<Intent> getIntentsFromVpls(String name) {
List<Intent> intents = Lists.newArrayList();
intentService.getIntents().forEach(intent -> {
if (intent.key().toString().startsWith(name)) {
intents.add(intent);
}
});
return intents;
}
/**
* Builds a broadcast intent.
*
* @param key key to identify the intent
* @param src the source connect point
* @param dsts the destination connect points
* @return the generated single-point to multi-point intent
*/
protected SinglePointToMultiPointIntent buildBrcIntent(Key key,
FilteredConnectPoint src,
Set<FilteredConnectPoint> dsts) {
log.debug(SP2MP, src);
SinglePointToMultiPointIntent intent;
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthDst(MacAddress.BROADCAST)
.build();
intent = SinglePointToMultiPointIntent.builder()
.appId(appId)
.key(key)
.selector(selector)
.filteredIngressPoint(src)
.filteredEgressPoints(dsts)
.priority(PRIORITY_OFFSET)
.build();
return intent;
}
/**
* Builds a unicast intent.
*
* @param key key to identify the intent
* @param srcs the source Connect Points
* @param dst the destination Connect Point
* @param host destination Host
* @return the generated multi-point to single-point intent
*/
protected MultiPointToSinglePointIntent buildUniIntent(Key key,
Set<FilteredConnectPoint> srcs,
FilteredConnectPoint dst,
Host host) {
log.debug(MP2SP, dst);
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthDst(host.mac())
.build();
return MultiPointToSinglePointIntent.builder()
.appId(appId)
.key(key)
.selector(selector)
.filteredIngressPoints(srcs)
.filteredEgressPoint(dst)
.priority(PRIORITY_OFFSET)
.build();
}
/**
* Builds an intent Key for either for a single-point to multi-point or
* multi-point to single-point intent, based on a prefix that defines
* the type of intent, the single connection point representing the source
* or the destination and the VLAN identifier representing the network.
*
* @param prefix key prefix
* @param cPoint connect point for single source/destination
* @param networkName VPLS network name
* @param hostMac source/destination mac address
* @return key to identify the intent
*/
protected Key buildKey(String prefix,
ConnectPoint cPoint,
String networkName,
MacAddress hostMac) {
String keyString = networkName +
DASH +
prefix +
DASH +
cPoint.deviceId() +
DASH +
cPoint.port() +
DASH +
hostMac;
return Key.of(keyString, appId);
}
/**
* Returns true if the specified intent exists; false otherwise.
*
* @param intentKey intent key
* @return true if the intent exists, false otherwise
*/
protected boolean intentExists(Key intentKey) {
if (intentService.getIntent(intentKey) == null) {
return false;
}
// Intent does not exist if intent withdrawn
IntentState currentIntentState = intentService.getIntentState(intentKey);
if (WITHDRAWN_INTENT_STATES.contains(currentIntentState)) {
return false;
}
return true;
}
}