mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-04 19:56:49 +02:00
[ONOS-5283] Arbitrary connect points, support multiple vlans
Change-Id: I9bd3536c08dfd8a637293460395de7e2a1dc1dc1
This commit is contained in:
parent
8d4e8bccdf
commit
5fd282e642
@ -15,18 +15,18 @@
|
||||
*/
|
||||
package org.onosproject.vpls;
|
||||
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onlab.packet.VlanId;
|
||||
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.DefaultTrafficTreatment;
|
||||
import org.onosproject.net.flow.TrafficSelector;
|
||||
import org.onosproject.net.flow.TrafficTreatment;
|
||||
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;
|
||||
@ -34,24 +34,37 @@ import org.onosproject.routing.IntentSynchronizationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 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 String PREFIX_BROADCAST = "brc";
|
||||
private static final String PREFIX_UNICAST = "uni";
|
||||
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;
|
||||
@ -71,174 +84,151 @@ public class IntentInstaller {
|
||||
this.intentSynchronizer = intentSynchronizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the requests for creating and submit intents.
|
||||
* Single Points to Multi Point intents are created for all the configured
|
||||
* Connect Points. Multi Point to Single Point intents are created for
|
||||
* Connect Points configured that have hosts attached.
|
||||
*
|
||||
* @param confHostPresentCPoint A map of Connect Points with the eventual
|
||||
* MAC address of the host attached, by VLAN
|
||||
*/
|
||||
protected void installIntents(SetMultimap<VlanId,
|
||||
Pair<ConnectPoint,
|
||||
MacAddress>> confHostPresentCPoint) {
|
||||
List<Intent> intents = new ArrayList<>();
|
||||
|
||||
confHostPresentCPoint.keySet()
|
||||
.stream()
|
||||
.filter(vlanId -> confHostPresentCPoint.get(vlanId) != null)
|
||||
.forEach(vlanId -> {
|
||||
Set<Pair<ConnectPoint, MacAddress>> cPoints =
|
||||
confHostPresentCPoint.get(vlanId);
|
||||
cPoints.forEach(cPoint -> {
|
||||
MacAddress mac = cPoint.getValue();
|
||||
ConnectPoint src = cPoint.getKey();
|
||||
Set<ConnectPoint> dsts = cPoints.stream()
|
||||
.map(Pair::getKey)
|
||||
.filter(cp -> !cp.equals(src))
|
||||
.collect(Collectors.toSet());
|
||||
Key brcKey = buildKey(PREFIX_BROADCAST, src, vlanId);
|
||||
|
||||
if (dsts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
intents.add(buildBrcIntent(brcKey, src, dsts, vlanId));
|
||||
|
||||
if (mac != null && countMacInCPoints(cPoints) > 1) {
|
||||
Key uniKey = buildKey(PREFIX_UNICAST, src, vlanId);
|
||||
MultiPointToSinglePointIntent uniIntent =
|
||||
buildUniIntent(uniKey,
|
||||
dsts,
|
||||
src,
|
||||
vlanId,
|
||||
mac);
|
||||
intents.add(uniIntent);
|
||||
}
|
||||
});
|
||||
});
|
||||
submitIntents(intents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to install the intents passed as argument to the Intent Service.
|
||||
*
|
||||
* @param intents intents to be submitted
|
||||
*/
|
||||
private void submitIntents(Collection<Intent> intents) {
|
||||
log.debug("Submitting intents to the Intent Synchronizer");
|
||||
intents.forEach(intent -> {
|
||||
intentSynchronizer.submit(intent);
|
||||
});
|
||||
protected void submitIntents(Collection<Intent> intents) {
|
||||
log.debug(SUBMIT);
|
||||
intents.forEach(intentSynchronizer::submit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Single Point to Multi Point intent.
|
||||
* Requests to withdraw the intents passed as argument to the Intent Service.
|
||||
*
|
||||
* @param src The source Connect Point
|
||||
* @param dsts The destination Connect Points
|
||||
* @return Single Point to Multi Point intent generated.
|
||||
* @param intents intents to be withdraw
|
||||
*/
|
||||
private SinglePointToMultiPointIntent buildBrcIntent(Key key,
|
||||
ConnectPoint src,
|
||||
Set<ConnectPoint> dsts,
|
||||
VlanId vlanId) {
|
||||
log.debug("Building p2mp intent from {}", src);
|
||||
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;
|
||||
|
||||
TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
|
||||
|
||||
TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
|
||||
TrafficSelector selector = DefaultTrafficSelector.builder()
|
||||
.matchEthDst(MacAddress.BROADCAST)
|
||||
.matchVlanId(vlanId);
|
||||
|
||||
TrafficSelector selector = builder.build();
|
||||
.build();
|
||||
|
||||
intent = SinglePointToMultiPointIntent.builder()
|
||||
.appId(appId)
|
||||
.key(key)
|
||||
.selector(selector)
|
||||
.treatment(treatment)
|
||||
.ingressPoint(src)
|
||||
.egressPoints(dsts)
|
||||
.filteredIngressPoint(src)
|
||||
.filteredEgressPoints(dsts)
|
||||
.priority(PRIORITY_OFFSET)
|
||||
.build();
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Multi Point to Single Point intent.
|
||||
* Builds a unicast intent.
|
||||
*
|
||||
* @param srcs The source Connect Points
|
||||
* @param dst The destination Connect Point
|
||||
* @return Multi Point to Single Point intent generated.
|
||||
* @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
|
||||
*/
|
||||
private MultiPointToSinglePointIntent buildUniIntent(Key key,
|
||||
Set<ConnectPoint> srcs,
|
||||
ConnectPoint dst,
|
||||
VlanId vlanId,
|
||||
MacAddress mac) {
|
||||
log.debug("Building mp2p intent to {}", dst);
|
||||
protected MultiPointToSinglePointIntent buildUniIntent(Key key,
|
||||
Set<FilteredConnectPoint> srcs,
|
||||
FilteredConnectPoint dst,
|
||||
Host host) {
|
||||
log.debug(MP2SP, dst);
|
||||
|
||||
MultiPointToSinglePointIntent intent;
|
||||
TrafficSelector selector = DefaultTrafficSelector.builder()
|
||||
.matchEthDst(host.mac())
|
||||
.build();
|
||||
|
||||
TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
|
||||
|
||||
TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
|
||||
.matchEthDst(mac)
|
||||
.matchVlanId(vlanId);
|
||||
|
||||
TrafficSelector selector = builder.build();
|
||||
|
||||
intent = MultiPointToSinglePointIntent.builder()
|
||||
return MultiPointToSinglePointIntent.builder()
|
||||
.appId(appId)
|
||||
.key(key)
|
||||
.selector(selector)
|
||||
.treatment(treatment)
|
||||
.ingressPoints(srcs)
|
||||
.egressPoint(dst)
|
||||
.filteredIngressPoints(srcs)
|
||||
.filteredEgressPoint(dst)
|
||||
.priority(PRIORITY_OFFSET)
|
||||
.build();
|
||||
return intent;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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 id representing the network.
|
||||
* or the destination and the VLAN identifier representing the network.
|
||||
*
|
||||
* @param cPoint the source or destination connect point
|
||||
* @param vlanId the network vlan id
|
||||
* @param prefix prefix string
|
||||
* @return
|
||||
* @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
|
||||
*/
|
||||
private Key buildKey(String prefix, ConnectPoint cPoint, VlanId vlanId) {
|
||||
String keyString = new StringBuilder()
|
||||
.append(prefix)
|
||||
.append("-")
|
||||
.append(cPoint.deviceId())
|
||||
.append("-")
|
||||
.append(cPoint.port())
|
||||
.append("-")
|
||||
.append(vlanId)
|
||||
.toString();
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of mac addresses associated to a specific list of
|
||||
* ConnectPoint.
|
||||
* Returns true if the specified intent exists; false otherwise.
|
||||
*
|
||||
* @param cPoints Set of ConnectPoints, eventually bound to the MAC of the
|
||||
* host attached
|
||||
* @return number of mac addresses found.
|
||||
* @param intentKey intent key
|
||||
* @return true if the intent exists, false otherwise
|
||||
*/
|
||||
private int countMacInCPoints(Set<Pair<ConnectPoint, MacAddress>> cPoints) {
|
||||
return (int) cPoints.stream().filter(p -> p.getValue() != null).count();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,10 +15,10 @@
|
||||
*/
|
||||
package org.onosproject.vpls;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.felix.scr.annotations.Activate;
|
||||
import org.apache.felix.scr.annotations.Component;
|
||||
import org.apache.felix.scr.annotations.Deactivate;
|
||||
@ -29,29 +29,56 @@ import org.onlab.packet.VlanId;
|
||||
import org.onosproject.app.ApplicationService;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.incubator.net.intf.Interface;
|
||||
import org.onosproject.incubator.net.intf.InterfaceEvent;
|
||||
import org.onosproject.incubator.net.intf.InterfaceListener;
|
||||
import org.onosproject.incubator.net.intf.InterfaceService;
|
||||
import org.onosproject.net.ConnectPoint;
|
||||
import org.onosproject.net.FilteredConnectPoint;
|
||||
import org.onosproject.net.Host;
|
||||
import org.onosproject.net.config.NetworkConfigEvent;
|
||||
import org.onosproject.net.config.NetworkConfigListener;
|
||||
import org.onosproject.net.config.NetworkConfigService;
|
||||
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||
import org.onosproject.net.flow.TrafficSelector;
|
||||
import org.onosproject.net.flow.criteria.Criterion;
|
||||
import org.onosproject.net.flow.criteria.VlanIdCriterion;
|
||||
import org.onosproject.net.host.HostEvent;
|
||||
import org.onosproject.net.host.HostListener;
|
||||
import org.onosproject.net.host.HostService;
|
||||
import org.onosproject.net.intent.Intent;
|
||||
import org.onosproject.net.intent.IntentService;
|
||||
import org.onosproject.net.intent.Key;
|
||||
import org.onosproject.routing.IntentSynchronizationService;
|
||||
import org.onosproject.vpls.config.VplsConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
import static org.onosproject.vpls.IntentInstaller.PREFIX_BROADCAST;
|
||||
import static org.onosproject.vpls.IntentInstaller.PREFIX_UNICAST;
|
||||
|
||||
/**
|
||||
* Application to create L2 broadcast overlay networks using VLAN.
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
public class Vpls {
|
||||
protected static final String VPLS_APP = "org.onosproject.vpls";
|
||||
/**
|
||||
* Application name of VPLS.
|
||||
*/
|
||||
static final String VPLS_APP = "org.onosproject.vpls";
|
||||
|
||||
private static final String HOST_FCP_NOT_FOUND =
|
||||
"Filtered connected point for host {} not found";
|
||||
private static final String HOST_EVENT = "Received HostEvent {}";
|
||||
private static final String INTF_CONF_EVENT =
|
||||
"Received InterfaceConfigEvent {}";
|
||||
private static final String NET_CONF_EVENT =
|
||||
"Received NetworkConfigEvent {}";
|
||||
|
||||
private final Logger log = getLogger(getClass());
|
||||
|
||||
@ -73,11 +100,20 @@ public class Vpls {
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected IntentSynchronizationService intentSynchronizer;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected NetworkConfigService configService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected VplsConfigurationService vplsConfigService;
|
||||
|
||||
private final HostListener hostListener = new InternalHostListener();
|
||||
|
||||
private final InternalInterfaceListener interfaceListener
|
||||
= new InternalInterfaceListener();
|
||||
|
||||
private final InternalNetworkConfigListener configListener =
|
||||
new InternalNetworkConfigListener();
|
||||
|
||||
private IntentInstaller intentInstaller;
|
||||
|
||||
private ApplicationId appId;
|
||||
@ -97,111 +133,250 @@ public class Vpls {
|
||||
|
||||
hostService.addListener(hostListener);
|
||||
interfaceService.addListener(interfaceListener);
|
||||
configService.addListener(configListener);
|
||||
|
||||
setupConnectivity();
|
||||
setupConnectivity(false);
|
||||
|
||||
log.info("Activated");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
configService.removeListener(configListener);
|
||||
intentSynchronizer.removeIntentsByAppId(appId);
|
||||
log.info("Deactivated");
|
||||
}
|
||||
|
||||
protected void setupConnectivity() {
|
||||
/*
|
||||
* Parse Configuration and get Connect Point by VlanId.
|
||||
*/
|
||||
SetMultimap<VlanId, ConnectPoint> confCPointsByVlan = getConfigCPoints();
|
||||
/**
|
||||
* Sets up connectivity for all VPLSs.
|
||||
*
|
||||
* @param isNetworkConfigEvent true if this function is triggered
|
||||
* by NetworkConfigEvent; false otherwise
|
||||
*/
|
||||
private void setupConnectivity(boolean isNetworkConfigEvent) {
|
||||
SetMultimap<String, Interface> networkInterfaces =
|
||||
vplsConfigService.getVplsNetworks();
|
||||
|
||||
/*
|
||||
* Check that configured Connect Points have hosts attached and
|
||||
* associate their Mac Address to the Connect Points configured.
|
||||
*/
|
||||
SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
|
||||
pairAvailableHosts(confCPointsByVlan);
|
||||
Set<String> vplsAffectedByApi =
|
||||
new HashSet<>(vplsConfigService.getVplsAffectedByApi());
|
||||
|
||||
/*
|
||||
* Create and submit intents between the Connect Points.
|
||||
* Intents for broadcast between all the configured Connect Points.
|
||||
* Intents for unicast between all the configured Connect Points with
|
||||
* hosts attached.
|
||||
*/
|
||||
intentInstaller.installIntents(confHostPresentCPoint);
|
||||
if (isNetworkConfigEvent && vplsAffectedByApi.isEmpty()) {
|
||||
vplsAffectedByApi.addAll(vplsConfigService.getOldVpls());
|
||||
}
|
||||
|
||||
networkInterfaces.asMap().forEach((networkName, interfaces) -> {
|
||||
Set<Host> hosts = Sets.newHashSet();
|
||||
interfaces.forEach(intf -> {
|
||||
// Add hosts that belongs to the specific VPLS
|
||||
hostService.getConnectedHosts(intf.connectPoint())
|
||||
.stream()
|
||||
.filter(host -> host.vlan().equals(intf.vlan()))
|
||||
.forEach(hosts::add);
|
||||
});
|
||||
|
||||
setupConnectivity(networkName, interfaces, hosts,
|
||||
vplsAffectedByApi.contains(networkName));
|
||||
vplsAffectedByApi.remove(networkName);
|
||||
});
|
||||
|
||||
if (!vplsAffectedByApi.isEmpty()) {
|
||||
for (String networkName:vplsAffectedByApi) {
|
||||
withdrawIntents(networkName, Lists.newArrayList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the list of configured interfaces with a VLAN Id.
|
||||
* Sets up connectivity for specific VPLS.
|
||||
*
|
||||
* @return the interfaces grouped by vlan id
|
||||
* @param networkName the VPLS name
|
||||
* @param interfaces the interfaces that belong to the VPLS
|
||||
* @param hosts the hosts that belong to the VPLS
|
||||
* @param affectedByApi true if this function is triggered from the APIs;
|
||||
* false otherwise
|
||||
*/
|
||||
protected SetMultimap<VlanId, ConnectPoint> getConfigCPoints() {
|
||||
log.debug("Checking interface configuration");
|
||||
private void setupConnectivity(String networkName,
|
||||
Collection<Interface> interfaces,
|
||||
Set<Host> hosts,
|
||||
boolean affectedByApi) {
|
||||
List<Intent> intents = Lists.newArrayList();
|
||||
List<Key> keys = Lists.newArrayList();
|
||||
Set<FilteredConnectPoint> fcPoints = buildFCPoints(interfaces);
|
||||
|
||||
SetMultimap<VlanId, ConnectPoint> confCPointsByVlan =
|
||||
HashMultimap.create();
|
||||
intents.addAll(buildUnicastIntents(
|
||||
networkName, hosts, fcPoints, affectedByApi));
|
||||
intents.addAll(buildBroadcastIntents(
|
||||
networkName, fcPoints, affectedByApi));
|
||||
|
||||
interfaceService.getInterfaces()
|
||||
.stream()
|
||||
.filter(intf -> intf.ipAddressesList().isEmpty())
|
||||
.forEach(intf -> confCPointsByVlan.put(intf.vlan(), intf.connectPoint()));
|
||||
return confCPointsByVlan;
|
||||
if (affectedByApi) {
|
||||
intents.forEach(intent -> keys.add(intent.key()));
|
||||
withdrawIntents(networkName, keys);
|
||||
}
|
||||
|
||||
intentInstaller.submitIntents(intents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if for any ConnectPoint configured there's an host presents
|
||||
* and in case it associates them together.
|
||||
* Withdraws intents belonging to a VPLS, given a VPLS name.
|
||||
*
|
||||
* @param confCPointsByVlan the configured ConnectPoints grouped by VLAN Id
|
||||
* @return the configured ConnectPoints with eventual hosts associated.
|
||||
* @param networkName the VPLS name
|
||||
* @param keys the keys of the intents to be installed
|
||||
*/
|
||||
protected SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> pairAvailableHosts(
|
||||
SetMultimap<VlanId, ConnectPoint> confCPointsByVlan) {
|
||||
log.debug("Binding connected hosts MAC addresses");
|
||||
private void withdrawIntents(String networkName,
|
||||
List<Key> keys) {
|
||||
List<Intent> intents = Lists.newArrayList();
|
||||
|
||||
SetMultimap<VlanId, Pair<ConnectPoint, MacAddress>> confHostPresentCPoint =
|
||||
HashMultimap.create();
|
||||
intentInstaller.getIntentsFromVpls(networkName)
|
||||
.forEach(intent -> {
|
||||
if (!keys.contains(intent.key())) {
|
||||
intents.add(intent);
|
||||
}
|
||||
});
|
||||
|
||||
confCPointsByVlan.entries()
|
||||
.forEach(e -> bindMacAddr(e, confHostPresentCPoint));
|
||||
|
||||
return confHostPresentCPoint;
|
||||
intentInstaller.withdrawIntents(intents);
|
||||
}
|
||||
|
||||
// Bind VLAN Id with hosts and connect points
|
||||
private void bindMacAddr(Map.Entry<VlanId, ConnectPoint> e,
|
||||
SetMultimap<VlanId, Pair<ConnectPoint,
|
||||
MacAddress>> confHostPresentCPoint) {
|
||||
VlanId vlanId = e.getKey();
|
||||
ConnectPoint cp = e.getValue();
|
||||
Set<Host> connectedHosts = hostService.getConnectedHosts(cp);
|
||||
connectedHosts.forEach(host -> {
|
||||
if (host.vlan().equals(vlanId)) {
|
||||
confHostPresentCPoint.put(vlanId, Pair.of(cp, host.mac()));
|
||||
} else {
|
||||
confHostPresentCPoint.put(vlanId, Pair.of(cp, null));
|
||||
/**
|
||||
* Sets up broadcast intents between any given filtered connect point.
|
||||
*
|
||||
* @param networkName the VPLS name
|
||||
* @param fcPoints the set of filtered connect points
|
||||
* @param affectedByApi true if the function triggered from APIs;
|
||||
* false otherwise
|
||||
* @return the set of broadcast intents
|
||||
*/
|
||||
private Set<Intent> buildBroadcastIntents(String networkName,
|
||||
Set<FilteredConnectPoint> fcPoints,
|
||||
boolean affectedByApi) {
|
||||
Set<Intent> intents = Sets.newHashSet();
|
||||
fcPoints.forEach(point -> {
|
||||
Set<FilteredConnectPoint> otherPoints =
|
||||
fcPoints.stream()
|
||||
.filter(fcp -> !fcp.equals(point))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Key brcKey = intentInstaller.buildKey(PREFIX_BROADCAST,
|
||||
point.connectPoint(),
|
||||
networkName,
|
||||
MacAddress.BROADCAST);
|
||||
|
||||
if ((!intentInstaller.intentExists(brcKey) || affectedByApi) &&
|
||||
!otherPoints.isEmpty()) {
|
||||
intents.add(intentInstaller.buildBrcIntent(brcKey,
|
||||
point,
|
||||
otherPoints));
|
||||
}
|
||||
});
|
||||
if (connectedHosts.isEmpty()) {
|
||||
confHostPresentCPoint.put(vlanId, Pair.of(cp, null));
|
||||
}
|
||||
|
||||
return ImmutableSet.copyOf(intents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up unicast intents between any given filtered connect point.
|
||||
*
|
||||
* @param networkName the VPLS name
|
||||
* @param hosts the set of destination hosts
|
||||
* @param fcPoints the set of filtered connect points
|
||||
* @param affectedByApi true if the function triggered from APIs;
|
||||
* false otherwise
|
||||
* @return the set of unicast intents
|
||||
*/
|
||||
private Set<Intent> buildUnicastIntents(String networkName,
|
||||
Set<Host> hosts,
|
||||
Set<FilteredConnectPoint> fcPoints,
|
||||
boolean affectedByApi) {
|
||||
Set<Intent> intents = Sets.newHashSet();
|
||||
hosts.forEach(host -> {
|
||||
FilteredConnectPoint hostPoint = getHostPoint(host, fcPoints);
|
||||
|
||||
if (hostPoint == null) {
|
||||
log.warn(HOST_FCP_NOT_FOUND, host);
|
||||
return;
|
||||
}
|
||||
|
||||
Set<FilteredConnectPoint> otherPoints =
|
||||
fcPoints.stream()
|
||||
.filter(fcp -> !fcp.equals(hostPoint))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Key uniKey = intentInstaller.buildKey(PREFIX_UNICAST,
|
||||
host.location(),
|
||||
networkName,
|
||||
host.mac());
|
||||
|
||||
if ((!intentInstaller.intentExists(uniKey) || affectedByApi) &&
|
||||
!otherPoints.isEmpty()) {
|
||||
intents.add(intentInstaller.buildUniIntent(uniKey,
|
||||
otherPoints,
|
||||
hostPoint,
|
||||
host));
|
||||
}
|
||||
});
|
||||
|
||||
return ImmutableSet.copyOf(intents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the filtered connect point a host is attached to.
|
||||
*
|
||||
* @param host the target host
|
||||
* @param fcps the filtered connected points
|
||||
* @return null if not found; the filtered connect point otherwise
|
||||
*/
|
||||
private FilteredConnectPoint getHostPoint(Host host,
|
||||
Set<FilteredConnectPoint> fcps) {
|
||||
return fcps.stream()
|
||||
.filter(fcp -> fcp.connectPoint().equals(host.location()))
|
||||
.filter(fcp -> {
|
||||
VlanIdCriterion vlanCriterion =
|
||||
(VlanIdCriterion) fcp.trafficSelector().
|
||||
getCriterion(Criterion.Type.VLAN_VID);
|
||||
|
||||
return vlanCriterion != null &&
|
||||
vlanCriterion.vlanId().equals(host.vlan());
|
||||
})
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a set of filtered connect points from a list of given interfaces.
|
||||
*
|
||||
* @param interfaces the interfaces to compute
|
||||
* @return the set of filtered connect points
|
||||
*/
|
||||
private Set<FilteredConnectPoint> buildFCPoints(Collection<Interface> interfaces) {
|
||||
// Build all filtered connected points in the network
|
||||
return interfaces
|
||||
.stream()
|
||||
.map(intf -> {
|
||||
TrafficSelector.Builder selectorBuilder =
|
||||
DefaultTrafficSelector.builder();
|
||||
|
||||
if (!intf.vlan().equals(VlanId.NONE)) {
|
||||
selectorBuilder.matchVlanId(intf.vlan());
|
||||
}
|
||||
|
||||
return new FilteredConnectPoint(intf.connectPoint(),
|
||||
selectorBuilder.build());
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for host events.
|
||||
*/
|
||||
class InternalHostListener implements HostListener {
|
||||
private class InternalHostListener implements HostListener {
|
||||
@Override
|
||||
public void event(HostEvent event) {
|
||||
log.debug("Received HostEvent {}", event);
|
||||
log.debug(HOST_EVENT, event);
|
||||
switch (event.type()) {
|
||||
case HOST_ADDED:
|
||||
case HOST_UPDATED:
|
||||
case HOST_REMOVED:
|
||||
setupConnectivity();
|
||||
setupConnectivity(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -214,16 +389,39 @@ public class Vpls {
|
||||
private class InternalInterfaceListener implements InterfaceListener {
|
||||
@Override
|
||||
public void event(InterfaceEvent event) {
|
||||
log.debug("Received InterfaceConfigEvent {}", event);
|
||||
log.debug(INTF_CONF_EVENT, event);
|
||||
switch (event.type()) {
|
||||
case INTERFACE_ADDED:
|
||||
case INTERFACE_UPDATED:
|
||||
case INTERFACE_REMOVED:
|
||||
setupConnectivity();
|
||||
setupConnectivity(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for VPLS configuration events.
|
||||
*/
|
||||
private class InternalNetworkConfigListener implements NetworkConfigListener {
|
||||
@Override
|
||||
public void event(NetworkConfigEvent event) {
|
||||
if (event.configClass() == VplsConfigurationService.CONFIG_CLASS) {
|
||||
log.debug(NET_CONF_EVENT, event.configClass());
|
||||
switch (event.type()) {
|
||||
case CONFIG_ADDED:
|
||||
case CONFIG_UPDATED:
|
||||
case CONFIG_REMOVED:
|
||||
setupConnectivity(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.net.config.Config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Configuration object for VPLS config.
|
||||
*/
|
||||
public class VplsConfig extends Config<ApplicationId> {
|
||||
private static final String VPLS = "vplsNetworks";
|
||||
private static final String NAME = "name";
|
||||
private static final String INTERFACE = "interfaces";
|
||||
|
||||
/**
|
||||
* Returns a set of configured VPLSs.
|
||||
*
|
||||
* @return set of VPLSs
|
||||
*/
|
||||
public Set<VplsNetworkConfig> vplsNetworks() {
|
||||
Set<VplsNetworkConfig> vpls = Sets.newHashSet();
|
||||
|
||||
JsonNode vplsNode = object.get(VPLS);
|
||||
|
||||
if (vplsNode == null) {
|
||||
return vpls;
|
||||
}
|
||||
|
||||
vplsNode.forEach(jsonNode -> {
|
||||
Set<String> ifaces = Sets.newHashSet();
|
||||
jsonNode.path(INTERFACE).forEach(ifacesNode ->
|
||||
ifaces.add(ifacesNode.asText())
|
||||
);
|
||||
|
||||
String name = jsonNode.get(NAME).asText();
|
||||
|
||||
vpls.add(new VplsNetworkConfig(name, ifaces));
|
||||
});
|
||||
|
||||
return vpls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the VPLS configuration given a VPLS name.
|
||||
*
|
||||
* @param name the VPLS name
|
||||
* @return the VPLS configuration if it exists; null otherwise
|
||||
*/
|
||||
public VplsNetworkConfig getVplsWithName(String name) {
|
||||
for (VplsNetworkConfig vpls : vplsNetworks()) {
|
||||
if (vpls.name().equals(name)) {
|
||||
return vpls;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a VPLS to the configuration.
|
||||
*
|
||||
* @param name the name of the VPLS to be added
|
||||
*/
|
||||
public void addVpls(VplsNetworkConfig name) {
|
||||
ObjectNode vplsNode = JsonNodeFactory.instance.objectNode();
|
||||
|
||||
vplsNode.put(NAME, name.name());
|
||||
|
||||
ArrayNode ifacesNode = vplsNode.putArray(INTERFACE);
|
||||
name.ifaces().forEach(ifacesNode::add);
|
||||
|
||||
ArrayNode vplsArray = vplsNetworks().isEmpty() ?
|
||||
initVplsConfiguration() : (ArrayNode) object.get(VPLS);
|
||||
vplsArray.add(vplsNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a VPLS from the configuration.
|
||||
*
|
||||
* @param name the name of the VPLS to be removed
|
||||
*/
|
||||
public void removeVpls(String name) {
|
||||
ArrayNode vplsArray = (ArrayNode) object.get(VPLS);
|
||||
|
||||
for (int i = 0; i < vplsArray.size(); i++) {
|
||||
if (vplsArray.get(i).hasNonNull(NAME) &&
|
||||
vplsArray.get(i).get(NAME).asText().equals(name)) {
|
||||
vplsArray.remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a VPLS with a given network interface.
|
||||
*
|
||||
* @param iface the network interface
|
||||
* @return the VPLS if found; null otherwise
|
||||
*/
|
||||
public VplsNetworkConfig getVplsFromInterface(String iface) {
|
||||
for (VplsNetworkConfig vpls : vplsNetworks()) {
|
||||
if (vpls.isAttached(iface)) {
|
||||
return vpls;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a network interface to a VPLS.
|
||||
*
|
||||
* @param name the name of the VPLS
|
||||
* @param iface the network interface to be added
|
||||
*/
|
||||
public void addInterfaceToVpls(String name, String iface) {
|
||||
JsonNode vplsNode = object.get(VPLS);
|
||||
vplsNode.forEach(jsonNode -> {
|
||||
|
||||
if (hasNamedNode(jsonNode, name)) {
|
||||
ArrayNode ifacesNode = (ArrayNode) jsonNode.get(INTERFACE);
|
||||
for (int i = 0; i < ifacesNode.size(); i++) {
|
||||
if (ifacesNode.get(i).asText().equals(iface)) {
|
||||
return; // Interface already exists.
|
||||
}
|
||||
}
|
||||
ifacesNode.add(iface);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a network interface from a VPLS.
|
||||
*
|
||||
* @param name the name of the VPLS
|
||||
* @param iface the network interface to be removed
|
||||
*/
|
||||
public void removeInterfaceFromVpls(VplsNetworkConfig name, String iface) {
|
||||
JsonNode vplsNode = object.get(VPLS);
|
||||
vplsNode.forEach(jsonNode -> {
|
||||
if (hasNamedNode(jsonNode, name.name())) {
|
||||
ArrayNode ifacesNode = (ArrayNode) jsonNode.get(INTERFACE);
|
||||
for (int i = 0; i < ifacesNode.size(); i++) {
|
||||
if (ifacesNode.get(i).asText().equals(iface)) {
|
||||
ifacesNode.remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* States if a JSON node has a "name" attribute and if the value is equal to
|
||||
* the name given.
|
||||
*
|
||||
* @param jsonNode the JSON node
|
||||
* @param name the node name
|
||||
* @return true if the JSON node has a "name" attribute with value equal to
|
||||
* the name given; false otherwise
|
||||
*/
|
||||
private boolean hasNamedNode(JsonNode jsonNode, String name) {
|
||||
return jsonNode.hasNonNull(NAME) &&
|
||||
jsonNode.get(NAME).asText().equals(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty VPLS configuration.
|
||||
*
|
||||
* @return empty ArrayNode to store the VPLS configuration
|
||||
*/
|
||||
private ArrayNode initVplsConfiguration() {
|
||||
return object.putArray(VPLS);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import org.onlab.packet.VlanId;
|
||||
import org.onosproject.incubator.net.intf.Interface;
|
||||
import org.onosproject.net.ConnectPoint;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provides information about the VPLS configuration.
|
||||
*/
|
||||
public interface VplsConfigurationService {
|
||||
Class<VplsConfig> CONFIG_CLASS = VplsConfig.class;
|
||||
|
||||
/**
|
||||
* Adds a VPLS to the configuration.
|
||||
*
|
||||
* @param name the name of the VPLS
|
||||
* @param ifaces the interfaces associated with the VPLS
|
||||
*/
|
||||
void addVpls(String name, Set<String> ifaces);
|
||||
|
||||
/**
|
||||
* Removes a VPLS from the configuration.
|
||||
*
|
||||
* @param name the name of the VPLS to be removed
|
||||
*/
|
||||
void removeVpls(String name);
|
||||
|
||||
/**
|
||||
* Adds a network interface to a VPLS.
|
||||
*
|
||||
* @param name the name of the VPLS
|
||||
* @param iface the network interface to be added to the VPLS
|
||||
*/
|
||||
void addInterfaceToVpls(String name, String iface);
|
||||
|
||||
/**
|
||||
* Removes a network interface from a VPLS.
|
||||
*
|
||||
* @param iface the network interface to be removed from the VPLS
|
||||
*/
|
||||
void removeInterfaceFromVpls(String iface);
|
||||
|
||||
/**
|
||||
* Cleans up the VPLS configuration. Removes all VPLSs.
|
||||
*/
|
||||
void cleanVpls();
|
||||
|
||||
/**
|
||||
* Retrieves the VPLS names modified from CLI.
|
||||
*
|
||||
* @return a set of VPLS names modified from CLI
|
||||
*/
|
||||
Set<String> getVplsAffectedByApi();
|
||||
// TODO Removes this function after intent framework fix race condition
|
||||
|
||||
/**
|
||||
* Retrieves the interfaces from the VPLS configuration.
|
||||
*
|
||||
* @return a set of interfaces contained in the VPLS configuration
|
||||
*/
|
||||
Set<Interface> getAllInterfaces();
|
||||
|
||||
/**
|
||||
* Retrieves the interfaces belonging to the VPLS.
|
||||
*
|
||||
* @param name the name of the VPLS
|
||||
* @return a set of interfaces belonging to the VPLS
|
||||
*/
|
||||
Set<Interface> getVplsInterfaces(String name);
|
||||
|
||||
/**
|
||||
* Retrieves all VPLS names.
|
||||
*
|
||||
* @return a set of VPLS names
|
||||
*/
|
||||
Set<String> getAllVpls();
|
||||
|
||||
/**
|
||||
* Retrieves all VPLS names from the old config.
|
||||
*
|
||||
* @return a set of VPLS names
|
||||
*/
|
||||
Set<String> getOldVpls();
|
||||
// TODO Removes this function after intent framework fix race condition
|
||||
|
||||
/**
|
||||
* Retrieves the VPLS names and associated interfaces from the configuration.
|
||||
*
|
||||
* @return a map VPLS names and associated interfaces
|
||||
*/
|
||||
SetMultimap<String, Interface> getVplsNetworks();
|
||||
|
||||
/**
|
||||
* Retrieves a VPLS network given a VLAN Id and a connect point.
|
||||
*
|
||||
* @param vlan the VLAN Id
|
||||
* @param connectPoint the connect point
|
||||
* @return a map VPLS names and associated interfaces; null otherwise
|
||||
*/
|
||||
SetMultimap<String, Interface> getVplsNetwork(VlanId vlan,
|
||||
ConnectPoint connectPoint);
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Configuration of a VPLS Network.
|
||||
*/
|
||||
public class VplsNetworkConfig {
|
||||
private final String name;
|
||||
private final Set<String> ifaces;
|
||||
|
||||
/**
|
||||
* Creates a new VPLS configuration.
|
||||
*
|
||||
* @param name the VPLS name
|
||||
* @param ifaces the interfaces associated with the VPLS
|
||||
*/
|
||||
public VplsNetworkConfig(String name, Set<String> ifaces) {
|
||||
this.name = checkNotNull(name);
|
||||
this.ifaces = checkNotNull(ImmutableSet.copyOf(ifaces));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the VPLS.
|
||||
*
|
||||
* @return the name of the VPLS
|
||||
*/
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of interfaces associated with the VPLS.
|
||||
*
|
||||
* @return a set of interface names associated with the VPLS
|
||||
*/
|
||||
public Set<String> ifaces() {
|
||||
return ImmutableSet.copyOf(ifaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* States if a given interface is part of a VPLS.
|
||||
*
|
||||
* @param iface the interface attached to a VPLS
|
||||
* @return true if the interface is associated to the VPLS; false otherwise
|
||||
*/
|
||||
public boolean isAttached(String iface) {
|
||||
return ifaces.stream().anyMatch(i -> i.equals(iface));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof VplsNetworkConfig) {
|
||||
final VplsNetworkConfig that = (VplsNetworkConfig) obj;
|
||||
return Objects.equals(this.name, that.name) &&
|
||||
Objects.equals(this.ifaces, that.ifaces);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, ifaces);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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.config.impl;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import org.apache.felix.scr.annotations.Activate;
|
||||
import org.apache.felix.scr.annotations.Component;
|
||||
import org.apache.felix.scr.annotations.Deactivate;
|
||||
import org.apache.felix.scr.annotations.Reference;
|
||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||
import org.apache.felix.scr.annotations.Service;
|
||||
import org.onlab.packet.VlanId;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.incubator.net.intf.Interface;
|
||||
import org.onosproject.incubator.net.intf.InterfaceService;
|
||||
import org.onosproject.net.ConnectPoint;
|
||||
import org.onosproject.net.config.NetworkConfigRegistry;
|
||||
import org.onosproject.net.config.NetworkConfigService;
|
||||
import org.onosproject.net.config.NetworkConfigListener;
|
||||
import org.onosproject.net.config.NetworkConfigEvent;
|
||||
import org.onosproject.net.config.ConfigFactory;
|
||||
import org.onosproject.net.config.basics.SubjectFactories;
|
||||
import org.onosproject.vpls.config.VplsConfig;
|
||||
import org.onosproject.vpls.config.VplsNetworkConfig;
|
||||
import org.onosproject.vpls.config.VplsConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Implementation of VPLSConfigurationService which reads VPLS configuration
|
||||
* from the network configuration service.
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
@Service
|
||||
public class VplsConfigurationImpl implements VplsConfigurationService {
|
||||
private static final String VPLS_APP = "org.onosproject.vpls";
|
||||
private static final String VPLS = "vpls";
|
||||
private static final String EMPTY = "";
|
||||
private static final String CONFIG_NULL = "VPLS configuration not defined";
|
||||
private static final String APP_ID_NULL = "VPLS application ID is null";
|
||||
private static final String CONFIG_CHANGED = "VPLS configuration changed: {}";
|
||||
private static final String CHECK_CONFIG =
|
||||
"Checking the interface configuration";
|
||||
private static final String NET_CONF_EVENT =
|
||||
"Received NetworkConfigEvent {}";
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected NetworkConfigRegistry registry;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected CoreService coreService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected InterfaceService interfaceService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected NetworkConfigService configService;
|
||||
|
||||
private final Set<String> vplsAffectedByApi = new HashSet<>();
|
||||
|
||||
private VplsConfig vplsConfig = new VplsConfig();
|
||||
|
||||
private SetMultimap<String, String> ifacesOfVpls = HashMultimap.create();
|
||||
private SetMultimap<String, String> oldIfacesOfVpls = HashMultimap.create();
|
||||
private SetMultimap<String, Interface> vplsNetworks = HashMultimap.create();
|
||||
|
||||
private final InternalNetworkConfigListener configListener =
|
||||
new InternalNetworkConfigListener();
|
||||
|
||||
private ConfigFactory<ApplicationId, VplsConfig> vplsConfigFactory =
|
||||
new ConfigFactory<ApplicationId, VplsConfig>(
|
||||
SubjectFactories.APP_SUBJECT_FACTORY, VplsConfig.class, VPLS) {
|
||||
@Override
|
||||
public VplsConfig createConfig() {
|
||||
return new VplsConfig();
|
||||
}
|
||||
};
|
||||
|
||||
private ApplicationId vplsAppId;
|
||||
|
||||
@Activate
|
||||
protected void active() {
|
||||
configService.addListener(configListener);
|
||||
registry.registerConfigFactory(vplsConfigFactory);
|
||||
loadConfiguration();
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
protected void deactive() {
|
||||
registry.unregisterConfigFactory(vplsConfigFactory);
|
||||
configService.removeListener(configListener);
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the VPLS configuration from network configuration.
|
||||
*/
|
||||
private void loadConfiguration() {
|
||||
loadAppId();
|
||||
|
||||
vplsConfig = configService.getConfig(vplsAppId, VplsConfig.class);
|
||||
|
||||
if (vplsConfig == null) {
|
||||
log.warn(CONFIG_NULL);
|
||||
configService.addConfig(vplsAppId, VplsConfig.class);
|
||||
return;
|
||||
}
|
||||
|
||||
oldIfacesOfVpls = ifacesOfVpls;
|
||||
ifacesOfVpls = getConfigInterfaces();
|
||||
vplsNetworks = getConfigCPoints();
|
||||
log.debug(CONFIG_CHANGED, ifacesOfVpls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the application identifier from core service.
|
||||
*/
|
||||
private void loadAppId() {
|
||||
vplsAppId = coreService.getAppId(VPLS_APP);
|
||||
if (vplsAppId == null) {
|
||||
log.warn(APP_ID_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a given configuration to the VPLS application.
|
||||
*/
|
||||
private void applyConfig(VplsConfig vplsConfig) {
|
||||
loadAppId();
|
||||
configService.applyConfig(vplsAppId, VplsConfig.class, vplsConfig.node());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the VPLS names and associated interfaces names from the configuration.
|
||||
*
|
||||
* @return a map VPLS names and associated interface names
|
||||
*/
|
||||
private SetMultimap<String, String> getConfigInterfaces() {
|
||||
SetMultimap<String, String> confIntfByVpls =
|
||||
HashMultimap.create();
|
||||
|
||||
vplsConfig.vplsNetworks().forEach(vpls -> {
|
||||
if (vpls.ifaces().isEmpty()) {
|
||||
confIntfByVpls.put(vpls.name(), EMPTY);
|
||||
} else {
|
||||
vpls.ifaces().forEach(iface -> confIntfByVpls.put(vpls.name(), iface));
|
||||
}
|
||||
});
|
||||
|
||||
return confIntfByVpls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the VPLS names and associated interfaces from the configuration.
|
||||
*
|
||||
* @return a map VPLS names and associated interfaces
|
||||
*/
|
||||
private SetMultimap<String, Interface> getConfigCPoints() {
|
||||
log.debug(CHECK_CONFIG);
|
||||
|
||||
SetMultimap<String, Interface> confCPointsByIntf =
|
||||
HashMultimap.create();
|
||||
|
||||
ifacesOfVpls.entries().forEach(vpls -> {
|
||||
interfaceService.getInterfaces()
|
||||
.stream()
|
||||
.filter(intf -> intf.ipAddressesList().isEmpty())
|
||||
.filter(intf -> intf.name().equals(vpls.getValue()))
|
||||
.forEach(intf -> confCPointsByIntf.put(vpls.getKey(), intf));
|
||||
});
|
||||
|
||||
return confCPointsByIntf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for VPLS configuration events.
|
||||
*/
|
||||
private class InternalNetworkConfigListener implements NetworkConfigListener {
|
||||
@Override
|
||||
public void event(NetworkConfigEvent event) {
|
||||
if (event.configClass() == VplsConfigurationService.CONFIG_CLASS) {
|
||||
log.debug(NET_CONF_EVENT, event.configClass());
|
||||
switch (event.type()) {
|
||||
case CONFIG_ADDED:
|
||||
case CONFIG_UPDATED:
|
||||
case CONFIG_REMOVED:
|
||||
loadConfiguration();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVpls(String name, Set<String> ifaces) {
|
||||
VplsNetworkConfig vpls;
|
||||
|
||||
if (ifacesOfVpls.containsKey(name)) {
|
||||
if (ifaces.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ifaces.forEach(iface ->
|
||||
vplsConfig.addInterfaceToVpls(name, iface));
|
||||
} else {
|
||||
vpls = new VplsNetworkConfig(name, ifaces);
|
||||
vplsConfig.addVpls(vpls);
|
||||
}
|
||||
|
||||
vplsAffectedByApi.add(name);
|
||||
applyConfig(vplsConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVpls(String name) {
|
||||
if (ifacesOfVpls.containsKey(name)) {
|
||||
vplsConfig.removeVpls(name);
|
||||
vplsAffectedByApi.add(name);
|
||||
applyConfig(vplsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterfaceToVpls(String name, String iface) {
|
||||
if (ifacesOfVpls.containsKey(name)) {
|
||||
vplsConfig.addInterfaceToVpls(name, iface);
|
||||
vplsAffectedByApi.add(name);
|
||||
applyConfig(vplsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeInterfaceFromVpls(String iface) {
|
||||
if (ifacesOfVpls.containsValue(iface)) {
|
||||
VplsNetworkConfig vpls = vplsConfig.getVplsFromInterface(iface);
|
||||
vplsConfig.removeInterfaceFromVpls(vpls, iface);
|
||||
vplsAffectedByApi.add(vpls.name());
|
||||
applyConfig(vplsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanVpls() {
|
||||
ifacesOfVpls.entries().forEach(e -> {
|
||||
vplsConfig.removeVpls(e.getKey());
|
||||
vplsAffectedByApi.add(e.getKey());
|
||||
});
|
||||
applyConfig(vplsConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getVplsAffectedByApi() {
|
||||
Set<String> vplsNames = ImmutableSet.copyOf(vplsAffectedByApi);
|
||||
|
||||
vplsAffectedByApi.clear();
|
||||
|
||||
return vplsNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Interface> getAllInterfaces() {
|
||||
Set<Interface> allInterfaces = new HashSet<>();
|
||||
vplsNetworks.values().forEach(allInterfaces::add);
|
||||
|
||||
return allInterfaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Interface> getVplsInterfaces(String name) {
|
||||
Set<Interface> vplsInterfaces = new HashSet<>();
|
||||
vplsNetworks.get(name).forEach(vplsInterfaces::add);
|
||||
|
||||
return vplsInterfaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAllVpls() {
|
||||
return ifacesOfVpls.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getOldVpls() {
|
||||
return oldIfacesOfVpls.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetMultimap<String, Interface> getVplsNetworks() {
|
||||
return ImmutableSetMultimap.copyOf(vplsNetworks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetMultimap<String, Interface> getVplsNetwork(VlanId vlan,
|
||||
ConnectPoint connectPoint) {
|
||||
String vplsNetworkName =
|
||||
vplsNetworks.entries().stream()
|
||||
.filter(e -> e.getValue().connectPoint().equals(connectPoint))
|
||||
.filter(e -> e.getValue().vlan().equals(vlan))
|
||||
.map(e -> e.getKey())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
SetMultimap<String, Interface> result = HashMultimap.create();
|
||||
if (vplsNetworkName != null && vplsNetworks.containsKey(vplsNetworkName)) {
|
||||
vplsNetworks.get(vplsNetworkName)
|
||||
.forEach(intf -> result.put(vplsNetworkName, intf));
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration implementation to create L2 broadcast network using VLAN.
|
||||
*/
|
||||
package org.onosproject.vpls.config.impl;
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration to create L2 broadcast network using VLAN.
|
||||
*/
|
||||
package org.onosproject.vpls.config;
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.onosproject.TestApplicationId;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.net.config.Config;
|
||||
import org.onosproject.net.config.ConfigApplyDelegate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for the {@link VplsConfig} class.
|
||||
*/
|
||||
public class VplsConfigTest {
|
||||
private static final String APP_NAME = "org.onosproject.vpls";
|
||||
private static final ApplicationId APP_ID = new TestApplicationId(APP_NAME);
|
||||
private static final String VPLS = "vplsNetworks";
|
||||
private static final String NAME = "name";
|
||||
private static final String INTERFACE = "interfaces";
|
||||
private static final String NET1 = "net1";
|
||||
private static final String NET2 = "net2";
|
||||
private static final String NEWNET = "newnet";
|
||||
|
||||
private static final String IF1 = "sw5-4-100";
|
||||
private static final String IF2 = "sw5-4-200";
|
||||
private static final String IF3 = "sw5-5-100";
|
||||
private static final String IF4 = "sw6-5-100";
|
||||
private static final String IF5 = "sw6-5-400";
|
||||
private static final String IF_NON_EXIST = "sw7-5-100";
|
||||
|
||||
private static final String JSON_TREE = "{\"" + VPLS +
|
||||
"\" : [{\"" + NAME + "\" : \"net1\"," +
|
||||
"\"" + INTERFACE + "\" : [" +
|
||||
"\"sw5-4-100\",\"sw5-4-200\",\"sw5-5-100\"]}]}";
|
||||
private static final String EMPTY_JSON_TREE = "{}";
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
private final ConfigApplyDelegate delegate = new MockCfgDelegate();
|
||||
private final VplsNetworkConfig initialNetwork = createInitialNetwork();
|
||||
|
||||
private Set<VplsNetworkConfig> networks = new HashSet<>();
|
||||
private VplsConfig vplsConfig = new VplsConfig();
|
||||
private VplsConfig emptyVplsConfig = new VplsConfig();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
JsonNode tree = new ObjectMapper().readTree(JSON_TREE);
|
||||
vplsConfig.init(APP_ID, APP_NAME, tree, mapper, delegate);
|
||||
JsonNode emptyTree = new ObjectMapper().readTree(EMPTY_JSON_TREE);
|
||||
emptyVplsConfig.init(APP_ID, APP_NAME, emptyTree, mapper, delegate);
|
||||
networks.add(initialNetwork);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a VPLS configuration can be retrieved from JSON.
|
||||
*/
|
||||
@Test
|
||||
public void testVplsNetworks() {
|
||||
assertEquals(networks, vplsConfig.vplsNetworks());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an empty VPLS application configuration is retrieved from JSON.
|
||||
*/
|
||||
@Test
|
||||
public void testEmptyVplsNetworks() {
|
||||
assertTrue(emptyVplsConfig.vplsNetworks().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a VPLS can be found by name.
|
||||
*/
|
||||
@Test
|
||||
public void testGetVplsWithName() {
|
||||
assertNotNull(vplsConfig.getVplsWithName(NET1));
|
||||
assertNull(vplsConfig.getVplsWithName(NET2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the addition of a new VPLS.
|
||||
*/
|
||||
@Test
|
||||
public void testAddNetwork() {
|
||||
int initialSize = vplsConfig.vplsNetworks().size();
|
||||
VplsNetworkConfig newNetwork = createNewNetwork();
|
||||
vplsConfig.addVpls(newNetwork);
|
||||
assertEquals(initialSize + 1, vplsConfig.vplsNetworks().size());
|
||||
networks.add(newNetwork);
|
||||
assertEquals(networks, vplsConfig.vplsNetworks());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the addition of new VPLS to an empty configuration.
|
||||
*/
|
||||
@Test
|
||||
public void testAddNetworkToEmpty() {
|
||||
VplsNetworkConfig newNetwork = createNewNetwork();
|
||||
emptyVplsConfig.addVpls(newNetwork);
|
||||
|
||||
assertFalse(emptyVplsConfig.vplsNetworks().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the removal of an existing VPLS from the configuration.
|
||||
*/
|
||||
@Test
|
||||
public void testRemoveExistingNetwork() {
|
||||
int initialSize = vplsConfig.vplsNetworks().size();
|
||||
vplsConfig.removeVpls(NET1);
|
||||
|
||||
assertEquals(initialSize - 1, vplsConfig.vplsNetworks().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the removal of a non-existing VPLS from the configuration.
|
||||
*/
|
||||
@Test
|
||||
public void testRemoveInexistingNetwork() {
|
||||
int initialSize = vplsConfig.vplsNetworks().size();
|
||||
vplsConfig.removeVpls(NET2);
|
||||
|
||||
assertEquals(initialSize, vplsConfig.vplsNetworks().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the addition of a new interface.
|
||||
*/
|
||||
@Test
|
||||
public void testAddInterfaceToNetwork() {
|
||||
int initialSize = vplsConfig.getVplsWithName(NET1).ifaces().size();
|
||||
vplsConfig.addInterfaceToVpls(NET1, IF4);
|
||||
|
||||
assertEquals(initialSize + 1, vplsConfig.getVplsWithName(NET1).ifaces().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the addition of a new interface when it already exists.
|
||||
*/
|
||||
@Test
|
||||
public void testAddExistingInterfaceToNetwork() {
|
||||
int initialSize = vplsConfig.getVplsWithName(NET1).ifaces().size();
|
||||
vplsConfig.addInterfaceToVpls(NET1, IF1);
|
||||
|
||||
assertEquals(initialSize, vplsConfig.getVplsWithName(NET1).ifaces().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the retrieval of a VPLS, given an interface name.
|
||||
*/
|
||||
@Test
|
||||
public void testgetNetworkFromInterface() {
|
||||
assertNotNull(vplsConfig.getVplsFromInterface(IF1));
|
||||
assertNull(vplsConfig.getVplsFromInterface(IF_NON_EXIST));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the removal of an interface.
|
||||
*/
|
||||
@Test
|
||||
public void testRemoveExistingInterfaceFromNetwork() {
|
||||
int initialSize = vplsConfig.getVplsWithName(NET1).ifaces().size();
|
||||
vplsConfig.removeInterfaceFromVpls(initialNetwork, IF1);
|
||||
|
||||
assertEquals(initialSize - 1, vplsConfig.getVplsWithName(NET1).ifaces().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the removal of an interface from a VPLS when it does not exist.
|
||||
*/
|
||||
@Test
|
||||
public void testRemoveNonExistingInterfaceFromNetwork() {
|
||||
int initialSize = vplsConfig.getVplsWithName(NET1).ifaces().size();
|
||||
vplsConfig.removeInterfaceFromVpls(initialNetwork, IF_NON_EXIST);
|
||||
|
||||
assertEquals(initialSize, vplsConfig.getVplsWithName(NET1).ifaces().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the two interfaces are attached to the network
|
||||
* while one of the interface is attached and another one is not.
|
||||
*/
|
||||
@Test
|
||||
public void testIsAttached() {
|
||||
VplsNetworkConfig network = createNewNetwork();
|
||||
|
||||
assertTrue(network.isAttached(IF4));
|
||||
assertFalse(network.isAttached(IF_NON_EXIST));
|
||||
}
|
||||
|
||||
private class MockCfgDelegate implements ConfigApplyDelegate {
|
||||
|
||||
@Override
|
||||
public void onApply(@SuppressWarnings("rawtypes") Config config) {
|
||||
config.apply();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private VplsNetworkConfig createInitialNetwork() {
|
||||
Set<String> ifaces = new HashSet<>(Arrays.asList(IF1, IF2, IF3));
|
||||
|
||||
return new VplsNetworkConfig(NET1, ifaces);
|
||||
}
|
||||
|
||||
private VplsNetworkConfig createNewNetwork() {
|
||||
Set<String> ifaces = new HashSet<>(Arrays.asList(IF4, IF5));
|
||||
|
||||
return new VplsNetworkConfig(NEWNET, ifaces);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user